Skip to Content
概念订单

订单

如果说 CheckoutSession 是买家看到的东西, 那么 Order 就是关心的东西。它是以下事实的永久记录:

  • 买了什么(明细项)
  • 应付多少、实际收到多少
  • 待处理与已执行的退款
  • 你的外部引用(external_ref)— 通常是你自己的订单 ID,存储在 Order 上并通过 GET /b2b/v1/orders/{id} 返回(不会在 Webhook 负载中回显 — 见下文)

CheckoutSession 在其某个 PaymentIntent 结算或 TTL 过期后就死掉了。 Order 永远存在。

何时创建 Order

当你调用 POST /b2b/v1/checkout-sessions/quick 时,payment-service 在一次事务里同时创建一个新 Order 一个新 CheckoutSession。 如果你已经有 Order 并想重试结账(例如买家放弃后),改用 POST /b2b/v1/checkout-sessions 在现有订单上挂一个新会话 — 保留 审计轨迹。

生命周期

状态含义
DRAFT保留给未来的草稿流程。目前没有任何代码路径会创建 DRAFT 订单 — 每个订单创建时都是 PENDING,所以你不会观察到这个状态。
PENDING一个 CheckoutSession 在运行且未决出。
PAID全额结算。Webhook payment.settled 在此触发。 可以放心履约。
PARTIAL_PAID资金到达但少于总额。见下面”欠付”。
CANCELED会话过期或商户取消。metadata.canceled_reason 解释原因(payment_timeoutmerchant_canceled、……)。
REFUNDED所有已付款金额都已退款。
PARTIALLY_REFUNDED部分退款已执行但仍有余额保持已付。

你履约逻辑要切换的状态是 PAID — 不是 CheckoutSession 的 COMPLETEDpayment.settled Webhook 才是规范信号。

external_ref 字段

创建会话时你可以包含 external_ref(任意字符串,最长 255 字符 — 通常是你自己的订单 ID)。它穿过整个管道:

  • 存储在 Order 上
  • 在商户仪表板可见,便于支持查询
  • GET /b2b/v1/orders/{id} 返回,这样 Webhook 处理函数收到 payment.settled 后可以读取

Webhook 负载今天直接回显 external_ref — 本文档早期草稿 曾声称 data.external_ref 流经每个事件,那是错的。要把一个 payment.* Webhook 映射回你 DB 中的行,请从负载里取 order_id, 然后反查订单。Webhook 负载上原生的 external_ref 字段在路线图上。

欠付

如果买家的链上转账清算金额少于订单总额,Order 进入 PARTIAL_PAID。 你有三种选择:

  1. 接受并解决。 把订单翻为 PAID,发出 order.resolved。这 是公共 REST 端点 — 解决今天是内部 / 运维动作,所以自助流程更倾向 选项 2(收齐剩款)。
  2. 等待剩款。amount_due = 剩余值,对同一个 Order 创建一个 新的 CheckoutSession。买家付差额;结算后,Order 转为 PAID
  3. 取消并退款。 退还部分金额并取消 Order。任何链上手续费由买家承担。

产品对此没有给出推荐 — 不同商户想要不同策略。挑一个并固化进你的 管理工具。

退款

退款是独立的 API 表面和独立的概念页。 见 概念 → 退款

API 端点

方法路径备注
POST/b2b/v1/orders不带会话创建 Order(罕见)
GET/b2b/v1/orders/:order_id读取含明细项 + 付款历史的完整订单
PATCH/b2b/v1/orders/:order_id/cancel取消未支付订单
PATCH/b2b/v1/orders/:order_id/reopen重新打开一个自动取消(payment_timeout)的订单

下一步