支付宝记账本
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

147 lines
3.9 KiB

5 months ago
  1. <?php
  2. namespace App\Jobs;
  3. use App\Models\MchApp;
  4. use App\Models\Order;
  5. use App\Models\OrderNotify;
  6. use App\Services\OutService;
  7. use Illuminate\Contracts\Queue\ShouldQueue;
  8. use Illuminate\Foundation\Queue\Queueable;
  9. use Illuminate\Support\Facades\Http;
  10. use Illuminate\Support\Str;
  11. use Throwable;
  12. class OrderChangedNotify implements ShouldQueue
  13. {
  14. use Queueable;
  15. /**
  16. * 可以尝试任务的次数
  17. * @var int
  18. */
  19. public int $tries = 8;
  20. /**
  21. * 订单ID
  22. * @var int
  23. */
  24. private int $orderId;
  25. /**
  26. * 推送状态
  27. * @var int
  28. */
  29. private int $state;
  30. /**
  31. * Create a new job instance.
  32. */
  33. public function __construct(int $orderId, int $state)
  34. {
  35. $this->orderId = $orderId;
  36. $this->state = $state;
  37. }
  38. /**
  39. * Execute the job.
  40. */
  41. public function handle(OutService $outService): void
  42. {
  43. $order = Order::find($this->orderId);
  44. if (!$order) {
  45. return;
  46. }
  47. if (!$order->notify_url) {
  48. return;
  49. }
  50. $mchApp = MchApp::query()
  51. ->where('mch_no', $order->mch_no)
  52. ->where('app_id', $order->app_id)
  53. ->first();
  54. if (!$mchApp) {
  55. return;
  56. }
  57. $params = [
  58. 'mchNo' => $order->mch_no,
  59. 'appId' => $order->app_id,
  60. 'mchOrderNo' => $order->mch_order_no,
  61. 'transferId' => $order->transfer_id,
  62. 'amount' => (string) $order->amount,
  63. 'currency' => $order->currency,
  64. 'ifCode' => $order->if_code,
  65. 'entryType' => $order->entry_type,
  66. 'state' => (string) $this->state,
  67. 'accountNo' => $order->account_no,
  68. 'accountName' => $order->account_name,
  69. 'bankName' => $order->bank_name,
  70. 'transferDesc' => $order->transfer_desc,
  71. 'channelOrderNo' => $order->channel_order_no,
  72. 'errCode' => $order->errCode,
  73. 'errMsg' => $order->errMsg,
  74. 'extraParam' => $order->ext_param,
  75. 'createdAt' => $order->created_at->format('Uv'),
  76. ];
  77. if ($this->state == 2) {
  78. $params['success_time'] = $order->success_time->format('Uv');
  79. }
  80. $params['sign'] = $outService->makeSign($params, $mchApp->secret_key);
  81. $notify = new OrderNotify();
  82. $notify->order_id = $this->orderId;
  83. $notify->state = $this->state;
  84. $notify->push_time = now();
  85. $notify->push_body = http_build_query($params);
  86. $notify->save();
  87. try {
  88. $options = [
  89. 'allow_redirects' => false,
  90. 'timeout' => 10,
  91. ];
  92. $response = Http::withOptions($options)
  93. ->withBody($notify->push_body, 'application/x-www-form-urlencoded')
  94. ->post($order->notify_url);
  95. $notify->response_code = $response->status();
  96. $notify->response_body = Str::limit($response->body(), 2000);
  97. } catch (Throwable) {
  98. $notify->response_code = 0;
  99. $notify->response_body = '';
  100. }
  101. $notify->response_time = now();
  102. $notify->push_duration = round($notify->push_time->diffInSeconds($notify->response_time) * 1000);
  103. $notify->save();
  104. if ($notify->response_body !== 'success') {
  105. $this->customRelease();
  106. }
  107. }
  108. private function customRelease(): void
  109. {
  110. // 下一次尝试的时间间隔
  111. $delayList = [
  112. 1 => 60 * 2,
  113. 2 => 60 * 10,
  114. 3 => 60 * 10,
  115. 4 => 3600,
  116. 5 => 3600 * 2,
  117. 6 => 3600 * 6,
  118. 7 => 3600 * 15,
  119. ];
  120. $currentAttempt = $this->attempts();
  121. $this->release($delayList[$currentAttempt]);
  122. }
  123. }