Adyen Token 的 created、updated 与 disabled 事件各自由什么触发
先给出结论:在 Adyen 的 Recurring tokens life cycle events webhook 中,recurring.token.created 表示令牌被创建;recurring.token.disabled 表示令牌被禁用,触发原因可能是商户删除已存储的支付详情,也可能是第三方禁用了该支付详情;recurring.token.updated 表示令牌对应的存储详情被更新,更新可以由商户发起,也可以由卡组织等第三方完成。这三个事件各有明确的触发边界,但文档并未对通知送达时效作出承诺,因此核对时应以事件内容为准,而不要假设“操作完成后必然在某个时间窗口内收到”。
三个事件的触发条件
按 webhook 的 type 字段区分,各取值的含义如下。
recurring.token.created:令牌已创建。若要在后续循环付款中使用它,需要把 storedPaymentMethodId 与 shopperReference 一起保存,从而把令牌与购物者关联起来。这个事件的关键动作是“落库并建立关联”,而不是仅记录一条日志。
recurring.token.disabled:令牌已被禁用。文档列出两种情形:一是商户删除已存储的支付详情;二是第三方禁用该支付详情。也就是说,disabled 不等于“商户主动删除”的同义词,收到该事件时不能默认是自己侧发起的操作。
recurring.token.updated:令牌的存储详情被更新。商户可以主动发起更新,但存储详情也可能由卡组织等第三方更新。因此 updated 事件同样不能简单归因于本方系统。
另外还有一个容易混淆的取值:recurring.token.alreadyExisting,表示创建或更新操作所携带的详情与一个已存在的令牌匹配,此时 storedPaymentMethodId 字段给出的是该既有令牌的 ID。它不属于上述三类“创建、更新、禁用”事件,核对时不要把它计入 created。
可执行的核对动作
订阅该 webhook 后,建议按以下顺序核对。
第一,确认订阅的是 Recurring tokens life cycle events webhook,而不是旧的 RECURRING_CONTRACT webhook。文档说明后者已不再继续开发,仍可用但不推荐,新 webhook 能提供更多 Token 生命周期事件。
第二,检查 webhook 配置是否包含所有默认事件。文档建议配置所有默认事件,以避免遗漏事件,不要只挑选部分类型订阅。
第三,对每条收到的事件,读取 type 与 storedPaymentMethodId,并区分处置路径:created 走“保存 ID 并关联 shopperReference”;disabled 走“标记令牌不可用,并区分删除与第三方禁用两种来源”;updated 走“刷新本地存储详情,不预设更新方”。
第四,遇到 alreadyExisting 时,用返回的 storedPaymentMethodId 去重,避免重复建令牌。
一个可复算的例子
假设某购物者已有令牌 T1,本地以 storedPaymentMethodId=T1 与对应 shopperReference 建档。以下情形均为假设,仅用于说明事件与本地状态的对应关系。
情形一:再次提交相同支付详情创建令牌,收到 recurring.token.alreadyExisting,其中 storedPaymentMethodId 仍为 T1。此时本地令牌数应保持为 1,而不是新增为 2。
情形二:卡组织更新了该卡的存储详情,收到 recurring.token.updated,storedPaymentMethodId 为 T1。本地应更新 T1 的详情字段,令牌数量不变。
情形三:商户删除该支付详情,或第三方禁用该支付详情,收到 recurring.token.disabled,storedPaymentMethodId 为 T1。本地应将 T1 标记为不可用。按机制推断,若后续要重新使用,需要重新走创建流程,而不应假设 disabled 会自动恢复;这一点属于对流程的合理推断,文档未直接说明。
这个例子不涉及任何金额、费率或时效假设。
边界与常见误解
需要明确三点。其一,文档只描述触发来源,没有给出事件通知的送达时限,因此不要把“未及时收到”直接判定为事件未发生。其二,disabled 可能来自第三方,updated 也可能来自卡组织,二者都不能只按本方操作日志归因。其三,RECURRING_CONTRACT 仍可用,但文档推荐迁移到新的生命周期事件 webhook,以获得更多令牌事件。核对时以 webhook 实际推送的 type 和 storedPaymentMethodId 为准,是成本最低且最不容易出错的做法。