Stripe Checkout Session、PaymentIntent、SetupIntent和Charge有什么区别?
Checkout Session管理一段完整结账会话,可包含商品、税费、折扣、配送、订阅和支付界面;PaymentIntent跟踪一次付款意图从创建、确认、认证到成功或失败的生命周期;SetupIntent用于保存并优化支付方式供未来使用,本身不产生扣款;Charge记录一次实际付款尝试及其金额、捕获、退款、争议和付款方式结果。
本文目录(19 节)
直接答案
Checkout Session管理一段完整结账会话,可包含商品、税费、折扣、配送、订阅和支付界面;PaymentIntent跟踪一次付款意图从创建、确认、认证到成功或失败的生命周期;SetupIntent用于保存并优化支付方式供未来使用,本身不产生扣款;Charge记录一次实际付款尝试及其金额、捕获、退款、争议和付款方式结果。
这些对象不是四种互斥的收款方式。一次Checkout Session在 payment 模式下通常会关联PaymentIntent,PaymentIntent在尝试收款时可能关联一个或多个Charge;仅保存支付方式的流程则使用SetupIntent。排障应先确定当前流程创建了哪个顶层对象,再沿关联ID追踪,而不是把所有 cs_、pi_、seti_ 和 ch_ 当成同类订单号。
一、对象职责对比
| 对象 | 常见ID前缀 | 主要职责 | 是否代表实际扣款 |
|---|---|---|---|
| Checkout Session | cs_ | 管理结账页面与完整会话 | 不直接等同于扣款 |
| PaymentIntent | pi_ | 管理一次付款的状态机 | 目标是完成一次成功付款 |
| SetupIntent | seti_ | 保存并优化未来使用的支付方式 | 否 |
| Charge | ch_ | 记录具体付款尝试及资金结果 | 是一次付款尝试记录 |
自己的订单ID仍应保存在业务数据库中,并通过受控的metadata或本地映射与Stripe对象关联。不要用客户邮箱或银行卡信息充当关联键。
二、Checkout Session是什么
Checkout Sessions API用于构建完整结账流程。Stripe官方说明,它可以管理托管页面、嵌入式表单或自定义Elements界面,并覆盖行项目、税费、折扣、配送、订阅和结账状态。Stripe将其作为多数集成的推荐起点,因为需要自行维护的结账逻辑更少。
Session有自身状态和过期规则。用户打开结账页不代表支付已成功;返回成功页面也不是服务器履约的充分证据。应用应根据Webhook和关联付款对象确认最终状态。
三、PaymentIntent是什么
PaymentIntent表示收取一笔付款的意图,并在生命周期中经历多个状态。它保存金额、币种、支付方式配置及认证要求,能够处理3D Secure等额外客户动作。Stripe建议通常为每个订单或客户会话创建一个PaymentIntent。
PaymentIntent不是“创建后立刻扣款”的静态记录。它可能处于 requires_、requires_、requires_action、processing、requires_、succeeded 或取消状态。业务逻辑必须按实际状态处理,不能只判断对象是否存在。
四、SetupIntent是什么
SetupIntent用于设置和保存支付方式,以便未来付款。Stripe官方明确说明,它类似付款设置流程,但不会创建Charge。银行或支付网络可能仍要求客户认证,以提高以后离线或在线使用该支付方式的成功率。
租赁押后扣款、订阅前保存卡、会员后续续费等场景可能使用SetupIntent。若当前就要收款,则通常应使用PaymentIntent,并按需要设置未来用途,而不是误把SetupIntent成功当作到账。
五、Charge是什么
Charge是具体付款尝试的记录,包含拟收金额、已捕获金额、已退款金额、支付方式详情、失败信息、收据、争议状态和余额交易等。使用现代PaymentIntents流程时,Charge通常由PaymentIntent在付款尝试过程中创建。
一个PaymentIntent可能因为重试而关联多个Charge,但最终最多形成一个成功付款结果。看到多个 ch_ 不应立即判定客户被重复扣款,应逐项检查状态、捕获金额、退款和关联的PaymentIntent。
六、四个对象如何关联
典型一次性Checkout流程可以表示为:
本地订单
└─ Checkout Session (cs_)
└─ PaymentIntent (pi_)
├─ Charge attempt 1 (ch_, failed)
└─ Charge attempt 2 (ch_, succeeded)
仅保存支付方式的流程可能是:
客户账户
└─ SetupIntent (seti_)
└─ PaymentMethod,供以后付款使用
订阅流程还可能关联Customer、Subscription、Invoice等对象,不能用上述简图替代具体集成文档。
七、Checkout Session和PaymentIntent怎么选
Stripe官方对比指出,Checkout Sessions适合希望用较少代码管理完整结账功能的多数集成;Payment Intents是更底层的API,适合需要完全自行控制结账状态、税费、折扣、订阅和货币转换逻辑的团队。
选择PaymentIntent意味着不仅自定义界面,还要承担更多状态管理、错误恢复和长期维护。若只是因为“自定义程度高”就绕过Checkout Session,应先列出确实无法由Session满足的需求。
八、PaymentIntent和Charge为什么不能混用
PaymentIntent是跨多次尝试的付款状态机,Charge是单次尝试的结果记录。订单履约通常关注PaymentIntent最终是否成功;分析拒付原因、收据、捕获或退款时,则常需要查看具体Charge。
只保存最后一个Charge ID会丢失PaymentIntent层的认证和重试上下文。只保存PaymentIntent ID又可能不足以解释某次失败尝试。合理做法是保存本地订单到PaymentIntent的主映射,并按需读取关联Charge。
九、SetupIntent和PaymentIntent有什么区别
SetupIntent的目标是准备支付凭据供未来使用,不产生付款;PaymentIntent的目标是收取指定金额。两者都可能触发客户认证,因此“用户完成3DS”也不能单独说明发生了扣款。
若支付方式需要以后离线扣款,应正确声明使用场景并取得客户授权。具体合规要求取决于地区、支付方式和业务模式,不能仅靠一个API参数代替授权流程。
十、前端成功页为什么不能作为到账依据
客户可能在跳转完成前关闭页面,攻击者也可以直接访问成功URL,异步支付方式还可能在页面返回后继续处理。服务器应监听并验证Stripe Webhook,根据适用于集成的最终事件与对象状态执行履约。
Webhook处理要验签、幂等并允许重复投递。把Session ID或PaymentIntent ID与本地订单关联,确保同一成功事件不会重复发货、充值或发送许可证。
十一、常见状态如何解释
- Session显示
open:结账会话仍可继续,不代表付款成功。 - PaymentIntent显示
requires_action:客户还需完成认证或其他动作。 - PaymentIntent显示
processing:付款仍在异步处理中。 - PaymentIntent显示
requires_:授权可能成功,但尚未完成捕获。capture - PaymentIntent显示
succeeded:付款意图成功,仍需核对订单关联和金额。 - SetupIntent显示成功:支付方式设置完成,不代表收款。
- Charge显示失败:该次尝试失败,不排除同一PaymentIntent后来成功。
状态枚举可能随对象和支付方式不同,应以当前API版本的官方说明为准。
十二、如何防止重复对象和重复付款
为同一本地购物车保存并复用既有PaymentIntent,而不是每次刷新都创建新对象。Stripe官方建议创建请求使用幂等键,且通常一个订单或客户会话对应一个PaymentIntent。
Checkout Session也应与本地订单建立唯一映射。接收Webhook时以事件ID去重,同时让“订单由未支付变为已支付”的数据库更新具有条件约束。幂等键、事件去重和订单状态约束解决的是不同层的问题,不能只实现一个。
十三、对账时看哪个对象
从本地订单开始,找到Session或PaymentIntent,再查看成功Charge与其balance transaction。金额、币种、捕获、退款和争议应在正确对象层核对。不要只凭Dashboard中的显示名称猜测关联关系。
若同一订单出现多个对象,记录创建时间、livemode、客户、metadata和关联ID。先排除测试与生产模式混用,再判断是客户重试、应用重复创建,还是确有多次独立订单。
十四、最小排障流程
- 记录本地订单ID及预期金额、币种,遮盖客户敏感数据。
- 判断入口是Checkout Session、自建PaymentIntent还是SetupIntent。
- 核对对象是否属于正确Stripe账户和live/test模式。
- 沿关联字段找到PaymentIntent与Charge。
- 读取状态、最近错误和下一步动作,而非只看HTTP 200。
- 核对Webhook验签、事件去重和订单状态更新日志。
- 对异步支付等待最终事件,不用浏览器返回页提前履约。
- 在测试模式重放最小场景,确认失败、认证和成功路径均可恢复。
不要把Secret Key、PaymentIntent client secret、完整Webhook内容或客户支付资料写入普通日志。
十五、常见误区
- 把Checkout Session当作付款成功证明。
- SetupIntent成功后直接标记订单已付款。
- 看到多个Charge就断定重复扣款。
- 为每次页面刷新创建新PaymentIntent。
- 只依赖前端成功回调发货。
- 用测试模式对象ID查询生产账户。
- 在metadata中存储银行卡或其他敏感数据。
- 忽略异步付款的
processing阶段。
十六、FAQ
一个Checkout Session一定有PaymentIntent吗?
不一定。关联对象取决于Session模式和流程,例如订阅或仅设置支付方式会有不同关系。应查看该Session的实际字段与官方模式说明。
一个PaymentIntent为什么会有多个Charge?
付款重试可能生成多个Charge尝试,其中部分失败。应核对每个Charge状态与最终成功结果,而不是按数量判断扣款次数。
SetupIntent会做小额扣款验证吗?
SetupIntent本身目标不是收款,但具体支付方式的验证过程可能由银行或网络显示临时验证行为。应依据支付方式文档和最终对象状态解释。
PaymentIntent成功后还要处理Webhook吗?
要。服务器端Webhook可覆盖客户未返回页面、异步状态变化和重试场景,是可靠履约的重要依据。
Charge和订单是一一对应吗?
不一定。Charge对应付款尝试,本地订单可能经历多个尝试;业务系统应通过PaymentIntent、Session和自己的订单映射建立关系。
十七、结论
Checkout Session管理完整结账体验,PaymentIntent管理一次付款生命周期,SetupIntent准备未来使用的支付方式,Charge记录具体付款尝试。把它们按层关联,并以Webhook、幂等和本地订单状态共同控制履约,才能正确处理认证、异步付款、重试与对账。
核验来源
- Stripe Docs:The Checkout Sessions API,https:
/ :2026-08-25)/ docs. stripe. com/ payments/ checkout- sessions(核验日期 - Stripe Docs:Compare Checkout Sessions and Payment Intents,https:
/ :2026-08-25)/ docs. stripe. com/ payments/ checkout- sessions- and- payment- intents- comparison(核验日期 - Stripe Docs:The Payment Intents API,https:
/ :2026-08-25)/ docs. stripe. com/ payments/ payment- intents(核验日期 - Stripe Docs:The Setup Intents API,https:
/ :2026-08-25)/ docs. stripe. com/ payments/ setup- intents(核验日期 - Stripe API Reference:The Charge object,https:
/ :2026-08-25)/ docs. stripe. com/ api/ charges/ object(核验日期