Order 能力规范
基本信息
- Capability Name:
dev.ucp.shopping.order - Version:
2026-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) - 何时到达(
description、fulfillable_on)
Expectations 可以在订单后拆分、合并或调整。例如:
- 按交付日期分组:“何时到达什么”
- 使用单一 expectation 配合宽泛日期范围以保持灵活性
- 目标是设定买家期望 — 提供最佳买家体验
Fulfillment Events(履约事件)
Fulfillment Events 是跟踪物理发货的仅追加日志:
- 按 ID 和数量引用行项目
- 包含跟踪信息
type是开放字符串字段 — 商家可使用任何有意义的值- 常见示例:
processing、shipped、in_transit、delivered、failed_attempt、canceled、undeliverable、returned_to_sender
- 常见示例:
Adjustments(调整)
Adjustments 是独立于履约存在的仅追加事件日志:
type是开放字符串字段 — 商家可使用任何有意义的值- 通常是资金流动:
refund、return、credit、price_adjustment、dispute、cancellation
- 通常是资金流动:
- 可以是任何订单后变更
- 可选择链接到行项目(或订单级别,如运费退款)
- 包含相关金额
- 可随时发生,不论履约状态
订单示例
{
"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 Webhook | POST | 平台提供的 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 由商家签名并由平台验证以确保真实性和完整性。
签名(商家)
- 从 UCP profile 的
signing_keys数组中选择一个密钥 - 使用选定密钥创建请求体的分离 JWT (RFC 7797)
- 在
Request-Signatureheader 中包含 JWT - 在 JWT header 的
kidclaim 中包含密钥 ID,使接收方能识别使用哪个密钥进行验证
验证(平台)
- 从传入的 webhook 请求中提取
Request-Signatureheader - 解析 JWT header 以检索
kid(密钥 ID) - 从
/.well-known/ucp获取商家的 UCP profile(适当缓存) - 在
signing_keys中定位具有匹配kid的密钥 - 使用公钥验证请求体的 JWT 签名
- 如果验证失败,以适当的错误响应拒绝 webhook
密钥轮换
signing_keys 数组支持多个密钥以实现零停机轮换:
- 添加新密钥:将新密钥添加到
signing_keys,然后开始使用它签名。验证者将通过kid找到它。 - 删除旧密钥:在足够时间让所有进行中的 webhook 交付后,从
signing_keys中删除旧密钥。
实现指南
平台要求
- MUST 快速响应 2xx HTTP 状态码以确认接收
- 响应后异步处理事件
商家要求
- MUST 使用其
signing_keys数组中的密钥(发布在/.well-known/ucp)对所有 webhook 负载签名。签名 MUST 包含在Request-Signatureheader 中作为分离 JWT (RFC 7797) - MUST 发送"订单已创建"事件并包含完整填充的订单实体
- MUST 在更新时发送完整订单实体(而非增量 delta)
- MUST 重试失败的 webhook 交付
- MUST 在 webhook 路径或 headers 中包含商家标识符
实施检查清单
平台实施检查
- 提供 webhook URL 端点
- 快速响应 2xx 状态码
- 异步处理 webhook 事件
- 验证 webhook 签名
- 处理密钥轮换
商家实施检查
- 签名所有 webhook 负载
- 发送完整订单实体
- 重试失败的交付
- 包含商家标识符
- 支持密钥轮换