// Package channel 把不同支付渠道(支付宝/微信…)收口到统一接口。 // 上层业务只面向 Channel,新增渠道 = 加一个实现 + 一行注册,主流程不动。 package channel import ( "context" "fmt" "net/http" "github.com/wangjia/pay/internal/model" ) // CreateReq 统一下单参数。 type CreateReq struct { OutTradeNo string Subject string Amount string // 元,两位小数 ReturnURL string NotifyURL string IsMobile bool // 客户端是否手机浏览器:支付宝据此走手机网站支付(wap.pay 拉起 App) 而非电脑网站支付(page.pay 扫码) } // NotifyResult 异步通知验签解析后的统一结果。 type NotifyResult struct { OutTradeNo string TradeNo string Amount string BuyerLogonID string Paid bool // 是否为支付成功状态 Raw string } // QueryResult 主动查单的统一结果。 type QueryResult struct { Found bool OutTradeNo string TradeNo string Amount string Paid bool } // Channel 支付渠道统一接口。 type Channel interface { Name() string // PagePay 统一下单,返回收银台跳转 URL。 PagePay(ctx context.Context, req CreateReq) (payURL string, err error) // PreCreate 扫码(当面付)预下单,返回二维码码串,由前端渲染成二维码供客户扫码付款。 PreCreate(ctx context.Context, req CreateReq) (qrCode string, err error) // VerifyNotify 验签并解析异步通知(内部完成 ParseForm 与签名校验)。 VerifyNotify(ctx context.Context, r *http.Request) (*NotifyResult, error) // Query 主动查单。 Query(ctx context.Context, outTradeNo string) (*QueryResult, error) } // Build 按商户配置构造渠道实例。 func Build(m *model.Merchant) (Channel, error) { switch m.Channel { case "alipay": return newAlipay(m) case "wechat": return newWechat(m) default: return nil, fmt.Errorf("未知支付渠道: %q", m.Channel) } }