From b434eda5c7a576271f466c6e0959e403fde46c8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B9=E8=BF=9B?= Date: Thu, 15 Oct 2026 16:51:28 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=E9=80=80=E6=AC=BE=E5=AE=A1=E6=89=B9?= =?UTF-8?q?=E9=80=9A=E8=BF=87=E6=97=B6=E4=BB=85=E5=8E=9F=E8=B7=AF=E9=80=80?= =?UTF-8?q?=E6=AC=BE=E6=A0=A1=E9=AA=8C=E6=94=B6=E6=AC=BE=E5=95=86=E6=88=B7?= =?UTF-8?q?=E5=87=AD=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 线上支付订单选择客户收款信息退款时,审批通过处理仍无条件校验收款商户的原路退款凭证, 商户凭证不完整(如微信 v2 缺 API 客户端证书)即阻断,导致企微已通过的退款无法完成。 将凭证校验移入原路退款分支,旧人工审批入口同步按退款方式判定。 Co-Authored-By: Claude Opus 5.5 --- internal/service/refund/approval_decision.go | 7 ++++--- internal/service/refund/payment_merchant.go | 3 +++ internal/service/refund/service.go | 6 ++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/internal/service/refund/approval_decision.go b/internal/service/refund/approval_decision.go index 9dbd486d..5fe9fdef 100644 --- a/internal/service/refund/approval_decision.go +++ b/internal/service/refund/approval_decision.go @@ -113,9 +113,6 @@ func (s *Service) applyApprovedDecision(ctx context.Context, event approvalapp.T if err := validateApprovedRefundAmount(approvedAmount, refund.RequestedRefundAmount, &order); err != nil { return err } - if err := s.preparePaymentRefundCredentials(ctx, tx, order.ID); err != nil { - return err - } // 原路退款只登记待执行事实:退款单转入原路处理中,订单在渠道明确成功前保持已支付。 // 客户收款信息与退回原钱包在审批通过时即完成,订单同时置为已退款。 originalRoute := refund.Method == constants.RefundMethodOriginalRoute @@ -163,6 +160,10 @@ func (s *Service) applyApprovedDecision(ctx context.Context, event approvalapp.T if order.PaymentStatus != model.PaymentStatusPaid && order.PaymentStatus != model.PaymentStatusRefunded { return errors.New(errors.CodeInvalidStatus, "订单状态不允许原路退款") } + // 收款商户凭证只约束原路退款;客户收款信息与钱包退款不经渠道,不受其完整性影响。 + if err := s.preparePaymentRefundCredentials(ctx, tx, order.ID); err != nil { + return err + } if err := s.prepareChannelRefundInTx(ctx, tx, &refund, attempt); err != nil { return err } diff --git a/internal/service/refund/payment_merchant.go b/internal/service/refund/payment_merchant.go index ff2f7ef6..67c61117 100644 --- a/internal/service/refund/payment_merchant.go +++ b/internal/service/refund/payment_merchant.go @@ -19,6 +19,9 @@ func (s *Service) SetPaymentMerchantRuntime(runtime *merchantpayment.RuntimeLoad // preparePaymentRefundCredentials 在企微通过事务内装载并校验原路退款所需凭证。 // +// 仅退款方式为原路退款时调用:线上支付订单也可选客户收款信息退款(如商户号余额不足), +// 该方式不经渠道,不能因收款商户凭证不完整被阻断。 +// // 钱包支付和线下支付没有收款商户凭证,直接放行。merchant_id 为空仅表示留存期内的历史 // 线上支付,仍按 payment_config_id 读取兼容配置;绝不能按当前商户池推断历史商户。 func (s *Service) preparePaymentRefundCredentials(ctx context.Context, tx *gorm.DB, orderID uint) error { diff --git a/internal/service/refund/service.go b/internal/service/refund/service.go index b98970a4..789906bc 100644 --- a/internal/service/refund/service.go +++ b/internal/service/refund/service.go @@ -449,8 +449,10 @@ func (s *Service) Approve(ctx context.Context, id uint, req *dto.ApproveRefundRe if orderResult.RowsAffected == 0 { return errors.New(errors.CodeInvalidStatus, "订单状态已变更,无法执行退款审批") } - if err := s.preparePaymentRefundCredentials(ctx, tx, order.ID); err != nil { - return err + if refund.Method == constants.RefundMethodOriginalRoute { + if err := s.preparePaymentRefundCredentials(ctx, tx, order.ID); err != nil { + return err + } } if err := s.refundWalletPayment(ctx, tx, refund, order, approvedAmount, userID); err != nil {