160 lines
3.3 KiB
Go
160 lines
3.3 KiB
Go
package wepay
|
|
|
|
import (
|
|
"context"
|
|
"crypto/rsa"
|
|
"encoding/json"
|
|
"errors"
|
|
"time"
|
|
|
|
w "quyun/providers/wechat"
|
|
|
|
"github.com/go-pay/gopay"
|
|
"github.com/go-pay/gopay/wechat/v3"
|
|
log "github.com/sirupsen/logrus"
|
|
"go.ipao.vip/atom/container"
|
|
"go.ipao.vip/atom/opt"
|
|
)
|
|
|
|
type Config struct{}
|
|
|
|
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) {
|
|
client, err := wechat.NewClientV3(
|
|
wechatConfig.Pay.MchID,
|
|
wechatConfig.Pay.SerialNo,
|
|
wechatConfig.Pay.ApiV3Key,
|
|
wechatConfig.Pay.PrivateKey,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
client.DebugSwitch = gopay.DebugOff
|
|
if wechatConfig.DevMode {
|
|
client.DebugSwitch = gopay.DebugOn
|
|
}
|
|
|
|
return &Client{
|
|
payClient: client,
|
|
config: wechatConfig,
|
|
}, nil
|
|
}, o.DiOptions()...)
|
|
}
|
|
|
|
type Client struct {
|
|
payClient *wechat.ClientV3
|
|
config *w.Config
|
|
}
|
|
|
|
func (c *Client) GetClient() *wechat.ClientV3 {
|
|
return c.payClient
|
|
}
|
|
|
|
// WxPublicKeyMap
|
|
func (c *Client) WxPublicKeyMap() map[string]*rsa.PublicKey {
|
|
return c.payClient.WxPublicKeyMap()
|
|
}
|
|
|
|
type PrepayData struct {
|
|
client *Client
|
|
|
|
AppID string `json:"app_id"`
|
|
PrepayID string `json:"prepay_id"`
|
|
}
|
|
|
|
// PaySignOfJSAPI
|
|
func (pay *PrepayData) PaySignOfJSAPI() (*wechat.JSAPIPayParams, error) {
|
|
return pay.client.payClient.PaySignOfJSAPI(pay.AppID, pay.PrepayID)
|
|
}
|
|
|
|
func (c *Client) V3TransactionJsapi(ctx context.Context, f func(*BodyMap)) (*PrepayData, error) {
|
|
bm := NewBodyMap(c.config)
|
|
f(bm)
|
|
|
|
resp, err := c.payClient.V3TransactionJsapi(ctx, bm.bm)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if resp.Code != wechat.Success {
|
|
b, _ := json.Marshal(resp)
|
|
log.Errorf("WePay V3TransactionJsapi error: %s", b)
|
|
return nil, errors.New(resp.Error)
|
|
}
|
|
|
|
return &PrepayData{
|
|
client: c,
|
|
|
|
AppID: c.config.AppID,
|
|
PrepayID: resp.Response.PrepayId,
|
|
}, nil
|
|
}
|
|
|
|
type BodyMap struct {
|
|
bm gopay.BodyMap
|
|
}
|
|
|
|
func NewBodyMap(c *w.Config) *BodyMap {
|
|
bm := make(gopay.BodyMap)
|
|
bm.Set("appid", c.AppID).
|
|
Set("mchid", c.Pay.MchID).
|
|
Set("notify_url", c.Pay.NotifyURL).
|
|
SetBodyMap("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("openid", spOpenId)
|
|
})
|
|
}
|
|
|
|
// SubMchId
|
|
func (b *BodyMap) SubMchId(subMchId string) *BodyMap {
|
|
return b.Set("sub_mchid", subMchId)
|
|
}
|