light-core/pkg/myPay/wechat.go
2024-12-17 22:28:48 +08:00

262 lines
7.1 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 myPay
import (
"context"
"errors"
"github.com/go-pay/gopay"
"github.com/go-pay/gopay/wechat/v3"
"net/http"
"time"
)
type Wechat struct {
ctx context.Context
cli *wechat.ClientV3
params *WechatPayV3Impl
orderNo string
amount int
description string
notifyUrl string
profitSharing bool
}
func NewWechat(params *WechatPayV3Impl) *Wechat {
// NewClientV3 初始化微信客户端 v3
// mchid商户ID 或者服务商模式的 sp_mchid
// serialNo商户证书的证书序列号
// apiV3KeyapiV3Key商户平台获取
// privateKey私钥 apiclient_key.pem 读取后的内容
client, err := wechat.NewClientV3(params.MchId, params.SerialNo, params.ApiV3Key, params.PKContent)
if err != nil {
panic(err.Error())
}
// 设置微信平台API证书和序列号推荐开启自动验签无需手动设置证书公钥等信息
//client.SetPlatformCert([]byte(""), "")
// 启用自动同步返回验签并定时更新微信平台API证书开启自动验签时无需单独设置微信平台API证书和序列号
client.SetPlatformCert([]byte(params.WxPkContent), params.WxPkSerialNo)
// 启用自动同步返回验签并定时更新微信平台API证书
//err = client.AutoVerifySign()
//if err != nil {
// return nil, err
//}
// 打开Debug开关输出日志默认是关闭的
if params.IsProd {
client.DebugSwitch = gopay.DebugOff
} else {
client.DebugSwitch = gopay.DebugOn
}
return &Wechat{params: params, cli: client, ctx: context.Background()}
}
func (t *Wechat) GetCli() *wechat.ClientV3 {
return t.cli
}
func (t *Wechat) SetCommonConfig(notifyUrl string) *Wechat {
t.notifyUrl = notifyUrl
return t
}
func (t *Wechat) SetOrderInfo(orderNo string, amount int, description string) *Wechat {
t.orderNo = orderNo
t.amount = amount
t.description = description
return t
}
func (t *Wechat) setBodyMap() gopay.BodyMap {
if t.description == "" || t.orderNo == "" || t.notifyUrl == "" {
panic("param is empty")
}
if t.amount == 0 {
panic("amount is zero")
}
bm := make(gopay.BodyMap)
bm.Set("description", t.description).
Set("out_trade_no", t.orderNo).
Set("time_expire", time.Now().Add(10*time.Minute).Format(time.RFC3339)).
Set("notify_url", t.notifyUrl).
SetBodyMap("amount", func(bm gopay.BodyMap) {
bm.Set("total", t.amount).Set("currency", "CNY")
})
if t.profitSharing {
bm.SetBodyMap("settle_info", func(bm gopay.BodyMap) {
bm.Set("profit_sharing", true)
})
}
return bm
}
func (t *Wechat) SetProfitSharing(b bool) *Wechat {
t.profitSharing = b
return t
}
func (t *Wechat) GetApp() (*wechat.AppPayParams, error) {
wxRsp, err := t.cli.V3TransactionApp(t.ctx, t.setBodyMap().Set("appid", t.params.AppAppid))
if err != nil {
return nil, err
}
if wxRsp.Code == wechat.Success {
//校验签名
if err2 := wechat.V3VerifySignByPK(wxRsp.SignInfo.HeaderTimestamp, wxRsp.SignInfo.HeaderNonce, wxRsp.SignInfo.SignBody, wxRsp.SignInfo.HeaderSignature, t.cli.WxPublicKey()); err != nil {
return nil, err2
}
//获取调起参数
return t.cli.PaySignOfApp(t.params.AppAppid, wxRsp.Response.PrepayId)
} else {
return nil, errors.New(wxRsp.Error)
}
}
func (t *Wechat) GetJsapi(openId string) (*wechat.JSAPIPayParams, error) {
wxRsp, err := t.cli.V3TransactionJsapi(t.ctx,
t.setBodyMap().Set("appid", t.params.MpAppid).SetBodyMap("payer", func(bm gopay.BodyMap) {
bm.Set("openid", openId)
}),
)
if err != nil {
return nil, err
}
if wxRsp.Code == wechat.Success {
//校验签名
if err2 := wechat.V3VerifySignByPK(wxRsp.SignInfo.HeaderTimestamp, wxRsp.SignInfo.HeaderNonce, wxRsp.SignInfo.SignBody, wxRsp.SignInfo.HeaderSignature, t.cli.WxPublicKey()); err != nil {
return nil, err2
}
//获取调起参数
return t.cli.PaySignOfJSAPI(t.params.MpAppid, wxRsp.Response.PrepayId)
} else {
return nil, errors.New(wxRsp.Error)
}
}
func (t *Wechat) GetJsapiForMini(openId string) (*wechat.JSAPIPayParams, error) {
wxRsp, err := t.cli.V3TransactionJsapi(t.ctx,
t.setBodyMap().Set("appid", t.params.MiniAppid).SetBodyMap("payer", func(bm gopay.BodyMap) {
bm.Set("openid", openId)
}),
)
if err != nil {
return nil, err
}
if wxRsp.Code == wechat.Success {
//校验签名
if err2 := wechat.V3VerifySignByPK(wxRsp.SignInfo.HeaderTimestamp, wxRsp.SignInfo.HeaderNonce, wxRsp.SignInfo.SignBody, wxRsp.SignInfo.HeaderSignature, t.cli.WxPublicKey()); err != nil {
return nil, err2
}
//获取调起参数
return t.cli.PaySignOfJSAPI(t.params.MiniAppid, wxRsp.Response.PrepayId)
} else {
return nil, errors.New(wxRsp.Error)
}
}
func (t *Wechat) GetNative() (*wechat.Native, error) {
wxRsp, err := t.cli.V3TransactionNative(t.ctx, t.setBodyMap().Set("appid", t.params.MpAppid))
if err != nil {
return nil, err
}
if wxRsp.Code == wechat.Success {
//校验签名
if err2 := wechat.V3VerifySignByPK(wxRsp.SignInfo.HeaderTimestamp, wxRsp.SignInfo.HeaderNonce, wxRsp.SignInfo.SignBody, wxRsp.SignInfo.HeaderSignature, t.cli.WxPublicKey()); err != nil {
return nil, err2
}
//获取调起参数
return wxRsp.Response, err
} else {
return nil, errors.New(wxRsp.Error)
}
}
func (t *Wechat) GetH5(ip string, appName string, appUrl string) (*wechat.H5Url, error) {
wxRsp, err := t.cli.V3TransactionH5(t.ctx, t.setBodyMap().Set("appid", t.params.MpAppid).SetBodyMap("scene_info", func(bm gopay.BodyMap) {
bm.Set("payer_client_ip", ip)
bm.SetBodyMap("h5_info", func(bm gopay.BodyMap) {
bm.Set("type", "Wap")
bm.Set("app_url", appUrl)
bm.Set("app_name", appName)
})
}))
if err != nil {
return nil, err
}
if wxRsp.Code == wechat.Success {
//校验签名
if err2 := wechat.V3VerifySignByPK(wxRsp.SignInfo.HeaderTimestamp, wxRsp.SignInfo.HeaderNonce, wxRsp.SignInfo.SignBody, wxRsp.SignInfo.HeaderSignature, t.cli.WxPublicKey()); err != nil {
return nil, err2
}
//获取调起参数
return wxRsp.Response, nil
} else {
return nil, errors.New(wxRsp.Error)
}
}
func (t *Wechat) Notify(req *http.Request) (*WechatNotifyResp, error) {
notifyReq, err := wechat.V3ParseNotify(req)
if err != nil {
return nil, errors.New("解析回调失败")
}
err = notifyReq.VerifySignByPK(t.cli.WxPublicKey())
if err != nil {
return nil, errors.New("sign Error")
}
if notifyReq.EventType == "TRANSACTION.SUCCESS" {
result, err := notifyReq.DecryptPayCipherText(t.params.ApiV3Key)
if err != nil {
return nil, errors.New("解密错误")
} else {
return &WechatNotifyResp{resp: result}, nil
}
}
return nil, errors.New(notifyReq.EventType)
}
func (t *Wechat) GetOrderNo() string {
return t.orderNo
}
func (t *Wechat) GetAmount() int {
return t.amount
}
func NotifySuccess(msg string) (int, *wechat.V3NotifyRsp) {
return http.StatusOK, &wechat.V3NotifyRsp{Code: gopay.SUCCESS, Message: msg}
}
func NotifyFail(msg string) (int, *wechat.V3NotifyRsp) {
return http.StatusBadRequest, &wechat.V3NotifyRsp{Code: gopay.FAIL, Message: msg}
}
type WechatPayV3Impl struct {
MpAppid string
AppAppid string
MiniAppid string
MchId string
ApiV3Key string
SerialNo string
PKContent string
WxPkSerialNo string
WxPkContent string
IsProd bool
}