You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

104 lines
2.8 KiB

package alipay
import (
"context"
"errors"
"net/url"
"sync"
)
type (
// 预支付响应参数(返回给Flutter客户端)
AppPayParams struct {
AppID string `json:"appid"` // 应用ID
PartnerID string `json:"partnerid"` // 商户号
PrepayID string `json:"prepayid"` // 预支付ID
Package string `json:"package"` // 固定值 "Sign=WXPay"
NonceStr string `json:"noncestr"` // 随机字符串
TimeStamp string `json:"timestamp"` // 时间戳(秒)
Sign string `json:"sign"` // 支付签名
}
ISys interface {
GenerateOrderNo(prefix string) string
CreateAppOrder(ctx context.Context, outTradeNo string, totalFee int64, description string, notifyurl string) (result string, err error)
DecryptWxPayNotify(values url.Values) (bool, error)
}
)
// defsys 由 OnInit(启动) 与 Reload(运行时热更) 写、各包级函数读,故必须加锁:
// 无锁并发读写接口值是 data race。
var (
mu sync.RWMutex
defsys ISys
)
// ErrNotInited 支付宝未初始化。OnInit 失败时调用方可选择降级;此时包级函数返回本错误,而不是 panic。
var ErrNotInited = errors.New("alipay 未初始化:配置缺失或密钥加载失败")
func get() ISys {
mu.RLock()
defer mu.RUnlock()
return defsys
}
func set(sys ISys) {
mu.Lock()
defsys = sys
mu.Unlock()
}
func OnInit(config map[string]interface{}, option ...Option) error {
sys, err := newSys(newOptions(config, option...))
if err != nil {
// 出错时不要给 defsys 赋值:newSys 出错时 sys 仍是非 nil 的 *Alipay(client 可能为 nil),
// 装进接口后 defsys != nil,守卫失效、调用时在 client 上 nil 解引用。
return err
}
set(sys)
return nil
}
// Reload 运行时热替换支付宝客户端(console 后台改配置后由业务侧调用)。
// 配置不合法时返回 error 且**保留原客户端不动**;启动时未初始化的场景下,
// 后台首次配好凭据即经此启用,无需重启。
func Reload(config map[string]interface{}, option ...Option) error {
sys, err := newSys(newOptions(config, option...))
if err != nil {
return err
}
set(sys)
return nil
}
func NewSys(option ...Option) (ISys, error) {
sys, err := newSys(newOptionsByOption(option...))
if err != nil {
return nil, err
}
return sys, nil
}
func GenerateOrderNo(prefix string) string {
sys := get()
if sys == nil {
return ""
}
return sys.GenerateOrderNo(prefix)
}
func CreateAppOrder(ctx context.Context, outTradeNo string, totalFee int64, description string, notifyurl string) (result string, err error) {
sys := get()
if sys == nil {
return "", ErrNotInited
}
return sys.CreateAppOrder(ctx, outTradeNo, totalFee, description, notifyurl)
}
func DecryptWxPayNotify(values url.Values) (bool, error) {
sys := get()
if sys == nil {
return false, ErrNotInited
}
return sys.DecryptWxPayNotify(values)
}