bugfix:支付

This commit is contained in:
2026-09-14 02:39:00 +08:00
parent d87f904e33
commit 714d8ff396
11 changed files with 699 additions and 42 deletions
+16 -10
View File
@@ -288,7 +288,7 @@ func (s *OrderService) handleGoodsDeliver(ctx context.Context, deliver *wechat.X
return errcode.DatabaseError
}
if updated {
s.finalizeVirtualPaidOrder(ctx, order, deliver, raw)
s.finalizeVirtualPaidOrder(ctx, order, deliver.WeChatPayInfo.PaidTime, deliver.WeChatPayInfo.TransactionID, raw)
return nil
}
@@ -314,7 +314,7 @@ func (s *OrderService) handleGoodsDeliver(ctx context.Context, deliver *wechat.X
if ok, uerr := s.orderDao.OrderUpdateStatusByOrderNo(ctx, deliver.OutTradeNo, OrderStatusExpired, OrderStatusPaid); uerr != nil {
return errcode.DatabaseError
} else if ok {
s.finalizeVirtualPaidOrder(ctx, current, deliver, raw)
s.finalizeVirtualPaidOrder(ctx, current, deliver.WeChatPayInfo.PaidTime, deliver.WeChatPayInfo.TransactionID, raw)
}
case OrderStatusCancelled:
// 防御分支:历史上已取消的虚拟支付订单用户仍完成了支付,补发货避免「钱已扣、权益不到账」。
@@ -322,7 +322,7 @@ func (s *OrderService) handleGoodsDeliver(ctx context.Context, deliver *wechat.X
if ok, uerr := s.orderDao.OrderUpdateStatusByOrderNo(ctx, deliver.OutTradeNo, OrderStatusCancelled, OrderStatusPaid); uerr != nil {
return errcode.DatabaseError
} else if ok {
s.finalizeVirtualPaidOrder(ctx, current, deliver, raw)
s.finalizeVirtualPaidOrder(ctx, current, deliver.WeChatPayInfo.PaidTime, deliver.WeChatPayInfo.TransactionID, raw)
}
}
return nil
@@ -376,16 +376,21 @@ func (s *OrderService) handleIOSRefundQuery(ctx context.Context, query *wechat.X
order, err := s.orderDao.OrderGetByOrderNo(ctx, query.OutTradeNo)
if err != nil {
slog.ErrorContext(ctx, "xpay ios refund query: order not found", "out_trade_no", query.OutTradeNo, "error", err)
return wechat.BuildIOSRefundQueryResponse(1, "order not found")
return wechat.BuildIOSRefundQueryResponse(1, "拒绝退款",
"订单号 "+query.OutTradeNo+" 在本地无记录,无法确认权益使用情况,拒绝退款")
}
// 已退款:款项已退回,再次建议退款会造成重复退款资损。
if order.OrderStatus == OrderStatusRefunded {
return wechat.BuildIOSRefundQueryResponse(0, "already refunded")
return wechat.BuildIOSRefundQueryResponse(1, "拒绝退款",
"订单 "+order.OrderNo+" 已处于已退款状态,不支持重复退款")
}
// 权益已消耗则拒绝退款,防止「已使用权益后白嫖退款」。
if s.iosRefundBenefitsConsumed(ctx, order) {
return wechat.BuildIOSRefundQueryResponse(1, "权益已使用,不支持退款")
return wechat.BuildIOSRefundQueryResponse(1, "拒绝退款",
"订单 "+order.OrderNo+" 发放的权益已被使用(上传额度已消耗或会员已生效),不支持退款")
}
return wechat.BuildIOSRefundQueryResponse(0, order.OrderNo)
return wechat.BuildIOSRefundQueryResponse(0, "建议退款",
"订单 "+order.OrderNo+" 发放的权益尚未使用,建议退款")
}
// iosRefundBenefitsConsumed 判断订单发放的权益是否已被消耗(用于 iOS 退款问询拒绝策略)。
@@ -414,10 +419,11 @@ func (s *OrderService) iosRefundBenefitsConsumed(ctx context.Context, order *mys
}
// finalizeVirtualPaidOrder 虚拟支付发货:记录支付信息、发放权益并发送通知。
func (s *OrderService) finalizeVirtualPaidOrder(ctx context.Context, order *mysqlmodel.Order, deliver *wechat.XPayGoodsDeliverNotify, raw string) {
// paidTime/transactionID 由调用方提供:推送路径取推送报文,查单补偿路径取 query_order 结果。
func (s *OrderService) finalizeVirtualPaidOrder(ctx context.Context, order *mysqlmodel.Order, paidTime int64, transactionID, raw string) {
_ = s.orderDao.OrderUpdateByOrderNo(ctx, order.OrderNo, map[string]any{
"pay_time": resolvePaidTime(deliver.WeChatPayInfo.PaidTime),
"transaction_id": deliver.WeChatPayInfo.TransactionID,
"pay_time": resolvePaidTime(paidTime),
"transaction_id": transactionID,
"callback_raw": raw,
})