CallbackLogic.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. <?php
  2. namespace App\Module\Transfer\Logics;
  3. use App\Module\Transfer\Enums\TransferStatus;
  4. use App\Module\Transfer\Models\TransferOrder;
  5. use App\Module\Transfer\Services\ExternalApiService;
  6. use Illuminate\Support\Facades\Log;
  7. /**
  8. * 回调处理逻辑
  9. */
  10. class CallbackLogic
  11. {
  12. /**
  13. * 发送回调通知
  14. *
  15. * @param TransferOrder $order 订单对象
  16. * @return bool
  17. */
  18. public static function sendCallback(TransferOrder $order): bool
  19. {
  20. try {
  21. $app = $order->transferApp;
  22. // 检查是否配置了回调URL
  23. if (empty($app->order_callback_url)) {
  24. // 没有配置回调URL,直接完成
  25. $order->updateStatus(TransferStatus::COMPLETED);
  26. return true;
  27. }
  28. // 准备回调数据
  29. $callbackData = [
  30. 'out_order_id' => $order->out_order_id,
  31. 'status' => $order->status->value,
  32. 'status_text' => $order->status->getDescription(),
  33. 'amount' => $order->out_amount,
  34. 'internal_amount' => $order->amount,
  35. 'user_id' => $order->user_id,
  36. 'processed_at' => $order->processed_at?->toDateTimeString(),
  37. 'callback_data' => $order->callback_data,
  38. 'timestamp' => now()->timestamp,
  39. ];
  40. // 发送回调
  41. $result = ExternalApiService::sendCallback($app, $callbackData);
  42. if ($result['success']) {
  43. // 回调成功
  44. $order->updateStatus(TransferStatus::CALLBACK);
  45. Log::info('Transfer callback sent successfully', [
  46. 'order_id' => $order->id,
  47. 'out_order_id' => $order->out_order_id,
  48. 'callback_url' => $app->order_callback_url
  49. ]);
  50. // 检查回调响应,决定是否完成订单
  51. $responseData = $result['data'] ?? [];
  52. if (isset($responseData['code']) && $responseData['code'] == 0) {
  53. $order->updateStatus(TransferStatus::COMPLETED);
  54. }
  55. return true;
  56. } else {
  57. // 回调失败,记录错误但不更新订单状态(等待重试)
  58. Log::error('Transfer callback failed', [
  59. 'order_id' => $order->id,
  60. 'out_order_id' => $order->out_order_id,
  61. 'callback_url' => $app->order_callback_url,
  62. 'error' => $result['message']
  63. ]);
  64. return false;
  65. }
  66. } catch (\Exception $e) {
  67. Log::error('Transfer callback exception', [
  68. 'order_id' => $order->id,
  69. 'error' => $e->getMessage(),
  70. 'trace' => $e->getTraceAsString()
  71. ]);
  72. return false;
  73. }
  74. }
  75. /**
  76. * 重试回调
  77. *
  78. * @param TransferOrder $order 订单对象
  79. * @param int $maxRetries 最大重试次数
  80. * @return bool
  81. */
  82. public static function retryCallback(TransferOrder $order, int $maxRetries = 3): bool
  83. {
  84. // 检查重试次数(可以通过callback_data中的retry_count字段记录)
  85. $callbackData = $order->callback_data;
  86. $retryCount = $callbackData['retry_count'] ?? 0;
  87. if ($retryCount >= $maxRetries) {
  88. Log::warning('Transfer callback max retries reached', [
  89. 'order_id' => $order->id,
  90. 'retry_count' => $retryCount
  91. ]);
  92. return false;
  93. }
  94. // 增加重试次数
  95. $callbackData['retry_count'] = $retryCount + 1;
  96. $order->update(['callback_data' => $callbackData]);
  97. // 重新发送回调
  98. return self::sendCallback($order);
  99. }
  100. /**
  101. * 批量处理待回调的订单
  102. *
  103. * @param int $limit 处理数量限制
  104. * @return int 处理的订单数量
  105. */
  106. public static function processPendingCallbacks(int $limit = 50): int
  107. {
  108. $processedCount = 0;
  109. // 查找需要回调的订单
  110. $orders = TransferOrder::where('status', TransferStatus::PROCESSING)
  111. ->whereHas('transferApp', function ($query) {
  112. $query->whereNotNull('order_callback_url');
  113. })
  114. ->where('created_at', '>', now()->subHours(24)) // 只处理24小时内的订单
  115. ->limit($limit)
  116. ->get();
  117. foreach ($orders as $order) {
  118. if (self::sendCallback($order)) {
  119. $processedCount++;
  120. }
  121. }
  122. return $processedCount;
  123. }
  124. /**
  125. * 批量重试失败的回调
  126. *
  127. * @param int $limit 处理数量限制
  128. * @return int 处理的订单数量
  129. */
  130. public static function retryFailedCallbacks(int $limit = 30): int
  131. {
  132. $processedCount = 0;
  133. // 查找回调失败的订单(状态为PROCESSING且创建时间超过5分钟)
  134. $orders = TransferOrder::where('status', TransferStatus::PROCESSING)
  135. ->whereHas('transferApp', function ($query) {
  136. $query->whereNotNull('order_callback_url');
  137. })
  138. ->where('created_at', '<', now()->subMinutes(5))
  139. ->where('created_at', '>', now()->subHours(24))
  140. ->limit($limit)
  141. ->get();
  142. foreach ($orders as $order) {
  143. if (self::retryCallback($order)) {
  144. $processedCount++;
  145. }
  146. }
  147. return $processedCount;
  148. }
  149. /**
  150. * 处理接收到的回调
  151. *
  152. * @param array $data 回调数据
  153. * @return bool
  154. */
  155. public static function handleIncomingCallback(array $data): bool
  156. {
  157. try {
  158. // 验证必要字段
  159. if (!isset($data['out_order_id']) || !isset($data['out_id'])) {
  160. Log::warning('Invalid callback data received', $data);
  161. return false;
  162. }
  163. // 查找订单
  164. $order = TransferOrder::where('out_order_id', $data['out_order_id'])
  165. ->where('out_id', $data['out_id'])
  166. ->first();
  167. if (!$order) {
  168. Log::warning('Callback order not found', $data);
  169. return false;
  170. }
  171. // 验证订单状态
  172. if ($order->isFinalStatus()) {
  173. Log::info('Callback received for completed order', [
  174. 'order_id' => $order->id,
  175. 'current_status' => $order->status->value
  176. ]);
  177. return true;
  178. }
  179. // 更新订单状态
  180. $success = $data['success'] ?? true;
  181. $message = $data['message'] ?? null;
  182. if ($success) {
  183. $order->updateStatus(TransferStatus::COMPLETED, $message);
  184. } else {
  185. $order->updateStatus(TransferStatus::FAILED, $message);
  186. }
  187. Log::info('Callback processed successfully', [
  188. 'order_id' => $order->id,
  189. 'out_order_id' => $data['out_order_id'],
  190. 'success' => $success
  191. ]);
  192. return true;
  193. } catch (\Exception $e) {
  194. Log::error('Callback processing exception', [
  195. 'error' => $e->getMessage(),
  196. 'data' => $data
  197. ]);
  198. return false;
  199. }
  200. }
  201. }