Skip to main content
它能做什么: 在 Stripe 已付周期结束前,让客户先在 Waffo 完成卡输入和必要的 3DS 验证;到期前不扣款,到期时 Waffo 自动发起首笔扣款。等待期间可以查询迁移状态,也可以立即取消并阻止首次扣款。 接入只需 3 步: 换成 WaffoStripe.client(...)、给目标订阅补充路由标记与交接时间、接入 Waffo Webhook。现有 com.stripe.* 类型和调用模式继续保留。快速接入展示了完整的代码改造;上线前还需按接入指南持久化幂等键及订阅对应关系。
迁移工具目前提供 Java 版本:com.waffo:waffo-java-stripe。Node.js、Python、Go 版本即将发布。

它不是 Waffo 原生 SDK

Waffo 提供两套完全不同的接入方式,先确认哪一套适合你。 全新接入请直接用原生 SDK 适配器的价值只在一种场景成立:你已经有一套跑在 Stripe 上的订阅代码,改动成本是主要顾虑。

迁移工具替你做了什么

路由

判断每个请求该发给 Waffo 还是原样发给 Stripe,你的调用代码不需要分支。

参数翻译

把 Stripe 的 SessionCreateParams 翻译成 Waffo 的订阅创建请求,包括金额、周期、币种、支付方式、收银台语言。

结果反向映射

把 Waffo 的响应装回 Stripe 的 SessionSubscription 对象,你照常用 getter 取值。

通知翻译

把 Waffo 的订阅通知翻译成 Stripe 的 Event,你原有的 Webhook 分支代码继续可用。

工作原理

适配器返回的是一个标准的 StripeClient。它拦截每个请求,按三条规则决定去向: 也就是说,没打标记的调用完全不受影响——一次性支付、未标记的订阅、客户对象、价格对象,行为和迁移前一模一样。你可以只把一部分订阅切到 Waffo,两边并行运行。 一次完整的订阅支付会这样流转:
1

创建订阅 Checkout

你照常调用 client.checkout().sessions().create(params),只是 params 里多了一行 metadata.source=waffo。适配器把它翻译成 Waffo 的订阅创建请求。
2

拿到收银台地址

返回的仍然是 Stripe 的 Session 对象,session.getUrl() 里装的是 Waffo 收银台地址。你的跳转代码不用改,它并不关心这个地址指向谁。
3

用户完成支付

用户在 Waffo 收银台完成支付。这一段完全由 Waffo 承接,你的应用不参与。
4

接收并翻译通知

Waffo 把订阅通知发到你配置的 notifyUrl。你的端点调用 WaffoStripeWebhooks.handle(...),拿到 WaffoStripeWebhookResult,再通过 result.getEvent() 取得标准的 Stripe Event
5

原有业务逻辑继续跑

你原来 switch (event.getType()) 里处理 customer.subscription.createdinvoice.paid 的代码不用改,直接接住翻译后的事件。

支持哪些场景

首期能力聚焦在跳转式收银台的订阅上。下面这张表用来判断你的现状能不能接住。 完整的回落条件、原因码和取消能力边界见接入指南的不支持用法

将 Stripe 的即将到期订阅无缝转移至 Waffo

假设 Stripe 订阅当前已付周期在时间 T 结束。你可以先按现有 Stripe 流程让旧订阅在 T 停止续费,再提前为同一客户创建从 T 开始的 Waffo 订阅:
1

读取交接时间

从 Stripe 订阅读取已付周期结束时间 T
2

设置 Waffo 开始时间

在新的 Waffo 路由请求中,把 subscription_data.billing_cycle_anchor 设为 T,同时设置 proration_behavior=none
3

提前完成验证

让客户在 T 之前打开 Waffo 收银台,完成卡输入和必要的 3DS 验证。此时不会收取首笔费用。
4

确认等待状态

在等待期间查询 wsub_…billing_cycle_anchorcurrent_period_end 都等于 Tmetadata.waffo_current_period=0 表示尚未开始首个账期。
5

自动完成首扣

到达 T 后,Waffo 自动发起首笔扣款,客户不需要再次操作。
如果客户在 T 之前取消迁移,调用 Subscription.cancel("wsub_…") 会立即取消 Waffo 订阅,并阻止预定的首次扣款。
Stripe 迁移工具只承接 Waffo 侧的申请、查询和取消,不会修改原 Stripe 订阅。你仍需通过现有 Stripe 代码或后台,把旧订阅配置为在同一个 T 结束。

快速接入

下面分三步展示关键代码改造。除了代码调整,你还需要在发送请求前持久化幂等键,并在创建成功后保存 Waffo 订阅 id 与业务订单的关系。这些示例是放进现有类中的局部片段,沿用你项目已有的 imports、依赖字段和业务方法。

第一步:换客户端构造

拿到的 client 就是标准的 StripeClient,可以直接替换你原来那个,调用它的所有代码不用动。

第二步:添加路由标记与幂等键

示例刻意不设置 uiMode。Stripe 默认使用跳转式收银台,迁移工具也把未设置的值按跳转式收银台处理。这样可以同时兼容 stripe-java 24.11.x、32.x 和 33.x;不要在 32.x 或 33.x 中改用 HOSTED_PAGE,因为对应的 hosted_page 值会被判定为非跳转式收银台。 不要依赖 stripe-java 自动生成幂等键。请显式传入并持久化一个不超过 32 个字符的稳定键,在每次重试中复用。详细规则见接入指南

第三步:接入 Waffo Webhook

你的应用仍需新增一个 HTTP 端点,原来的 Stripe Webhook 端点不用动。SDK 的 handle(...) 已经完成验签、解析、事件翻译和确认响应生成;端点只负责把翻译结果交给你的业务代码,并把 SDK 生成的确认响应交给 Web 框架返回。
WaffoStripeWebhookResult 已包含确认响应正文。示例最后几行只是把它映射为 Spring 的 ResponseEntity;使用其他 Web 框架时做等价映射即可。详见接入指南

接入指南

配置参数全表、Webhook 处理方式、不支持的 Stripe 用法全表、接入检查表与 Sandbox 验证要求。

用 AI 迁移技能自动完成

如果你使用 Claude Code、Codex 或 Cursor,可以让 AI 完成扫描与改造:
安装后在你的项目里对 AI 说「迁移 Stripe」。它会扫描你项目里所有 Stripe 调用、标出无法路由的地方、在你确认改动后写入代码,并引导完成 Sandbox 验收。
扫描结果只用于发现风险,不等于验收结论。无论用哪条路径接入,都必须通过你项目自己的接口跑通 Sandbox 全链路才算完成,参见接入指南的 Sandbox 验证

版本与前提

stripe-java 是 provided 依赖,意味着适配器不会替你升级或降级它,你项目里现有的版本保持不动。请确保版本不低于 24.11.0。 接入前还需要确认:
  • 你与 Waffo 已签订订阅业务合约,并拿到了 Sandbox 凭据
  • 你要路由的币种在合约范围内,可用 paymethodconfig/inquiry 查询
  • 你有一个可公网访问的 HTTPS 端点用于接收 Waffo 通知

相关资源