136 lines
3.4 KiB
Go
136 lines
3.4 KiB
Go
package wepay
|
||
|
||
import (
|
||
"context"
|
||
"errors"
|
||
"time"
|
||
|
||
w "quyun/providers/wechat"
|
||
|
||
"github.com/go-pay/gopay"
|
||
"github.com/go-pay/gopay/wechat/v3"
|
||
"go.ipao.vip/atom/container"
|
||
"go.ipao.vip/atom/opt"
|
||
)
|
||
|
||
func Provide(opts ...opt.Option) error {
|
||
o := opt.New(opts...)
|
||
var config Config
|
||
if err := o.UnmarshalConfig(&config); err != nil {
|
||
return err
|
||
}
|
||
return container.Container.Provide(func(wechatConfig *w.Config) (*Client, error) {
|
||
// NewClientV3 初始化微信客户端 v3
|
||
// mchid:商户ID 或者服务商模式的 sp_mchid
|
||
// serialNo:商户证书的证书序列号
|
||
// apiV3Key:apiV3Key,商户平台获取
|
||
// privateKey:私钥 apiclient_key.pem 读取后的内容
|
||
// 1、你最多可同时使用3个有效证书,为减少风险,建议及时作废不使用的API证书;
|
||
// 2、API证书包括:私钥文件及公钥证书(配对使用),仅保存在申请证书的电脑本地,无法从系统下载;
|
||
// 3、私钥文件名为“prikey_序列号”,公钥证书名为“pubkey_序列号”,序列号请查看上述列表。若无法找到证书文件,可申请新证书。
|
||
client, err := wechat.NewClientV3(
|
||
w.Pay.MchID, w.Pay.SerialNo, w.Pay.ApiV3Key, w.Pay.PrivateKey,
|
||
wechatConfig.MchId, wechatConfig.SerialNo, wechatConfig.APIv3Key, wechatConfig.PrivateKey
|
||
)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
client.DebugSwitch = gopay.DebugOff
|
||
if config.Debug {
|
||
client.DebugSwitch = gopay.DebugOn
|
||
}
|
||
|
||
return &Client{
|
||
payClient: client,
|
||
config: &config,
|
||
}, nil
|
||
}, o.DiOptions()...)
|
||
}
|
||
|
||
type Client struct {
|
||
payClient *wechat.ClientV3
|
||
config *Config
|
||
}
|
||
|
||
func (c *Client) GetClient() *wechat.ClientV3 {
|
||
return c.payClient
|
||
}
|
||
|
||
func (c *Client) V3TransactionJsapi(ctx context.Context, bm *BodyMap) (*wechat.PrepayRsp, error) {
|
||
resp, err := c.payClient.V3TransactionJsapi(ctx, bm.bm)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
if resp.Code != wechat.Success {
|
||
return nil, errors.New(resp.Error)
|
||
}
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
func (c *Client) BodyMap() *BodyMap { return NewBodyMap(c.config) }
|
||
|
||
type BodyMap struct {
|
||
bm gopay.BodyMap
|
||
}
|
||
|
||
func NewBodyMap(c *Config) *BodyMap {
|
||
bm := make(gopay.BodyMap)
|
||
bm.Set("sp_appid", c.AppId).
|
||
Set("sp_mchid", c.MchId).
|
||
Set("notify_url", c.NotifyURL).
|
||
Set("amount", func(bm gopay.BodyMap) {
|
||
bm.Set("total", 1).
|
||
Set("currency", "CNY")
|
||
})
|
||
return &BodyMap{
|
||
bm: bm,
|
||
}
|
||
}
|
||
|
||
func (b *BodyMap) Set(key string, value interface{}) *BodyMap {
|
||
b.bm.Set(key, value)
|
||
return b
|
||
}
|
||
|
||
func (b *BodyMap) SetBodyMap(key string, f func(bm gopay.BodyMap)) *BodyMap {
|
||
b.bm.SetBodyMap(key, f)
|
||
return b
|
||
}
|
||
|
||
// Expire time
|
||
func (b *BodyMap) Expire(t time.Duration) *BodyMap {
|
||
return b.Set("time_expire", time.Now().Add(t).Format(time.RFC3339))
|
||
}
|
||
|
||
// Description
|
||
func (b *BodyMap) Description(desc string) *BodyMap {
|
||
return b.Set("description", desc)
|
||
}
|
||
|
||
// OutTradeNo
|
||
func (b *BodyMap) OutTradeNo(outTradeNo string) *BodyMap {
|
||
return b.Set("out_trade_no", outTradeNo)
|
||
}
|
||
|
||
// Amount
|
||
func (b *BodyMap) Amount(total int, currency string) *BodyMap {
|
||
return b.SetBodyMap("amount", func(bm gopay.BodyMap) {
|
||
bm.Set("total", total).Set("currency", currency)
|
||
})
|
||
}
|
||
|
||
// Payer
|
||
func (b *BodyMap) Payer(spOpenId string) *BodyMap {
|
||
return b.SetBodyMap("payer", func(bm gopay.BodyMap) {
|
||
bm.Set("sp_openid", spOpenId)
|
||
})
|
||
}
|
||
|
||
// SubMchId
|
||
func (b *BodyMap) SubMchId(subMchId string) *BodyMap {
|
||
return b.Set("sub_mchid", subMchId)
|
||
}
|