H7.06.2idempotent payment retry设计研究
重试不得造成重复扣款
别名: 支付重试 · 重复扣款 · idempotent payment
概念解释
失败或看起来没响应之后,人会再点支付。重试不得重复扣款指第二次点击要么接上同一笔支付意图,要么在确认第一笔未捕获之前绝不新开一笔。它是按钮与意图的幂等,不是超时之后怎么查询,也不是万一已经扣了两笔怎么自动退——那是未知状态和退回时限。这里要保证「再点一次」在交互上不会变成两笔授权。
机制
支付请求不是读操作。网络慢、页面还在转,人的模型是「没点上」,于是连点。若每次点击生成新的商户订单号,渠道会当两笔。前端禁用按钮只解决同屏连点;刷新、后退、第二台设备仍会再发。真正的约束是幂等键:同一订单、同一金额、同一意图号,渠道把后到的请求认成重复。界面要让人看见「仍是这一笔」而不是「新的一次支付」。失败已经确定时,重试应是新意图但绑定同一订单,并在发起前声明上一笔未扣。
怎么研究
在模拟延迟下记录连点、刷新后再付、双设备同时付。比较无幂等、仅禁用按钮、意图号贯穿。
自变量:按钮禁用时长、是否使用幂等键、刷新后是否恢复同一意图。 因变量:渠道侧授权笔数、用户以为失败但已扣、因双扣进线。
实验室点得慢,看不到真实连点。要用延迟注入。不要把「最终只有一笔成交」当成充分——可能第二笔授权后被人工退,用户已经受惊。
边界
人明确改了金额、券或方式,那是新意图,应新开,并作废旧意图,而不是误用旧幂等键把新金额吞掉。部分捕获(预授权)的补捕获不是重试。线下 POS 与线上各一笔是渠道设计,要在界面上标成两笔来源。幂等窗口过期后渠道会当新单,界面不能无限显示「还是刚才那笔」。
怎么落地
- 点击支付后立即禁用并绑定意图号;响应返回前的再次点击被吞掉,不生成新号。
- 刷新或从渠道返回「未完成」时,先查询该意图再决定是否允许新的一次;允许时文案为「继续支付这一单」而不是「重新下单」。
- 已确定失败的,展示「上一笔未扣款」再开新意图。
- 验证:在支付请求上加数秒延迟,连点、刷新、两台设备同时付,对账渠道授权次数。大于一笔且用户未确认第二笔,即失败。