API 变更

Stripe API 版本控制的运作方式,以及值得借鉴的做法

阅读约 1 分钟

Stripe API 版本控制是按日期来运作的。每个账户都被固定在一个以发布日期命名的 API 版本上,而任何一次请求,都可以用 Stripe-Version 请求头覆盖这个固定版本。截至本文撰写时(2026 年 10 月),Stripe 文档中的当前版本是 2026-09-30.endive,而同样的方案,一个小得多的 API 一个周末就能照着实现。

下面所有关于 Stripe 的事实,都来自 Stripe 自己的页面,并在用到的地方附上了链接。

机制Stripe 的做法来源
版本名称一个日期,自 2024 年起再加一个发布名称(2026-09-30.endive)Versioning
默认版本固定在账户上,在 Workbench 中修改Versioning
单次请求覆盖Stripe-Version 请求头,或 SDK 选项Upgrades
Webhook以端点上设置的版本渲染Upgrades
发布节奏每月发布不含破坏性变更的版本,每年两次大版本发布Versioning
旧版本通过内部的版本变更模块保持可用Engineering post

Stripe API 版本控制是如何运作的?

Stripe 为每个账户设定一个默认 API 版本,而每一个没有指明版本的请求,都使用这个版本。调用方自己选择何时迁移,办法是修改默认版本,或者在单个请求上设置版本。

Stripe 的工程博客文章说,账户在第一次发出 API 请求时就被固定了:该账户”自动被固定在当时可用的最新版本”上,此后每一次调用都隐式地被分配这个版本。

版本字符串是一个日期。自 2024-09-30.acacia 发布起,它还带有一个名称,例如 2026-09-30.endive。日期决定版本的先后顺序,名称则告诉你这个版本属于哪个大版本系列。

如何为每个请求选择版本?

在请求上发送 Stripe-Version 请求头,或者在 SDK 中设置版本。Stripe 的升级指南展示了请求头的写法,同样的调用在正式环境和测试环境中都适用。

curl https://api.stripe.com/v1/charges \
  -u "$STRIPE_SECRET_KEY:" \
  -H "Stripe-Version: 2026-09-30.endive"

Stripe 的指南指出,当你在 SDK 中全局设置版本或者按请求设置版本时,返回的响应对象就是该版本的形态。

Stripe 也建议不要依赖账户的默认版本。用它的话说,应该为每个请求指定版本,使用请求头或者固定版本的 SDK,这样决定版本的是你的代码,而不是仪表盘上的某项设置。

不同语言的 SDK 固定版本的方式不同。文档说,动态类型语言库的近期版本,使用该 SDK 发布时最新的 API 版本,而强类型的库(Java、Go 和 .NET)则固定在这个版本上。安装某个库版本,实际上就是在选择一个 API 版本。

版本变化时,webhook 会怎样?

一个 webhook 事件,是按照其端点所关联的 API 版本来渲染的,而不是按你的服务器代码所使用的版本。Stripe 的文档说,事件使用创建端点时设置的版本,否则使用账户默认版本。更改你的 SDK 版本,并不会改变 webhook 处理程序收到的内容。

因此,你的请求路径和事件路径可能处于两个不同的版本上。对于事件目标,snapshot_api_version 只能在创建目标时设置,所以要换一个版本就得新建一个目标。

Stripe 给出的升级路径是并行运行。创建一个目标版本的新端点,把同样的事件发送给两个端点,让处理程序处理其中一个、忽略另一个,然后切换并停用旧端点。由于在重叠期间每个事件都会到达两次,处理程序必须是幂等的。对任何会发出事件的 API 来说,这都是一个值得借鉴的好模式,而Webhook 体验日志正是你公布那些使这一做法成为必要的负载变更的地方。

月度发布和大版本发布是什么?

自 2024-09-30.acacia 发布起,Stripe 每月发布一个不含破坏性变更的新 API 版本,并且每年两次发布新的大版本,以一个包含破坏性变更的版本为开端。它的版本控制页面说,你可以升级到任何一个月度版本而无需修改代码,而大版本则可能需要改动。

大版本带有名称。版本控制页面以 Basil 为例,而 Stripe 关于这一流程的公告说,名称取自植物,从 Acacia 开始,月度版本沿用之前那个大版本的名称,这样名称就表明可以放心升级。Stripe 的变更日志列出了在用的名称,截至本文撰写时,最新的一条是 2026-09-30.endive。

所以,日期回答的是”有多新”,名称回答的是”这里是不是一个破坏性的分界点”。Stripe 的公告还为例外留出了空间:如果不发布就会严重影响某个集成,它保留在周期之外发布破坏性变更的权利。公告见 Stripe’s new API release process。

