From 8ce5ead2032fcd09a1bafe6a686a377841ca35f8 Mon Sep 17 00:00:00 2001 From: wolter <11@gmail> Date: Mon, 21 Apr 2025 14:08:48 +0800 Subject: [PATCH] feat: wxmini --- app/constants/errorcode/error_code.go | 2 + .../controllers/front/payment_controller.go | 29 ++- app/http/entities/front/wechat.go | 35 ++- app/http/entities/front/wx.go | 13 ++ app/http/requestmapping/front.go | 20 +- app/http/routes/route.go | 9 +- app/services/thirdpay/do/pay.go | 25 ++- app/services/thirdpay/do/pay_way.go | 1 + app/services/thirdpay/do/refund_way.go | 2 + app/services/thirdpay/do/wx_mini.go | 208 ++++++++++++++++++ app/services/thirdpay/wx.go | 2 +- app/services/thirdpay/wx_mini.go | 120 ++++++++++ app/third/paymentService/payment_service.go | 6 +- app/third/paymentService/wechat_service.go | 2 +- go.mod | 1 - go.sum | 4 - 16 files changed, 453 insertions(+), 26 deletions(-) create mode 100644 app/http/entities/front/wx.go create mode 100644 app/services/thirdpay/do/wx_mini.go create mode 100644 app/services/thirdpay/wx_mini.go diff --git a/app/constants/errorcode/error_code.go b/app/constants/errorcode/error_code.go index 30b6cc8..474948c 100644 --- a/app/constants/errorcode/error_code.go +++ b/app/constants/errorcode/error_code.go @@ -104,6 +104,7 @@ const ( // 微信授权 WechatAuthFail = 1901 WechatAuthSignFail = 1902 + WechatPayError = 1903 ClientEnvErr = 2000 ) @@ -194,6 +195,7 @@ var MsgZH = map[int]string{ WechatAuthSignFail: "微信签名失败", ClientEnvErr: "支付环境错误", OrderPayRequestAcquireLock: "系统繁忙,请稍后再试", + WechatPayError: "微信支付配置错误", } var MsgMap map[string]map[int]string = map[string]map[int]string{"en": MsgZH} diff --git a/app/http/controllers/front/payment_controller.go b/app/http/controllers/front/payment_controller.go index c72f506..e863e28 100644 --- a/app/http/controllers/front/payment_controller.go +++ b/app/http/controllers/front/payment_controller.go @@ -201,7 +201,7 @@ func GetWxAuthUrl(c *gin.Context) { controllers.HandCodeRes(c, url, code) } -// 通过code获取授权,openid +// 通过code获取授权,openid, 微信公众号 使用 func GetWxAuth(c *gin.Context) { req, _ := controllers.GetRequest(c).(*front.GetWxAuthRequest) rsp, code := thirdpay.GetWxAuth(*req) @@ -259,3 +259,30 @@ func WxJsApiPay(c *gin.Context) { }) } } + +// 微信小程序 通过code获取openId, +func GetWxAuthMini(c *gin.Context) { + req, _ := controllers.GetRequest(c).(*front.GetWxAuthRequest) + rsp, code := thirdpay.GetWxAuthMini(*req) + controllers.HandCodeRes(c, rsp, code) +} + +// 小程序 获取加密scheme码 +func GetWxMiniScheme(c *gin.Context) { + req, _ := controllers.GetRequest(c).(*front.GetWxMiniSchemeRequest) + rsp, code := thirdpay.GetWxMiniSchemeService(*req) + controllers.HandCodeRes(c, rsp, code) +} + +// 微信小程序支付,返回支付参数给前端 +func WxMiniPay(c *gin.Context) { + req, _ := controllers.GetRequest(c).(*front.WxMiniPayRequest) + request := front.WxJsApiPayRequest{ + Code: req.Code, + State: req.OrderId, + ClientIp: c.ClientIP(), + } + + rsp, code := thirdpay.WxMiniPay(request) + controllers.HandCodeRes(c, rsp, code) +} diff --git a/app/http/entities/front/wechat.go b/app/http/entities/front/wechat.go index 6358358..fe44094 100644 --- a/app/http/entities/front/wechat.go +++ b/app/http/entities/front/wechat.go @@ -9,7 +9,7 @@ type GetWxAuthRequest struct { PayChannelId string `json:"state" form:"state"` } -// 获取微信用户信息 +// 获取微信用户信息, 微信公众号 type GetWxAuthResponse struct { AccessToken string `json:"access_token"` //网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同 ExpiresIn int `json:"expires_in"` //access_token接口调用凭证超时时间,单位(秒) @@ -20,6 +20,15 @@ type GetWxAuthResponse struct { Unionid string `json:"unionid"` // 用户统一标识(针对一个微信开放平台账号下的应用,同一用户的 unionid 是唯一的),只有当scope为"snsapi_userinfo"时返回 } +// 获取微信用户信息, 微信小程序 +type GetWxAuthMiniResponse struct { + Openid string `json:"openid"` // 用户唯一标识 + SessionKey string `json:"session_key"` //会话密钥 + Unionid string `json:"unionid"` //用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台帐号下会返回 + Errcode int `json:"errcode"` + Errmsg string `json:"errmsg"` +} + // jsapi支付 type WxJsApiPayRequest struct { Code string `json:"code" form:"code" ` @@ -44,3 +53,27 @@ type WxJsApiPayResponse struct { ThirdMsg string `json:"third_msg"` ReturnUrl string } + +// 微信小程序支付 +type WxMiniPayRequest struct { + Code string `json:"code" form:"code" ` + OrderId string `json:"order_id" form:"order_id"` // 支付中心的订单id + ClientIp string `json:"client_ip" form:"client_ip"` +} + +// 微信小程序支付 返回 +type WxMiniPayResponse struct { + AppId string `json:"appId"` + TimeStamp string `json:"timeStamp"` + NonceStr string `json:"nonceStr"` + Package string `json:"package"` + SignType string `json:"signType"` + PaySign string `json:"paySign"` + ThirdMsg string `json:"third_msg"` + ReturnUrl string `json:"return_url"` +} + +type GetWxMiniSchemeRequest struct { + PayChannelId string `json:"pay_channel_id" form:"pay_channel_id" validate:"required"` + GenerateSchemeRequest +} diff --git a/app/http/entities/front/wx.go b/app/http/entities/front/wx.go new file mode 100644 index 0000000..4658b0f --- /dev/null +++ b/app/http/entities/front/wx.go @@ -0,0 +1,13 @@ +package front + +type GenerateSchemeRequest struct { + JumpWxa JumpWxa `json:"jump_wxa"` + IsExpire bool `json:"is_expire"` // + ExpireType int `json:"expire_type"` // 默认值0,到期失效的 scheme 码失效类型,失效时间:0,失效间隔天数:1 + ExpireInterval int `json:"expire_interval"` //到期失效的 scheme 码的失效间隔天数。生成的到期失效 scheme 码在该间隔时间到达前有效。最长间隔天数为30天。is_expire 为 true 且 expire_type 为 1 时必填 +} +type JumpWxa struct { + Path string `json:"path"` + Query string `json:"query"` + EnvVersion string `json:"env_version"` +} diff --git a/app/http/requestmapping/front.go b/app/http/requestmapping/front.go index 68d9abc..e0fc90f 100644 --- a/app/http/requestmapping/front.go +++ b/app/http/requestmapping/front.go @@ -19,15 +19,17 @@ var FrontRequestMap = map[string]func() (validForm interface{}, isSaveLog bool){ var FrontRequestMapBeforeDecrypt = map[string]func() interface{}{ - common.FRONT_V1 + "/pay/url": func() interface{} { return new(front.RequestBody) }, - common.FRONT_V2 + "/pay/url": func() interface{} { return new(front.RequestBody) }, - common.FRONT_V1 + "/pay/refund": func() interface{} { return new(front.RequestBody) }, - common.FRONT_V1 + "/pay/query": func() interface{} { return new(front.RequestBody) }, - common.FRONT_V1 + "/pay/close": func() interface{} { return new(front.CloseReqs) }, - common.FRONT_V1 + "/wx/index": func() interface{} { return new(entities.PageRequest) }, - common.FRONT_V1 + "/wx/getWxAuthUrl": func() interface{} { return new(front.GetWxAuthUrlRequest) }, - common.FRONT_V1 + "/wx/getWxAuth": func() interface{} { return new(front.GetWxAuthRequest) }, - common.FRONT_V1 + "/wx/getCode": func() interface{} { return new(front.GetWxAuthRequest) }, + common.FRONT_V1 + "/pay/url": func() interface{} { return new(front.RequestBody) }, + common.FRONT_V2 + "/pay/url": func() interface{} { return new(front.RequestBody) }, + common.FRONT_V1 + "/pay/refund": func() interface{} { return new(front.RequestBody) }, + common.FRONT_V1 + "/pay/query": func() interface{} { return new(front.RequestBody) }, + common.FRONT_V1 + "/pay/close": func() interface{} { return new(front.CloseReqs) }, + common.FRONT_V1 + "/wx/index": func() interface{} { return new(entities.PageRequest) }, + common.FRONT_V1 + "/wx/getWxAuthUrl": func() interface{} { return new(front.GetWxAuthUrlRequest) }, + common.FRONT_V1 + "/wx/getWxAuth": func() interface{} { return new(front.GetWxAuthRequest) }, + common.FRONT_V1 + "/wx/getWxAuthMini": func() interface{} { return new(front.GetWxAuthRequest) }, + common.FRONT_V1 + "/wx/getCode": func() interface{} { return new(front.GetWxAuthRequest) }, + common.FRONT_V1 + "/wx/getScheme": func() interface{} { return new(front.GetWxMiniSchemeRequest) }, common.FRONT_V1 + "/payPage/list": func() interface{} { return new(front.PayChannelListRequest) }, common.FRONT_V1 + "/payPage/submit": func() interface{} { return new(front.GetPayLinkRequest) }, diff --git a/app/http/routes/route.go b/app/http/routes/route.go index 49f6513..443aecc 100644 --- a/app/http/routes/route.go +++ b/app/http/routes/route.go @@ -70,9 +70,12 @@ func RegisterRoute(router *gin.Engine) { router.LoadHTMLGlob("./front/templates/*") wx := v1.Group("/wx", middlewares.ValidateRequest()) { - wx.POST("/getWxAuthUrl", front.GetWxAuthUrl) // 获取授权codeUrl - wx.GET("/getWxAuth", front.GetWxAuth) // 获取openId - wx.GET("/getCode", front.GetWxCode) // 接收微信code + wx.POST("/getWxAuthUrl", front.GetWxAuthUrl) // 获取授权codeUrl + wx.GET("/getWxAuth", front.GetWxAuth) // 获取openId, 公众号授权 + wx.GET("/getCode", front.GetWxCode) // 接收微信code + wx.POST("/getScheme", front.GetWxMiniScheme) // 小程序 获取加密scheme码 + wx.GET("/getWxAuthMini", front.GetWxAuthMini) // 小程序 获取openId, 授权 + wx.POST("/wxMini", front.WxMiniPay) // 小程序 获取支付参数 } // 微信jsapi支付链接 diff --git a/app/services/thirdpay/do/pay.go b/app/services/thirdpay/do/pay.go index e908b7b..8373266 100644 --- a/app/services/thirdpay/do/pay.go +++ b/app/services/thirdpay/do/pay.go @@ -3,6 +3,8 @@ package do import ( "PaymentCenter/app/constants/common" "PaymentCenter/app/constants/errorcode" + "PaymentCenter/app/http/entities/front" + "PaymentCenter/app/models/merchantmodel" "PaymentCenter/app/models/paychannelmodel" "PaymentCenter/app/services" @@ -124,6 +126,8 @@ func (w *Pay) PayUrl() (url string) { w.PayCode = errorcode.PayChannelExtJsonError return } + + // 根据渠道类型,调用对应的支付方式 switch w.PayParam.Channel.ChannelType { // 微信公众号支付,返回的是用户授权链接 case common.PAY_CHANNEL_WECHAT_JSAPI: @@ -138,13 +142,30 @@ func (w *Pay) PayUrl() (url string) { if res.Result != "" { res.Result = config.GetConf().PayService.Host + "/pay/front/api/v1/brokerWechatUrl" + "?url=" + res.Result } + case common.PAY_CHANNEL_WECHAT_MINI: + req := front.GetWxMiniSchemeRequest{ + PayChannelId: strconv.Itoa(int(w.PayParam.Channel.Id)), + GenerateSchemeRequest: front.GenerateSchemeRequest{ + JumpWxa: front.JumpWxa{Query: "?order_id=" + strconv.Itoa(int(w.Order.Id))}, + }} + if config.GetEnv() == config.LocalEnv { + req.GenerateSchemeRequest.JumpWxa.EnvVersion = "develop" + } + // 微信小程序支付,返回小程序的scheme, todo 拼接订单id参数 + wx := NewWxMini().WithPayChannel(w.PayParam.Channel) + url, err = wx.GetWxMiniScheme(req) + res.Result = url + if err != nil { + w.PayCode = errorcode.PayChannelExtJsonError + w.ThirdMsg = err.Error() + return + } + default: w.PayCode = errorcode.PayChannelNotBuild return } - //res := paymentService.PaymentService(*w.ctx, *thirdPay) - if res.Code == payCommon.PAY_SUCCESS_CODE { w.Order.Status = common.ORDER_STATUS_PAYING code := services.OrderUpdate(w.Order, "status") diff --git a/app/services/thirdpay/do/pay_way.go b/app/services/thirdpay/do/pay_way.go index 666c75a..6dd9867 100644 --- a/app/services/thirdpay/do/pay_way.go +++ b/app/services/thirdpay/do/pay_way.go @@ -13,6 +13,7 @@ var PayWayList = map[int]func(commonPayInfo *paymentService.PayOrderRequest, cha common.PAY_CHANNEL_ALIPAY_WEB: AlipayWeb, common.PAY_CHANNEL_ALIPAY_PC: AlipayWeb, common.PAY_CHANNEL_WECHAT_JSAPI: WechatJSAPI, + common.PAY_CHANNEL_WECHAT_MINI: WechatJSAPI, } func WechatH5(commonPayInfo *paymentService.PayOrderRequest, channel *paychannelmodel.PayChannel) error { diff --git a/app/services/thirdpay/do/refund_way.go b/app/services/thirdpay/do/refund_way.go index 6149888..33ce693 100644 --- a/app/services/thirdpay/do/refund_way.go +++ b/app/services/thirdpay/do/refund_way.go @@ -10,7 +10,9 @@ import ( var RefundWayList = map[int]func(commonRefundInfo *paymentService.OrderRefundRequest, channel *paychannelmodel.PayChannel) error{ common.PAY_CHANNEL_WECHAT_H5: WechatH5Refund, common.PAY_CHANNEL_ALIPAY_WEB: AlipayWebRefund, + common.PAY_CHANNEL_ALIPAY_PC: AlipayWebRefund, common.PAY_CHANNEL_WECHAT_JSAPI: WechatJSAPIRefund, + common.PAY_CHANNEL_WECHAT_MINI: WechatJSAPIRefund, } func WechatH5Refund(commonRefundInfo *paymentService.OrderRefundRequest, channel *paychannelmodel.PayChannel) error { diff --git a/app/services/thirdpay/do/wx_mini.go b/app/services/thirdpay/do/wx_mini.go new file mode 100644 index 0000000..a2741dd --- /dev/null +++ b/app/services/thirdpay/do/wx_mini.go @@ -0,0 +1,208 @@ +package do + +import ( + "PaymentCenter/app/data" + "PaymentCenter/app/http/entities/front" + "PaymentCenter/app/models/paychannelmodel" + "PaymentCenter/app/third/paymentService" + "PaymentCenter/app/utils" + "PaymentCenter/app/utils/httpclient" + "encoding/json" + "fmt" + "xorm.io/builder" +) + +type WxMini struct { + payChannel *paychannelmodel.PayChannel +} + +func NewWxMini() *WxMini { + return &WxMini{} +} + +func (wm *WxMini) WithPayChannel(payChannel *paychannelmodel.PayChannel) *WxMini { + wm.payChannel = payChannel + return wm +} + +// 小程序,获取接口调用凭据 +func (wm *WxMini) GetAccessToken(appid, secret string) (accessToken string, err error) { + var ( + targetUrl = fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appid, secret) + header = map[string]string{ + "Content-Type": "application/json", + } + rsp = make(map[string]interface{}) + ) + + // 发送请求 + response, err := httpclient.FastHttpGet(targetUrl, header, nil, 0) + if err != nil { + err = fmt.Errorf("getAccessToken 获取接口调用凭据 err:%s", err.Error()) + return + } + + utils.Log(nil, "getAccessToken 获取接口调用凭据 ", "response ="+string(response)) + + err = json.Unmarshal(response, &rsp) + if err != nil { + err = fmt.Errorf("getAccessToken 获取接口调用凭据 err:%s", err.Error()) + return + } + accessToken = rsp["access_token"].(string) + if accessToken == "" { + err = fmt.Errorf("getAccessToken 获取接口调用凭据失败") + } + + return +} + +// 小程序,获取加密scheme码 +func (wm *WxMini) generateScheme(accessToken string, param front.GenerateSchemeRequest) (scheme string, err error) { + var ( + targetUrl = "https://api.weixin.qq.com/wxa/generatescheme?access_token=" + accessToken + header = map[string]string{ + "Content-Type": "application/json", + } + body []byte + ) + + type SchemeResponse struct { + Errcode int `json:"errcode"` + Errmsg string `json:"errmsg"` + Openlink string `json:"openlink"` + } + + body, err = json.Marshal(param) + if err != nil { + return + } + + // 发送请求 + response, err := httpclient.FastHttpPost(targetUrl, header, body, 0) + if err != nil { + err = fmt.Errorf("GenerateScheme 获取加密scheme码 err:%s", err.Error()) + return + } + utils.Log(nil, "GenerateScheme 获取加密scheme码 ", "response ="+string(response)) + + var rsp SchemeResponse + err = json.Unmarshal(response, &rsp) + if err != nil { + err = fmt.Errorf("GenerateScheme 获取加密scheme码 err:%s", err.Error()) + return + } else if rsp.Errcode != 0 { + err = fmt.Errorf("GenerateScheme 获取加密scheme码 code:%d err:%s", rsp.Errcode, rsp.Errmsg) + return + } + + return +} + +// 小程序 获取sechema 链接 通过 pay_channel_id 获取 微信小程序的appid 和 secret 生成 access_token 然后生成scheme +func (wm *WxMini) GetWxMiniScheme(param front.GetWxMiniSchemeRequest) (url string, err error) { + var ( + has bool + repo = data.NewPayChannelRepo(paychannelmodel.GetInstance().GetDb()) + payChannel = paychannelmodel.PayChannel{} + payConfig = paymentService.PayOrderRequest{} + ) + + // 获取支付渠道 + if wm.payChannel == nil { + has, err = repo.PayChannelGet(&payChannel, builder.Eq{"id": param.PayChannelId}) + if err != nil { + return + } else if !has { + err = fmt.Errorf("获取支付渠道不存在") + return + } + } + + // 支付渠道支付配置解析 + if configFun, ok := PayWayList[payChannel.ChannelType]; !ok { + err = fmt.Errorf("解析支付方式不存在") + return + } else { + err = configFun(&payConfig, &payChannel) + if err != nil { + return + } + } + + if payConfig.Wx.Secret == "" { + err = fmt.Errorf("微信小程序的secret为空") + return + } + + // 小程序的配置参数解析, 适配不同小程序配置需求 + if param.JumpWxa.Query == "" { + err = json.Unmarshal([]byte(payChannel.ExtJson), ¶m.GenerateSchemeRequest) + if err != nil { + return + } + } + + // 获取access_token + accessToken, err := wm.GetAccessToken(payChannel.AppId, payConfig.Wx.Secret) + if err != nil { + return + } + + // 获取scheme + scheme, err := wm.generateScheme(accessToken, param.GenerateSchemeRequest) + + return scheme, err +} + +// 小程序支付 通过code换取网页授权access_token,openid, +func (wm *WxMini) GetWxAuthMini(param front.GetWxAuthRequest) (rsp front.GetWxAuthMiniResponse, err error) { + var ( + has bool + payChannel = paychannelmodel.PayChannel{} + repo = data.NewPayChannelRepo(paychannelmodel.GetInstance().GetDb()) + ) + + // 获取支付渠道的配置 + has, err = repo.PayChannelGet(&payChannel, builder.Eq{"id": param.PayChannelId}) + if err != nil { + return + } else if !has { + err = fmt.Errorf("获取支付渠道不存在") + return + } + + // 配置支付的解析 + wxConfig := make(map[string]interface{}) + err = json.Unmarshal([]byte(payChannel.ExtJson), &wxConfig) + if err != nil { + return + } + sk := wxConfig["secret"].(string) + if sk == "" { + err = fmt.Errorf("微信小程序的secret为空") + return + } + + // 小程序 + targetUrl := fmt.Sprintf("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", + payChannel.AppId, + sk, + param.Code, + ) + + header := map[string]string{ + "Content-Type": "application/json", + } + body := map[string]string{} + response, err := httpclient.FastHttpGet(targetUrl, header, body, 0) + if err != nil { + return + } + utils.Log(nil, "小程序获取微信授权信息", string(response), targetUrl) + + // 解析返回数据 + err = json.Unmarshal(response, &rsp) + + return +} diff --git a/app/services/thirdpay/wx.go b/app/services/thirdpay/wx.go index 0cd16ed..0a7f7d6 100644 --- a/app/services/thirdpay/wx.go +++ b/app/services/thirdpay/wx.go @@ -58,7 +58,7 @@ func GetWxAuthUrl(param front.GetWxAuthUrlRequest) (targetUrl string, code int) return } -// // 通过code换取网页授权access_token,openid +// // 通过code换取网页授权access_token,openid, 公众号网页支付 func GetWxAuth(param front.GetWxAuthRequest) (rsp front.GetWxAuthResponse, code int) { // 获取支付渠道的配置 diff --git a/app/services/thirdpay/wx_mini.go b/app/services/thirdpay/wx_mini.go new file mode 100644 index 0000000..a8be8f8 --- /dev/null +++ b/app/services/thirdpay/wx_mini.go @@ -0,0 +1,120 @@ +package thirdpay + +import ( + "PaymentCenter/app/constants/common" + "PaymentCenter/app/constants/errorcode" + "PaymentCenter/app/http/entities/front" + "PaymentCenter/app/services" + "PaymentCenter/app/services/thirdpay/do" + "PaymentCenter/app/third/paymentService" + "PaymentCenter/app/third/paymentService/payCommon" + "PaymentCenter/app/utils" + "context" + "strconv" + "time" +) + +// 小程序支付 通过code换取网页授权access_token,openid, +func GetWxAuthMini(param front.GetWxAuthRequest) (rsp front.GetWxAuthMiniResponse, code int) { + wx := do.NewWxMini() + rsp, err := wx.GetWxAuthMini(param) + code = handErr(err) + return +} + +// 小程序 获取sechema 链接 +func GetWxMiniSchemeService(param front.GetWxMiniSchemeRequest) (scheme string, code int) { + var err error + + wx := do.NewWxMini() + scheme, err = wx.GetWxMiniScheme(param) + if err != nil { + code = handErr(err) + } + + return scheme, code +} + +// 微信小程序支付 +func WxMiniPay(param front.WxJsApiPayRequest) (response front.WxMiniPayResponse, code int) { + var ctx = context.Background() + task := newWxJsapiPay(param) + + // 1 获取订单 + task.getOrder() + if task.code != errorcode.Success { + return response, task.code + } + + // 获取支付渠道配置 + task.getPayChannel() + if task.code != errorcode.Success { + return response, task.code + } + // 获取下单的请求参数 + task.getOrderRequestLogs() + if task.code != errorcode.Success { + return response, task.code + } + // 2 通过code获取openid + rsp, code := GetWxAuthMini(front.GetWxAuthRequest{ + Code: param.Code, + PayChannelId: strconv.Itoa(int(task.order.PayChannelId)), + }) + if code != errorcode.Success { + response.ThirdMsg = rsp.Errmsg + return + } + task.openId = rsp.Openid + + task.wxConfig.AppId = task.payChannel.AppId + + order := task.order + // 通过openid,订单数据,请求微信下单, 获取prepay_id + orderRequest := paymentService.PayOrderRequest{ + PayChannelId: order.PayChannelId, + OrderId: order.Id, + ChannelType: task.payChannel.ChannelType, + Description: order.Desc, + Amount: order.Amount, + PayerClientIp: param.ClientIp, + ReturnUrl: task.orderPayRequest.ReturnUrl, + Wx: task.wxConfig, + OpenId: task.openId, + } + res := paymentService.PaymentService(ctx, orderRequest) + // 下单失败 + if res.Code != payCommon.PAY_SUCCESS_CODE { + task.code = errorcode.PrePayFail + response.ThirdMsg = res.ErrorMsg + return response, task.code + } + // 更新订单状态 + order.Status = common.ORDER_STATUS_PAYING + task.code = services.OrderUpdate(order, "status") + if task.code != errorcode.Success { + utils.Log(nil, "成功下单,更新订单状态失败", order) + } + + // 3 组装返回数据 + response = front.WxMiniPayResponse{ + AppId: task.payChannel.AppId, + TimeStamp: strconv.Itoa(int(time.Now().Unix())), + NonceStr: strconv.Itoa(int(time.Now().Unix())), + Package: "prepay_id=" + res.Result, + SignType: "RSA", + PaySign: "", + ThirdMsg: "", + } + + // 4 签名 + signValue, err := task.Sign(response.AppId, response.TimeStamp, response.NonceStr, response.Package) + if err != nil { + utils.Log(nil, "签名失败", err) + return response, errorcode.WechatAuthFail + } + response.PaySign = signValue + response.ReturnUrl = task.orderPayRequest.ReturnUrl + + return response, task.code +} diff --git a/app/third/paymentService/payment_service.go b/app/third/paymentService/payment_service.go index 1921f64..4939b1e 100644 --- a/app/third/paymentService/payment_service.go +++ b/app/third/paymentService/payment_service.go @@ -47,7 +47,7 @@ type PayOrderResponse struct { Result string `json:"result"` } -// PaymentService 统一发起支付 +// 统一发起支付 func PaymentService(c context.Context, payOrderRequest PayOrderRequest) PayOrderResponse { //logger.Info(c, "PaymentService 收到支付请求", payOrderRequest) var err error @@ -60,8 +60,8 @@ func PaymentService(c context.Context, payOrderRequest PayOrderRequest) PayOrder case payCommon.PAY_CHANNEL_ALIPAY_WEB: // 支付宝H5支付 info, err = ALiH5PayInfo(c, payOrderRequest) - case payCommon.PAY_CHANNEL_WECHAT_JSAPI: - // 微信JSAPI支付 + case payCommon.PAY_CHANNEL_WECHAT_JSAPI, payCommon.PAY_CHANNEL_WECHAT_MINI: + // 微信JSAPI支付,JSAPI/小程序下单API info, err = WxJsApiPayInfo(c, payOrderRequest) case payCommon.PAY_CHANNEL_ALIPAY_PC: // 支付宝PC支付 diff --git a/app/third/paymentService/wechat_service.go b/app/third/paymentService/wechat_service.go index fbc2d3e..5007a27 100644 --- a/app/third/paymentService/wechat_service.go +++ b/app/third/paymentService/wechat_service.go @@ -95,7 +95,7 @@ func WxH5PayInfo(c context.Context, payOrderRequest PayOrderRequest) (string, er return wxRsp.Response.H5Url, nil } -// 微信JSAPI支付 +// 微信JSAPI支付,JSAPI/小程序下单API func WxJsApiPayInfo(c context.Context, payOrderRequest PayOrderRequest) (string, error) { if payOrderRequest.OpenId == "" { return "", errors.New("jsapi方式openId不能为空") diff --git a/go.mod b/go.mod index c58f0d1..71baaec 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,6 @@ require ( github.com/swaggo/swag v1.7.9 github.com/tjfoc/gmsm v1.4.1 github.com/valyala/fasthttp v1.31.0 - github.com/wechatpay-apiv3/wechatpay-go v0.2.20 google.golang.org/grpc v1.56.3 google.golang.org/protobuf v1.30.0 gopkg.in/go-playground/validator.v9 v9.31.0 diff --git a/go.sum b/go.sum index f676eb0..3fce182 100644 --- a/go.sum +++ b/go.sum @@ -57,8 +57,6 @@ github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/ github.com/ZZMarquis/gm v1.3.2 h1:lFtpzg5zeeVMZ/gKi0gtYcKLBEo9XTqsZDHDz6s3Gow= github.com/ZZMarquis/gm v1.3.2/go.mod h1:wWbjZYgruQVd7Bb8UkSN8ujU931kx2XUW6nZLCiDE0Q= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/agiledragon/gomonkey v2.0.2+incompatible h1:eXKi9/piiC3cjJD1658mEE2o3NjkJ5vDLgYjCQu0Xlw= -github.com/agiledragon/gomonkey v2.0.2+incompatible/go.mod h1:2NGfXu1a80LLr2cmWXGBDaHEjb1idR6+FVlX5T3D9hw= github.com/agiledragon/gomonkey/v2 v2.3.1 h1:k+UnUY0EMNYUFUAQVETGY9uUTxjMdnUkP0ARyJS1zzs= github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY= github.com/ahmetb/go-linq/v3 v3.2.0 h1:BEuMfp+b59io8g5wYzNoFe9pWPalRklhlhbiU3hYZDE= @@ -758,8 +756,6 @@ github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPU github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= -github.com/wechatpay-apiv3/wechatpay-go v0.2.20 h1:gS8oFn1bHGnyapR2Zb4aqTV6l4kJWgbtqjCq6k1L9DQ= -github.com/wechatpay-apiv3/wechatpay-go v0.2.20/go.mod h1:A254AUBVB6R+EqQFo3yTgeh7HtyqRRtN2w9hQSOrd4Q= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=