Merge branch 'dev-lwl/wechat'
This commit is contained in:
commit
ccf4417659
|
@ -28,6 +28,12 @@ const (
|
||||||
PayTypeOp = "op" // op直冲
|
PayTypeOp = "op" // op直冲
|
||||||
PayTypeAlipay = "alipay" // 支付宝
|
PayTypeAlipay = "alipay" // 支付宝
|
||||||
PayTypeAlipayH5 = "alipay_h5" // 支付宝 h5
|
PayTypeAlipayH5 = "alipay_h5" // 支付宝 h5
|
||||||
|
PayTypeWxpayNative = "wxpay_native" // 微信native
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
CallBackPayTypeAlipay = "alipay"
|
||||||
|
CallBackPayTypeWxpay = "wxpay"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -56,6 +62,7 @@ type CreateOrderData struct {
|
||||||
OrderId string `json:"order_id"` // 订单id
|
OrderId string `json:"order_id"` // 订单id
|
||||||
AlipayParamStr string `json:"alipay_param_str"` // 支付宝 app支付参数
|
AlipayParamStr string `json:"alipay_param_str"` // 支付宝 app支付参数
|
||||||
AlipayH5ParamStr string `json:"alipay_h5_param_str"` // 支付宝 h5支付参数
|
AlipayH5ParamStr string `json:"alipay_h5_param_str"` // 支付宝 h5支付参数
|
||||||
|
WxpayNativeParamStr string `json:"wxpay_native_param_str"` // 微信支付 native支付参数
|
||||||
}
|
}
|
||||||
|
|
||||||
// 预解锁联系方式
|
// 预解锁联系方式
|
||||||
|
@ -136,6 +143,7 @@ type H5DirectUnlockWechatData struct {
|
||||||
OrderId string `json:"order_id"` // 订单id
|
OrderId string `json:"order_id"` // 订单id
|
||||||
AlipayParamStr string `json:"alipay_param_str"` // 支付宝 app支付参数
|
AlipayParamStr string `json:"alipay_param_str"` // 支付宝 app支付参数
|
||||||
AlipayH5ParamStr string `json:"alipay_h5_param_str"` // 支付宝 h5支付参数
|
AlipayH5ParamStr string `json:"alipay_h5_param_str"` // 支付宝 h5支付参数
|
||||||
|
WxpayNativeParamStr string `json:"wxpay_native_param_str"` // 微信支付 native支付参数
|
||||||
}
|
}
|
||||||
|
|
||||||
// 支付宝回调参数
|
// 支付宝回调参数
|
||||||
|
@ -144,6 +152,13 @@ type AlipayCallbackParamIn struct {
|
||||||
AlipayOrderId string `json:"alipay_order_id"` // 支付宝订单id
|
AlipayOrderId string `json:"alipay_order_id"` // 支付宝订单id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 支付回调参数
|
||||||
|
type PayCallbackParamIn struct {
|
||||||
|
OrderId string `json:"order_id"` // 我们自己服务的订单id
|
||||||
|
OutOrderId string `json:"out_order_id"` // 外部订单id,比如支付宝、微信
|
||||||
|
CallbackPayType string `json:"callback_pay_type"` // 支付类型
|
||||||
|
}
|
||||||
|
|
||||||
// 解锁会员资格
|
// 解锁会员资格
|
||||||
type UnlockMembershipReq struct {
|
type UnlockMembershipReq struct {
|
||||||
base.BaseRequest
|
base.BaseRequest
|
||||||
|
|
|
@ -19,9 +19,10 @@ func AlipayCallback(ctx *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if bm.GetString("trade_status") == "TRADE_SUCCESS" {
|
if bm.GetString("trade_status") == "TRADE_SUCCESS" {
|
||||||
service.DefaultService.AlipayCallback(ctx, &vasproto.AlipayCallbackParamIn{
|
service.DefaultService.PayCallback(ctx, &vasproto.PayCallbackParamIn{
|
||||||
OrderId: bm.GetString("out_trade_no"),
|
OrderId: bm.GetString("out_trade_no"),
|
||||||
AlipayOrderId: bm.GetString("trade_no"),
|
OutOrderId: bm.GetString("trade_no"),
|
||||||
|
CallbackPayType: vasproto.CallBackPayTypeAlipay,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ctx.String(200, "success")
|
ctx.String(200, "success")
|
||||||
|
|
|
@ -226,6 +226,7 @@ func Init(r *gin.Engine) {
|
||||||
|
|
||||||
extVasPayGroup := r.Group("/ext/vas")
|
extVasPayGroup := r.Group("/ext/vas")
|
||||||
extVasPayGroup.POST("alipay_callback", AlipayCallback)
|
extVasPayGroup.POST("alipay_callback", AlipayCallback)
|
||||||
|
extVasPayGroup.POST("wxpay_callback", WxpayCallback)
|
||||||
|
|
||||||
opVasPayGroup := r.Group("/op/vas", PrepareOp())
|
opVasPayGroup := r.Group("/op/vas", PrepareOp())
|
||||||
opVasPayGroup.POST("create_order", middleware.JSONParamValidator(vasproto.OpCreateOrderReq{}), OpCreateOrder)
|
opVasPayGroup.POST("create_order", middleware.JSONParamValidator(vasproto.OpCreateOrderReq{}), OpCreateOrder)
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
wxpay "github.com/go-pay/gopay/wechat/v3"
|
||||||
|
vasproto "service/api/proto/vas/proto"
|
||||||
|
"service/app/mix/service"
|
||||||
|
"service/bizcommon/util"
|
||||||
|
"service/library/logger"
|
||||||
|
"service/library/payclients/wxpaycli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func WxpayCallback(ctx *gin.Context) {
|
||||||
|
notify, err := wxpaycli.GetDefaultWxpayClient().ParseNotify(ctx.Request)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("ParseNotify fail, req: %v, err: %v", util.ToJson(notify), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if notify == nil {
|
||||||
|
logger.Error("ParseNotify nil, req: %v, err: %v", util.ToJson(notify), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
logger.Info("WxpayCallback, notify: %v", util.ToJson(notify))
|
||||||
|
|
||||||
|
if notify.TradeState == wxpay.TradeStateSuccess {
|
||||||
|
service.DefaultService.PayCallback(ctx, &vasproto.PayCallbackParamIn{
|
||||||
|
OrderId: notify.OutTradeNo,
|
||||||
|
OutOrderId: notify.TransactionId,
|
||||||
|
CallbackPayType: vasproto.CallBackPayTypeWxpay,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
ctx.String(200, "success")
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"service/library/idgenerator"
|
"service/library/idgenerator"
|
||||||
"service/library/logger"
|
"service/library/logger"
|
||||||
"service/library/payclients/alipaycli"
|
"service/library/payclients/alipaycli"
|
||||||
|
"service/library/payclients/wxpaycli"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-pay/gopay/alipay"
|
"github.com/go-pay/gopay/alipay"
|
||||||
|
@ -95,6 +96,7 @@ func (v *Vas) CreateOrder(ctx *gin.Context, req *vasproto.CreateOrderReq) (data
|
||||||
var (
|
var (
|
||||||
alipayParamStr string
|
alipayParamStr string
|
||||||
alipayH5ParamStr string
|
alipayH5ParamStr string
|
||||||
|
wxpayNativeParamStr string
|
||||||
)
|
)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -180,16 +182,29 @@ func (v *Vas) CreateOrder(ctx *gin.Context, req *vasproto.CreateOrderReq) (data
|
||||||
}
|
}
|
||||||
case vasproto.PayTypeAlipayH5:
|
case vasproto.PayTypeAlipayH5:
|
||||||
alipayCli := alipaycli.GetDefaultAlipayClient()
|
alipayCli := alipaycli.GetDefaultAlipayClient()
|
||||||
appPayParam := &alipaycli.WapPayParam{
|
wapPayParam := &alipaycli.WapPayParam{
|
||||||
OutTradeNo: orderId,
|
OutTradeNo: orderId,
|
||||||
Subject: product.Subject,
|
Subject: product.Subject,
|
||||||
TotalAmount: product.RealPrice,
|
TotalAmount: product.RealPrice,
|
||||||
TimeOutSeconds: 900,
|
TimeOutSeconds: 900,
|
||||||
ReturnUrl: req.ReturnUrl,
|
ReturnUrl: req.ReturnUrl,
|
||||||
}
|
}
|
||||||
alipayH5ParamStr, err = alipayCli.WapPay(ctx, appPayParam)
|
alipayH5ParamStr, err = alipayCli.WapPay(ctx, wapPayParam)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("alipay WapPay fail, req: %v, wapPayParam: %v, err: %v", util.ToJson(req), util.ToJson(appPayParam), err)
|
logger.Error("alipay WapPay fail, req: %v, wapPayParam: %v, err: %v", util.ToJson(req), util.ToJson(wapPayParam), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case vasproto.PayTypeWxpayNative:
|
||||||
|
wxpayCli := wxpaycli.GetDefaultWxpayClient()
|
||||||
|
nativePayParam := &wxpaycli.NativePayParam{
|
||||||
|
Description: product.Subject,
|
||||||
|
OutTradeNo: orderId,
|
||||||
|
TotalAmount: product.RealPrice,
|
||||||
|
TimeOutSeconds: 900,
|
||||||
|
}
|
||||||
|
wxpayNativeParamStr, err = wxpayCli.NativePay(ctx, nativePayParam)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("wxpay NativePay fail, req: %v, wapPayParam: %v, err: %v", util.ToJson(req), util.ToJson(nativePayParam), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -233,6 +248,7 @@ func (v *Vas) CreateOrder(ctx *gin.Context, req *vasproto.CreateOrderReq) (data
|
||||||
OrderId: orderId,
|
OrderId: orderId,
|
||||||
AlipayParamStr: alipayParamStr,
|
AlipayParamStr: alipayParamStr,
|
||||||
AlipayH5ParamStr: alipayH5ParamStr,
|
AlipayH5ParamStr: alipayH5ParamStr,
|
||||||
|
WxpayNativeParamStr: wxpayNativeParamStr,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1500,6 +1516,7 @@ func (v *Vas) H5DirectUnlockWechat(ctx *gin.Context, req *vasproto.H5DirectUnloc
|
||||||
OrderId: cData.OrderId,
|
OrderId: cData.OrderId,
|
||||||
AlipayParamStr: cData.AlipayParamStr,
|
AlipayParamStr: cData.AlipayParamStr,
|
||||||
AlipayH5ParamStr: cData.AlipayH5ParamStr,
|
AlipayH5ParamStr: cData.AlipayH5ParamStr,
|
||||||
|
WxpayNativeParamStr: cData.WxpayNativeParamStr,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1524,13 +1541,14 @@ func (v *Vas) GetUserWechatUnlock(ctx *gin.Context, mid, uid int64) (uu *dbstruc
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 支付宝【支付】回调
|
// 【支付】回调
|
||||||
func (v *Vas) AlipayCallback(ctx *gin.Context, p *vasproto.AlipayCallbackParamIn) {
|
func (v *Vas) PayCallback(ctx *gin.Context, p *vasproto.PayCallbackParamIn) {
|
||||||
var (
|
var (
|
||||||
orderId = p.OrderId
|
orderId = p.OrderId
|
||||||
alipayOrderId = p.AlipayOrderId
|
outOrderId = p.OutOrderId
|
||||||
afterStatus int32
|
afterStatus int32
|
||||||
)
|
)
|
||||||
|
logger.Info("PayCallback, param: %v", util.ToJson(p))
|
||||||
|
|
||||||
// 获取订单
|
// 获取订单
|
||||||
checkOrder, err := v.store.GetOrderById(ctx, nil, orderId)
|
checkOrder, err := v.store.GetOrderById(ctx, nil, orderId)
|
||||||
|
@ -1548,8 +1566,8 @@ func (v *Vas) AlipayCallback(ctx *gin.Context, p *vasproto.AlipayCallbackParamIn
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ali_order_id检查
|
// out_order_id检查
|
||||||
outOrder, err := v.store.GetOrderByOutOrderId(ctx, nil, alipayOrderId)
|
outOrder, err := v.store.GetOrderByOutOrderId(ctx, nil, outOrderId)
|
||||||
switch err {
|
switch err {
|
||||||
case sql.ErrNoRows:
|
case sql.ErrNoRows:
|
||||||
err = nil
|
err = nil
|
||||||
|
@ -1665,8 +1683,8 @@ func (v *Vas) AlipayCallback(ctx *gin.Context, p *vasproto.AlipayCallbackParamIn
|
||||||
}
|
}
|
||||||
afterStatus = dbstruct.VasOrderStatusPaySuccess
|
afterStatus = dbstruct.VasOrderStatusPaySuccess
|
||||||
|
|
||||||
// 更新支付宝订单
|
// 更新外部订单
|
||||||
err = v.store.UpdateOutOrderId(ctx, tx, orderId, alipayOrderId)
|
err = v.store.UpdateOutOrderId(ctx, tx, orderId, outOrderId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("UpdateOutOrderId fail, p: %v", util.ToJson(p))
|
logger.Error("UpdateOutOrderId fail, p: %v", util.ToJson(p))
|
||||||
return
|
return
|
||||||
|
@ -2062,8 +2080,11 @@ func (v *Vas) DealOneOrder(ctx *gin.Context, orderId string) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 支付宝查询订单
|
// 支付宝查询订单
|
||||||
|
switch order.GetPayType() {
|
||||||
|
case vasproto.PayTypeAlipayH5:
|
||||||
alipayCli := alipaycli.GetDefaultAlipayClient()
|
alipayCli := alipaycli.GetDefaultAlipayClient()
|
||||||
alipayResp, err := alipayCli.QueryOrder(ctx, &alipaycli.QueryOrderParam{
|
var alipayResp *alipay.TradeQueryResponse
|
||||||
|
alipayResp, err = alipayCli.QueryOrder(ctx, &alipaycli.QueryOrderParam{
|
||||||
OutTradeNo: orderId,
|
OutTradeNo: orderId,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -2086,6 +2107,10 @@ func (v *Vas) DealOneOrder(ctx *gin.Context, orderId string) (err error) {
|
||||||
err = errors.New("closed order")
|
err = errors.New("closed order")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
case vasproto.CallBackPayTypeWxpay:
|
||||||
|
err = errors.New("暂不处理微信订单")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 判断时间,小于7天不处理
|
// 判断时间,小于7天不处理
|
||||||
if time.Now().Unix()-order.GetCt() < 7*86400 {
|
if time.Now().Unix()-order.GetCt() < 7*86400 {
|
||||||
|
|
|
@ -49,6 +49,7 @@ import (
|
||||||
"service/library/melody"
|
"service/library/melody"
|
||||||
"service/library/mycrypto"
|
"service/library/mycrypto"
|
||||||
"service/library/payclients/alipaycli"
|
"service/library/payclients/alipaycli"
|
||||||
|
"service/library/payclients/wxpaycli"
|
||||||
"service/library/redis"
|
"service/library/redis"
|
||||||
|
|
||||||
"go.mongodb.org/mongo-driver/mongo"
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
@ -129,7 +130,13 @@ func (s *Service) Init(c any) (err error) {
|
||||||
|
|
||||||
err = alipaycli.Init(cfg.Alipay)
|
err = alipaycli.Init(cfg.Alipay)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("alipaycli.Init fail, cfg: %v, err: %v", util.ToJson(cfg), err)
|
logger.Error("alipaycli.Init fail, cfg: %v, err: %v", util.ToJson(cfg.Alipay), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = wxpaycli.Init(cfg.Wxpay)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("wxpaycli.Init fail, cfg: %v, err: %v", util.ToJson(cfg.Wxpay), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -369,9 +369,9 @@ func (s *Service) H5DirectUnlockWechat(ctx *gin.Context, req *vasproto.H5DirectU
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 支付宝回调
|
// 支付回调
|
||||||
func (s *Service) AlipayCallback(ctx *gin.Context, req *vasproto.AlipayCallbackParamIn) (data *vasproto.H5DirectUnlockWechatData, ec errcode.ErrCode) {
|
func (s *Service) PayCallback(ctx *gin.Context, req *vasproto.PayCallbackParamIn) (data *vasproto.H5DirectUnlockWechatData, ec errcode.ErrCode) {
|
||||||
_DefaultVas.AlipayCallback(ctx, req)
|
_DefaultVas.PayCallback(ctx, req)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,11 +27,6 @@ mix_mysql:
|
||||||
read_timeout_s: 5
|
read_timeout_s: 5
|
||||||
write_timeout_s: 3
|
write_timeout_s: 3
|
||||||
|
|
||||||
wxpay:
|
|
||||||
mchid: "1111"
|
|
||||||
serial_no: "1111"
|
|
||||||
apiv3_key: "1111"
|
|
||||||
private_key: "af21aw65aw23efwa132f1waef56wa56awef"
|
|
||||||
|
|
||||||
crypto:
|
crypto:
|
||||||
aes:
|
aes:
|
||||||
|
@ -48,6 +43,14 @@ alipay:
|
||||||
private_key: "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCtj6Nu2olEB8c8SDSANExaPbmk8LoYPEGB/APZDskhezO/w4OwPmG1Ak79XDpUUIihdmTZ8i2nBLhhRpFZGU4MMdil4X7a5nYHBm5dkGo3isIInn/qV7AYDqek4pGpMUPI6fbR05NWnUTZ+3AvMjTNBa979MgLyqS3jzpvuK6yXM5RinKVv8IF9KgthRKjH4LHyyRXBGu2cJSA5utjzFCL9KIu/T4XXZ09HOgz+JKPxXDj25Ob5eTtcBDsoJfXChcOvwCA7nxb1jzvGDrkqF36H1CC8KT1aoLRLisBsM+7sjEfNcB4RG5pGHSDGQJwZ0stGAhXf/fuWiLmI/zMOXODAgMBAAECggEAEL7CAuj8w16Iv20r+46QK0i3R42eNsZhf5wD9wYxK5TKal7/rppmLOObIWCrlATtGb7lfg2aj/mpnGEFlvYVDKImh+KYrZ/8lTLupQJQ7SjrDY/VQZPSPo/zZrohWZSSOKkyEg56samcwfc7XKJYa8t3odr9Df4wJDGibrL/z99xrJrz85le+NHBISXUyddS5ojuDNfGwE39wgLu52P74QYxv6s0xZKj2aALXaLXyTzF4ys34nVhhv75gXFtENiUet5/PVRYe7OE4cndcOP9WI3nXP5ojak8N4fY15S0YOm/0NZP8w6nWUemFjUNRXYRY42J+W+/myW8RIppaGuwkQKBgQDYH263Lh8C9EkjGA2po68LUTBhM2fT2L3batzHjXo0jvLT0IR88/9V7xhC3ZQZNcxQCK0xaCYfzFx3UV9veC1zeVRW0i/hyJ8B40w3WXCoGDiHgzQ/kcu/Iaw2qmJyhEFzOwAfrxIgco9EiZBaY7fXyy7YkZLGqXNFcLsuWR5qWwKBgQDNlc19CESIukT31Ap2QBe6t9YNXHZuKTePBRaIUCan3vZwPfZePLJQCgtoVhnCGoHZJ+ZlNhYri9x6DNLZpxCSHZNjccmqFGj3N7xWBqU38gu2dcPdMAxT1ERwf2gdlhgWAhVzD56hsWyrbP9YZACXy7TlevSj7s/5GaNaVuHT+QKBgQC2VZZ3zt51BJnrlLB6LVFRz/ZsGw1+qj5LLpYDeXXff7aYQzRzovsJigVC7GO0/TFZWGid5Us8ypI8TBejGJXn9TXVZdDlwPd9hUFY9QlZl82hbm0XMK7fms4K9KbIDJKXX/CTyoUVgPEkFpcF21lQIuhr6C0XlABfVmNlD+TcPwKBgHJuot2ov3UXsZH8/gHKNSsibswrHmS9HobGPz+K1al1Stk5NCxKPrqcjLL70gSf+ozkT7MggwCkLgnln2u1OV0Lh2HAEY9RIwgQhw2fT1GvseNS873no8T5j0rLMCnfxPJjIItWM2cvOhzFY/BQYaAcrElbwlaJdEvkgG+lkrgJAoGBAInYRdHo9V1exDUS0ucQuraoEtuvgOrqatnCbuNZ9EpgjFJxDbHXOIJYPvgfpyws4amdksNQL0Ux9+p+esJOS+JYYkE1nmCTCrfb6SNKr+PdeUteKtTiHJb4zJhGVC2Lk4uBg9AGa/d7j5apWw4RsZ/R1ky1S6KQUkqItbVrhC8l"
|
private_key: "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCtj6Nu2olEB8c8SDSANExaPbmk8LoYPEGB/APZDskhezO/w4OwPmG1Ak79XDpUUIihdmTZ8i2nBLhhRpFZGU4MMdil4X7a5nYHBm5dkGo3isIInn/qV7AYDqek4pGpMUPI6fbR05NWnUTZ+3AvMjTNBa979MgLyqS3jzpvuK6yXM5RinKVv8IF9KgthRKjH4LHyyRXBGu2cJSA5utjzFCL9KIu/T4XXZ09HOgz+JKPxXDj25Ob5eTtcBDsoJfXChcOvwCA7nxb1jzvGDrkqF36H1CC8KT1aoLRLisBsM+7sjEfNcB4RG5pGHSDGQJwZ0stGAhXf/fuWiLmI/zMOXODAgMBAAECggEAEL7CAuj8w16Iv20r+46QK0i3R42eNsZhf5wD9wYxK5TKal7/rppmLOObIWCrlATtGb7lfg2aj/mpnGEFlvYVDKImh+KYrZ/8lTLupQJQ7SjrDY/VQZPSPo/zZrohWZSSOKkyEg56samcwfc7XKJYa8t3odr9Df4wJDGibrL/z99xrJrz85le+NHBISXUyddS5ojuDNfGwE39wgLu52P74QYxv6s0xZKj2aALXaLXyTzF4ys34nVhhv75gXFtENiUet5/PVRYe7OE4cndcOP9WI3nXP5ojak8N4fY15S0YOm/0NZP8w6nWUemFjUNRXYRY42J+W+/myW8RIppaGuwkQKBgQDYH263Lh8C9EkjGA2po68LUTBhM2fT2L3batzHjXo0jvLT0IR88/9V7xhC3ZQZNcxQCK0xaCYfzFx3UV9veC1zeVRW0i/hyJ8B40w3WXCoGDiHgzQ/kcu/Iaw2qmJyhEFzOwAfrxIgco9EiZBaY7fXyy7YkZLGqXNFcLsuWR5qWwKBgQDNlc19CESIukT31Ap2QBe6t9YNXHZuKTePBRaIUCan3vZwPfZePLJQCgtoVhnCGoHZJ+ZlNhYri9x6DNLZpxCSHZNjccmqFGj3N7xWBqU38gu2dcPdMAxT1ERwf2gdlhgWAhVzD56hsWyrbP9YZACXy7TlevSj7s/5GaNaVuHT+QKBgQC2VZZ3zt51BJnrlLB6LVFRz/ZsGw1+qj5LLpYDeXXff7aYQzRzovsJigVC7GO0/TFZWGid5Us8ypI8TBejGJXn9TXVZdDlwPd9hUFY9QlZl82hbm0XMK7fms4K9KbIDJKXX/CTyoUVgPEkFpcF21lQIuhr6C0XlABfVmNlD+TcPwKBgHJuot2ov3UXsZH8/gHKNSsibswrHmS9HobGPz+K1al1Stk5NCxKPrqcjLL70gSf+ozkT7MggwCkLgnln2u1OV0Lh2HAEY9RIwgQhw2fT1GvseNS873no8T5j0rLMCnfxPJjIItWM2cvOhzFY/BQYaAcrElbwlaJdEvkgG+lkrgJAoGBAInYRdHo9V1exDUS0ucQuraoEtuvgOrqatnCbuNZ9EpgjFJxDbHXOIJYPvgfpyws4amdksNQL0Ux9+p+esJOS+JYYkE1nmCTCrfb6SNKr+PdeUteKtTiHJb4zJhGVC2Lk4uBg9AGa/d7j5apWw4RsZ/R1ky1S6KQUkqItbVrhC8l"
|
||||||
notify_url: "https://api.tiefen.fun/ext/vas/alipay_callback"
|
notify_url: "https://api.tiefen.fun/ext/vas/alipay_callback"
|
||||||
|
|
||||||
|
wxpay:
|
||||||
|
mchid: "1665016206"
|
||||||
|
appid: "wxc28fd8aaf31984b6"
|
||||||
|
serial_no: "51D8E75620B9569F10FF5363022F3C9D2152DF50"
|
||||||
|
apiv3_key: "UoaswgnuKYwIadqxCVag1IZlq5n9USvt"
|
||||||
|
private_key_path: "/app/wishpal-ironfan/etc/mix/wxpaycert/apiclient_key.pem"
|
||||||
|
notify_url: "https://api.tiefen.fun/ext/vas/wxpay_callback"
|
||||||
|
|
||||||
apollo:
|
apollo:
|
||||||
app_id: "wishpal_live_service"
|
app_id: "wishpal_live_service"
|
||||||
cluster: "dev"
|
cluster: "dev"
|
||||||
|
|
|
@ -28,10 +28,12 @@ mix_mysql:
|
||||||
write_timeout_s: 3
|
write_timeout_s: 3
|
||||||
|
|
||||||
wxpay:
|
wxpay:
|
||||||
mchid: "1111"
|
mchid: "1665016206"
|
||||||
serial_no: "1111"
|
appid: "wxc28fd8aaf31984b6"
|
||||||
apiv3_key: "1111"
|
serial_no: "51D8E75620B9569F10FF5363022F3C9D2152DF50"
|
||||||
private_key: "af21aw65aw23efwa132f1waef56wa56awef"
|
apiv3_key: "UoaswgnuKYwIadqxCVag1IZlq5n9USvt"
|
||||||
|
private_key_path: "/app/wishpal-ironfan/etc/mix/wxpaycert/apiclient_key.pem"
|
||||||
|
notify_url: "https://api.wishpal.cn/ext/vas/wxpay_callback"
|
||||||
|
|
||||||
crypto:
|
crypto:
|
||||||
aes:
|
aes:
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,25 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEKDCCAxCgAwIBAgIUUdjnViC5Vp8Q/1NjAi88nSFS31AwDQYJKoZIhvcNAQEL
|
||||||
|
BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
|
||||||
|
FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
|
||||||
|
Q0EwHhcNMjQwMTMwMDIxMDEyWhcNMjkwMTI4MDIxMDEyWjCBgTETMBEGA1UEAwwK
|
||||||
|
MTY2NTAxNjIwNjEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMS0wKwYDVQQL
|
||||||
|
DCTmiJDpg73lv4PmhI/liLDkuobnp5HmioDmnInpmZDlhazlj7gxCzAJBgNVBAYT
|
||||||
|
AkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
|
||||||
|
AQoCggEBAODFaaohlVkRV079c07NzrpSTJgBLr8vNMBY/pZb/Ah+KVoNIMB732NS
|
||||||
|
ykUqXVia5smQMnljZZodw7KKuB9hfcYcyuvXHu+2o43p5A+IZKGV/0eU5AJ2LXOZ
|
||||||
|
SsF4xaPlNyWX6V3JrNhqpHjIbpqGGPUGeypn5bpJr3G1N8y1NSsG8m4ebh1YBBHr
|
||||||
|
YDZN562T1g31zGI7AvsFdomjmFhq6Y2hvPukjPpceoGASEEfpC/yRrvjo05HVQVK
|
||||||
|
8x6oda/67IHNS2F0goUsJESBCYVOhezugmy4XaeyFkqcw+1rde+LzBs9sBlzhvgr
|
||||||
|
Asu/1LEEqJGHO1qAXwqpifWThEHyYUMCAwEAAaOBuTCBtjAJBgNVHRMEAjAAMAsG
|
||||||
|
A1UdDwQEAwID+DCBmwYDVR0fBIGTMIGQMIGNoIGKoIGHhoGEaHR0cDovL2V2Y2Eu
|
||||||
|
aXRydXMuY29tLmNuL3B1YmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIwRTUwREJDMDRC
|
||||||
|
MDZBRDM5NzU0OTg0NkMwMUMzRThFQkQyJnNnPUhBQ0M0NzFCNjU0MjJFMTJCMjdB
|
||||||
|
OUQzM0E4N0FEMUNERjU5MjZFMTQwMzcxMA0GCSqGSIb3DQEBCwUAA4IBAQAcaVb/
|
||||||
|
Eg+fOt1qPr9we38kzUwVRktgamFB3hRfKvZpva3hx4lh8ZC3Et7bIP/r4IV5qCNC
|
||||||
|
wzN1Niq0aBXtnehOWL+mnnBmmW5QnB80UX1/yFxtaBEK+6R6IObAj7ClUSb0F8ak
|
||||||
|
0fRkCyWGl985sAUyZVE5g0jQEEcWFhdV9lpwPdprY4S9vck+cCfjPi4EyxEzRh7z
|
||||||
|
knsvZbjoj/0oTSKgg39D4UEQl6X0e3YR74kIXfKmFK08WxoKKet201pL3bzJKBAY
|
||||||
|
s+8VBqAKsTvNZJ1/GYPqax7ArpACX4LjgmzCv7/rrM75ce6rXWlkIOBSAz2dHuF0
|
||||||
|
Q6iPI92vMh32p19Q
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -0,0 +1,28 @@
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDgxWmqIZVZEVdO
|
||||||
|
/XNOzc66UkyYAS6/LzTAWP6WW/wIfilaDSDAe99jUspFKl1YmubJkDJ5Y2WaHcOy
|
||||||
|
irgfYX3GHMrr1x7vtqON6eQPiGShlf9HlOQCdi1zmUrBeMWj5Tcll+ldyazYaqR4
|
||||||
|
yG6ahhj1BnsqZ+W6Sa9xtTfMtTUrBvJuHm4dWAQR62A2Teetk9YN9cxiOwL7BXaJ
|
||||||
|
o5hYaumNobz7pIz6XHqBgEhBH6Qv8ka746NOR1UFSvMeqHWv+uyBzUthdIKFLCRE
|
||||||
|
gQmFToXs7oJsuF2nshZKnMPta3Xvi8wbPbAZc4b4KwLLv9SxBKiRhztagF8KqYn1
|
||||||
|
k4RB8mFDAgMBAAECggEAFfMxXmvpKcmHvS8DE68FgSyITk/PQNxbSm1mb0iMVEf9
|
||||||
|
wc2GZUWziv+KwTZh50U5RHXQeAo84dAGTGk/kdDzd2VYa6+WVdKAJluw6dNoAF+l
|
||||||
|
jlf77EGeLqvJoRsqMdcwi3tKTt5jAr9nUGRCaNSvmz4GyR1cUdTgTTplOJh5mLnm
|
||||||
|
GGZQPVR87pex00QCTtQ7dggG/vg8QM+XbBeSAkWByeUDsrCo4pKbsY+kxKGCkhV0
|
||||||
|
3hxgHz2v7QZ8kanbgVPZzB76tOxRf9ghUQ5TFPc9kjgtQmn5ViqzMTXdotFXlE/u
|
||||||
|
n82BreEK03E9kWE3Uvt9jf21oJkQGQsRqTNYd8uIAQKBgQDyNOIIOnOgwt3coiZk
|
||||||
|
LYmo+F/zQQm6R8gebYWO1XCKLkMto9JaeJyEpehZQngMJvJc4r+4tWNFv8rcOHu5
|
||||||
|
/7SnteVUJK4RBXpKosLqswqD0ySEXzNLloumvxXz8HnXIiTSQ3rtISQSHzp0uunq
|
||||||
|
fkTzezc9ZRT08Jx6rmLvpKsJ3QKBgQDtklbus1fRQ/zbdddKbTfYMZsWSi7qQiA3
|
||||||
|
AKM7rY6wrS1gUJtVk9mhNgUe0uIvkkdQvtm/QKiSrtgGkre59g9sekZppCyWId6a
|
||||||
|
i1tlFvkG16Oc/TsAJDBNJgtWrkPDsjjHSx2VExTeRJ30XGd8lx3EEWHEbSboGPbf
|
||||||
|
G3gxm9a1nwKBgAdH06uPpj4k3WpubV0BiWvM24WCZPp2get4O1WJ0PI2ZcqPbBlQ
|
||||||
|
GtRZ8FwOhXFIEmz8W+r/eNZ153ErOXzj1NhdvWEEIT9dvMlVjypi62P/Cs/31KDn
|
||||||
|
C5edktlcVy1CV30CjkVmg6EP00ADBlkIJqZzA7wSt8iNGwcNCuhNON75AoGBAOGA
|
||||||
|
GXIj24RwM1Agr8UenHZix6HFsnh7YdazjT11RU7gYoTcnkUBvP5vpzaV10puX7D+
|
||||||
|
JvOJrTjmK3k5xJkIPaWq/rEBu6yZ45DwHEV9I81h3BSErX852nswVGznprzXq1tI
|
||||||
|
KoE5BoLfwMqU90nkqsVT9mgbb2W5ZINrsI/uK0RjAoGBAL+9L8iJx6/M4yQosTrQ
|
||||||
|
IL6SOxPU3HlfkqZzObiQ8vs7VdIpGhB1EMc9UEKe8RcnpTUeLsVeNHdiDZzRHtJ3
|
||||||
|
RxZS/AsjJtYAZ2f/maJhgQsh6JN1AceDhMhx1iTsjr/ockyUZuXKiCr5Q43tzrMJ
|
||||||
|
tMrOrkquEUSn+XDIomat7Bnw
|
||||||
|
-----END PRIVATE KEY-----
|
|
@ -64,9 +64,11 @@ type RedisConfig struct {
|
||||||
// 微信支付客户端配置
|
// 微信支付客户端配置
|
||||||
type WxpayClientConfig struct {
|
type WxpayClientConfig struct {
|
||||||
MchId string `json:"mchid" yaml:"mchid"` // 商户id
|
MchId string `json:"mchid" yaml:"mchid"` // 商户id
|
||||||
|
AppId string `json:"appid" yaml:"appid"` // appid
|
||||||
SerialNo string `json:"serial_no" yaml:"serial_no"` // 商户API证书的证书序列号
|
SerialNo string `json:"serial_no" yaml:"serial_no"` // 商户API证书的证书序列号
|
||||||
ApiV3Key string `json:"apiv3_key" yaml:"apiv3_key"` // APIv3Key,商户平台获取
|
ApiV3Key string `json:"apiv3_key" yaml:"apiv3_key"` // APIv3Key,商户平台获取
|
||||||
PrivateKey string `json:"private_key" yaml:"private_key"` // 商户API证书下载后,私钥 apiclient_key.pem 读取后的字符串内容
|
PrivateKeyPath string `json:"private_key_path" yaml:"private_key_path"` // 商户API证书下载后,私钥 apiclient_key.pem 读取后的字符串内容
|
||||||
|
NotifyUrl string `json:"notify_url" yaml:"notify_url"` // 回调地址
|
||||||
}
|
}
|
||||||
|
|
||||||
// 账号相关验密配置
|
// 账号相关验密配置
|
||||||
|
|
|
@ -1,24 +1,117 @@
|
||||||
package wxpaycli
|
package wxpaycli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-pay/gopay"
|
||||||
wxpay "github.com/go-pay/gopay/wechat/v3"
|
wxpay "github.com/go-pay/gopay/wechat/v3"
|
||||||
|
|
||||||
"service/bizcommon/util"
|
"service/bizcommon/util"
|
||||||
"service/library/configcenter"
|
"service/library/configcenter"
|
||||||
"service/library/logger"
|
"service/library/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DefaultOrderTimeoutSeconds = 900 // 默认订单超时时间,单位: s
|
||||||
|
)
|
||||||
|
|
||||||
|
var defaultWxpayClient *WxpayClient
|
||||||
|
|
||||||
type WxpayClient struct {
|
type WxpayClient struct {
|
||||||
*wxpay.ClientV3
|
*wxpay.ClientV3
|
||||||
|
AppId string `json:"app_id"`
|
||||||
|
NotifyUrl string `json:"notify_url"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWxpayClient(cfg *configcenter.WxpayClientConfig) (cli *WxpayClient, err error) {
|
func GetDefaultWxpayClient() *WxpayClient {
|
||||||
wxPayCli, err := wxpay.NewClientV3(cfg.MchId, cfg.SerialNo, cfg.ApiV3Key, cfg.PrivateKey)
|
return defaultWxpayClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func Init(cfg *configcenter.WxpayClientConfig) (err error) {
|
||||||
|
// private key
|
||||||
|
bs, err := os.ReadFile(cfg.PrivateKeyPath)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("real PrivateKeyPath fail, cfg: %v, err: %v", util.ToJson(cfg), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
privateKey := string(bs)
|
||||||
|
|
||||||
|
wxpayCli, err := wxpay.NewClientV3(cfg.MchId, cfg.SerialNo, cfg.ApiV3Key, privateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("NewClientV3 fail, cfg: %v, err: %v", util.ToJson(cfg), err)
|
logger.Error("NewClientV3 fail, cfg: %v, err: %v", util.ToJson(cfg), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cli = &WxpayClient{
|
|
||||||
wxPayCli,
|
defaultWxpayClient = &WxpayClient{
|
||||||
|
ClientV3: wxpayCli,
|
||||||
|
AppId: cfg.AppId,
|
||||||
|
NotifyUrl: cfg.NotifyUrl,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 验签
|
||||||
|
func (c *WxpayClient) ParseNotify(req *http.Request) (notify *wxpay.V3DecryptResult, err error) {
|
||||||
|
notifyReq, err := wxpay.V3ParseNotify(req)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("V3ParseNotify fail, notifyReq: %v, err: %v", util.ToJson(notifyReq), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if notifyReq == nil {
|
||||||
|
logger.Error("V3ParseNotify nil, err: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyTmp, err := notifyReq.DecryptCipherText(string(c.ApiV3Key))
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("DecryptCipherText fail, notifyTmp: %v, err: %v", util.ToJson(notifyTmp), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if notifyTmp == nil {
|
||||||
|
logger.Error("DecryptCipherText nil, err: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
logger.Info("Wxpay ParseNotify, %v", util.ToJson(notifyTmp))
|
||||||
|
|
||||||
|
notify = notifyTmp
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 微信支付 native支付
|
||||||
|
type NativePayParam struct {
|
||||||
|
Description string
|
||||||
|
OutTradeNo string // 商家订单id,我们自己的订单id
|
||||||
|
TotalAmount int64 // 金额,单位:分
|
||||||
|
TimeOutSeconds int // 订单有效时间,单位:秒
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *WxpayClient) NativePay(ctx context.Context, param *NativePayParam) (wxpayNativeParamStr string, err error) {
|
||||||
|
if param.TimeOutSeconds <= 0 {
|
||||||
|
param.TimeOutSeconds = DefaultOrderTimeoutSeconds
|
||||||
|
}
|
||||||
|
bm := gopay.BodyMap{
|
||||||
|
"appid": c.AppId,
|
||||||
|
"description": param.Description,
|
||||||
|
"out_trade_no": param.OutTradeNo,
|
||||||
|
"time_expire": time.Now().Add(time.Second * time.Duration(param.TimeOutSeconds)).Format(time.RFC3339),
|
||||||
|
"notify_url": c.NotifyUrl,
|
||||||
|
"amount": gopay.BodyMap{
|
||||||
|
"total": param.TotalAmount,
|
||||||
|
"currency": "CNY",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
resp, err := c.V3TransactionNative(ctx, bm)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if resp.Code != wxpay.Success {
|
||||||
|
logger.Info("wxpay NativePay fail, code: %v, error: %v, response: %v", resp.Code, resp.Error, util.ToJson(resp.Response))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
wxpayNativeParamStr = resp.Response.CodeUrl
|
||||||
|
logger.Info("wxpay NativePay success, code: %v, error: %v, response: %v", resp.Code, resp.Error, util.ToJson(resp.Response))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package wxpaycli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"service/app/mix/conf"
|
||||||
|
"service/library/configcenter"
|
||||||
|
"service/library/idgenerator"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
cfg := new(conf.ConfigSt)
|
||||||
|
err := configcenter.LoadConfig("/Users/erwin/wishpalv2/service/etc/mix/mix-test.yaml", cfg)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("%v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = Init(cfg.Wxpay)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
m.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWxpayClient_NativePay(t *testing.T) {
|
||||||
|
cli := GetDefaultWxpayClient()
|
||||||
|
resp, err := cli.NativePay(context.Background(), &NativePayParam{
|
||||||
|
Description: "测试哈哈",
|
||||||
|
OutTradeNo: idgenerator.GenOrderId(),
|
||||||
|
TotalAmount: 1,
|
||||||
|
TimeOutSeconds: 3600 * 24,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Log(fmt.Sprintf("%#v", resp))
|
||||||
|
return
|
||||||
|
}
|
Loading…
Reference in New Issue