Stripe API 的最新版本是什么?

截至本文撰写时(2026 年 10 月),Stripe 的版本控制页面声明当前版本是 2026-09-30.endive,它的变更日志也把同一个版本列为最新。Stripe 每月发布一个新版本,所以任何印在文章里的字符串都会很快过时。在固定任何版本之前,请先查看实时的变更日志,并固定你测试过的那个版本。

Stripe 如何让旧版本继续可用?

Stripe 的做法是,把每一项破坏性变更写成一个自包含的版本变更模块,并从数据的最新形态开始,向后依次应用这些模块。它的关于 API 版本控制的工程文章描述了这一机制。

每个模块都声明自己改变了什么,记录这项变更,并包含一个转换函数。文章举了一个例子:某个字段从字符串变成了哈希。要构建一个响应,系统先确定目标版本,然后沿着时间向后回溯,沿途遇到的每个模块都依次应用,直到抵达那个版本。

这个设计带来两个副作用,文章里都提到了。其一,由于模块声明了它们所涉及的字段和资源,Stripe 可以在部署时据此生成它的 API 体验日志。其二,由于账户的版本是已知的,文档就可以根据它做出调整,并对自该版本以来的向后不兼容变更给出警告。

它的代价是什么,较小的 API 应该借鉴什么?

版本控制需要消耗工程上的注意力,Stripe 自己也这么说。工程文章承认存在维护负担,并提出了这样的目标:编写新代码时,需要为旧行为考虑得越少越好。文章还描述了发布之前的轻量级 API 评审,目的是从一开始就避免需要变更版本。

一个小型 API 负担不起为每个旧版本维护一条模块链,也不需要。借鉴那些承载价值的部分就够了:

  1. **带日期的版本。**日期不需要判断什么算”大版本”,调用方也读得懂。API 版本控制最佳实践一文把它与 URL 和请求头方案做了对比。
  2. **固定的默认版本。**在首次使用时,把账户或密钥固定到某个版本,这样 API 永远不会在一个正常工作的集成之下发生变化。
  3. **单次请求覆盖。**一个请求头,让调用方可以在正式环境里,对一次调用测试新版本,然后再决定是否迁移。
  4. **webhook 端点上的版本。**事件负载是调用方最容易感到意外的地方。
  5. **每个版本一条体验日志条目。**让它写明版本、日期、谁受影响以及该做什么。什么才算破坏性变更是判断什么内容应该进入新版本的标准,而 API 体验日志一文则讲解了条目本身。

在受支持的版本数量迫使你这样做之前,先跳过模块链。两三个在线版本,用几个分支和一个停用日期就能处理,停用一个 API 版本里有详细的演示。

如果你发布了一份带日期的体验日志,版本历史的质量就取决于它的条目。在 Changeloop 中,每个已合并的 pull request 都会生成一条草稿条目,并留给人批准,之后才会发布到体验日志页面和信息流。每个版本的条目就是在这里写成的,而唯一一道人工关卡,就是那次说明调用方必须做什么的评审。

FAQ

Stripe API 的最新版本是什么? 截至本文撰写时(2026 年 10 月),Stripe 的版本控制页面声明当前版本是 2026-09-30.endive。Stripe 每月发布一个新版本,所以固定版本之前请查看它的变更日志,并把版本写进你的代码,而不要依赖账户默认版本。

如何在请求上设置 Stripe API 版本? 发送 Stripe-Version 请求头,例如 Stripe-Version: 2026-09-30.endive,或者在服务端 SDK 中全局设置版本或按请求设置版本。两者都没有时,请求会使用你账户的默认版本,它由你在 Workbench 中设置。

Webhook 使用的 Stripe API 版本与我的请求相同吗? 不一定。Webhook 事件使用创建端点时设置的版本,如果没有设置,则使用账户默认版本。升级 SDK 并不会改变你的 webhook 处理程序收到的负载,所以要单独升级端点,并且并行测试它们。

Stripe 式的日期版本控制适合小型 API 吗? 带日期的版本、固定的默认版本、单次请求的请求头,以及每个版本一条体验日志条目,成本都很低,值得借鉴。内部的版本变更模块链则不适合,除非你要同时支持很多旧版本。可以先从两个在线版本和一个旧版本的停用日期开始。


本文的技术内容未经独立审核。如有错误,请告诉我们,我们会更正。

changeloop 相关页面: 开发者文档

changeloop
打造闭环 changelog 的团队。用户提出需求,你的团队交付,提出需求的人得知结果。