From a50b2823b39a5fababf9165ca001a516b18ea6ac Mon Sep 17 00:00:00 2001 From: Mrx <18278715334@163.com> Date: Sun, 7 Jun 2026 15:11:33 +0800 Subject: [PATCH] fadd --- .../admin_order/adminrefundorderlogic.go | 1 + .../internal/logic/pay/paymentchecklogic.go | 11 ++++++- .../api/internal/logic/pay/xpay_refund.go | 1 + app/main/api/internal/service/xpayService.go | 33 +++++++++++++++---- 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/app/main/api/internal/logic/admin_order/adminrefundorderlogic.go b/app/main/api/internal/logic/admin_order/adminrefundorderlogic.go index a394479..c4ca85f 100644 --- a/app/main/api/internal/logic/admin_order/adminrefundorderlogic.go +++ b/app/main/api/internal/logic/admin_order/adminrefundorderlogic.go @@ -122,6 +122,7 @@ func (l *AdminRefundOrderLogic) handleXpayRefund(order *model.Order, req *types. } refundNo := l.generateRefundNo(order.OrderNo) _ = l.createRefundRecordOnly(order, req, refundNo, "", model.OrderRefundStatusSuccess) + l.Infof("[xpay] admin refund OK order_no=%s amount=%.2f", order.OrderNo, req.RefundAmount) return &types.AdminRefundOrderResp{ Status: model.OrderStatusRefunded, RefundNo: refundNo, diff --git a/app/main/api/internal/logic/pay/paymentchecklogic.go b/app/main/api/internal/logic/pay/paymentchecklogic.go index 6eaaf00..3a73efb 100644 --- a/app/main/api/internal/logic/pay/paymentchecklogic.go +++ b/app/main/api/internal/logic/pay/paymentchecklogic.go @@ -105,8 +105,17 @@ func (l *PaymentCheckLogic) syncXpayOrderStatus(order *model.Order) (xpaySyncInf return info, nil } + if service.IsXpayRefundedStatus(status.Status) || service.IsXpayAlreadyRefunded(status) { + order.Status = model.OrderStatusRefunded + if updateErr := l.svcCtx.OrderModel.UpdateWithVersion(l.ctx, nil, order); updateErr != nil { + return info, updateErr + } + l.Infof("[xpay] check sync refunded order_no=%s wx_status=%d left_fee=%d", order.OrderNo, status.Status, status.LeftFee) + return info, nil + } + if service.IsXpayClosedStatus(status.Status) { - order.Status = "closed" + order.Status = model.OrderStatusClosed if updateErr := l.svcCtx.OrderModel.UpdateWithVersion(l.ctx, nil, order); updateErr != nil { return info, updateErr } diff --git a/app/main/api/internal/logic/pay/xpay_refund.go b/app/main/api/internal/logic/pay/xpay_refund.go index f1eab10..648da2c 100644 --- a/app/main/api/internal/logic/pay/xpay_refund.go +++ b/app/main/api/internal/logic/pay/xpay_refund.go @@ -27,6 +27,7 @@ func RefundXpayQueryOrder(ctx context.Context, svcCtx *svc.ServiceContext, order if refundErr := svcCtx.XpayService.RefundOrder(ctx, openid, order.OrderNo, refundOrderID, refundFeeFen); refundErr != nil { return refundErr } + logx.WithContext(ctx).Infof("[xpay] refund local sync order_no=%s", order.OrderNo) return svcCtx.OrderModel.Trans(ctx, func(transCtx context.Context, session sqlx.Session) error { order.Status = model.OrderStatusRefunded diff --git a/app/main/api/internal/service/xpayService.go b/app/main/api/internal/service/xpayService.go index 2d4520d..62a9554 100644 --- a/app/main/api/internal/service/xpayService.go +++ b/app/main/api/internal/service/xpayService.go @@ -294,8 +294,8 @@ func (s *XpayService) QueryOrder(ctx context.Context, openid, orderNo, sessionKe status.RawOrder = string(orderRaw) _ = json.Unmarshal(orderRaw, &status) } - logx.WithContext(ctx).Infof("[xpay] query_order order_no=%s status=%d paid_fee=%d left_fee=%d wx_order_id=%s err_msg=%s raw=%s", - orderNo, status.Status, status.PaidFee, status.LeftFee, status.WxOrderID, status.ErrMsg, status.RawOrder) + logx.WithContext(ctx).Infof("[xpay] query_order order_no=%s status=%d paid_fee=%d left_fee=%d wx_order_id=%s err_msg=%s", + orderNo, status.Status, status.PaidFee, status.LeftFee, status.WxOrderID, status.ErrMsg) return &status, nil } @@ -309,6 +309,11 @@ func (s *XpayService) RefundOrder(ctx context.Context, openid, orderNo, refundOr if err != nil { return fmt.Errorf("退款前查单失败: %w", err) } + if IsXpayAlreadyRefunded(status) { + logx.WithContext(ctx).Infof("[xpay] refund_order skip already refunded order_no=%s wx_status=%d left_fee=%d paid_fee=%d", + orderNo, status.Status, status.LeftFee, status.PaidFee) + return nil + } leftFee := status.LeftFee if leftFee <= 0 { leftFee = status.PaidFee @@ -339,7 +344,7 @@ func (s *XpayService) RefundOrder(ctx context.Context, openid, orderNo, refundOr apiResp, err := s.callAPI(ctx, "/xpay/refund_order", bodyJSON, "", false) if err != nil { if xpayErr, ok := err.(*XpayAPIError); ok { - if xpayErr.ErrCode == 268490004 || xpayErr.ErrCode == 268490014 { + if xpayErr.ErrCode == 268490004 || xpayErr.ErrCode == 268490005 || xpayErr.ErrCode == 268490014 { logx.WithContext(ctx).Infof("[xpay] refund_order idempotent order_no=%s errcode=%d", orderNo, xpayErr.ErrCode) return nil } @@ -384,14 +389,30 @@ func (s *XpayService) NotifyProvideGoods(ctx context.Context, openid, orderNo, w return nil } -// IsPaidStatus 微信订单状态 2/3/4 视为支付成功 +// IsXpayPaidStatus 微信订单状态 2/3/4 视为支付成功 func IsXpayPaidStatus(status int) bool { return status == 2 || status == 3 || status == 4 } -// IsXpayClosedStatus 5~10 视为关闭 +// IsXpayRefundedStatus 微信侧已退款:5=订单已经退款,8=用户退款完成 +func IsXpayRefundedStatus(status int) bool { + return status == 5 || status == 8 +} + +// IsXpayAlreadyRefunded 查单结果表示微信侧已无可退金额(含在微信后台手动退款、本地未同步的情况) +func IsXpayAlreadyRefunded(status *xpayOrderStatus) bool { + if status == nil { + return false + } + if IsXpayRefundedStatus(status.Status) { + return true + } + return status.PaidFee > 0 && status.LeftFee == 0 && status.Status >= 2 +} + +// IsXpayClosedStatus 6 视为关闭 func IsXpayClosedStatus(status int) bool { - return status >= 5 && status <= 10 + return status == 6 } // VerifyPushSignature GET 验签(消息推送配置)