UrsWithdrawRequest.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. <?php
  2. namespace ThirdParty\Urs\Request;
  3. use App\Module\ThirdParty\Services\BaseRequest;
  4. /**
  5. * URS提取请求类
  6. *
  7. * 专门处理提取请求,遵循"一个Request类只完成一种请求"的原则
  8. */
  9. class UrsWithdrawRequest extends BaseRequest
  10. {
  11. /**
  12. * 构造函数
  13. */
  14. public function __construct()
  15. {
  16. // 使用'urs'作为服务代码,需要在thirdparty_services表中注册
  17. parent::__construct('urs');
  18. }
  19. /**
  20. * 处理提取请求
  21. *
  22. * @param array $params 请求参数
  23. * @return array
  24. * @throws \Exception
  25. */
  26. protected function handler(array $params): array
  27. {
  28. return $this->handleWithdraw($params);
  29. }
  30. /**
  31. * 处理提取操作
  32. *
  33. * @param array $params 请求参数
  34. * @return array
  35. * @throws \Exception
  36. */
  37. protected function handleWithdraw(array $params): array
  38. {
  39. // 验证必需参数
  40. if (empty($params['user_id'])) {
  41. throw new \Exception('user_id参数是必填的');
  42. }
  43. if (empty($params['amount'])) {
  44. throw new \Exception('amount参数是必填的');
  45. }
  46. if (empty($params['order_id'])) {
  47. throw new \Exception('order_id参数是必填的');
  48. }
  49. // 获取URS配置
  50. $config = $this->getConfig();
  51. $apiUrl = $config['api_url'] ?? '';
  52. $appId = $config['app_id'] ?? '';
  53. $appSecret = $config['app_secret'] ?? '';
  54. if (empty($apiUrl) || empty($appId) || empty($appSecret)) {
  55. throw new \Exception('URS配置不完整,缺少api_url、app_id或app_secret');
  56. }
  57. $requestData = [
  58. 'app_id' => $appId,
  59. 'user_id' => $params['user_id'],
  60. 'amount' => $params['amount'],
  61. 'order_id' => $params['order_id'],
  62. 'timestamp' => time(),
  63. ];
  64. $requestData['sign'] = $this->generateSign($requestData, $appSecret);
  65. $response = $this->sendHttpRequest($apiUrl . '/withdraw', $requestData);
  66. return [
  67. 'success' => $response['code'] === 0,
  68. 'message' => $response['message'] ?? '',
  69. 'data' => $response['data'] ?? [],
  70. ];
  71. }
  72. /**
  73. * 生成签名
  74. *
  75. * @param array $data 数据
  76. * @param string $secret 密钥
  77. * @return string
  78. */
  79. protected function generateSign(array $data, string $secret): string
  80. {
  81. // 排序参数
  82. ksort($data);
  83. // 构建签名字符串
  84. $signString = '';
  85. foreach ($data as $key => $value) {
  86. if ($key !== 'sign') {
  87. $signString .= $key . '=' . $value . '&';
  88. }
  89. }
  90. $signString .= 'key=' . $secret;
  91. return md5($signString);
  92. }
  93. /**
  94. * 发送HTTP请求
  95. *
  96. * @param string $url 请求URL
  97. * @param array $data 请求数据
  98. * @return array
  99. * @throws \Exception
  100. */
  101. protected function sendHttpRequest(string $url, array $data): array
  102. {
  103. $ch = curl_init();
  104. curl_setopt_array($ch, [
  105. CURLOPT_URL => $url,
  106. CURLOPT_POST => true,
  107. CURLOPT_POSTFIELDS => json_encode($data),
  108. CURLOPT_RETURNTRANSFER => true,
  109. CURLOPT_TIMEOUT => 30,
  110. CURLOPT_HTTPHEADER => [
  111. 'Content-Type: application/json',
  112. 'User-Agent: KKU-ThirdParty-URS/1.0',
  113. ],
  114. ]);
  115. $response = curl_exec($ch);
  116. $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  117. $error = curl_error($ch);
  118. curl_close($ch);
  119. if ($error) {
  120. throw new \Exception("HTTP请求失败: {$error}");
  121. }
  122. if ($httpCode !== 200) {
  123. throw new \Exception("HTTP请求失败,状态码: {$httpCode}");
  124. }
  125. $result = json_decode($response, true);
  126. if (json_last_error() !== JSON_ERROR_NONE) {
  127. throw new \Exception("响应数据格式错误: " . json_last_error_msg());
  128. }
  129. return $result;
  130. }
  131. }