feat: v1支付支持微信小程序
This commit is contained in:
parent
7a2d9fa1d7
commit
de6bed55ef
|
@ -35,6 +35,7 @@ func PayUrl(c *gin.Context) {
|
|||
|
||||
res.Order = thirdpay.NewOrdersResp(pay.Order)
|
||||
res.Url = pay.Url
|
||||
res.JsInfo = pay.JsApiInfo
|
||||
controllers.ApiRes(c, res, pay.PayCode)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -57,8 +57,9 @@ type CloseReqs struct {
|
|||
|
||||
// api 接口返回数据, 统一返回结构, order数据会进行加密
|
||||
type ApiResponse struct {
|
||||
Order interface{} `json:"order,omitempty"`
|
||||
Url string `json:"url,omitempty"`
|
||||
Order interface{} `json:"order,omitempty"`
|
||||
Url string `json:"url,omitempty"`
|
||||
JsInfo *WxMiniPayResponse `json:"js_info,omitempty"`
|
||||
}
|
||||
|
||||
type PayChannelListRequest struct {
|
||||
|
|
|
@ -1,5 +1,16 @@
|
|||
package front
|
||||
|
||||
import (
|
||||
"PaymentCenter/app/utils"
|
||||
"crypto"
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type GetWxAuthUrlRequest struct {
|
||||
PayChannelId string `json:"pay_channel_id" form:"pay_channel_id" validate:"required"`
|
||||
}
|
||||
|
@ -77,6 +88,36 @@ type WxMiniPayResponse struct {
|
|||
ReturnUrl string `json:"return_url"`
|
||||
}
|
||||
|
||||
func (this *WxMiniPayResponse) SignPaySign(PrivateKey string) (err error) {
|
||||
//组装被加密的字符串
|
||||
targetStr := this.AppId + "\n" + this.TimeStamp + "\n" + this.NonceStr + "\n" + this.Package + "\n"
|
||||
|
||||
//var keypath = "商户证书私钥地址"
|
||||
//key, err := ioutil.ReadFile(keypath)
|
||||
var key []byte
|
||||
if PrivateKey == "" {
|
||||
err = fmt.Errorf("配置的私钥不存在")
|
||||
return
|
||||
}
|
||||
key = []byte(PrivateKey)
|
||||
|
||||
blocks, _ := pem.Decode(key)
|
||||
if blocks == nil || blocks.Type != "PRIVATE KEY" {
|
||||
utils.Log(nil, "failed to decode PRIVATE KEY")
|
||||
return
|
||||
|
||||
}
|
||||
privateKey, err := x509.ParsePKCS8PrivateKey(blocks.Bytes)
|
||||
|
||||
h := sha256.New()
|
||||
h.Write([]byte(targetStr))
|
||||
digest := h.Sum(nil)
|
||||
s, _ := rsa.SignPKCS1v15(nil, privateKey.(*rsa.PrivateKey), crypto.SHA256, digest)
|
||||
this.PaySign = base64.StdEncoding.EncodeToString(s)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type GetWxMiniSchemeRequest struct {
|
||||
PayChannelId string `json:"pay_channel_id" form:"pay_channel_id" validate:"required"`
|
||||
GenerateSchemeRequest
|
||||
|
|
|
@ -11,3 +11,19 @@ type JumpWxa struct {
|
|||
Query string `json:"query"`
|
||||
EnvVersion string `json:"env_version"`
|
||||
}
|
||||
|
||||
type GenerateUrlLinkRequest struct {
|
||||
Path string `json:"path"`
|
||||
Query string `json:"query"`
|
||||
ExpireType int `json:"expire_type"`
|
||||
ExpireInterval int `json:"expire_interval"`
|
||||
EnvVersion string `json:"env_version"`
|
||||
CloudBase CloudBase `json:"cloud_base"`
|
||||
}
|
||||
|
||||
type CloudBase struct {
|
||||
Env string `json:"env"`
|
||||
Domain string `json:"domain"`
|
||||
Path string `json:"path"`
|
||||
Query string `json:"query"`
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ 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"
|
||||
|
@ -14,6 +13,7 @@ import (
|
|||
"context"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
"xorm.io/builder"
|
||||
|
||||
"PaymentCenter/app/models/ordersmodel"
|
||||
|
@ -38,9 +38,10 @@ type Pay struct {
|
|||
PayParam *PayParam
|
||||
RelationOrder *ordersmodel.Orders
|
||||
Order *ordersmodel.Orders
|
||||
PayCode int
|
||||
Url string
|
||||
ThirdMsg string
|
||||
PayCode int // 支付状态码
|
||||
Url string // 支付链接
|
||||
ThirdMsg string // 第三方错误信息
|
||||
JsApiInfo *front.WxMiniPayResponse // jsapi支付参数
|
||||
}
|
||||
|
||||
func NewPayWithPayCheck(paycheck *PayCheck) *Pay {
|
||||
|
@ -143,22 +144,36 @@ func (w *Pay) PayUrl() (url string) {
|
|||
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
|
||||
// 微信小程序支付
|
||||
|
||||
// 如果传openid,获取支付参数
|
||||
if w.PayParam.OpenId != "" {
|
||||
res = paymentService.PaymentService(*w.ctx, *thirdPay)
|
||||
} else {
|
||||
// 如果没有传openid,获取小程序scheme链接
|
||||
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"
|
||||
} else if config.GetEnv() == config.DevEnv {
|
||||
req.GenerateSchemeRequest.JumpWxa.EnvVersion = "trial"
|
||||
}
|
||||
|
||||
// 微信小程序支付,返回小程序的scheme,
|
||||
wx := NewWxMini().WithPayChannel(w.PayParam.Channel)
|
||||
|
||||
// 拼接订单id参数
|
||||
req.JumpWxa.Query = "?order_id=" + strconv.Itoa(int(w.Order.Id))
|
||||
url, err = wx.GetWxMiniScheme(req)
|
||||
res.Result = url
|
||||
if err != nil {
|
||||
w.PayCode = errorcode.PayChannelExtJsonError
|
||||
w.ThirdMsg = err.Error()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
|
@ -172,7 +187,27 @@ func (w *Pay) PayUrl() (url string) {
|
|||
if code != errorcode.Success {
|
||||
w.PayCode = code
|
||||
}
|
||||
w.Url = res.Result
|
||||
|
||||
// 微信小程序
|
||||
if w.PayParam.Channel.ChannelType == common.PAY_CHANNEL_WECHAT_MINI {
|
||||
// 组装返回数据
|
||||
if res.Result != "" {
|
||||
w.JsApiInfo = &front.WxMiniPayResponse{
|
||||
AppId: w.PayParam.Channel.AppId,
|
||||
TimeStamp: strconv.Itoa(int(time.Now().Unix())),
|
||||
NonceStr: strconv.Itoa(int(time.Now().Unix())),
|
||||
Package: "prepay_id=" + res.Result,
|
||||
SignType: "RSA",
|
||||
ThirdMsg: res.ErrorMsg,
|
||||
ReturnUrl: w.PayParam.ReturnUrl,
|
||||
}
|
||||
|
||||
// 获取签名
|
||||
err = w.JsApiInfo.SignPaySign(thirdPay.Wx.PrivateKey)
|
||||
}
|
||||
} else {
|
||||
w.Url = res.Result
|
||||
}
|
||||
} else {
|
||||
w.PayCode = errorcode.PrePayFail
|
||||
w.ThirdMsg = res.ErrorMsg
|
||||
|
|
|
@ -102,14 +102,14 @@ func (wm *WxMini) generateScheme(accessToken string, param front.GenerateSchemeR
|
|||
// 小程序 获取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{}
|
||||
has bool
|
||||
repo = data.NewPayChannelRepo(paychannelmodel.GetInstance().GetDb())
|
||||
payConfig = paymentService.PayOrderRequest{}
|
||||
)
|
||||
|
||||
// 获取支付渠道
|
||||
if wm.payChannel == nil {
|
||||
payChannel := paychannelmodel.PayChannel{}
|
||||
has, err = repo.PayChannelGet(&payChannel, builder.Eq{"id": param.PayChannelId})
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -117,14 +117,15 @@ func (wm *WxMini) GetWxMiniScheme(param front.GetWxMiniSchemeRequest) (url strin
|
|||
err = fmt.Errorf("获取支付渠道不存在")
|
||||
return
|
||||
}
|
||||
wm.payChannel = &payChannel
|
||||
}
|
||||
|
||||
// 支付渠道支付配置解析
|
||||
if configFun, ok := PayWayList[payChannel.ChannelType]; !ok {
|
||||
if configFun, ok := PayWayList[wm.payChannel.ChannelType]; !ok {
|
||||
err = fmt.Errorf("解析支付方式不存在")
|
||||
return
|
||||
} else {
|
||||
err = configFun(&payConfig, &payChannel)
|
||||
err = configFun(&payConfig, wm.payChannel)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -137,14 +138,14 @@ func (wm *WxMini) GetWxMiniScheme(param front.GetWxMiniSchemeRequest) (url strin
|
|||
|
||||
// 小程序的配置参数解析, 适配不同小程序配置需求
|
||||
if param.JumpWxa.Query == "" {
|
||||
err = json.Unmarshal([]byte(payChannel.ExtJson), ¶m.GenerateSchemeRequest)
|
||||
err = json.Unmarshal([]byte(wm.payChannel.ExtJson), ¶m.GenerateSchemeRequest)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 获取access_token
|
||||
accessToken, err := wm.GetAccessToken(payChannel.AppId, payConfig.Wx.Secret)
|
||||
accessToken, err := wm.GetAccessToken(wm.payChannel.AppId, payConfig.Wx.Secret)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -209,3 +210,45 @@ func (wm *WxMini) GetWxAuthMini(param front.GetWxAuthRequest) (rsp front.GetWxAu
|
|||
|
||||
return
|
||||
}
|
||||
|
||||
// 小程序 获取加密URLLink
|
||||
func (wm *WxMini) generateUrlLink(accessToken string, param front.GenerateUrlLinkRequest) (url string, err error) {
|
||||
var (
|
||||
targetUrl = "https://api.weixin.qq.com/wxa/generate_urllink?access_token=" + accessToken
|
||||
header = map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
body []byte
|
||||
)
|
||||
|
||||
type UrlLinkResponse struct {
|
||||
Errcode int `json:"errcode"`
|
||||
Errmsg string `json:"errmsg"`
|
||||
UrlLink string `json:"url_link"`
|
||||
}
|
||||
|
||||
body, err = json.Marshal(param)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 发送请求
|
||||
response, err := httpclient.FastHttpPost(targetUrl, header, body, 0)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("GenerateUrlLink 获取加密scheme码 err:%s", err.Error())
|
||||
return
|
||||
}
|
||||
utils.Log(nil, "GenerateUrlLink 获取加密scheme码 ", "response ="+string(response))
|
||||
|
||||
var rsp UrlLinkResponse
|
||||
err = json.Unmarshal(response, &rsp)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("GenerateUrlLink 获取加密scheme码 err:%s", err.Error())
|
||||
return
|
||||
} else if rsp.Errcode != 0 {
|
||||
err = fmt.Errorf("GenerateUrlLink 获取加密scheme码 code:%d err:%s", rsp.Errcode, rsp.Errmsg)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue