> ## Documentation Index
> Fetch the complete documentation index at: https://waffo.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 非卡 Token 与 Token 失败原因

> 卡 FAQ 未覆盖的 tokenization 内容：CARD 之外的 token 类型、钱包类 token 的额外字段和固定有效期、为什么 tokenization 提交被拒绝、持卡人姓名规则、MIT 与 CIT 行为上的差异、为什么卡支付在发出之前就可能被拒绝，以及已保存支付方式的自助管理。

[Tokenization 与卡支付](/docs/zh/support/tokenization-faq)是主页面：token 是什么、如何绑卡、token 生命周期、卡的会话和 token 有效期、请求层面的 CIT 与 MIT，以及设置默认卡。**请先读那一页。**

本页是补充。它回答在基础卡集成之后会出现的问题：非卡的 token、tokenization 尝试被拒绝的业务原因、商户发起扣款的行为差异，以及能在卡支付发出之前就将其拦下的限制。

## `tokenType` 永远是 `CARD` 吗？

不是。`CARD` 是大多数集成使用的值，也是公开规范唯一记录的值，但 `tokenType` 是一个通用字段：token 服务维护着一组类型，也涵盖非卡工具，尤其是**钱包类 token**，在必填字段和有效期上遵循不同的规则（均见下文）。

你应该据此做的：

* **不要把 `"CARD"` 硬编码**为你的代码唯一能产生或解析的值。从查询响应和通知中回读 `tokenType`，遇到不熟悉的值时存储它而不是失败。
* \*\*不要假设某种类型对你可用。\*\*你的账户实际能 tokenize 哪些类型取决于你的支付方式配置。不支持的类型在生成时作为参数错误被拒绝。
* 请询问你的 Waffo 集成联系人哪些类型适用于你拥有的支付方式，而不是去探测 API。

## 钱包类 token 需要什么卡 token 不需要的东西？

token 数据内的三个额外字段，全部必填：

| 字段 | 原因 |
| - | - |
| `payMethodName` | token 属于哪个支付方式 |
| `payMethodCountry` | 该方式的哪个国家的配置 |
| `orderId` | 用户授权绑定时所在的订单 |

缺任何一个，生成都会以 `A0003` **Parameter validation failed** 失败。

`orderId` 要求是值得理解的结构性差异：卡可以独立 tokenize，而钱包绑定是用户**在支付过程中**授权的。所以钱包 token 是针对真实订单创建的，不是凭空创建的。实际上你是把它作为支付的一部分来请求，而不是作为单独的"添加支付方式"步骤。

## 钱包 token 能用多久？

| Token 类别 | 有效期 |
| - | - |
| 卡 | 自创建起的平台固定 token 有效期，与卡自身有效期月份的最后一刻，两者取**较早者** |
| 钱包类 | 自创建起**相同的固定**平台有效期，截断到当天结束 |

所以钱包 token 没有卡有效期上限的等价物——没有需要遵守的底层有效期——并且到期落在日边界而不是月边界。

由此得出两点：

* \*\*不要用卡的逻辑推导钱包 token 的剩余寿命。\*\*token 数据中没有 `expiry` 字段可供推理。
* token 仍可能在计算出的到期之前很久就失效，因为用户在钱包侧解除了授权。这对你是不可见的，直到某次扣款失败。把 `A0037`（**the user payment token is invalid or has expired**）当作重新授权的提示来处理，而不是瞬时错误。

## 同一用户再次授权同一钱包，我拿到的是同一个 token 吗？

不一定——这是钱包 token 与卡差别最大的地方。钱包类 token 的复用键包括绑定发生时所在的**订单**，以及你的商户 ID（和你发送的子商户 ID，如有）、你的 `merchantUserId`、token 类型和支付方式。

因为新授权发生在新订单上，同一用户对同一钱包的第二次绑定通常会产生一个**新的** `tokenId`。卡 token 的行为不同：其键基于凭据本身，所以重新绑定同一张卡返回现有 token（见卡 FAQ）。

设计后果：

* **以 `tokenId` 为存储键**，并预期用户会随时间积累多个钱包 token。
* **向用户展示可管理的列表**而不是不断堆积：暂停或解绑他们不再需要的（本页最后一节）。
* **不要把存在一个 token 当作用户恰好只有一个钱包绑定的证明。**

## 非卡 token 的查询和移除必须发什么？

