本指南提供技術 API 參考資料和酬載結構定義,說明如何使用通用商務通訊協定 (UCP) 第 2026-04-08 版的 Webhook,將完整的訂單狀態更新、出貨事件和調整項目推送至 Google。
建立端點前,請務必先查看訂單生命週期總覽,瞭解高階概念、必要事件和 Webhook 端點詳細資料。
驗證和要求簽署
版本 2026-04-08 的主要變更包括導入新的必要 Webhook 標頭和特定要求簽署程序。
必要的 Webhook 標頭
所有 Webhook 要求都必須包含下列 HTTP 標頭:
Webhook-Id:這個特定 Webhook 事件的專屬 ID。這個 ID 應與傳送的主要事件 (例如履單事件 ID 或調整事件 ID) 的id相符。Webhook-Timestamp:指出事件發生時間的時間戳記。
這些標頭會取代訂單酬載中先前預期的 id 和 created_time 欄位。
要求簽署
- 計算原始要求主體的 SHA-256 摘要,並設定
Content-Digest標頭。 - 在 UCP 設定檔中選取
signing_keys的簽署金鑰。 - 根據 RFC 9421 建構簽章基底。
- 查看已簽署元件的規格
- 設定
UCP-Agent、Signature-Input和Signature標頭。UCP-Agent是 UCP 設定檔的連結,格式為profile="https://merchant.example.com/.well-known/ucp"。Signature-Input是描述簽章內所含元件的字典結構化欄位,以及用於簽署的keyid,必須與 UCP 設定檔中signing_keys所選簽署金鑰的kid相符。Signature標頭包含簽章基底,該基底會使用您的私密金鑰簽署,然後以 Base64 編碼。
詳情請參閱 ucp.dev 上的簽署說明。
訂單建立事件
- 觸發條件:訂單確認後 (
status: processing) 立即傳送。
這個版本的主要異動:
- 現在,Order 物件的頂層必須有
currency欄位。 totals陣列中每個物件的type欄位現在是開放式字串 (例如「小計」、「稅金」、「費用」、「總計」)。- 強制性
Webhook-Id標頭包含 Webhook 事件的專屬 ID。請注意,酬載中包含訂單確認 ID 的id欄位仍為必填。 - 強制性
Webhook-Timestamp標頭會提供建立時間,取代酬載中的舊created_time欄位。
範例:這個範例顯示買家完成結帳後建立的訂單。
必要標頭:
Webhook-Id: order_01Webhook-Timestamp: 2026-03-23T19:00:00Z
{
"ucp": {
"version": "2026-04-08",
"capabilities": {
"dev.ucp.shopping.order": [{"version": "2026-04-08"}]
}
},
"id": "order_01",
"checkout_id": "checkout_01",
"currency": "USD",
// Always include all line items, even for single-item checkouts. This ensures any add-ons, gifts, or separate charges are accounted for.
"line_items": [
{
"id": "line_1",
"item":
{
"id": "product_123",
"title": "Running Shoes",
"price": 10000
},
"quantity": { "total": 1, "fulfilled": 0 },
"totals": [
{"type": "subtotal", "display_text": null, "amount": 10000},
{"type": "total", "display_text": null, "amount": 10000}
],
// The status of a line item must match total and fulfilled quantities (e.g., total 1, fulfilled 0 -> status: processing).
"status": "processing"
}
],
"totals": [
{"type": "subtotal", "display_text": "Subtotal", "amount": 10000}, // Tax-inclusive markets: Set display_text to "Subtotal (including taxes)". Amount must include tax.
{"type": "fee", "display_text": "Service Fee", "amount": 100},
{"type": "tax", "display_text": "Tax", "amount": 800}, // Tax-inclusive markets: Omit this entry.
{"type": "total", "display_text": "Total", "amount": 10900}
],
"fulfillment": {
"expectations": [
{
"id": "exp_1",
"line_items": [{ "id": "line_1", "quantity": 1 }],
"method_type": "shipping",
"destination": {
"first_name": "Alice",
"last_name": "Example",
"street_address": "123 Main St",
"address_locality": "Austin",
"address_region": "TX",
"address_country": "US",
"postal_code": "78701"
},
"description": "Arrives in 2-3 business days", // Maximum length: 200 characters.
"fulfillable_on": "now"
}
]
},
"permalink_url": "https://merchant.example.com/orders/789"
}
配送事件
這些事件會以 fulfillment.events 陣列的形式傳送。
訂單已出貨
訂單中的商品出貨時。「已出貨」事件必須提供 tracking_number 和 tracking_url 欄位,系統才能在「我的訂單」頁面上正確分組項目。
訂購商品已送達
訂單中的商品送達時。
範例 (shipped 和 delivered):這個範例顯示商品出貨並送達後,訂單的更新情形。
必要標頭:
Webhook-Id: fulfill_evt_2Webhook-Timestamp: 2026-02-10T14:00:00Z
{
"ucp": {
"version": "2026-04-08",
"capabilities": {
"dev.ucp.shopping.order": [{"version": "2026-04-08"}]
}
},
"id": "order_01",
"checkout_id": "checkout_01",
"currency": "USD",
"line_items": [
{
"id": "line_1",
"item":
{
"id": "product_123",
"title": "Running Shoes",
"price": 10000
},
"quantity": { "total": 1, "fulfilled": 1 },
"totals": [
{"type": "subtotal", "amount": 10000},
{"type": "total", "amount": 10000}
],
"status": "fulfilled"
}
],
"totals": [
{"type": "subtotal", "amount": 10000},
{"type": "total", "amount": 10000}
],
// Updated fulfillment details
"fulfillment": {
"events": [
{
"id": "fulfill_evt_1",
"occurred_at": "2026-02-08T10:30:00Z",
"type": "shipped",
"line_items": [{ "id": "line_1", "quantity": 1 }],
"tracking_number": "123456789",
"tracking_url": "https://fedex.com/track/123456789",
"carrier": "FedEx",
"description": "Shipping departed from warehouse"
},
{
"id": "fulfill_evt_2",
"occurred_at": "2026-02-10T14:00:00Z",
"type": "delivered",
"line_items": [{ "id": "line_1", "quantity": 1 }],
"tracking_number": "123456789",
"tracking_url": "https://fedex.com/track/123456789",
"carrier": "FedEx",
"description": "Package delivered"
}
],
"expectations": [{ "...": "..." }]
},
"permalink_url": "https://merchant.example.com/orders/123"
}
多項商品訂單範例
下列範例說明如何為多項商品訂單和分批出貨訂單建構更新。如要瞭解包裹狀態的推導規則,請參閱這篇文章。
多件商品訂單,以同一包裹運送
這個範例顯示包含多個項目的單一包裹訂單更新。所有委刊項都會歸入同一個 shipped 事件,並共用相同的追蹤號碼。
必要標頭:
Webhook-Id: fulfill_evt_1Webhook-Timestamp: 2026-02-08T10:30:00Z
{
"ucp": {
"version": "2026-04-08",
"capabilities": {
"dev.ucp.shopping.order": [{"version": "2026-04-08"}]
}
},
"id": "order_multi_01",
"checkout_id": "checkout_multi_01",
"currency": "USD",
"line_items": [
{
"id": "line_1",
"item": { "id": "product_1", "title": "Item 1", "price": 5000 },
"quantity": { "total": 1, "fulfilled": 1 },
"totals": [
{"type": "subtotal", "display_text": null, "amount": 5000},
{"type": "total", "display_text": null, "amount": 5000}
],
"status": "fulfilled"
},
{
"id": "line_2",
"item": { "id": "product_2", "title": "Item 2", "price": 5000 },
"quantity": { "total": 1, "fulfilled": 1 },
"totals": [
{"type": "subtotal", "display_text": null, "amount": 5000},
{"type": "total", "display_text": null, "amount": 5000}
],
"status": "fulfilled"
}
],
"totals": [
{"type": "subtotal", "display_text": "Subtotal", "amount": 10000},
{"type": "fee", "display_text": "Shipping", "amount": 500},
{"type": "total", "display_text": "Total", "amount": 10500}
],
"fulfillment": {
"expectations": [
{
"id": "exp_1",
"line_items": [
{ "id": "line_1", "quantity": 1 },
{ "id": "line_2", "quantity": 1 }
],
"method_type": "shipping",
"destination": {
"first_name": "Alice",
"last_name": "Example",
"street_address": "123 Main St",
"address_locality": "Austin",
"address_region": "TX",
"address_country": "US",
"postal_code": "78701"
},
"description": "Standard Shipping",
"fulfillable_on": "now"
}
],
"events": [
{
"id": "fulfill_evt_1",
"occurred_at": "2026-02-08T10:30:00Z",
"type": "shipped",
"line_items": [
{ "id": "line_1", "quantity": 1 },
{ "id": "line_2", "quantity": 1 }
],
"tracking_number": "123456789",
"tracking_url": "https://fedex.com/track/123456789",
"carrier": "FedEx",
"description": "Both items shipped together"
}
]
},
"permalink_url": "https://merchant.example.com/orders/456"
}
多項商品訂單,分批出貨
這個範例顯示訂單更新,適用於分批出貨。有多個 shipped 事件,每個事件都參照該相應包裹中的特定 line_items,並有不同的追蹤號碼。由於每個包裹代表不同的出貨承諾 (例如多組結帳時的不同速度和費用),因此 expectations 也會分開。
必要標頭:
Webhook-Id: fulfill_evt_2Webhook-Timestamp: 2026-02-09T14:00:00Z
{
"ucp": {
"version": "2026-04-08",
"capabilities": {
"dev.ucp.shopping.order": [{"version": "2026-04-08"}]
}
},
"id": "order_multi_02",
"checkout_id": "checkout_multi_02",
"currency": "USD",
"line_items": [
{
"id": "line_1",
"item": { "id": "product_1", "title": "Item 1", "price": 5000 },
"quantity": { "total": 1, "fulfilled": 1 },
"totals": [
{"type": "subtotal", "display_text": null, "amount": 5000},
{"type": "total", "display_text": null, "amount": 5000}
],
"status": "fulfilled"
},
{
"id": "line_2",
"item": { "id": "product_2", "title": "Item 2", "price": 5000 },
"quantity": { "total": 1, "fulfilled": 1 },
"totals": [
{"type": "subtotal", "display_text": null, "amount": 5000},
{"type": "total", "display_text": null, "amount": 5000}
],
"status": "fulfilled"
}
],
"totals": [
{"type": "subtotal", "display_text": "Subtotal", "amount": 10000},
{"type": "fee", "display_text": "Shipping", "amount": 1500},
{"type": "total", "display_text": "Total", "amount": 11500}
],
"fulfillment": {
"expectations": [
{
"id": "exp_1",
"line_items": [{ "id": "line_1", "quantity": 1 }],
"method_type": "shipping",
"destination": {
"first_name": "Alice",
"last_name": "Example",
"street_address": "123 Main St",
"address_locality": "Austin",
"address_region": "TX",
"address_country": "US",
"postal_code": "78701"
},
"description": "Standard Shipping",
"fulfillable_on": "now"
},
{
"id": "exp_2",
"line_items": [{ "id": "line_2", "quantity": 1 }],
"method_type": "shipping",
"destination": {
"first_name": "Alice",
"last_name": "Example",
"street_address": "123 Main St",
"address_locality": "Austin",
"address_region": "TX",
"address_country": "US",
"postal_code": "78701"
},
"description": "Express Shipping",
"fulfillable_on": "now"
}
],
"events": [
{
"id": "fulfill_evt_1",
"occurred_at": "2026-02-08T10:30:00Z",
"type": "shipped",
"line_items": [{ "id": "line_1", "quantity": 1 }],
"tracking_number": "PKG1_TRACKING",
"tracking_url": "https://fedex.com/track/PKG1_TRACKING",
"carrier": "FedEx",
"description": "First item shipped in package 1"
},
{
"id": "fulfill_evt_2",
"occurred_at": "2026-02-09T14:00:00Z",
"type": "shipped",
"line_items": [{ "id": "line_2", "quantity": 1 }],
"tracking_number": "PKG2_TRACKING",
"tracking_url": "https://fedex.com/track/PKG2_TRACKING",
"carrier": "FedEx",
"description": "Second item shipped in package 2"
}
]
},
"permalink_url": "https://merchant.example.com/orders/457"
}
調整事件範例
以下範例說明如何建構退款、退貨和取消的更新。如需支援的事件及其定義清單,請參閱「訂單生命週期總覽」中的「調整事件」。
取消訂單和退款
這個範例顯示訂單在下訂後不久即取消並退款。
本例中,這個版本的主要變更如下:
- 受
cancellation影響的委刊項現在會使用主要line_items陣列中的"status": "removed"。 - 當
line_items.status為removed時:line_items.quantity.total設為0。- 原始數量會儲存在新的
line_items.quantity.original欄位中。
必要標頭:
Webhook-Id: adj_refund_1Webhook-Timestamp: 2026-02-09T11:05:00Z
{
"ucp": {
"version": "2026-04-08",
"capabilities": {
"dev.ucp.shopping.order": [{"version": "2026-04-08"}]
}
},
"id": "order_02",
"checkout_id": "checkout_02",
"currency": "USD",
"line_items": [
{
"id": "line_2",
"item": {
"id": "product_456",
"title": "Smart Watch",
"price": 29900
},
"quantity": {
"total": 0, // Item removed from order total.
"original": 1, // Original quantity before removal.
"fulfilled": 0 // Item was not fulfilled before cancellation.
},
"totals": [
{"type": "subtotal", "amount": 29900},
{"type": "tax", "amount": 2400},
{"type": "total", "amount": 32300}
],
"status": "removed" // Item is cancelled, returned, or refunded.
}
],
"totals": [
{"type": "subtotal", "amount": 29900},
{"type": "tax", "amount": 2400},
{"type": "total", "amount": 32300}
],
// Fulfillment expectations should still be present even if cancelled early.
"fulfillment": {
"expectations": [
{
"id": "exp_1",
"line_items": [{ "id": "line_2", "quantity": 1 }],
"method_type": "shipping",
"destination": {
"first_name": "Bob",
"last_name": "Consumer",
"street_address": "456 Oak Ave",
"address_locality": "Anytown",
"address_region": "CA",
"address_country": "US",
"postal_code": "90210"
},
"description": "Standard Shipping",
"fulfillable_on": "now"
}
]
// "events": [] // No fulfillment events occurred before cancellation.
},
"adjustments": [
{
"id": "adj_cancel_1",
"type": "cancellation",
"description": "Customer changed mind",
"line_items": [{ "id": "line_2", "quantity": -1 }],
"occurred_at": "2026-02-09T11:00:00Z",
"status": "completed"
},
{
"id": "adj_refund_1",
"type": "refund",
"description": "Refund for cancelled item",
"line_items": [{ "id": "line_2", "quantity": -1 }],
"totals": [
{"type": "subtotal", "display_text": "Subtotal", "amount": -29900}, // Negative amounts indicate money returned to the buyer. Tax-inclusive markets: Set display_text to "Subtotal (including taxes)". Amount must include tax.
{"type": "tax", "amount": -2400}, // Tax-inclusive markets: Omit this entry.
{"type": "total", "display_text": "Total", "amount": -32300}
],
"occurred_at": "2026-02-09T11:05:00Z",
"status": "completed"
}
],
"permalink_url": "https://merchant.example.com/orders/12345"
}
訂單退貨和退款
這個範例顯示訂單商品已出貨、送達,但後來退貨並退款。
本例中,這個版本的主要變更如下:
- 受
return影響的委刊項現在會使用主要line_items陣列中的"status": "removed"。 - 當
line_items.status為removed時:line_items.quantity.total設為0。- 原始數量會儲存在新的
line_items.quantity.original欄位中。
- 在
adjustments類型的return中,調整項內的line_items.quantity欄位會使用負值 (例如-1) 表示退回的項目。
必要標頭:
Webhook-Id: adj_refund_2Webhook-Timestamp: 2026-02-10T10:00:00Z
{
"ucp": {
"version": "2026-04-08",
"capabilities": {
"dev.ucp.shopping.order": [{"version": "2026-04-08"}]
}
},
"id": "order_03",
"checkout_id": "checkout_03",
"currency": "USD",
"line_items": [
{
"id": "line_3",
"item": {
"id": "product_789",
"title": "Wireless Earbuds",
"price": 14900
},
"quantity": {
"total": 0, // Item removed from order total.
"original": 1, // Original quantity before removal.
"fulfilled": 1 // Was fulfilled before return.
},
"totals": [
{"type": "subtotal", "amount": 14900},
{"type": "tax", "amount": 1200},
{"type": "total", "amount": 16100}
],
"status": "removed" // Item is cancelled, returned, or refunded.
}
],
"totals": [
{"type": "subtotal", "amount": 14900},
{"type": "tax", "amount": 1200},
{"type": "total", "amount": 16100}
],
"fulfillment": {
"events": [
{
"id": "fulfill_evt_1",
"occurred_at": "2026-02-05T09:00:00Z",
"type": "shipped",
"line_items": [{ "id": "line_3", "quantity": 1 }],
"tracking_number": "987654321",
"tracking_url": "https://fedex.com/track/987654321",
"carrier": "FedEx",
"description": "Item shipped"
},
{
"id": "fulfill_evt_2",
"occurred_at": "2026-02-07T16:00:00Z",
"type": "delivered",
"line_items": [{ "id": "line_3", "quantity": 1 }],
"tracking_number": "987654321",
"tracking_url": "https://fedex.com/track/987654321",
"carrier": "FedEx",
"description": "Item delivered"
},
{
"id": "fulfill_evt_3",
"occurred_at": "2026-02-09T09:00:00Z",
"type": "returned",
"line_items": [{ "id": "line_3", "quantity": 1 }],
"tracking_number": "987654321",
"tracking_url": "https://fedex.com/track/987654321",
"carrier": "FedEx",
"description": "Item returned"
}
],
"expectations": [{ "...": "..." }]
},
"adjustments": [
{
"id": "adj_return_1",
"type": "return", // a matching fulfillment event is also added to represent return shipping.
"description": "Item not compatible",
"line_items": [{ "id": "line_3", "quantity": -1 }], // Uses a negative value (such as -1) to indicate a return.
"occurred_at": "2026-02-09T09:00:00Z",
"status": "completed"
},
{
"id": "adj_refund_2",
"type": "refund",
"description": "Refund for returned item",
"line_items": [{ "id": "line_3", "quantity": -1 }],
"totals": [
{"type": "subtotal", "amount": -14900}, // Negative amounts indicate money returned to the buyer.
{"type": "tax", "amount": -1200},
{"type": "total", "amount": -16100}
],
"occurred_at": "2026-02-10T10:00:00Z",
"status": "completed"
}
],
"permalink_url": "https://merchant.example.com/orders/67890"
}