fix(stability): 支付并发事务内加锁、组合支付流水记录、省市区树形缓存与地址安全防越权 (TDD)
这个提交包含在:
@@ -342,12 +342,43 @@ class Pay extends Base
|
||||
// 支付成功流程
|
||||
$pay_fee = $payment == 'alipay' ? $data['total_amount'] : $data['total_fee'] / 100;
|
||||
|
||||
// 你可以在此编写订单逻辑
|
||||
$order = $order->nopay()->where('order_sn', $out_trade_no)->lock(true)->find();
|
||||
$timeStr = $data['time_end'] ?? ($data['gmt_payment'] ?? '');
|
||||
$notify_time = $timeStr && ($ts = strtotime($timeStr)) ? date('Y-m-d H:i:s', $ts) : date('Y-m-d H:i:s');
|
||||
|
||||
if (!$order) {
|
||||
// 已支付则直接返回成功,否则记录日志并通知微信重试
|
||||
$paidOrder = Order::where('order_sn', $out_trade_no)->where('status', '>', 0)->find();
|
||||
$payment_json = json_encode(
|
||||
$data instanceof \think\Collection || (is_object($data) && method_exists($data, 'all'))
|
||||
? $data->all()
|
||||
: (array)$data
|
||||
);
|
||||
|
||||
$buyer_email = $payment == 'alipay' ? ($data['buyer_logon_id'] ?? ($data['buyer_id'] ?? '')) : ($data['openid'] ?? '');
|
||||
$transaction_id = $payment == 'alipay' ? ($data['trade_no'] ?? '') : ($data['transaction_id'] ?? '');
|
||||
|
||||
$isProcessed = false;
|
||||
Db::transaction(function () use ($order, $out_trade_no, $transaction_id, $notify_time, $buyer_email, $payment_json, $pay_fee, $payment, &$isProcessed) {
|
||||
// 必须在事务内加排他锁复查,确保高并发回调互斥幂等
|
||||
$lockOrder = $order->nopay()->where('order_sn', $out_trade_no)->lock(true)->find();
|
||||
if (!$lockOrder) {
|
||||
$isProcessed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
$notify = [
|
||||
'order_sn' => $out_trade_no,
|
||||
'transaction_id' => $transaction_id,
|
||||
'notify_time' => $notify_time,
|
||||
'buyer_email' => $buyer_email,
|
||||
'payment_json' => $payment_json,
|
||||
'pay_fee' => $pay_fee,
|
||||
'pay_type' => $lockOrder->pay_type == 'group' ? 'group' : $payment
|
||||
];
|
||||
|
||||
$lockOrder->paymentProcess($lockOrder, $notify);
|
||||
});
|
||||
|
||||
if ($isProcessed) {
|
||||
// 已经被并发处理过,直接向网关确认成功
|
||||
$paidOrder = $order->where('order_sn', $out_trade_no)->where('status', '>', 0)->find();
|
||||
if ($paidOrder) {
|
||||
return $pay->success()->send();
|
||||
}
|
||||
@@ -355,20 +386,6 @@ class Pay extends Base
|
||||
return false;
|
||||
}
|
||||
|
||||
Db::transaction(function () use ($order, $data, $payment, $platform, $pay_fee, $prepay_type) {
|
||||
$notify = [
|
||||
'order_sn' => $data['out_trade_no'],
|
||||
'transaction_id' => $payment == 'alipay' ? $data['trade_no'] : $data['transaction_id'],
|
||||
'notify_time' => date('Y-m-d H:i:s', strtotime($data['time_end'])),
|
||||
'buyer_email' => $payment == 'alipay' ? $data['buyer_logon_id'] : $data['openid'],
|
||||
'payment_json' => json_encode($data->all()),
|
||||
'pay_fee' => $pay_fee,
|
||||
'pay_type' => $order->pay_type == 'group' ? 'group' : $payment // 支付方式
|
||||
];
|
||||
|
||||
$order->paymentProcess($order, $notify);
|
||||
});
|
||||
|
||||
return $pay->success()->send();
|
||||
} catch (\Exception $e) {
|
||||
Log::write('notifyx-error:' . $e->getMessage());
|
||||
|
||||
在新工单中引用
屏蔽一个用户