feat: wxmini
This commit is contained in:
parent
3f26ffa8cb
commit
8ce5ead203
|
@ -104,6 +104,7 @@ const (
|
||||||
// 微信授权
|
// 微信授权
|
||||||
WechatAuthFail = 1901
|
WechatAuthFail = 1901
|
||||||
WechatAuthSignFail = 1902
|
WechatAuthSignFail = 1902
|
||||||
|
WechatPayError = 1903
|
||||||
|
|
||||||
ClientEnvErr = 2000
|
ClientEnvErr = 2000
|
||||||
)
|
)
|
||||||
|
@ -194,6 +195,7 @@ var MsgZH = map[int]string{
|
||||||
WechatAuthSignFail: "微信签名失败",
|
WechatAuthSignFail: "微信签名失败",
|
||||||
ClientEnvErr: "支付环境错误",
|
ClientEnvErr: "支付环境错误",
|
||||||
OrderPayRequestAcquireLock: "系统繁忙,请稍后再试",
|
OrderPayRequestAcquireLock: "系统繁忙,请稍后再试",
|
||||||
|
WechatPayError: "微信支付配置错误",
|
||||||
}
|
}
|
||||||
var MsgMap map[string]map[int]string = map[string]map[int]string{"en": MsgZH}
|
var MsgMap map[string]map[int]string = map[string]map[int]string{"en": MsgZH}
|
||||||
|
|
||||||
|
|
|
@ -201,7 +201,7 @@ func GetWxAuthUrl(c *gin.Context) {
|
||||||
controllers.HandCodeRes(c, url, code)
|
controllers.HandCodeRes(c, url, code)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 通过code获取授权,openid
|
// 通过code获取授权,openid, 微信公众号 使用
|
||||||
func GetWxAuth(c *gin.Context) {
|
func GetWxAuth(c *gin.Context) {
|
||||||
req, _ := controllers.GetRequest(c).(*front.GetWxAuthRequest)
|
req, _ := controllers.GetRequest(c).(*front.GetWxAuthRequest)
|
||||||
rsp, code := thirdpay.GetWxAuth(*req)
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ type GetWxAuthRequest struct {
|
||||||
PayChannelId string `json:"state" form:"state"`
|
PayChannelId string `json:"state" form:"state"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取微信用户信息
|
// 获取微信用户信息, 微信公众号
|
||||||
type GetWxAuthResponse struct {
|
type GetWxAuthResponse struct {
|
||||||
AccessToken string `json:"access_token"` //网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
|
AccessToken string `json:"access_token"` //网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
|
||||||
ExpiresIn int `json:"expires_in"` //access_token接口调用凭证超时时间,单位(秒)
|
ExpiresIn int `json:"expires_in"` //access_token接口调用凭证超时时间,单位(秒)
|
||||||
|
@ -20,6 +20,15 @@ type GetWxAuthResponse struct {
|
||||||
Unionid string `json:"unionid"` // 用户统一标识(针对一个微信开放平台账号下的应用,同一用户的 unionid 是唯一的),只有当scope为"snsapi_userinfo"时返回
|
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支付
|
// jsapi支付
|
||||||
type WxJsApiPayRequest struct {
|
type WxJsApiPayRequest struct {
|
||||||
Code string `json:"code" form:"code" `
|
Code string `json:"code" form:"code" `
|
||||||
|
@ -44,3 +53,27 @@ type WxJsApiPayResponse struct {
|
||||||
ThirdMsg string `json:"third_msg"`
|
ThirdMsg string `json:"third_msg"`
|
||||||
ReturnUrl string
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -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"`
|
||||||
|
}
|
|
@ -19,15 +19,17 @@ var FrontRequestMap = map[string]func() (validForm interface{}, isSaveLog bool){
|
||||||
|
|
||||||
var FrontRequestMapBeforeDecrypt = map[string]func() interface{}{
|
var FrontRequestMapBeforeDecrypt = map[string]func() interface{}{
|
||||||
|
|
||||||
common.FRONT_V1 + "/pay/url": func() interface{} { return new(front.RequestBody) },
|
common.FRONT_V1 + "/pay/url": func() interface{} { return new(front.RequestBody) },
|
||||||
common.FRONT_V2 + "/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/refund": func() interface{} { return new(front.RequestBody) },
|
||||||
common.FRONT_V1 + "/pay/query": 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 + "/pay/close": func() interface{} { return new(front.CloseReqs) },
|
||||||
common.FRONT_V1 + "/wx/index": func() interface{} { return new(entities.PageRequest) },
|
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/getWxAuthUrl": func() interface{} { return new(front.GetWxAuthUrlRequest) },
|
||||||
common.FRONT_V1 + "/wx/getWxAuth": func() interface{} { return new(front.GetWxAuthRequest) },
|
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 + "/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/list": func() interface{} { return new(front.PayChannelListRequest) },
|
||||||
common.FRONT_V1 + "/payPage/submit": func() interface{} { return new(front.GetPayLinkRequest) },
|
common.FRONT_V1 + "/payPage/submit": func() interface{} { return new(front.GetPayLinkRequest) },
|
||||||
|
|
|
@ -70,9 +70,12 @@ func RegisterRoute(router *gin.Engine) {
|
||||||
router.LoadHTMLGlob("./front/templates/*")
|
router.LoadHTMLGlob("./front/templates/*")
|
||||||
wx := v1.Group("/wx", middlewares.ValidateRequest())
|
wx := v1.Group("/wx", middlewares.ValidateRequest())
|
||||||
{
|
{
|
||||||
wx.POST("/getWxAuthUrl", front.GetWxAuthUrl) // 获取授权codeUrl
|
wx.POST("/getWxAuthUrl", front.GetWxAuthUrl) // 获取授权codeUrl
|
||||||
wx.GET("/getWxAuth", front.GetWxAuth) // 获取openId
|
wx.GET("/getWxAuth", front.GetWxAuth) // 获取openId, 公众号授权
|
||||||
wx.GET("/getCode", front.GetWxCode) // 接收微信code
|
wx.GET("/getCode", front.GetWxCode) // 接收微信code
|
||||||
|
wx.POST("/getScheme", front.GetWxMiniScheme) // 小程序 获取加密scheme码
|
||||||
|
wx.GET("/getWxAuthMini", front.GetWxAuthMini) // 小程序 获取openId, 授权
|
||||||
|
wx.POST("/wxMini", front.WxMiniPay) // 小程序 获取支付参数
|
||||||
}
|
}
|
||||||
|
|
||||||
// 微信jsapi支付链接
|
// 微信jsapi支付链接
|
||||||
|
|
|
@ -3,6 +3,8 @@ package do
|
||||||
import (
|
import (
|
||||||
"PaymentCenter/app/constants/common"
|
"PaymentCenter/app/constants/common"
|
||||||
"PaymentCenter/app/constants/errorcode"
|
"PaymentCenter/app/constants/errorcode"
|
||||||
|
"PaymentCenter/app/http/entities/front"
|
||||||
|
|
||||||
"PaymentCenter/app/models/merchantmodel"
|
"PaymentCenter/app/models/merchantmodel"
|
||||||
"PaymentCenter/app/models/paychannelmodel"
|
"PaymentCenter/app/models/paychannelmodel"
|
||||||
"PaymentCenter/app/services"
|
"PaymentCenter/app/services"
|
||||||
|
@ -124,6 +126,8 @@ func (w *Pay) PayUrl() (url string) {
|
||||||
w.PayCode = errorcode.PayChannelExtJsonError
|
w.PayCode = errorcode.PayChannelExtJsonError
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 根据渠道类型,调用对应的支付方式
|
||||||
switch w.PayParam.Channel.ChannelType {
|
switch w.PayParam.Channel.ChannelType {
|
||||||
// 微信公众号支付,返回的是用户授权链接
|
// 微信公众号支付,返回的是用户授权链接
|
||||||
case common.PAY_CHANNEL_WECHAT_JSAPI:
|
case common.PAY_CHANNEL_WECHAT_JSAPI:
|
||||||
|
@ -138,13 +142,30 @@ func (w *Pay) PayUrl() (url string) {
|
||||||
if res.Result != "" {
|
if res.Result != "" {
|
||||||
res.Result = config.GetConf().PayService.Host + "/pay/front/api/v1/brokerWechatUrl" + "?url=" + 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:
|
default:
|
||||||
w.PayCode = errorcode.PayChannelNotBuild
|
w.PayCode = errorcode.PayChannelNotBuild
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//res := paymentService.PaymentService(*w.ctx, *thirdPay)
|
|
||||||
|
|
||||||
if res.Code == payCommon.PAY_SUCCESS_CODE {
|
if res.Code == payCommon.PAY_SUCCESS_CODE {
|
||||||
w.Order.Status = common.ORDER_STATUS_PAYING
|
w.Order.Status = common.ORDER_STATUS_PAYING
|
||||||
code := services.OrderUpdate(w.Order, "status")
|
code := services.OrderUpdate(w.Order, "status")
|
||||||
|
|
|
@ -13,6 +13,7 @@ var PayWayList = map[int]func(commonPayInfo *paymentService.PayOrderRequest, cha
|
||||||
common.PAY_CHANNEL_ALIPAY_WEB: AlipayWeb,
|
common.PAY_CHANNEL_ALIPAY_WEB: AlipayWeb,
|
||||||
common.PAY_CHANNEL_ALIPAY_PC: AlipayWeb,
|
common.PAY_CHANNEL_ALIPAY_PC: AlipayWeb,
|
||||||
common.PAY_CHANNEL_WECHAT_JSAPI: WechatJSAPI,
|
common.PAY_CHANNEL_WECHAT_JSAPI: WechatJSAPI,
|
||||||
|
common.PAY_CHANNEL_WECHAT_MINI: WechatJSAPI,
|
||||||
}
|
}
|
||||||
|
|
||||||
func WechatH5(commonPayInfo *paymentService.PayOrderRequest, channel *paychannelmodel.PayChannel) error {
|
func WechatH5(commonPayInfo *paymentService.PayOrderRequest, channel *paychannelmodel.PayChannel) error {
|
||||||
|
|
|
@ -10,7 +10,9 @@ import (
|
||||||
var RefundWayList = map[int]func(commonRefundInfo *paymentService.OrderRefundRequest, channel *paychannelmodel.PayChannel) error{
|
var RefundWayList = map[int]func(commonRefundInfo *paymentService.OrderRefundRequest, channel *paychannelmodel.PayChannel) error{
|
||||||
common.PAY_CHANNEL_WECHAT_H5: WechatH5Refund,
|
common.PAY_CHANNEL_WECHAT_H5: WechatH5Refund,
|
||||||
common.PAY_CHANNEL_ALIPAY_WEB: AlipayWebRefund,
|
common.PAY_CHANNEL_ALIPAY_WEB: AlipayWebRefund,
|
||||||
|
common.PAY_CHANNEL_ALIPAY_PC: AlipayWebRefund,
|
||||||
common.PAY_CHANNEL_WECHAT_JSAPI: WechatJSAPIRefund,
|
common.PAY_CHANNEL_WECHAT_JSAPI: WechatJSAPIRefund,
|
||||||
|
common.PAY_CHANNEL_WECHAT_MINI: WechatJSAPIRefund,
|
||||||
}
|
}
|
||||||
|
|
||||||
func WechatH5Refund(commonRefundInfo *paymentService.OrderRefundRequest, channel *paychannelmodel.PayChannel) error {
|
func WechatH5Refund(commonRefundInfo *paymentService.OrderRefundRequest, channel *paychannelmodel.PayChannel) error {
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -58,7 +58,7 @@ func GetWxAuthUrl(param front.GetWxAuthUrlRequest) (targetUrl string, code int)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// // 通过code换取网页授权access_token,openid
|
// // 通过code换取网页授权access_token,openid, 公众号网页支付
|
||||||
func GetWxAuth(param front.GetWxAuthRequest) (rsp front.GetWxAuthResponse, code int) {
|
func GetWxAuth(param front.GetWxAuthRequest) (rsp front.GetWxAuthResponse, code int) {
|
||||||
|
|
||||||
// 获取支付渠道的配置
|
// 获取支付渠道的配置
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -47,7 +47,7 @@ type PayOrderResponse struct {
|
||||||
Result string `json:"result"`
|
Result string `json:"result"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PaymentService 统一发起支付
|
// 统一发起支付
|
||||||
func PaymentService(c context.Context, payOrderRequest PayOrderRequest) PayOrderResponse {
|
func PaymentService(c context.Context, payOrderRequest PayOrderRequest) PayOrderResponse {
|
||||||
//logger.Info(c, "PaymentService 收到支付请求", payOrderRequest)
|
//logger.Info(c, "PaymentService 收到支付请求", payOrderRequest)
|
||||||
var err error
|
var err error
|
||||||
|
@ -60,8 +60,8 @@ func PaymentService(c context.Context, payOrderRequest PayOrderRequest) PayOrder
|
||||||
case payCommon.PAY_CHANNEL_ALIPAY_WEB:
|
case payCommon.PAY_CHANNEL_ALIPAY_WEB:
|
||||||
// 支付宝H5支付
|
// 支付宝H5支付
|
||||||
info, err = ALiH5PayInfo(c, payOrderRequest)
|
info, err = ALiH5PayInfo(c, payOrderRequest)
|
||||||
case payCommon.PAY_CHANNEL_WECHAT_JSAPI:
|
case payCommon.PAY_CHANNEL_WECHAT_JSAPI, payCommon.PAY_CHANNEL_WECHAT_MINI:
|
||||||
// 微信JSAPI支付
|
// 微信JSAPI支付,JSAPI/小程序下单API
|
||||||
info, err = WxJsApiPayInfo(c, payOrderRequest)
|
info, err = WxJsApiPayInfo(c, payOrderRequest)
|
||||||
case payCommon.PAY_CHANNEL_ALIPAY_PC:
|
case payCommon.PAY_CHANNEL_ALIPAY_PC:
|
||||||
// 支付宝PC支付
|
// 支付宝PC支付
|
||||||
|
|
|
@ -95,7 +95,7 @@ func WxH5PayInfo(c context.Context, payOrderRequest PayOrderRequest) (string, er
|
||||||
return wxRsp.Response.H5Url, nil
|
return wxRsp.Response.H5Url, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 微信JSAPI支付
|
// 微信JSAPI支付,JSAPI/小程序下单API
|
||||||
func WxJsApiPayInfo(c context.Context, payOrderRequest PayOrderRequest) (string, error) {
|
func WxJsApiPayInfo(c context.Context, payOrderRequest PayOrderRequest) (string, error) {
|
||||||
if payOrderRequest.OpenId == "" {
|
if payOrderRequest.OpenId == "" {
|
||||||
return "", errors.New("jsapi方式openId不能为空")
|
return "", errors.New("jsapi方式openId不能为空")
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -30,7 +30,6 @@ require (
|
||||||
github.com/swaggo/swag v1.7.9
|
github.com/swaggo/swag v1.7.9
|
||||||
github.com/tjfoc/gmsm v1.4.1
|
github.com/tjfoc/gmsm v1.4.1
|
||||||
github.com/valyala/fasthttp v1.31.0
|
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/grpc v1.56.3
|
||||||
google.golang.org/protobuf v1.30.0
|
google.golang.org/protobuf v1.30.0
|
||||||
gopkg.in/go-playground/validator.v9 v9.31.0
|
gopkg.in/go-playground/validator.v9 v9.31.0
|
||||||
|
|
4
go.sum
4
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 h1:lFtpzg5zeeVMZ/gKi0gtYcKLBEo9XTqsZDHDz6s3Gow=
|
||||||
github.com/ZZMarquis/gm v1.3.2/go.mod h1:wWbjZYgruQVd7Bb8UkSN8ujU931kx2XUW6nZLCiDE0Q=
|
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/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 h1:k+UnUY0EMNYUFUAQVETGY9uUTxjMdnUkP0ARyJS1zzs=
|
||||||
github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY=
|
github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY=
|
||||||
github.com/ahmetb/go-linq/v3 v3.2.0 h1:BEuMfp+b59io8g5wYzNoFe9pWPalRklhlhbiU3hYZDE=
|
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 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
|
||||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
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/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/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.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
|
Loading…
Reference in New Issue