This commit is contained in:
Mrx
2026-05-09 18:24:59 +08:00
parent d68184fa59
commit f2ac09acdd
3 changed files with 53 additions and 3 deletions

View File

@@ -7,6 +7,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"os" "os"
"strings"
"time" "time"
"tyc-server/app/main/api/internal/svc" "tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types" "tyc-server/app/main/api/internal/types"
@@ -35,6 +36,21 @@ type PaymentTypeResp struct {
payMerchantID string payMerchantID string
} }
// prepayDataMissing 判断第三方支付预创建是否未返回可用参数(含 interface 包了一层 nil 的情况)
func prepayDataMissing(v interface{}) bool {
if v == nil {
return true
}
switch t := v.(type) {
case string:
return t == ""
case map[string]string:
return len(t) == 0
default:
return false
}
}
func NewPaymentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PaymentLogic { func NewPaymentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PaymentLogic {
return &PaymentLogic{ return &PaymentLogic{
Logger: logx.WithContext(ctx), Logger: logx.WithContext(ctx),
@@ -44,6 +60,10 @@ func NewPaymentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PaymentLo
} }
func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp, err error) { func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp, err error) {
req.PayMethod = strings.TrimSpace(req.PayMethod)
req.PayType = strings.TrimSpace(req.PayType)
req.Id = strings.TrimSpace(req.Id)
var paymentTypeResp *PaymentTypeResp var paymentTypeResp *PaymentTypeResp
var prepayData interface{} var prepayData interface{}
l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error { l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
@@ -90,6 +110,21 @@ func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp,
if createOrderErr != nil { if createOrderErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 创建支付订单失败: %+v", createOrderErr) return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 创建支付订单失败: %+v", createOrderErr)
} }
// 在事务内校验并失败则回滚,避免订单已落库却无 prepay此前仅事务外校验会产生脏订单
if req.PayMethod == "wechat" || req.PayMethod == "alipay" {
if prepayDataMissing(prepayData) {
platformVal := l.ctx.Value("platform")
logx.WithContext(l.ctx).Errorf(
"[Payment] 事务内 prepay 为空将回滚: pay_method=%q pay_type=%q order_no=%s platform=%v prepayData_type=%T",
req.PayMethod, req.PayType, paymentTypeResp.outTradeNo, platformVal, prepayData,
)
return errors.Wrapf(
xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, "获取支付参数失败,请确认在微信内打开且已完成网页授权后重试"),
"创建支付失败: prepay 为空 platform=%v",
platformVal,
)
}
}
return nil return nil
}) })
if err != nil { if err != nil {
@@ -97,8 +132,13 @@ func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp,
} }
if req.PayMethod == "wechat" || req.PayMethod == "alipay" { if req.PayMethod == "wechat" || req.PayMethod == "alipay" {
if prepayData == nil { if prepayDataMissing(prepayData) {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "创建支付失败: 未生成支付参数") logx.WithContext(l.ctx).Errorf("[Payment] 事务提交后 prepay 仍为空(不应出现): pay_method=%q id=%q platform=%v",
req.PayMethod, req.Id, l.ctx.Value("platform"))
return nil, errors.Wrapf(
xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, "获取支付参数失败,请稍后重试"),
"创建支付失败: 未生成支付参数",
)
} }
} }

View File

@@ -3,6 +3,7 @@ package middleware
import ( import (
"context" "context"
"net/http" "net/http"
"strings"
) )
const ( const (
@@ -12,7 +13,7 @@ const (
func GlobalSourceInterceptor(next http.HandlerFunc) http.HandlerFunc { func GlobalSourceInterceptor(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
// 获取请求头 X-Platform 的值 // 获取请求头 X-Platform 的值
platform := r.Header.Get(PlatformKey) platform := strings.TrimSpace(r.Header.Get(PlatformKey))
// 将值放入新的 context 中 // 将值放入新的 context 中
ctx := r.Context() ctx := r.Context()

View File

@@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"strconv" "strconv"
"strings"
"time" "time"
"tyc-server/app/main/api/internal/config" "tyc-server/app/main/api/internal/config"
"tyc-server/app/main/model" "tyc-server/app/main/model"
@@ -273,10 +274,14 @@ func (w *WechatPayService) CreateWechatH5Order(ctx context.Context, amount float
func (w *WechatPayService) CreateWechatOrder(ctx context.Context, amount float64, description string, outTradeNo string) (interface{}, error) { func (w *WechatPayService) CreateWechatOrder(ctx context.Context, amount float64, description string, outTradeNo string) (interface{}, error) {
platformVal := ctx.Value("platform") platformVal := ctx.Value("platform")
platform, ok := platformVal.(string) platform, ok := platformVal.(string)
platform = strings.TrimSpace(platform)
if !ok || platform == "" { if !ok || platform == "" {
logx.WithContext(ctx).Errorf("[WechatPay] CreateWechatOrder 缺少 X-Platform")
return "", fmt.Errorf("缺少 X-Platform 请求头(微信内请传 wxh5") return "", fmt.Errorf("缺少 X-Platform 请求头(微信内请传 wxh5")
} }
logx.WithContext(ctx).Infof("[WechatPay] CreateWechatOrder platform=%q out_trade_no=%s", platform, outTradeNo)
var prepayData interface{} var prepayData interface{}
var err error var err error
@@ -319,6 +324,10 @@ func (w *WechatPayService) CreateWechatOrder(ctx context.Context, amount float64
return "", fmt.Errorf("支付订单创建失败: %v", err) return "", fmt.Errorf("支付订单创建失败: %v", err)
} }
if prepayData == nil {
logx.WithContext(ctx).Errorf("[WechatPay] CreateWechatOrder 返回 prepayData 为 nil platform=%q", platform)
}
// 返回预支付ID // 返回预支付ID
return prepayData, nil return prepayData, nil
} }