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
}