170 lines
4.8 KiB
Go
170 lines
4.8 KiB
Go
package paymentService
|
||
|
||
import (
|
||
"PaymentCenter/app/third/paymentService/payCommon"
|
||
"context"
|
||
"errors"
|
||
"fmt"
|
||
"github.com/go-pay/gopay"
|
||
"github.com/go-pay/gopay/wechat/v3"
|
||
"sync"
|
||
"time"
|
||
)
|
||
|
||
var (
|
||
wxClient *wechat.ClientV3
|
||
clientErr error
|
||
once sync.Once
|
||
)
|
||
|
||
// InitClient 使用提供的支付请求参数初始化微信客户端
|
||
func InitClient(wxConfig WxPay) {
|
||
once.Do(func() {
|
||
// NewClientV3 初始化微信客户端 v3
|
||
// mchid:商户ID 或者服务商模式的 sp_mchid
|
||
// serialNo:商户证书的证书序列号
|
||
// apiV3Key:apiV3Key,商户平台获取
|
||
// privateKey:私钥 apiclient_key.pem 读取后的内容
|
||
wxClient, clientErr = wechat.NewClientV3(
|
||
wxConfig.MchId,
|
||
wxConfig.SerialNo,
|
||
wxConfig.ApiV3Key,
|
||
wxConfig.PrivateKey,
|
||
)
|
||
})
|
||
// 启用自动同步返回验签,并定时更新微信平台API证书(开启自动验签时,无需单独设置微信平台API证书和序列号)
|
||
clientErr = wxClient.AutoVerifySign()
|
||
|
||
// 自定义配置http请求接收返回结果body大小,默认 10MB
|
||
wxClient.SetBodySize(10) // 没有特殊需求,可忽略此配置
|
||
|
||
// 打开Debug开关,输出日志,默认是关闭的
|
||
wxClient.DebugSwitch = gopay.DebugOn
|
||
}
|
||
|
||
// GetClient 获取已经初始化的微信客户端
|
||
func GetClient() (*wechat.ClientV3, error) {
|
||
if wxClient == nil {
|
||
return nil, errors.New("client not initialized")
|
||
}
|
||
if clientErr != nil {
|
||
return nil, clientErr
|
||
}
|
||
return wxClient, nil
|
||
}
|
||
|
||
// WxH5PayInfo 微信H5支付
|
||
func WxH5PayInfo(c context.Context, payOrderRequest PayOrderRequest) (string, error) {
|
||
// 初始化微信客户端
|
||
InitClient(payOrderRequest.Wx)
|
||
|
||
// 获取微信客户端
|
||
wxClient, err := GetClient()
|
||
if err != nil {
|
||
fmt.Println("Failed to get client:", err)
|
||
return "", err
|
||
}
|
||
expire := time.Now().Add(10 * time.Minute).Format(time.RFC3339)
|
||
// 初始化 BodyMap
|
||
bm := make(gopay.BodyMap)
|
||
bm.Set("appid", payOrderRequest.Wx.AppId).
|
||
Set("mchid", payOrderRequest.Wx.MchId).
|
||
Set("description", payOrderRequest.Description).
|
||
Set("out_trade_no", payOrderRequest.OrderId).
|
||
Set("time_expire", expire).
|
||
Set("notify_url", payCommon.WX_NOTIFY_URL).
|
||
SetBodyMap("amount", func(bm gopay.BodyMap) {
|
||
bm.Set("total", payOrderRequest.Amount).
|
||
Set("currency", "CNY")
|
||
}).
|
||
SetBodyMap("scene_info", func(bm gopay.BodyMap) {
|
||
bm.Set("payer_client_ip", payOrderRequest.PayerClientIp).
|
||
SetBodyMap("h5_info", func(bm gopay.BodyMap) {
|
||
bm.Set("type", "common")
|
||
})
|
||
})
|
||
|
||
wxRsp, err := wxClient.V3TransactionH5(c, bm)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
if wxRsp.Code != wechat.Success || wxRsp.Response.H5Url == "" {
|
||
return "", errors.New(fmt.Sprintf("发起支付失败,失败状态码:%d, 失败原因:%s", wxRsp.Code, wxRsp.Error))
|
||
}
|
||
return wxRsp.Response.H5Url, nil
|
||
}
|
||
|
||
//func WxPayCallBack(notifyReq *wechat.V3NotifyReq) error {
|
||
// // 获取附加数据中的信息
|
||
// appId := notifyReq.Resource.AssociatedData
|
||
//
|
||
// payOrderRequest := PayOrderRequest{}
|
||
// // 初始化微信客户端
|
||
// InitClient(payOrderRequest)
|
||
//
|
||
// // 获取微信客户端
|
||
// wxClient, err := GetClient()
|
||
// if err != nil {
|
||
// fmt.Println("Failed to get client:", err)
|
||
// return err
|
||
// }
|
||
//
|
||
// // 获取微信平台证书
|
||
// certMap := wxClient.WxPublicKeyMap()
|
||
// // 验证异步通知的签名
|
||
// err = notifyReq.VerifySignByPKMap(certMap)
|
||
// if err != nil {
|
||
// return err
|
||
// }
|
||
// objPtr := ""
|
||
// // 通用通知解密(推荐此方法)
|
||
// result := notifyReq.DecryptCipherTextToStruct(apiV3Key, objPtr)
|
||
//}
|
||
|
||
// WxOrderQuery 查询微信订单
|
||
func WxOrderQuery(ctx context.Context, wxConfig WxPay, orderNo string) (PayOrderQueryInfo, error) {
|
||
// 初始化微信客户端
|
||
InitClient(wxConfig)
|
||
|
||
// 获取微信客户端
|
||
wxClient, err := GetClient()
|
||
if err != nil {
|
||
fmt.Println("Failed to get client:", err)
|
||
return PayOrderQueryInfo{}, err
|
||
}
|
||
|
||
wxRsp, err := wxClient.V3TransactionQueryOrder(ctx, payCommon.ORDER_NO_TYPE_ORDER_NO, orderNo)
|
||
if err != nil {
|
||
return PayOrderQueryInfo{}, err
|
||
}
|
||
if wxRsp.Code != wechat.Success {
|
||
return PayOrderQueryInfo{}, errors.New(fmt.Sprintf("查询订单接口错误,错误状态码:%d, 错误信息:%s", wxRsp.Code, wxRsp.Error))
|
||
}
|
||
|
||
// 映射交易状态
|
||
tradeState := ""
|
||
switch wxRsp.Response.TradeState {
|
||
case "SUCCESS":
|
||
tradeState = "SUCCESS"
|
||
case "REFUND":
|
||
tradeState = "REFUND"
|
||
case "NOTPAY":
|
||
tradeState = "NOTPAY"
|
||
case "CLOSED":
|
||
tradeState = "CLOSED"
|
||
}
|
||
amountTotal := wxRsp.Response.Amount.Total
|
||
payerTotal := wxRsp.Response.Amount.PayerTotal
|
||
|
||
return PayOrderQueryInfo{
|
||
AppId: wxRsp.Response.Appid,
|
||
OutTradeNo: wxRsp.Response.OutTradeNo,
|
||
TransactionId: wxRsp.Response.TransactionId,
|
||
TradeState: tradeState,
|
||
TradeStateDesc: wxRsp.Response.TradeStateDesc,
|
||
SuccessTime: wxRsp.Response.SuccessTime,
|
||
AmountTotal: int64(amountTotal),
|
||
PayerTotal: int64(payerTotal),
|
||
}, nil
|
||
}
|