支付三渠归一:策略模式在收银系统中的实战
支付三渠归一:策略模式在收银系统中的实战
老张最怕听到的一句话:“老板,钱到哪了?”
以前用别的收银系统,顾客扫了码,钱先进了系统公司的账户,T+3才到老张的卡。
老张问:“我的钱,为什么先到你们那?”
01 钱不过我们的手
龙讯POS最核心的设计原则——“非金融中转方”:
顾客 ──微信支付──→ 商户微信支付账户(mch_id)
↑
龙讯POS仅调用官方API
(不碰钱、不碰资金流、不做资金归集)
顾客扫码付的钱,直接进了商户在微信/支付宝的商户账户。龙讯POS不经手、不持有、不转移任何资金。
02 三种支付方式,一个界面
现金收银
快捷金额(¥10/¥20/¥50/¥100/刚好)+ 累加按钮(+5/+10/+20/+50/+100),不需要键盘,不需要计算器。
扫码支付
选择渠道→扫付款码→3秒到账→语音播报。系统自动识别渠道:18位数字前缀1015是微信,2530是支付宝,62开头是银联。
混合支付
勾选"混合支付",四个渠道同时显示,分别输入金额,各行之和必须等于订单总额。
03 技术实现:策略模式 + 注册表模式
PaymentSDK 接口
type PaymentSDK interface {
Pay(authCode string, amount decimal.Decimal, outTradeNo string) (*PayResult, error)
Query(outTradeNo string, transactionID string) (*QueryResult, error)
Refund(outTradeNo string, transactionID string, totalAmount decimal.Decimal, refundAmount decimal.Decimal) (*RefundResult, error)
Cancel(outTradeNo string, transactionID string) (*CancelResult, error)
VerifyNotify(params map[string]string) (*NotifyResult, error)
GenerateOutTradeNo() string
IsMockMode() bool
}
7个方法覆盖被扫支付全生命周期。三个渠道各自实现这个接口,调用方只需要知道渠道名。
Manager 注册表
type Manager struct {
mu sync.RWMutex
wechat PaymentSDK
alipay PaymentSDK
unionpay PaymentSDK
mockMode bool
}
通过 sync.RWMutex 保护并发读取。新增渠道只需实现 PaymentSDK 接口并注册到 Manager。
04 扫码支付核心流程
LockOrder加锁,防止并发操作- 校验订单状态(必须为pending)
- 自动识别渠道或使用指定渠道
- 预创建payment记录(status=pending)
- 调用SDK.Pay()执行扣款
- 成功 → 3次事务重试更新payment+order
- 事务3次均失败 → 自动调用SDK.Cancel()撤销
- 撤销也失败 → 标记"需人工处理"
事务重试:指数退避
200ms → 400ms → 600ms,3次重试。全部失败则自动撤销支付,防止"钱扣了但订单没更新"。
05 混合支付:分步执行 + 自动回滚
逐渠道执行支付,任一渠道失败则回滚已完成的渠道:
- 现金渠道:无法自动回滚,标记
rollback_pending - 电子渠道:先尝试Cancel(撤销),失败则Refund(退款)
- 退款也失败:标记
rollback_pending(需人工介入)
06 支付回调:双检锁 + 金额校验
- 签名验证(伪造回调直接拒绝)
- 加锁 + 双检锁(已处理的记录做幂等处理)
- 金额校验(回调金额必须与记录金额一致)
- 支付宝额外二次主动查询确认
- 更新payment+order(3次事务重试)
07 没有公网IP?主动轮询
客户端每5秒查询一次支付状态,最多12次(共60秒)。不需要回调URL,不需要公网IP。
08 模拟模式
PAYMENT_MOCK_MODE=true(默认开启),所有渠道使用MockSDK,支付立即成功。填入真实密钥后关闭模拟模式,零切换成本。
09 总结
| 设计模式 | 应用场景 |
|---|---|
| 策略模式 | PaymentSDK接口统一三渠道差异 |
| 注册表模式 | Manager持有SDK实例,按渠道分发 |
| 双检锁 | 支付回调的幂等处理 |
| 事务重试 | 支付确认的3次指数退避 |
| 自动回滚 | 混合支付失败时的分步撤销 |
三个渠道,一个接口,一套逻辑。钱直接进你的账户,我们只是帮你调了一下API。
下期预告:《退款不翻车:从两步确认到自动回滚的工程实践》