| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- // Package channel 抽象在线支付渠道(ADR-0001)。
- // 到账确认以主动查单为主(ADR-0002):每个渠道必须实现 QueryOrder,
- // 回调仅作为可选加速器的挂点。
- package channel
- import (
- "context"
- "errors"
- "sync"
- "go.uber.org/zap"
- "wails-app/internal/global"
- )
- // 渠道代码。渠道代码同时是出口自助支付的支付方式代码(wechat/alipay),
- // mock 仅用于联调,结算时归入 wechat 方式。
- const (
- ChannelWechat = "wechat"
- ChannelAlipay = "alipay"
- ChannelMock = "mock"
- )
- type CreateOrderRequest struct {
- OrderNo string // 商户订单号(exit_order.order_no)
- Amount float64 // 金额(元)
- Currency string // CNY 等
- Description string // 订单标题,如 "停车费-粤A12345"
- }
- type CreateOrderResult struct {
- CodeURL string // 二维码内容,出口屏渲染为订单二维码
- }
- type QueryStatus string
- const (
- QueryPaid QueryStatus = "paid"
- QueryPending QueryStatus = "pending"
- QueryClosed QueryStatus = "closed" // 已关闭/过期,订单应转 expired
- )
- type QueryOrderResult struct {
- Status QueryStatus
- TransactionID string // 渠道流水号
- }
- // PaymentChannel 在线支付渠道接口。查单是一等能力。
- type PaymentChannel interface {
- Code() string
- CreateOrder(ctx context.Context, req CreateOrderRequest) (CreateOrderResult, error)
- QueryOrder(ctx context.Context, orderNo string) (QueryOrderResult, error)
- }
- var (
- mu sync.RWMutex
- registry = map[string]PaymentChannel{}
- )
- // Register 注册渠道实现,重复注册覆盖(便于测试)。
- func Register(ch PaymentChannel) {
- mu.Lock()
- defer mu.Unlock()
- registry[ch.Code()] = ch
- }
- // Get 按代码取渠道;未注册返回错误。
- func Get(code string) (PaymentChannel, error) {
- mu.RLock()
- defer mu.RUnlock()
- ch, ok := registry[code]
- if !ok {
- return nil, errors.New("支付渠道未注册: " + code)
- }
- return ch, nil
- }
- // DefaultChannel 出口自助支付使用的默认渠道:
- // 微信凭据齐全时用 wechat,否则回落 mock(联调)。可用 exit-kiosk.channel 显式覆盖。
- func DefaultChannel() string {
- cfg := global.GVA_CONFIG.ExitKiosk.Channel
- if cfg != "" {
- return cfg
- }
- if global.GVA_CONFIG.WechatPay.Enabled {
- return ChannelWechat
- }
- return ChannelMock
- }
- // SetupChannels 注册内置渠道实现,在路由初始化前调用一次。
- func SetupChannels() {
- Register(NewMockChannel())
- if wc, err := NewWechatChannelFromConfig(global.GVA_CONFIG.WechatPay); err == nil {
- Register(wc)
- } else if global.GVA_LOG != nil {
- global.GVA_LOG.Warn("微信支付渠道未启用", zap.Error(err))
- }
- }
|