This commit is contained in:
Mrx
2026-02-09 14:51:03 +08:00
parent ad28fc2301
commit 07ad436fd5
4 changed files with 37 additions and 9 deletions

View File

@@ -51,6 +51,7 @@ type (
Id string `json:"id"` Id string `json:"id"`
PayMethod string `json:"pay_method"` // 支付方式: wechat, alipay, appleiap, test(仅开发环境), test_empty(仅开发环境-空报告模式) PayMethod string `json:"pay_method"` // 支付方式: wechat, alipay, appleiap, test(仅开发环境), test_empty(仅开发环境-空报告模式)
PayType string `json:"pay_type" validate:"required,oneof=query agent_vip agent_upgrade whitelist"` PayType string `json:"pay_type" validate:"required,oneof=query agent_vip agent_upgrade whitelist"`
Code string `json:"code,optional"` // 微信小程序登录 code未绑定 openid 时传此参数以换取 openid 并调起支付
} }
PaymentResp { PaymentResp {
PrepayData interface{} `json:"prepay_data"` PrepayData interface{} `json:"prepay_data"`

View File

@@ -53,6 +53,27 @@ func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp,
isDevTestPayment := env == "development" && (req.PayMethod == "test" || req.PayMethod == "test_empty") isDevTestPayment := env == "development" && (req.PayMethod == "test" || req.PayMethod == "test_empty")
isEmptyReportMode := env == "development" && req.PayMethod == "test_empty" isEmptyReportMode := env == "development" && req.PayMethod == "test_empty"
// 微信小程序:若未绑定 openid 但前端传了 code则用 code 换取 openid 并写入 user_auth以便 CreateWechatOrder 能拿到 openid 并返回 prepay_data
if req.PayMethod == "wechat" && req.Code != "" {
platformVal := l.ctx.Value("platform")
platform, _ := platformVal.(string)
if platform == model.PlatformWxMini {
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
if getUidErr == nil {
_, findErr := l.svcCtx.UserAuthModel.FindOneByUserIdAuthType(l.ctx, userID, model.UserAuthTypeWxMiniOpenID)
if findErr != nil {
openid, codeErr := l.svcCtx.VerificationService.GetWechatMiniOpenID(l.ctx, req.Code)
if codeErr == nil {
ua := &model.UserAuth{Id: uuid.NewString(), UserId: userID, AuthType: model.UserAuthTypeWxMiniOpenID, AuthKey: openid}
if _, insertErr := l.svcCtx.UserAuthModel.Insert(l.ctx, nil, ua); insertErr != nil {
logx.Infof("支付前绑定 openid 写入失败(可忽略): %v", insertErr)
}
}
}
}
}
}
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 {
switch req.PayType { switch req.PayType {
case "agent_vip": case "agent_vip":

View File

@@ -252,8 +252,12 @@ func (w *WechatPayService) CreateWechatH5Order(ctx context.Context, amount float
// CreateWechatOrder 创建微信支付订单(集成 APP、H5、小程序 // CreateWechatOrder 创建微信支付订单(集成 APP、H5、小程序
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) {
// 根据 ctx 中的 platform 判断平台 // 安全读取 platform未设置或非小程序时避免误走 APP 支付导致 prepay_data 为空
platform := ctx.Value("platform").(string) platformVal := ctx.Value("platform")
platform, _ := platformVal.(string)
if platform == "" {
return nil, fmt.Errorf("请携带 X-Platform 请求头wxmini/h5/app以使用微信支付")
}
var prepayData interface{} var prepayData interface{}
var err error var err error
@@ -262,34 +266,35 @@ func (w *WechatPayService) CreateWechatOrder(ctx context.Context, amount float64
case model.PlatformWxMini: case model.PlatformWxMini:
userID, getUidErr := ctxdata.GetUidFromCtx(ctx) userID, getUidErr := ctxdata.GetUidFromCtx(ctx)
if getUidErr != nil { if getUidErr != nil {
return "", getUidErr return nil, getUidErr
} }
userAuthModel, findAuthModelErr := w.userAuthModel.FindOneByUserIdAuthType(ctx, userID, model.UserAuthTypeWxMiniOpenID) userAuthModel, findAuthModelErr := w.userAuthModel.FindOneByUserIdAuthType(ctx, userID, model.UserAuthTypeWxMiniOpenID)
if findAuthModelErr != nil { if findAuthModelErr != nil {
return "", findAuthModelErr // 返回明确文案,便于前端用 code 重试
return nil, fmt.Errorf("未绑定微信小程序,请重试或携带 code 参数")
} }
prepayData, err = w.CreateWechatMiniProgramOrder(ctx, amount, description, outTradeNo, userAuthModel.AuthKey) prepayData, err = w.CreateWechatMiniProgramOrder(ctx, amount, description, outTradeNo, userAuthModel.AuthKey)
if err != nil { if err != nil {
return "", err return nil, err
} }
case model.PlatformWxH5: case model.PlatformWxH5:
userID, getUidErr := ctxdata.GetUidFromCtx(ctx) userID, getUidErr := ctxdata.GetUidFromCtx(ctx)
if getUidErr != nil { if getUidErr != nil {
return "", getUidErr return nil, getUidErr
} }
userAuthModel, findAuthModelErr := w.userAuthModel.FindOneByUserIdAuthType(ctx, userID, model.UserAuthTypeWxh5OpenID) userAuthModel, findAuthModelErr := w.userAuthModel.FindOneByUserIdAuthType(ctx, userID, model.UserAuthTypeWxh5OpenID)
if findAuthModelErr != nil { if findAuthModelErr != nil {
return "", findAuthModelErr return nil, findAuthModelErr
} }
prepayData, err = w.CreateWechatH5Order(ctx, amount, description, outTradeNo, userAuthModel.AuthKey) prepayData, err = w.CreateWechatH5Order(ctx, amount, description, outTradeNo, userAuthModel.AuthKey)
if err != nil { if err != nil {
return "", err return nil, err
} }
case model.PlatformApp: case model.PlatformApp:
// 如果是 APP 平台,调用 APP 支付订单创建 // 如果是 APP 平台,调用 APP 支付订单创建
prepayData, err = w.CreateWechatAppOrder(ctx, amount, description, outTradeNo) prepayData, err = w.CreateWechatAppOrder(ctx, amount, description, outTradeNo)
default: default:
return "", fmt.Errorf("不支持的支付平台: %s", platform) return nil, fmt.Errorf("不支持的支付平台: %s", platform)
} }
// 如果创建支付订单失败,返回错误 // 如果创建支付订单失败,返回错误

View File

@@ -1975,6 +1975,7 @@ type PaymentReq struct {
Id string `json:"id"` Id string `json:"id"`
PayMethod string `json:"pay_method"` // 支付方式: wechat, alipay, appleiap, test(仅开发环境), test_empty(仅开发环境-空报告模式) PayMethod string `json:"pay_method"` // 支付方式: wechat, alipay, appleiap, test(仅开发环境), test_empty(仅开发环境-空报告模式)
PayType string `json:"pay_type" validate:"required,oneof=query agent_vip agent_upgrade whitelist"` PayType string `json:"pay_type" validate:"required,oneof=query agent_vip agent_upgrade whitelist"`
Code string `json:"code"` // 微信小程序登录 code用于未绑定 openid 时换取 openid 并调起支付(可选)
} }
type PaymentResp struct { type PaymentResp struct {