Order 能力规范

基本信息

  • Capability Namedev.ucp.shopping.order
  • Version2026-01-11
  • 官方规范order.md

概述

Order 代表从成功结账提交产生的确认交易。它提供完整的购买记录、交付方式和下单后发生的事件。

核心概念

订单有三个主要组件:

Line Items(行项目) — 结账时购买的内容:

  • 包含当前数量计数(总计、已履约)

Fulfillment(履约) — 商品如何交付:

  • Expectations(期望) — 面向买家的交付承诺
  • Events(事件) — 仅追加日志,记录实际发生的事件

Adjustments(调整) — 独立于履约的订单后事件:

  • 通常是资金流动(退款、退货、积分、争议、取消)
  • 可以是任何订单后变更
  • 可以在履约前、中、后发生

数据模型

Line Items(行项目)

行项目反映结账时购买的内容及其当前状态:

  • 商品详情(产品、价格、订购数量)
  • 数量计数和状态是派生的

数量结构

{
  "total": 3,      // 当前总数量
  "fulfilled": 2   // 已履约数量
}

状态派生

if (fulfilled == total) → "fulfilled"
else if (fulfilled > 0) → "partial"
else → "processing"

Fulfillment(履约)

履约跟踪商品如何交付给买家。

Expectations(期望)

