IcbcQueue.php 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. <?php
  2. namespace app\command;
  3. use think\console\Command;
  4. use think\console\Input;
  5. use think\console\Output;
  6. use think\Db;
  7. /**
  8. * 工行积分队列处理命令
  9. * 命令行运行: php think icbc_queue
  10. */
  11. class IcbcQueue extends Command
  12. {
  13. protected function configure()
  14. {
  15. $this->setName('icbc_queue')
  16. ->setDescription('处理工行积分推送队列');
  17. }
  18. protected function execute(Input $input, Output $output)
  19. {
  20. $output->writeln("开始处理工行积分队列...");
  21. // 获取待处理的任务
  22. $tasks = Db::name('icbc_queue')
  23. ->where('status', 0)
  24. ->where('retry_count', '<', 3)
  25. ->limit(50)
  26. ->select();
  27. if (empty($tasks)) {
  28. $output->writeln("没有待处理的任务");
  29. return;
  30. }
  31. $output->writeln("找到 " . count($tasks) . " 个待处理任务");
  32. foreach ($tasks as $task) {
  33. try {
  34. // 更新状态为处理中
  35. Db::name('icbc_queue')->where('id', $task['id'])->update([
  36. 'status' => 1,
  37. 'updatetime' => time()
  38. ]);
  39. $output->writeln("处理任务 ID: {$task['id']}, 手机号: {$task['mobile_phone']}, 积分: {$task['integral_value']}");
  40. // 调用工行接口
  41. $result = $this->callIcbcApi($task);
  42. // 先检查返回值是否为数组
  43. if (!is_array($result)) {
  44. $output->writeln("✗ 任务 {$task['id']} 返回值异常: " . var_export($result, true));
  45. // 返回值异常,标记为失败
  46. $retry_count = $task['retry_count'] + 1;
  47. $status = $retry_count >= 3 ? 3 : 0;
  48. Db::name('icbc_queue')->where('id', $task['id'])->update([
  49. 'status' => $status,
  50. 'retry_count' => $retry_count,
  51. 'result' => json_encode(['error' => '返回值不是数组', 'raw' => var_export($result, true)], JSON_UNESCAPED_UNICODE),
  52. 'error_msg' => '接口返回值格式错误',
  53. 'updatetime' => time()
  54. ]);
  55. continue;
  56. }
  57. // 根据结果更新状态
  58. if (isset($result['return_code']) && $result['return_code'] == 0) {
  59. // 成功
  60. Db::name('icbc_queue')->where('id', $task['id'])->update([
  61. 'status' => 2,
  62. 'result' => json_encode($result, JSON_UNESCAPED_UNICODE),
  63. 'updatetime' => time()
  64. ]);
  65. $output->writeln("✓ 任务 {$task['id']} 处理成功");
  66. } else {
  67. // 失败,增加重试次数
  68. $retry_count = $task['retry_count'] + 1;
  69. $status = $retry_count >= 3 ? 3 : 0;
  70. $error_msg = isset($result['return_msg']) ? $result['return_msg'] : '未知错误';
  71. Db::name('icbc_queue')->where('id', $task['id'])->update([
  72. 'status' => $status,
  73. 'retry_count' => $retry_count,
  74. 'result' => json_encode($result, JSON_UNESCAPED_UNICODE),
  75. 'error_msg' => $error_msg,
  76. 'updatetime' => time()
  77. ]);
  78. $output->writeln("✗ 任务 {$task['id']} 处理失败: " . $error_msg);
  79. }
  80. } catch (\Exception $e) {
  81. // 异常处理
  82. Db::name('icbc_queue')->where('id', $task['id'])->update([
  83. 'status' => 0,
  84. 'retry_count' => $task['retry_count'] + 1,
  85. 'error_msg' => $e->getMessage(),
  86. 'updatetime' => time()
  87. ]);
  88. $output->writeln("✗ 任务 {$task['id']} 异常: " . $e->getMessage());
  89. }
  90. // 避免请求过快
  91. usleep(100000); // 0.1秒
  92. }
  93. $output->writeln("队列处理完成");
  94. }
  95. /**
  96. * 调用工行接口
  97. */
  98. private function callIcbcApi($task)
  99. {
  100. include_once EXTEND_PATH . 'icbc/DefaultIcbcClient.php';
  101. // 生成16位唯一序列号
  102. $fSeqNo = time() . str_pad(mt_rand(0, 999999), 6, '0', STR_PAD_LEFT);
  103. // 构建业务参数 (PHP 8+ 兼容)
  104. $biz_content = [
  105. 'fSeqNo' => $fSeqNo,
  106. 'corpCode' => 'xingfulishequ',
  107. 'mobilePhone' => $task['mobile_phone'] ?? '',
  108. 'integralValue' => (string)($task['integral_value'] ?? 0),
  109. 'integralType' => $task['integral_type'] ?? '',
  110. 'remark1' => $task['nickname'] ?? '',
  111. ];
  112. // 工行RSA密钥
  113. $public_key = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwFgHD4kzEVPdOj03ctKM7KV+16bWZ5BMNgvEeuEQwfQYkRVwI9HFOGkwNTMn5hiJXHnlXYCX+zp5r6R52MY0O7BsTCLT7aHaxsANsvI9ABGx3OaTVlPB59M6GPbJh0uXvio0m1r/lTW3Z60RU6Q3oid/rNhP3CiNgg0W6O3AGqwIDAQAB';
  114. $private_key = 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCR8/ZvKPAdZzsyvapySvztQm56s1N59ynKMOWpUbK4c5MNWMl+q3dvsp+UiSAx2TAeGkYfW3W6nO/3Y0hAZki99fmuzpPujEeHhs79HNwGZYQjN71Vck2JeflTq8jpL+9/up0Kz2nbwtZDMKTTEgbfNeO24gV1bmvD2kQ9j66RIyuXSDwQbVbQfl6LiqKoJm3rbtsbwX1Ytc0/Szslyor1VdPZWnHDMm3m78Hqu7X3vL6K7fAW/4FVbeKV7vWjvyiTQfETmuADqMdsqV5YeqUZWE/Dnzg+6JV/3L9nJ8f+/mPlh8k1h1oW035GrADKFKf1M2ujKKeHICnj7qKCdBeNAgMBAAECggEAHkh+U2YtHAy1Tbvox7ojbJ8iCTd4FJBiDV/D5zPaX0crtdM8S5oMOBLZ5ZnmIjGsODK/ZfY2ITg62huxfBs88J0+5zRZoV9d4BLqk74PMQyTNDN2h2omCGZUgzXbg/a8PMZdm0aZ8k0k4+AN8vWEk3+89c9Dzq/QkFyTWCqdz+Mp9NkcOjA255kj5/D1q9Zj0x9VcmKg3oTtrKL/dkspUxVaMKXcpo6J4AszC05tT3N0SNLhcq51I6B9QdbYsYCkP9whPNYIl/y4dN4QnNEivQzA5/ltr5DDQZc7Xke1+SpJN+ylBOBJ8yvNoDnuxx0xEWuNJ5bUzyri/DNjZRKNQQKBgQDKkxn5R4Q3rChI/KVIXHMecTs9fXN5pbnA8UKU6ZeTl+wHffxwRieHZJJp1nDcQ5i8YXCtqEJcJGFn3T0rEjVCJ/RVHclFO+TjYaK9HtyNJLPrvKmAzjCzV1yPfe4qmpgJddzZI7Vii2uFgklixvhkoY74hwSJtvLPTO0p0xrYdQKBgQC4cgfpCMLYlaHQGz+dAEf4IewQpwBGn7XShCpiXGFciGZZEIzvJMzXP7yo8pDMHQbB4kQsTRRG2fcdHGWI5VQGHPqG5O0tUueKGUlSg7j8Y/Pp8ZrBGSrlilAf17I/u9MC7Xe2ZRVGNgPDYAyjMEGmClI0n2+aN6b4CFVBjYmfuQKBgEKO9KDIE7QrF41rnW7aGWTuNVWty2wzvIWdf4/n9EqlRwLrLS9CjahZrhWiRLDKcPusVFZqi2s09OAoe/mT4PXcpNX2lHPwCvN+1/allje10HvrIBJXLP8v/BSVftR2uO+azzZ1GhrHzksulKgk0eZWguA7lI0fFEZycxYj65UlAoGAD9p1RZlkLfuGgf2llRgOF4zK3o+MHYXiuep0PioUkECFE4ixpGh0Vtf6nkbjHTgteYK6O1iQsppPfCgRrheQBkp9WhTZMfkbP6p2u+nof4ET2PrUQ16naj1eL655erLpKypADORZVMSVxDhAPdKLAfuHH1DI5ed8qXsF4PGKb7kCgYEAm/d+daT6YsbHDZlJ/J9Q8rRkKmiqj43NGQSHKg6Z6BEDibm8wRmj3Itu1N6XVChuaH+ekJzvUnZ/q1nyYzGvy6bOHYn3ziF9aH7wuhcRZ4qARmKDnzTBLg2QXBK1+400O3LJ+sAH/yuH/Y4hzRE6YMxBQpdYfnlJcIFVimAsT1w=';
  115. // 构建通用请求参数
  116. $data = [
  117. 'app_id' => '10000000000004096993',
  118. 'msg_id' => createUniqueNo('msg', time()),
  119. 'format' => 'json',
  120. 'charset' => 'UTF-8',
  121. 'encrypt_type' => 'AES',
  122. 'sign_type' => 'RSA2',
  123. ];
  124. try {
  125. // 创建工行客户端
  126. $client = new \DefaultIcbcClient(
  127. $data['app_id'],
  128. $private_key,
  129. $data['sign_type'],
  130. $data['charset'],
  131. $data['format'],
  132. $public_key,
  133. '', '', '', ''
  134. );
  135. // 构建请求参数
  136. $request = [
  137. 'serviceUrl' => 'https://gw.dccnet.com.cn:8084/api/mybank/farm/farmplatf/updateVillagerIntegral/V1',
  138. 'method' => 'POST',
  139. 'isNeedEncrypt' => false,
  140. 'extraParams' => null,
  141. 'biz_content' => $biz_content,
  142. ];
  143. // 发送请求
  144. $response = $client->execute($request, $data['msg_id'], '');
  145. // 解析响应
  146. if (empty($response)) {
  147. return ['return_code' => '-1', 'return_msg' => '接口无响应'];
  148. }
  149. $result = json_decode($response, true);
  150. if (json_last_error() !== JSON_ERROR_NONE) {
  151. return ['return_code' => '-2', 'return_msg' => 'JSON解析失败'];
  152. }
  153. // 写入日志
  154. $this->writeLog($result['return_code'] == 0, $result, $biz_content);
  155. return $result;
  156. } catch (\Exception $e) {
  157. return ['return_code' => '-99', 'return_msg' => '异常: ' . $e->getMessage()];
  158. }
  159. }
  160. /**
  161. * 写入日志
  162. */
  163. private function writeLog($is_success, $result, $request_data)
  164. {
  165. $log_dir = RUNTIME_PATH . 'icbc_log/';
  166. if (!is_dir($log_dir)) {
  167. mkdir($log_dir, 0755, true);
  168. }
  169. $filename = $is_success ? 'suc.txt' : 'failicbc.txt';
  170. $filepath = $log_dir . $filename;
  171. $log_content = [
  172. '时间' => date('Y-m-d H:i:s'),
  173. '请求数据' => $request_data,
  174. '返回数据' => $result,
  175. '分隔线' => str_repeat('-', 80)
  176. ];
  177. $log_text = "\n" . json_encode($log_content, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n";
  178. file_put_contents($filepath, $log_text, FILE_APPEND);
  179. }
  180. }