两个接口都是条件形态，而不是单一的必填标识：

| 调用 | 规则 |
| - | - |
| `/api/v1/tokenization/inquiry` | 提供 `tokenId`、`merchantUserId`、`tokenRequestId` 中至少一个。当 `tokenId` 缺失时，`tokenType` 变为**必填**——没有 token ID 时，类型是限定查找范围的依据。 |
| `/api/v1/tokenization/remove` | `tokenType` **必填**，加上 `tokenId` 或 `merchantUserId` 至少一个。 |

实际的解读：在这两个调用上 `tokenType` 不是装饰。如果你围绕卡构建了集成且不传 `tokenType`，增加第二种 token 类别会以看起来像"token 不存在"的方式破坏你的查找。

所有三个 token 接口还会断言 body 中的 `merchantId` 与你 API key 所签发的商户 ID 一致，不一致时以 `A0003` 拒绝，详情为 `mid in params is inconsistent with apiKey`。

## 为什么我的 tokenization 提交被拒绝？

除签名和字段形态问题外，卡提交被拒绝有三个**业务**原因。三者都在存储任何内容之前决定，对该输入都是永久性的——用相同数据重试会得到相同的失败。

| 原因 | 含义 | 怎么做 |
| - | - | - |
| 卡的发卡号段不被识别 | Waffo 无法从卡号前几位识别该卡 | 请用户检查卡号，或换一张卡。不要用相同的数字重试。 |
| 卡的卡组织或类型不在你的配置覆盖范围内 | 卡是真实的，但该卡组织或产品类型未为你的账户启用 | 报告为 `A0031` **Card scheme or type provided by Merchant cannot be supported**。这是找你 Waffo 联系人的配置问题，不是数据问题。 |
| 有效期无效或已过期 | 有效期必须为 `MM/YYYY`，月份 `01`–`12`，且不得在过去 | 修正输入格式，或要求一张有效的卡。 |

两个让人意外的细节：

* \*\*校验位不是门槛。\*\*未通过标准校验和的卡号会被记为警告并继续处理——权威答案来自发卡号段查找。所以不要期待校验和拒绝，但请保留你自己的客户端校验和检查，以便为用户尽早捕获输错。
* 采集 SDK **接受 `MM/YY` 输入**，但查询和通知始终返回 `MM/YYYY`。请存储四位年份形式。

你可能在支付时而非绑定时看到的相关错误码：`A0029`（card data invalid）、`A0030`（card issuing range not found）、`A0032`（payment token data invalid）、`A0023`（order cannot be created due to expired token）。

## 为什么持卡人姓名被拒绝？

因为它包含拉丁字母之外的字符。规则很严格：持卡人姓名必须**只包含英文字母**。带重音字符或非拉丁文字的姓名会以失败原因 `INVALID_CARDHOLDER_NAME` 和消息 *Cardholder name must contain only English letters* 被拒绝，在 API 上表现为 `A0029`。

如何妥善处理：

* \*\*在采集时转写。\*\*要求填写"卡面印刷的姓名"；卡是以拉丁字符压印的，所以正确的值几乎总是存在。
* **在你自己的表单中校验**并给出清晰提示，而不是让用户在支付时才发现。
* 记住姓名是卡 token 复用键的一部分：同一张卡以不同拼写的姓名提交会被视为不同凭据，并获得自己的 token。

## MIT 扣款与 CIT 扣款有什么不同？

请求层面的差异（`merchantInitiatedMode`，以及对已可用凭据的 `A0045` 要求）在[卡 tokenization 页面](/docs/zh/support/tokenization-faq)上。**行为**上的差异同样重要：

| | CIT | MIT |
| - | - | - |
| 到达 Waffo 收银台页面 | 是，当流程需要时 | **从不**——MIT 扣款按设计被阻止进入收银台页面 |
| 3DS | 可通过 `threeDsDecision`（`3DS_FORCE` / `NO_3DS`）影响，受风控约束 | `threeDsDecision` 被**静默忽略** |
| 失败后用户可选择其他支付方式 | 是，在收银台页面 | 否——没有页面也没有用户在场 |
| 需要用户输入的税费采集 | 可在收银台页面收集 | 此路径不可用 |

需要记住的一句话：\*\*MIT 扣款没有用户界面也没有用户。\*\*你的流程依赖收银台页面做的任何事——跳转、同意步骤、用户填写的字段——在这里都不存在。

