Files
full/module/finance/wallet/internal/logic/wechat/wechat.go

197 lines
5.2 KiB
Go
Raw Normal View History

package wechat
import (
"context"
"encoding/json"
"os"
"time"
"bsm/full/module/finance/wallet/internal/config"
"bsm/full/module/finance/wallet/internal/excode"
"github.com/go-pay/gopay"
"github.com/go-pay/gopay/wechat/v3"
)
type WeChatPay struct {
ctx context.Context
Client *wechat.ClientV3
Body *gopay.BodyMap
}
var (
mchID string
SerialNumber string
mchAPIv3Key string
ApiClientKey string
AppId string
Currency string
NotifyUrl string
)
func new() {
mchID = config.Spec.WeChat.MchID // 商户号
SerialNumber = config.Spec.WeChat.SerialNo // 商户证书序列号
mchAPIv3Key = config.Spec.WeChat.APIV3Key // 商户APIv3密钥
ApiClientKey = config.Spec.WeChat.PrivateKey // 私钥
AppId = config.Spec.WeChat.AppID // Appid
Currency = config.Spec.WeChat.Currency // 货币类型 CNY人民币境内商户号仅支持人民币。
NotifyUrl = config.Spec.WeChat.NotifyURL // 通知URL必须为直接可访问的URL不允许携带查询串要求必须为https地址。
}
func NewWechat() (*WeChatPay, error) {
new()
// NewClientV3 初始化微信客户端 v3
// mchid商户ID 或者服务商模式的 sp_mchid
// serialNo商户证书的证书序列号
// apiV3KeyapiV3Key商户平台获取
// privateKey私钥 apiclient_key.pem 读取后的内容
privateKey, err := os.ReadFile(ApiClientKey)
if err != nil {
return nil, err
}
client, err := wechat.NewClientV3(mchID, SerialNumber, mchAPIv3Key, string(privateKey))
if err != nil {
return nil, err
}
// 设置微信平台API证书和序列号如开启自动验签请忽略此步骤
//client.SetPlatformCert([]byte(""), "")
// 启用自动同步返回验签并定时更新微信平台API证书开启自动验签时无需单独设置微信平台API证书和序列号
err = client.AutoVerifySign()
if err != nil {
return nil, err
}
// 打开Debug开关输出日志默认是关闭的
client.DebugSwitch = gopay.DebugOn
return &WeChatPay{
ctx: context.Background(),
Client: client,
}, nil
}
// GetResponse tradeNo:finance_payment表的identity
func (srv *WeChatPay) GetResponse(Attach, OrderNo, desc, openid string, amount int64) (*wechat.Prepay, error) {
expire := time.Now().Add(60 * time.Minute).Format(time.RFC3339)
// 初始化 BodyMap
bm := make(gopay.BodyMap)
bm.Set("appid", AppId).
Set("mchid", mchID).
Set("description", desc).
Set("attach", Attach). //finance_payment表的identity 附加数据在查询API和支付通知中原样返回可作为自定义参数使用实际情况下只有支付完成状态才会返回该字段
Set("out_trade_no", OrderNo).
Set("time_expire", expire).
Set("notify_url", NotifyUrl).
SetBodyMap("amount", func(bm gopay.BodyMap) {
bm.Set("total", amount).
Set("currency", Currency)
}).
SetBodyMap("payer", func(bm gopay.BodyMap) {
bm.Set("openid", openid)
})
wxRsp, err := srv.Client.V3TransactionJsapi(srv.ctx, bm)
if err != nil {
return nil, err
}
return wxRsp.Response, nil
}
func (srv *WeChatPay) MiniPaySign(prepayid string) (map[string]string, error) {
applet, err := srv.Client.PaySignOfApplet(AppId, prepayid)
if err != nil {
return nil, err
}
reply, err := struct2map(applet)
if err != nil {
return nil, err
}
return reply, nil
}
func (srv *WeChatPay) AppPaySign(prepayid string) (map[string]string, error) {
app, err := srv.Client.PaySignOfApp(AppId, prepayid)
if err != nil {
return nil, err
}
reply, err := struct2map(app)
if err != nil {
return nil, err
}
return reply, nil
}
func (srv *WeChatPay) JsapiPaySign(prepayid string) (map[string]string, error) {
jsapi, err := srv.Client.PaySignOfJSAPI(AppId, prepayid)
if err != nil {
return nil, err
}
reply, err := struct2map(jsapi)
if err != nil {
return nil, err
}
return reply, nil
}
func (srv *WeChatPay) NativePaySign(Attach, OrderNo, description, expire, openid string, amount int64) (map[string]string, error) {
// 初始化 BodyMap
body := make(gopay.BodyMap)
body.Set("appid", AppId).
Set("mchid", mchID).
Set("description", description).
Set("attach", Attach). //finance_payment表的identity 附加数据在查询API和支付通知中原样返回可作为自定义参数使用实际情况下只有支付完成状态才会返回该字段
Set("out_trade_no", OrderNo).
Set("time_expire", expire).
Set("notify_url", NotifyUrl).
SetBodyMap("amount", func(bm gopay.BodyMap) {
bm.Set("total", amount).
Set("currency", Currency)
}).
SetBodyMap("payer", func(bm gopay.BodyMap) {
bm.Set("openid", openid)
})
native, err := srv.Client.V3TransactionNative(srv.ctx, body)
if err != nil {
return nil, err
}
reply, err := struct2map(native)
if err != nil {
return nil, err
}
return reply, nil
}
func struct2map(in any) (map[string]string, error) {
b, err := json.Marshal(in)
var m map[string]string
err = json.Unmarshal(b, &m)
return m, err
}
func CheckParam(amount int64, auth_code string, identity string, order_no string) (err error) {
if amount == 0 {
return excode.ErrAmount
}
if auth_code == "" {
return excode.ErrAuthCode
}
if identity == "" {
return excode.ErrPassportId
}
if order_no == "" {
return excode.ErrOrderNo
}
return nil
}