手册
付款错误分类 (Payment Failure Taxonomy)
超时、429、5xx、业务下降和基础设施错误不是一回事。每个类别都需要不同的重试策略。
分布式支付引擎
部分 11 的 22
一系列分布式支付架构弥合了捕获和完成之间的差距。
在上一节中,我们看到诸如 PaymentFailed 之类的语义事件隐藏了提供程序的状态代码。但即使是单个 PaymentFailed 事件也是不够的;因为“失败”这个词涵盖了截然不同的现实。
卡被拒绝、网络超时、PSP返回429、PSP返回500都可以显示为“失败”;但每一个都需要完全不同的行动。本章讨论构建一个分类法,使这些差异变得可见。```text PaymentFailed ├─ Business Decline (kart reddedildi — retry etme) ├─ Timeout (belirsiz sonuç — dikkatli retry) ├─ Rate Limited (429) (çok istek — backoff ile retry) └─ Infrastructure (5xx) (provider tarafı arıza — retry)
## 第一次提到的概念```text
📦 Business Decline
PSP'nin, kartın kendisiyle ilgili bir nedenle isteği reddetmesi: yetersiz bakiye, dolandırıcılık şüphesi.
📦 Transient Hata
Aynı isteğin tekrar denenmesi mantıklı olan, geçici bir arıza: timeout, 5xx, 429.
📦 Permanent Hata
Tekrar denemenin sonucu değiştirmeyeceği hata: geçersiz kart numarası, desteklenmeyen para birimi.
📦 Belirsiz Sonuç
İsteğin PSP'ye ulaşıp ulaşmadığının bilinmediği durum: bağlantı timeout'u.
```重试业务下降是浪费时间;不重试不确定的结果是错过付款的真正风险。分类法的存在是为了区分这两种风险。
## 四个基本类别
**业务下降**:PSP 收到请求,对其进行处理并做出决定 - 该卡被拒绝。这不是系统错误,而是业务决策。再试一次不会改变结果;有必要向用户建议另一种支付方式。
**超时/不确定结果**:请求已发送,但响应从未到来。这里的危险是——付款可能发生在 PSP 端,只是您丢失了响应。这一类别不能通过盲目的“再试一次”来解决。首先,应对情况进行质疑(使用幂等性密钥),然后做出决定。
**速率限制 (429)**:PSP 暂时拒绝您控制请求量。这不是一个错误,而是一个信号。立即重试会使情况变得更糟;需要进行退避等待。
**基础设施 (5xx)**:PSP 端出现故障。如果请求尚未被处理,通常可以安全地重试 - 但如果不断收到 5xx,则这是一个断路器信号。```text
Hata alındı
│
├─ PSP isteği net biçimde reddetti mi? → Business Decline → retry etme
│
├─ Yanıt hiç gelmedi mi? → Belirsiz Sonuç → önce durumu sorgula
│
├─ 429 mu? → Rate Limited → backoff ile retry
│
└─ 5xx mi? → Infrastructure → retry, ama circuit breaker'ı izle
```## 为什么单个“重试”规则是不够的
使用相同重试逻辑处理所有错误的工作人员将以两种方式失败:它将毫无意义地重试业务拒绝(延迟用户体验,有时会推动卡网络限制),或者根本不重试而留下不明确的结果(导致系统忘记实际上成功的付款)。该分类法通过将每个错误放入正确的框中来降低这两种风险。
## 我们如何在代码中表示分类法
语义事件的 `failureReason` 字段必须包含这四个类别之一,而不是提供程序的原始错误文本。提供商网关负责将原始错误映射到此类别 - 这是上一节中转换层的扩展。
|失败原因 |重试是否合适?行动|
| --- | --- | --- |
|业务下滑 |没有 |向用户建议另一种方法 |
|模糊超时 |先查询 |状态查询然后决定 |
|价格有限 |是的 |后退重试 |
|基础设施错误|是的 |观看重试+断路器|
## 经常混淆的区别```text
❌ Her hata retry edilmelidir
✓ Business decline retry edilmemelidir; sonuç değişmez
❌ Timeout = hata yok, sadece tekrar dene
✓ Timeout = belirsizlik; önce gerçek durum sorgulanmalı
❌ 429 bir arızadır
✓ 429 bir sinyaldir; sistem sizi kasıtlı olarak yavaşlatıyor
```## 类别之间的快速比较
|类别 |结果清楚了吗?重试有意义吗?典型原因 |
| --- | --- | --- | --- |
|业务下滑 |是的 |没有 |卡、余额、欺诈 |
|超时 |没有 |先查询 |网络、PSP 缓慢 |
|价格有限 |是的 |是的(等待)|音量控制|
|基础设施|是的 |是的 | PSP端故障|
## 设置分类时的清单
1. Provider 返回的每个错误代码是否清楚地映射到四个类别之一?
2、当新的未映射错误码到来时,系统是默认查询状态还是盲目重试? (真正的默认值:查询状态。)
3、超时场景下,是否真的实现了预重试状态检查?
4. 429 的退避时间是否考虑 PSP 的 `Retry-After` 标头(如果有)?
5. 是否将 5xx 频率作为触发断路器的指标进行监控?
6、业务下滑后的用户流量是否不会进入重试周期?
## 本文中您应该记住的内容
1.“失败”不是单一的状态;它们是四种不同的现实,需要至少四种不同的行动。
2、业务下降不重试; timeout不是盲目重试,而是先查询。
3、429是信号,5xx是故障;两者都会重试,但纪律不同。
4. 分类法使错误可以从您自己的 `failureReason` 枚举中读取,而不是从原始提供程序文本中读取。
> 如果在不了解错误的情况下编写了重试策略;不但无益,反而会无声无息地造成伤害。
在下一节中,我们将为这四个类别(退避、抖动、上限和断路器)中的每一个设置实际的重试算法。
FAQ
Frequently asked questions
什么是业务衰退?
PSP 拒绝该请求的原因与该卡本身有关:资金不足、涉嫌欺诈。
什么是瞬态误差?
暂时失败,再次尝试相同的请求是有意义的:超时、5xx、429。
难道真的是“每一个错误都必须重试”吗?
业务衰退不应重演;结果没有改变
本节修复了什么?
卡被拒绝、网络超时、PSP返回429、PSP返回500都可以显示为“失败”;但每一个都需要完全不同的行动。本章讨论构建一个分类法,使这些差异变得可见。 “失败”不是单一的状态;它们是四种不同的现实,需要至少四种不同的行动。在上一节中,我们看到诸如 `PaymentFailed` 之类的语义事件隐藏了提供程序的状态代码。但即使是单个 `PaymentFailed` 事件也是不够的;因为“失败”这个词涵盖了截然不同的现实。
学到的工程原理
- 失败不是个案;每个类别都需要不同的操作。
- 不确定的结果不是盲目重试,而是先质疑。
- 429 是一个信号,而不是故障——这是符合纪律的。
继续阅读
继续阅读
系列中的下一个
支付工作人员的重试算法
指数退避、抖动、上限、延迟与重试差异以及断路器——将上一节中的分类法转换为工作代码。
系列中的下一个
语义事件而不是原始提供者数据
提供商网关接收到的 Webhook 是否应该通过 PSP 的事件名称或语义事件(例如 PaymentCaptured/PaymentFailed)到达下游?
同系列
SDK (ソフトウェア開発キット) を漏らさないプロバイダーの抽象化: ゲートウェイの限界
プロバイダー ゲートウェイは PSP SDK をどのように所有しているのですか。なぜチェックアウト オーケストレーターはセマンティック インターフェイスのみを参照する必要があるのでしょうか?カードとウォレットの流れは異なります...