## 我的 MIT 扣款失败了，直接重试就行吗？

不要盲目重试，有三个独立的原因：

1. \*\*没有用户侧的重试。\*\*CIT 失败可以以用户在收银台页面选择其他方式收尾。MIT 失败就是结束。
2. **有些失败对该凭据是永久的。**`A0045`（存储的凭据不处于可用状态）和 `A0037`（token 无效或已过期）重试不会变成功。解决方法是一次新的客户发起授权。
3. **重试本身受卡组织规则限速**——见下一个问题。

有效的模式：对失败分类。凭据问题意味着"请用户重新授权"。真正的瞬时失败意味着"稍后按计划重试"。永远不要在紧循环中重试，也永远不要把 MIT 拒绝当作用户无需被告知就能修复的事情。

对于订阅，不要自己构建——Waffo 自己的重试排程和备用支付方式处理已经做了，见[订阅生命周期与支付方式管理](/docs/zh/support/subscription-lifecycle-management)。

## 为什么卡支付在还没尝试之前就被拒绝了？

因为卡组织对**同一笔卡支付可重试的次数施加合规限制**，Waffo 在本地强制执行。当一次尝试会突破限制时，它会被系统拒绝而不是转发——这就是为什么失败可能比正常拒绝返回得更快，以及为什么卡账单上什么都不出现。

关于计数你需要知道的：

* 它**按卡组织**计数，并再按卡组织自身对商户的分类分别计数。同一订单上来自不同卡组织的两张卡不合并计算。
* Waffo 不公布阈值，你也不应尝试反推：它们由卡组织设定，可能在你账户没有任何变化的情况下改变。
* 该失败表现为失败原因 `CARD_PAYMENT_RETRY_LIMIT`，在 API 上映射为 `C0005`。

正确的处理是行为上的，不是数字上的：

* \*\*永远不要立即自动重试被拒绝的卡支付。\*\*它消耗额度却没有得到不同答案的机会。
* **在两次尝试之间改变点什么**——不同的支付方式、重新输入的卡、更晚的排期——或者询问用户。
* 如果你经常撞到这个限制，问题在上游：对不会授权的卡重试太多了。

## 我的用户能自己管理已保存的支付方式吗？

能，通过一个接口而不是通过创建订单：`POST /api/v1/saved-payment-methods/config`，接收你的 `merchantId`、`merchantUserId`、已保存方式的 token，以及一个 `action`：

| 操作 | 效果 |
| - | - |
| `SET_DEFAULT` | 把该已保存方式设为用户的默认。每个用户最多一个默认，因此先前的默认被替换。 |
| `SUSPEND` | 停止向用户提供该已保存方式。 |

配合 `/api/v1/tokenization/remove`（完全解绑），足以构建完整的"管理我的支付方式"页面：列出、设默认、隐藏、删除。每项操作对收银台排序的影响见[卡 tokenization 页面](/docs/zh/support/tokenization-faq)。

设计页面之前值得了解的两个边界：

* 该接口位于 API key 的 **payin** scope 内，所以它是后端调用——永远不要直接暴露给浏览器或移动客户端。
* 移除是最终的：已移除的 token 被排除在查找之外，且永不重新签发。暂停是看起来可逆的选项；请把移除当作永久的。

## 这些问题分别属于哪一页？

| 问题 | 页面 |
| - | - |
| token 是什么、如何绑卡、会话和 token 有效期、重绑同一张卡、默认卡 | [Tokenization 与卡支付](/docs/zh/support/tokenization-faq) |
| 请求层面的 CIT 与 MIT、`A0045`、绑定结果通知到哪里 | [Tokenization 与卡支付](/docs/zh/support/tokenization-faq) |
| `CARD` 之外的 token 类型、钱包 token 字段和有效期、钱包重新授权 | 本页 |
| tokenization 提交的业务失败、持卡人姓名规则 | 本页 |
| MIT 行为、重试策略、卡组织重试限制 | 本页 |
| 每个错误码的一般含义 | [常见错误排查](/docs/zh/support/errors-troubleshooting-guide) |
| 哪些方式允许哪些退款 | [支付方式退款限制](/docs/zh/support/payment-method-refund-limits-faq) |

仍不确定某次具体绑定或扣款为何被拒？请[联系支持](mailto:support@waffo.com)，附上 `tokenRequestId` 或订单 ID——失败原因同时记录在两者上。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.