用户提交退款后,系统若立即显示已退款,可能把审核、通道处理与到账几个阶段混为一谈。
本文使用团购业务的虚构订单与关系数据模型,伪代码不连接真实支付。团购把用户购买、平台收款、商家履约与结算连接起来。下单、支付、成团、消费和退款必须保留各自状态,不能用一个布尔字段表达整个生命周期。
1. 从现象推到机制
退款有自己的业务身份和状态,关联原支付流水与金额上限。多次部分退款的累计值不能超过已确认可退金额。通道超时进入待查询,不能在未知结果下生成另一笔新退款。
图中的四个节点分别表示退款申请、额度预占、通道处理、最终确认。顺着实线检查输入如何变成输出,再沿虚线核对反馈条件。图示表达的是本文讨论的关系,不是实测曲线或现场截图。
2. 最小实现与输入条件
先冻结本次退款额度,再按稳定退款号请求通道。数据库事务只保护本地额度和状态,外部结果通过通知与查询收敛。
1
2
3
REQUESTED -> APPROVED -> PROCESSING
PROCESSING -> SUCCEEDED | FAILED | UNKNOWN
refund_total <= verified_refundable_amount
先列业务事件与允许的状态迁移,再用少量匿名订单演算。涉及金额的地方保存成交快照,涉及并发的地方使用数据库约束,外部支付行为按支付协议另行实现。
3. 用对照区分原因
下表列出需要主动改变的条件。预期行为来自机制分析,复现时还需记录运行环境和原始输出,不能将预期当作已经测得的结果。
| 改变的条件 | 需要验证的行为 |
|---|---|
| 用户重复提交同一申请 | 应关联已有退款单 |
| 部分退款并发发生 | 累计退款不能超过上限 |
| 通道响应超时 | 保留未知状态并查询 |
对照 1:用户重复提交同一申请
应关联已有退款单。观察时记录申请身份与退款号。把这个条件与基准情形分开,有助于判断变化来自哪一层;若得到相反结果,应先核对前提,再修改实现。
对照 2:部分退款并发发生
累计退款不能超过上限。观察时记录额度预占与数据库约束。把这个条件与基准情形分开,有助于判断变化来自哪一层;若得到相反结果,应先核对前提,再修改实现。
对照 3:通道响应超时
保留未知状态并查询。观察时记录稳定退款号对应的通道结果。把这个条件与基准情形分开,有助于判断变化来自哪一层;若得到相反结果,应先核对前提,再修改实现。
4. 适用条件与取舍
界面要让用户知道当前阶段和后续预期,但不应承诺无法由系统控制的具体到账时间。财务确认与用户提示要用相同状态依据。
一次正常运行只覆盖了这组输入。继续扩展前,应把上面的异常对照保留下来,尤其关注“通道响应超时”这一分支。后续方案若改变了图中任意一处依赖,原来的判断就要重新验证,不能仅凭界面相似或返回值相同沿用结论。