From 80844ae1a0ccc6b9177c80b504c132625f484d8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=AF=E4=B9=90=E5=8A=A0=E5=86=B0?= <11869599+addie66@user.noreply.gitee.com> Date: Fri, 2 Oct 2026 14:56:52 +0800 Subject: [PATCH] =?UTF-8?q?```=20feat(order):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=AE=A2=E5=8D=95=E6=94=AF=E4=BB=98=E9=98=B2=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 防止同一笔订单被多次处理导致数据异常的问题。实现数据库事务锁机制, 确保订单支付状态变更的原子性。 fix(huifu-onboard): 重构上传组件并优化银行信息录入流程 - 将原有的u-upload组件替换为自定义上传选择器 - 新增银行支行联行号手动输入功能 - 添加区域选择联动和草稿数据应用功能 - 增加上传错误处理和隐私保护相关提示 feat(auth-modal): 完善微信授权登录和隐私协议功能 - 添加微信小程序隐私授权初始化 - 实现手机号一键登录防频控机制 - 集成用户协议和隐私协议勾选验证 - 优化登录流程错误处理和用户体验 ``` --- .../library/traits/model/order/OrderOper.php | 47 +++++++++++++------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/addons/shopro/library/traits/model/order/OrderOper.php b/addons/shopro/library/traits/model/order/OrderOper.php index 18d3077..c945af9 100644 --- a/addons/shopro/library/traits/model/order/OrderOper.php +++ b/addons/shopro/library/traits/model/order/OrderOper.php @@ -824,19 +824,41 @@ trait OrderOper public function paymentProcess($order, $notify) { - $order->status = Order::STATUS_PAYED; - $order->paytime = time(); - $order->transaction_id = $notify['transaction_id']; - $order->payment_json = $notify['payment_json']; - $order->pay_type = $notify['pay_type']; - $order->pay_fee = $notify['pay_fee']; - - // 组合支付更新付款金额 - if ($order->pay_type == 'group') { - $order->total_fee = bcsub($order->total_fee, $order->pay_money, 2); + $orderId = is_object($order) ? (int) $order->id : (int) ($order['id'] ?? 0); + if ($orderId <= 0) { + return $order; } - $order->save(); + $firstPaid = false; + $order = Db::transaction(function () use ($orderId, $notify, &$firstPaid) { + $order = Order::where('id', $orderId)->lock(true)->find(); + if (!$order) { + return null; + } + if ((int) $order->status > Order::STATUS_NOPAY) { + \think\Log::info('[order_pay] paymentProcess skip duplicate order_id=' . $orderId); + return $order; + } + + $firstPaid = true; + $order->status = Order::STATUS_PAYED; + $order->paytime = time(); + $order->transaction_id = $notify['transaction_id']; + $order->payment_json = $notify['payment_json']; + $order->pay_type = $notify['pay_type']; + $order->pay_fee = $notify['pay_fee']; + + if ($order->pay_type == 'group') { + $order->total_fee = bcsub($order->total_fee, $order->pay_money, 2); + } + + $order->save(); + return $order; + }); + + if (!$order || !$firstPaid) { + return $order; + } try { saveUserMessage([ @@ -855,12 +877,10 @@ trait OrderOper \think\Log::error('[order_pay] operAdd failed: ' . $e->getMessage()); } - // 组合支付扣除用户余额 if ($order->pay_type == 'group') { User::where(['id' => $user->id])->setDec('money', $order->pay_money); } - // 预约抢购标记成已使用 if ($order->activity_type === 'robbuy') { RobOrderModel::where([ 'user_id' => $user->id, @@ -876,7 +896,6 @@ trait OrderOper \think\Log::error('[order_pay] order_payed_after hook failed: ' . $e->getMessage()); } - // 支付成功后续使用异步队列处理 try { \think\Queue::push('\addons\shopro\job\OrderPayed@payed', ['order' => $order, 'user' => $user], 'shopro-high'); } catch (\Throwable $e) {