关键支付请求必须使用带幂等键、可中断、可验证的重试机制:绑定唯一idempotency-key,仅对502/503/504等可恢复错误重试,超时3秒、指数退避、最多2次,全程可取消并反馈状态。

关键支付请求不能靠“多试几次”来凑成功率,必须用可验证、可中断、带幂等保障的重试机制。核心是:只在安全前提下重试,且每次重试都必须有明确反馈。
必须绑定幂等键,杜绝重复扣款
每次支付请求都要携带服务端能识别的唯一幂等键,例如使用 crypto.randomUUID() 生成,并在整个重试链路中复用——不能每次重试都换一个。这个键要通过请求头传递:Idempotency-Key: xxxxxxxx。如果后端不校验该字段,前端不应发起重试,因为此时重试等于制造风险。
建议把幂等键存入 sessionStorage,页面刷新后仍可续传;成功后立即清除。避免用 Date.now() 或 Math.random() 单独生成,易冲突且不可追溯。
只对真正可恢复的错误触发重试
不是所有失败都能重试。前端需严格区分错误类型:
- ✅ 可重试:网络中断(TypeError)、超时(AbortError)、HTTP 状态码 502/503/504
- ❌ 禁止重试:400(参数错)、401(token 失效)、403(无权限)、404(订单不存在)、409(业务冲突)
把判断逻辑封装成函数,例如:shouldRetry(err, res),返回布尔值,便于统一控制。
短超时 + 指数退避 + 次数封顶
支付是强实时场景,单次请求超时建议设为 3 秒;重试间隔采用指数增长(1s → 2s → 4s),避免集中冲击;最大重试次数不超过 2 次(含首次),总耗时控制在 10 秒内。
每次重试都新建 AbortController,并用 setTimeout(() => controller.abort(), 3000) 绑定独立超时;延迟等待用:await new Promise(r => setTimeout(r, 1000 * Math.pow(2, attempt)))。
重试过程必须可取消、有状态、可感知
用户切走标签页、关闭页面或点击“取消”,所有重试任务必须立即终止。对外暴露 abort() 方法,UI 层可监听 beforeunload 或绑定按钮事件。
界面上显示明确进度,如:“正在重新提交… (1/2)”;成功后跳转或弹窗提示;最终失败则展示结构化提示,例如:“网络不稳定,请稍后在订单页查看支付结果”,而非笼统的“请求失败”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