Expectations 是面向买家的商品分组(如"包裹 📦"),代表:

  • 哪些商品被分组在一起
  • 它们去哪里(destination
  • 如何交付(method_type
  • 何时到达(descriptionfulfillable_on

Expectations 可以在订单后拆分、合并或调整。例如:

  • 按交付日期分组:“何时到达什么”
  • 使用单一 expectation 配合宽泛日期范围以保持灵活性
  • 目标是设定买家期望 — 提供最佳买家体验

Fulfillment Events(履约事件)

Fulfillment Events 是跟踪物理发货的仅追加日志:

  • 按 ID 和数量引用行项目
  • 包含跟踪信息
  • type 是开放字符串字段 — 商家可使用任何有意义的值
    • 常见示例:processingshippedin_transitdeliveredfailed_attemptcanceledundeliverablereturned_to_sender

Adjustments(调整)

Adjustments 是独立于履约存在的仅追加事件日志:

  • type 是开放字符串字段 — 商家可使用任何有意义的值
    • 通常是资金流动:refundreturncreditprice_adjustmentdisputecancellation
  • 可以是任何订单后变更
  • 可选择链接到行项目(或订单级别,如运费退款)
  • 包含相关金额
  • 可随时发生,不论履约状态

订单示例

{
  "ucp": {
    "version": "2026-01-11",
    "capabilities": [
      {"name": "dev.ucp.shopping.order", "version": "2026-01-11"}
    ]
  },
  "id": "order_abc123",
  "checkout_id": "checkout_xyz789",
  "permalink_url": "https://business.com/orders/abc123",
  "line_items": [
    {
      "id": "li_shoes",
      "item": { "id": "prod_shoes", "title": "Running Shoes", "price": 3000 },
      "quantity": { "total": 3, "fulfilled": 3 },
      "totals": [
        {"type": "subtotal", "amount": 9000},
        {"type": "total", "amount": 9000}
      ],
      "status": "fulfilled"
    },
    {
      "id": "li_shirts",
      "item": { "id": "prod_shirts", "title": "Cotton T-Shirt", "price": 2000 },
      "quantity": { "total": 2, "fulfilled": 0 },
      "totals": [
        {"type": "subtotal", "amount": 4000},
        {"type": "total", "amount": 4000}
      ],
      "status": "processing"
    }
  ],
  "fulfillment": {
    "expectations": [
      {
        "id": "exp_1",
        "line_items": [{ "id": "li_shoes", "quantity": 3 }],
        "method_type": "shipping",
        "destination": {
          "street_address": "123 Main St",
          "address_locality": "Austin",
          "address_region": "TX",
          "address_country": "US",
          "postal_code": "78701"
        },
        "description": "Arrives in 2-3 business days",
        "fulfillable_on": "now"
      },
      {
        "id": "exp_2",
        "line_items": [{ "id": "li_shirts", "quantity": 2 }],
        "method_type": "shipping",
        "destination": {
          "street_address": "123 Main St",
          "address_locality": "Austin",
          "address_region": "TX",
          "address_country": "US",
          "postal_code": "78701"
        },
        "description": "Backordered - ships Jan 15, arrives in 7-10 days",
        "fulfillable_on": "2025-01-15T00:00:00Z"
      }
    ],
    "events": [
      {
        "id": "evt_1",
        "occurred_at": "2025-01-08T10:30:00Z",
        "type": "delivered",
        "line_items": [{ "id": "li_shoes", "quantity": 3 }],
        "tracking_number": "123456789",
        "tracking_url": "https://fedex.com/track/123456789",
        "description": "Delivered to front door"
      }
    ]
  },
  "adjustments": [
    {
      "id": "adj_1",
      "type": "refund",
      "occurred_at": "2025-01-10T14:30:00Z",
      "status": "completed",
      "line_items": [{ "id": "li_shoes", "quantity": 1 }],
      "amount": 3000,
      "description": "Defective item"
    }
  ],
  "totals": [
    { "type": "subtotal", "amount": 13000 },
    { "type": "shipping", "amount": 1200 },
    { "type": "tax", "amount": 1142 },
    { "type": "total", "amount": 15342 }
  ]
}

事件机制

商家在订单下单后发送订单状态变更事件。

事件机制方法端点描述
Order Event WebhookPOST平台提供的 URL商家向平台发送订单生命周期事件

Order Event Webhook

商家 POST 订单事件到合作伙伴入驻期间平台提供的 webhook URL。URL 格式是平台特定的。

Webhook URL 配置

平台在能力协商期间在 order 能力的 config 字段中提供其 webhook URL。商家从平台的 profile 发现此 URL 并用于发送订单生命周期事件。

示例:

{
  "name": "dev.ucp.shopping.order",
  "version": "2026-01-11",
  "config": {
    "webhook_url": "https://platform.example.com/webhooks/ucp/orders"
  }
}

Webhook 签名验证

Webhook 负载 MUST 由商家签名并由平台验证以确保真实性和完整性。

签名(商家)

  1. 从 UCP profile 的 signing_keys 数组中选择一个密钥
  2. 使用选定密钥创建请求体的分离 JWT (RFC 7797)
  3. Request-Signature header 中包含 JWT
  4. 在 JWT header 的 kid claim 中包含密钥 ID,使接收方能识别使用哪个密钥进行验证

验证(平台)

  1. 从传入的 webhook 请求中提取 Request-Signature header
  2. 解析 JWT header 以检索 kid(密钥 ID)
  3. /.well-known/ucp 获取商家的 UCP profile(适当缓存)
  4. signing_keys 中定位具有匹配 kid 的密钥
  5. 使用公钥验证请求体的 JWT 签名
  6. 如果验证失败,以适当的错误响应拒绝 webhook

密钥轮换

signing_keys 数组支持多个密钥以实现零停机轮换:

  • 添加新密钥:将新密钥添加到 signing_keys,然后开始使用它签名。验证者将通过 kid 找到它。
  • 删除旧密钥:在足够时间让所有进行中的 webhook 交付后,从 signing_keys 中删除旧密钥。

实现指南

平台要求

  • MUST 快速响应 2xx HTTP 状态码以确认接收
  • 响应后异步处理事件

商家要求

  • MUST 使用其 signing_keys 数组中的密钥(发布在 /.well-known/ucp)对所有 webhook 负载签名。签名 MUST 包含在 Request-Signature header 中作为分离 JWT (RFC 7797)
  • MUST 发送"订单已创建"事件并包含完整填充的订单实体
  • MUST 在更新时发送完整订单实体(而非增量 delta)
  • MUST 重试失败的 webhook 交付
  • MUST 在 webhook 路径或 headers 中包含商家标识符

实施检查清单

平台实施检查

  • 提供 webhook URL 端点
  • 快速响应 2xx 状态码
  • 异步处理 webhook 事件
  • 验证 webhook 签名
  • 处理密钥轮换

商家实施检查

  • 签名所有 webhook 负载
  • 发送完整订单实体
  • 重试失败的交付
  • 包含商家标识符
  • 支持密钥轮换

参考链接