11 changed files with 190 additions and 25 deletions
-
6app/Admin/Controllers/OrderController.php
-
40app/Admin/Controllers/OrderNotifyController.php
-
147app/Jobs/OrderChangedNotify.php
-
4app/Models/Order.php
-
5app/Models/OrderNotify.php
-
2app/Services/OutService.php
-
1composer.json
-
2database/migrations/2025_08_27_163509_create_orders_table.php
-
2database/migrations/2025_08_27_170155_create_order_notifies_table.php
-
2lang/zh_CN/order-notify.php
-
2lang/zh_CN/order.php
@ -0,0 +1,147 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Jobs; |
||||
|
|
||||
|
use App\Models\MchApp; |
||||
|
use App\Models\Order; |
||||
|
use App\Models\OrderNotify; |
||||
|
use App\Services\OutService; |
||||
|
use Illuminate\Contracts\Queue\ShouldQueue; |
||||
|
use Illuminate\Foundation\Queue\Queueable; |
||||
|
use Illuminate\Support\Facades\Http; |
||||
|
use Illuminate\Support\Str; |
||||
|
use Throwable; |
||||
|
|
||||
|
class OrderChangedNotify implements ShouldQueue |
||||
|
{ |
||||
|
use Queueable; |
||||
|
|
||||
|
/** |
||||
|
* 可以尝试任务的次数 |
||||
|
* @var int |
||||
|
*/ |
||||
|
public int $tries = 8; |
||||
|
|
||||
|
/** |
||||
|
* 订单ID |
||||
|
* @var int |
||||
|
*/ |
||||
|
private int $orderId; |
||||
|
|
||||
|
/** |
||||
|
* 推送状态 |
||||
|
* @var int |
||||
|
*/ |
||||
|
private int $state; |
||||
|
|
||||
|
/** |
||||
|
* Create a new job instance. |
||||
|
*/ |
||||
|
public function __construct(int $orderId, int $state) |
||||
|
{ |
||||
|
$this->orderId = $orderId; |
||||
|
$this->state = $state; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Execute the job. |
||||
|
*/ |
||||
|
public function handle(OutService $outService): void |
||||
|
{ |
||||
|
$order = Order::find($this->orderId); |
||||
|
|
||||
|
if (!$order) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (!$order->notify_url) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
$mchApp = MchApp::query() |
||||
|
->where('mch_no', $order->mch_no) |
||||
|
->where('app_id', $order->app_id) |
||||
|
->first(); |
||||
|
|
||||
|
if (!$mchApp) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
$params = [ |
||||
|
'mchNo' => $order->mch_no, |
||||
|
'appId' => $order->app_id, |
||||
|
'mchOrderNo' => $order->mch_order_no, |
||||
|
'transferId' => $order->transfer_id, |
||||
|
'amount' => (string) $order->amount, |
||||
|
'currency' => $order->currency, |
||||
|
'ifCode' => $order->if_code, |
||||
|
'entryType' => $order->entry_type, |
||||
|
'state' => (string) $this->state, |
||||
|
'accountNo' => $order->account_no, |
||||
|
'accountName' => $order->account_name, |
||||
|
'bankName' => $order->bank_name, |
||||
|
'transferDesc' => $order->transfer_desc, |
||||
|
'channelOrderNo' => $order->channel_order_no, |
||||
|
'errCode' => $order->errCode, |
||||
|
'errMsg' => $order->errMsg, |
||||
|
'extraParam' => $order->ext_param, |
||||
|
'createdAt' => $order->created_at->format('Uv'), |
||||
|
]; |
||||
|
|
||||
|
if ($this->state == 2) { |
||||
|
$params['success_time'] = $order->success_time->format('Uv'); |
||||
|
} |
||||
|
|
||||
|
$params['sign'] = $outService->makeSign($params, $mchApp->secret_key); |
||||
|
|
||||
|
$notify = new OrderNotify(); |
||||
|
$notify->order_id = $this->orderId; |
||||
|
$notify->state = $this->state; |
||||
|
$notify->push_time = now(); |
||||
|
$notify->push_body = http_build_query($params); |
||||
|
$notify->save(); |
||||
|
|
||||
|
try { |
||||
|
$options = [ |
||||
|
'allow_redirects' => false, |
||||
|
'timeout' => 10, |
||||
|
]; |
||||
|
|
||||
|
$response = Http::withOptions($options) |
||||
|
->withBody($notify->push_body, 'application/x-www-form-urlencoded') |
||||
|
->post($order->notify_url); |
||||
|
|
||||
|
$notify->response_code = $response->status(); |
||||
|
$notify->response_body = Str::limit($response->body(), 2000); |
||||
|
} catch (Throwable) { |
||||
|
$notify->response_code = 0; |
||||
|
$notify->response_body = ''; |
||||
|
} |
||||
|
|
||||
|
$notify->response_time = now(); |
||||
|
$notify->push_duration = round($notify->push_time->diffInSeconds($notify->response_time) * 1000); |
||||
|
$notify->save(); |
||||
|
|
||||
|
if ($notify->response_body !== 'success') { |
||||
|
$this->customRelease(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private function customRelease(): void |
||||
|
{ |
||||
|
// 下一次尝试的时间间隔
|
||||
|
$delayList = [ |
||||
|
1 => 60 * 2, |
||||
|
2 => 60 * 10, |
||||
|
3 => 60 * 10, |
||||
|
4 => 3600, |
||||
|
5 => 3600 * 2, |
||||
|
6 => 3600 * 6, |
||||
|
7 => 3600 * 15, |
||||
|
]; |
||||
|
|
||||
|
$currentAttempt = $this->attempts(); |
||||
|
|
||||
|
$this->release($delayList[$currentAttempt]); |
||||
|
} |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue