PaymentCenter/app/third/paymentService/wechat_service.go

170 lines
4.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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商户证书的证书序列号
// apiV3KeyapiV3Key商户平台获取
// 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
}