From 085e3a487565a35bf6b0470101641b367e12ceea Mon Sep 17 00:00:00 2001 From: Billy <641833868@qq.com> Date: Tue, 28 Oct 2025 16:08:12 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=80=E6=AC=BE=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- addons/shopro/controller/Ccbpayment.php | 46 ++++++++++++- .../library/ccblife/CcbPaymentService.php | 69 ++++++++++++++++--- addons/shopro/service/pay/PayRefund.php | 45 ++++++++++++ application/admin/model/shopro/Pay.php | 3 +- 4 files changed, 153 insertions(+), 10 deletions(-) diff --git a/addons/shopro/controller/Ccbpayment.php b/addons/shopro/controller/Ccbpayment.php index d5fdc40..47e82e4 100644 --- a/addons/shopro/controller/Ccbpayment.php +++ b/addons/shopro/controller/Ccbpayment.php @@ -6,6 +6,7 @@ use addons\shopro\controller\Common; use addons\shopro\library\ccblife\CcbPaymentService; use addons\shopro\library\ccblife\CcbOrderService; use app\admin\model\shopro\order\Order as OrderModel; +use app\admin\model\shopro\Pay as PayModel; use think\Db; use think\Exception; use think\Log; @@ -319,7 +320,50 @@ class Ccbpayment extends Common Log::info('[建行支付查询] 本地订单状态更新成功 order_id:' . $orderId . ' status:paid'); - // 10.4 提交事务 + // 10.4 ✅ 创建shopro_pay支付记录(与notify回调逻辑保持一致) + // 检查是否已存在pay记录(幂等性保护:可能notify回调已创建) + $existingPay = PayModel::where('order_type', 'order') + ->where('order_id', $orderId) + ->where('pay_type', 'ccb') + ->lock(true) // 加锁防止并发 + ->find(); + + if (!$existingPay) { + // 不存在则创建新记录 + $payModel = new PayModel(); + $payModel->order_type = 'order'; + $payModel->order_id = $orderId; + $payModel->pay_sn = $lockedOrder->ccb_pay_flow_id; // 使用建行支付流水号 + $payModel->user_id = $lockedOrder->user_id; + $payModel->pay_type = 'ccb'; // 建行支付类型 + $payModel->pay_fee = $lockedOrder->pay_fee; // 支付金额 + $payModel->real_fee = $lockedOrder->pay_fee; // 建行支付实际金额=订单金额 + $payModel->transaction_id = $ccbTransId ?? ''; // 建行交易流水号 + $payModel->payment_json = json_encode([ + 'source' => 'query_payment_status', // 标记来源:主动查询 + 'ccb_pay_time' => $ccbPayTime, + 'ccb_trans_id' => $ccbTransId, + 'query_time' => date('Y-m-d H:i:s') + ], JSON_UNESCAPED_UNICODE); + $payModel->paid_time = time(); + $payModel->status = PayModel::PAY_STATUS_PAID; + $payModel->refund_fee = 0; // 初始退款金额为0 + $payModel->save(); + + Log::info('[建行支付查询] 创建shopro_pay记录成功 order_id:' . $orderId . ' pay_id:' . $payModel->id . ' pay_sn:' . $payModel->pay_sn); + } else { + // 已存在则更新状态(notify回调可能已创建但状态未更新) + $existingPay->status = PayModel::PAY_STATUS_PAID; + $existingPay->paid_time = time(); + if (empty($existingPay->transaction_id) && !empty($ccbTransId)) { + $existingPay->transaction_id = $ccbTransId; + } + $existingPay->save(); + + Log::info('[建行支付查询] shopro_pay记录已存在,更新状态 order_id:' . $orderId . ' pay_id:' . $existingPay->id); + } + + // 10.5 提交事务 Db::commit(); // 11. ✅ 更新订单状态到建行外联系统(异步,失败不影响本地) diff --git a/addons/shopro/library/ccblife/CcbPaymentService.php b/addons/shopro/library/ccblife/CcbPaymentService.php index 5d22a2f..1228158 100644 --- a/addons/shopro/library/ccblife/CcbPaymentService.php +++ b/addons/shopro/library/ccblife/CcbPaymentService.php @@ -3,6 +3,7 @@ namespace addons\shopro\library\ccblife; use app\admin\model\shopro\order\Order; +use app\admin\model\shopro\Pay as PayModel; use think\Db; use think\Log; @@ -536,20 +537,72 @@ class CcbPaymentService /** * 更新订单支付状态 + * ✅ 修复:同时创建shopro_pay记录,确保退款逻辑能够正常工作 * * @param object $order 订单对象 - * @param array $params 支付参数 + * @param array $params 支付参数(建行回调参数) */ private function updateOrderPaymentStatus($order, $params) { - Order::where('id', $order['id'])->update([ - 'status' => 'paid', - 'paid_time' => time() * 1000, // 毫秒时间戳 - 'updatetime' => time() - ]); + // 开启事务,确保订单状态和pay记录同时创建 + Db::startTrans(); - // 记录支付日志 - $this->recordPaymentLog($order['id'], 'payment_success', $params); + try { + // 1. 更新订单状态 + Order::where('id', $order['id'])->update([ + 'status' => 'paid', + 'paid_time' => time() * 1000, // 毫秒时间戳 + 'updatetime' => time() + ]); + + // 2. ✅ 创建shopro_pay支付记录(与其他支付方式保持一致) + // 检查是否已存在pay记录(幂等性保护) + $existingPay = PayModel::where('order_type', 'order') + ->where('order_id', $order['id']) + ->where('pay_type', 'ccb') + ->find(); + + if (!$existingPay) { + // 不存在则创建新记录 + $payModel = new PayModel(); + $payModel->order_type = 'order'; + $payModel->order_id = $order['id']; + $payModel->pay_sn = $order['ccb_pay_flow_id'] ?? ($params['ORDERID'] ?? ''); // 使用建行支付流水号 + $payModel->user_id = $order['user_id']; + $payModel->pay_type = 'ccb'; // 建行支付类型 + $payModel->pay_fee = $order['pay_fee']; // 支付金额 + $payModel->real_fee = $order['pay_fee']; // 建行支付实际金额=订单金额 + $payModel->transaction_id = $params['ORDERID'] ?? ''; // 建行交易流水号 + $payModel->payment_json = json_encode($params, JSON_UNESCAPED_UNICODE); // 回调原始参数 + $payModel->paid_time = time(); + $payModel->status = PayModel::PAY_STATUS_PAID; + $payModel->refund_fee = 0; // 初始退款金额为0 + $payModel->save(); + + Log::info('[建行支付] 创建shopro_pay记录成功 order_id:' . $order['id'] . ' pay_id:' . $payModel->id . ' pay_sn:' . $payModel->pay_sn); + } else { + // 已存在则更新状态(理论上不会执行到这里,但为了安全) + $existingPay->status = PayModel::PAY_STATUS_PAID; + $existingPay->paid_time = time(); + $existingPay->transaction_id = $params['ORDERID'] ?? ''; + $existingPay->payment_json = json_encode($params, JSON_UNESCAPED_UNICODE); + $existingPay->save(); + + Log::warning('[建行支付] shopro_pay记录已存在,更新状态 order_id:' . $order['id'] . ' pay_id:' . $existingPay->id); + } + + // 3. 记录支付日志(原有逻辑) + $this->recordPaymentLog($order['id'], 'payment_success', $params); + + // 提交事务 + Db::commit(); + + } catch (\Exception $e) { + // 回滚事务 + Db::rollback(); + Log::error('[建行支付] 更新支付状态失败 order_id:' . $order['id'] . ' error:' . $e->getMessage()); + throw $e; + } } diff --git a/addons/shopro/service/pay/PayRefund.php b/addons/shopro/service/pay/PayRefund.php index df982c3..acbae08 100755 --- a/addons/shopro/service/pay/PayRefund.php +++ b/addons/shopro/service/pay/PayRefund.php @@ -9,6 +9,7 @@ use app\admin\model\shopro\Pay as PayModel; use app\admin\model\shopro\user\User; use app\admin\model\shopro\Refund as RefundModel; use addons\shopro\service\Wallet as WalletService; +use addons\shopro\library\ccblife\CcbOrderService; class PayRefund @@ -268,6 +269,50 @@ class PayRefund } + /** + * 退建行支付 + * 调用建行生活退款API + * + * @param \think\Model $pay 支付记录 + * @param \think\Model $refund 退款单 + * @return \think\Model + */ + private function ccb($pay, $refund) + { + try { + Log::info('[建行退款] 开始处理退款 pay_id:' . $pay->id . ' refund_id:' . $refund->id . ' refund_fee:' . $refund->refund_fee); + + // 调用建行订单服务进行退款 + $ccbOrderService = new CcbOrderService(); + $result = $ccbOrderService->refundOrder( + $pay->order_id, // 订单ID + $refund->refund_fee, // 退款金额 + $refund->refund_sn // 退款流水号(refund_code) + ); + + if ($result['status']) { + // 建行退款成功,标记退款单完成 + Log::info('[建行退款] 退款成功 pay_id:' . $pay->id . ' refund_id:' . $refund->id . ' result:' . json_encode($result, JSON_UNESCAPED_UNICODE)); + + // 完成退款单 + $refund = $this->completed($refund, json_encode($result['data'] ?? [], JSON_UNESCAPED_UNICODE)); + + return $refund; + } else { + // 建行退款失败 + Log::error('[建行退款] 退款失败 pay_id:' . $pay->id . ' refund_id:' . $refund->id . ' error:' . $result['message']); + error_stop('建行退款失败: ' . $result['message']); + } + + } catch (\Exception $e) { + Log::error('[建行退款] 退款异常 pay_id:' . $pay->id . ' refund_id:' . $refund->id . ' error:' . $e->getMessage()); + error_stop('建行退款异常: ' . $e->getMessage()); + } + + return $refund; + } + + /** * 添加 pay 记录 diff --git a/application/admin/model/shopro/Pay.php b/application/admin/model/shopro/Pay.php index 70967e9..0fa3642 100644 --- a/application/admin/model/shopro/Pay.php +++ b/application/admin/model/shopro/Pay.php @@ -36,6 +36,7 @@ class Pay extends Common 'money' => '钱包支付', 'score' => '积分支付', 'offline' => '货到付款', + 'ccb' => '建行支付', ]; } @@ -60,7 +61,7 @@ class Pay extends Common public function scopeIsMoney($query) { - return $query->whereIn('pay_type', ['wechat', 'alipay', 'money']); + return $query->whereIn('pay_type', ['wechat', 'alipay', 'money', 'ccb']); }