Skip to Content
概念会话
View as Markdown

会话

CheckoutSession 是买家交互的对象 — 有时限、一次性,拥有托管收银台 URL。它是三大核心实体里最轻的一个。你的大部分逻辑与 Orders 和 Payment Intents(见下文)打交道。

三实体数据模型

CheckoutSession ← 1:1 → Order ← 1:N → PaymentIntent (buyer) (catalog) (each pay attempt)
实体用途生命周期
CheckoutSession买家向外 — 有 session_key、checkout_url、TTL数分钟(默认 30)
Order你的目录状态 — 明细项、总额、退款永久记录
PaymentIntent一条链/资产上的一次支付尝试数小时;结算或过期

你通过 POST /b2b/v1/checkout-sessions/quick 同时创建一个会话和 一个订单。每次买家在结账页上挑一种资产时,都会针对对应的链打开一个 全新的 PaymentIntent。如果他们中途切换资产,之前的 intent 进入 EXPIRED,新 intent 开始。

标识符

会话由其 session_key 标识:

cst_G-SO92J7HNWkwMHEHjD4oO1Z

URL 安全,前缀之后约 24 个字符。 托管收银台是 https://checkout.infraio.xyz/<session_key> — 把 session_key 当作那一次结账的 bearer 凭据对待。

生命周期 — CheckoutSession

状态含义
ACTIVE会话已创建并开放。结账 URL 可用。
COMPLETED该会话上的某条 PaymentIntent 已结算。Order 现在是 PAID(欠付则 PARTIAL_PAID)。
EXPIREDexpires_at 已过且未结算。任何打开的 Order 都会被取消。
CANCELED显式取消 — 要么买家点了”取消”,要么你调用了取消端点。

三个终态互斥且终局。如果你想重试(例如欠付后),可以对同一 Order 创建一个新的 CheckoutSession。

TTL

  • 默认: 30 分钟(可通过 create 上的 expires_in 字段配置,单位秒)。
  • 边界: 不强制最小或最大值。请选择匹配你买家决策窗口的值: 低于 60 秒可能让合法买家超时,而保持打开超过 7 天的会话几乎 肯定已被放弃。
  • 每商户默认: 可在仪表板中设置,但只有 POST /b2b/v1/checkout-sessions(两步)会遵守它。 POST /b2b/v1/checkout-sessions/quick 在省略 expires_in 时使用 30 分钟,不论仪表板如何设置。如果要在 /quick 上使用不同的 默认值,请在每次调用时传 expires_in。
  • 执行: 一个 expires_at 已过的会话即便状态尚未更新,也会被视为 EXPIRED,所以不要在到期的精确时刻依赖状态值。

欠付

如果买家发送的金额少于会话金额,PaymentIntent 仍然按部分金额结算, Order 转为 PARTIAL_PAID。CheckoutSession 进入 COMPLETED (一条 PaymentIntent 已结算),所以它不再可重用。

要把缺额视为全额支付,可以把订单解决为 PAID。见 概念 → 订单(无法通过 API 解决; 要保持自助,请改为收齐剩款)。要收齐剩款,对同一 Order 用剩余金额 创建新的 CheckoutSession。

超付

如果买家发送的金额超过会话金额(罕见,但人工转账时会发生),InfraIO Pay 会在 24 小时内检测到超付并通知你。它不会自动退款,请通过 退款 API 或仪表板发起退款。

错资产支付

收款地址是为某一个会话、网络和资产生成的。如果买家向它发送其他资产, 该付款不会被匹配,PaymentIntent 会一直保持打开,直到会话过期。 支持团队可以协助找回资金,但这不是自动的。请告诉买家发送结账页面 显示的精确资产。

TRON、Solana 和 TON 没有独立收款地址,因此这仅适用于 EVM 网络:买家直接向你的资金库钱包付款。见直达钱包的网络。

create 上的幂等

POST /b2b/v1/checkout-sessions/quick 接受请求 body 中的 idempotency_key 字段(注意:body 字段,不是 HTTP 标头)。 如果你没有天然 key,请生成一个 UUID。

这个 key 去重的是 Order,而不是 CheckoutSession。用同一个 key 重试时, /quick 返回 原始 order(order_id 稳定),但每次都铸造一个全新的 CheckoutSession — 每次都是新的 session_key 和 checkout_url。这是 有意为之:一个 Order 可以背靠多次结账尝试(见 订单),所以重试的 /quick 会在不重复 order 的前提下给买家一个干净的会话。

有两点行为需要注意:

  • body 不会被哈希或比较。 用 不同 的 body 复用一个 key 不会 返回 409 — 服务端会静默返回该 key 名下已存的 order,并忽略新的 body。所以请把 idempotency_key 当作单个逻辑 order 的一次性令牌; 绝不要跨不同购物车回收使用。
  • 只有 Order 被去重,会话不会。 如果你需要拿回 同一个 结账 URL, 请把第一次响应里的 session_key / checkout_url 持久化下来 — 再次 调用 /quick 不会返回旧的。要枚举某个 order 名下铸造过的每一个会话, 用 GET /b2b/v1/checkout-sessions/by-order/:order_id。

API 端点

方法路径备注
POST/b2b/v1/checkout-sessions/quick一次调用创建订单 + 会话
POST/b2b/v1/checkout-sessions针对已存在订单创建会话
GET/b2b/v1/checkout-sessions/by-order/:order_id列出某订单的所有会话(用于重试历史)

完整 create 请求 body 与签名见 快速入门。

下一步