Hướng dẫn này cung cấp thông tin tham khảo kỹ thuật về API và giản đồ tải trọng để gửi thông tin cập nhật đầy đủ về trạng thái đơn đặt hàng, sự kiện thực hiện đơn hàng và các khoản điều chỉnh cho Google bằng cách sử dụng webhook cho phiên bản 2026-04-08 của Giao thức thương mại toàn cầu (UCP).
Trước khi tạo các điểm cuối, hãy đảm bảo rằng bạn đã xem Tổng quan về vòng đời của đơn đặt hàng để biết các khái niệm cấp cao, sự kiện bắt buộc và thông tin chi tiết về điểm cuối webhook.
Xác thực và ký yêu cầu
Những thay đổi chính trong phiên bản 2026-04-08 bao gồm việc giới thiệu các tiêu đề webhook bắt buộc mới và các quy trình ký yêu cầu cụ thể.
Tiêu đề webhook bắt buộc
Các tiêu đề HTTP sau đây là bắt buộc đối với tất cả các yêu cầu webhook:
Webhook-Id: Giá trị nhận dạng duy nhất cho sự kiện webhook cụ thể này. Mã nhận dạng này phải khớp vớiidcủa sự kiện chính đang được gửi (ví dụ: mã sự kiện thực hiện hoặc mã sự kiện điều chỉnh).Webhook-Timestamp: Dấu thời gian cho biết thời điểm xảy ra sự kiện.
Các tiêu đề này thay thế các trường id và created_time mà trước đây được dự kiến trong phần dữ liệu thực tế của đơn đặt hàng.
Yêu cầu ký
- Tính toán chuỗi đại diện SHA-256 của nội dung yêu cầu thô và đặt tiêu đề
Content-Digest. - Chọn một khoá ký trong
signing_keystrong hồ sơ UCP. - Tạo cơ sở chữ ký theo RFC 9421.
- Xem quy cách cho các thành phần đã ký
- Đặt tiêu đề
UCP-Agent,Signature-InputvàSignature.UCP-Agentlà đường liên kết đến hồ sơ UCP của bạn ở định dạngprofile="https://merchant.example.com/.well-known/ucp".Signature-Inputlà một trường có cấu trúc dạng từ điển mô tả các thành phần có trong chữ ký, cũng nhưkeyidđược dùng để ký. này phải khớp vớikidcủa khoá ký mà bạn đã chọn trongsigning_keystrong hồ sơ UCP.- Tiêu đề
Signaturechứa cơ sở chữ ký của bạn được ký bằng khoá riêng tư của bạn rồi mã hoá dưới dạng base64.
Hãy xem hướng dẫn ký trên ucp.dev để biết thêm thông tin.
Sự kiện đã tạo đơn đặt hàng
- Gửi thư: Ngay sau khi đơn đặt hàng được xác nhận (
status: processing).
Các thay đổi chính trong phiên bản này:
- Trường
currencyhiện là trường bắt buộc ở cấp cao nhất của đối tượng Đơn đặt hàng. - Trường
typetrong mỗi đối tượng trong mảngtotalshiện là một chuỗi mở (ví dụ: "tổng phụ", "thuế", "phí", "tổng"). - Tiêu đề
Webhook-Idbắt buộc chứa giá trị nhận dạng duy nhất cho sự kiện webhook. Xin lưu ý rằng bạn vẫn phải có trườngidtrong tải trọng chứa mã xác nhận đơn đặt hàng. - Tiêu đề
Webhook-Timestampbắt buộc cung cấp thời gian tạo, thay thế trườngcreated_timetrước đây trong tải trọng.
Ví dụ: Ví dụ này cho thấy một đơn đặt hàng được tạo sau khi người mua hoàn tất quy trình thanh toán.
Tiêu đề bắt buộc:
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"
}
Sự kiện thực hiện
Các sự kiện này được gửi trong mảng fulfillment.events.
Đơn đặt hàng đã được vận chuyển
Khi các mặt hàng trong đơn đặt hàng đã được vận chuyển. Bạn phải điền các trường tracking_number và tracking_url cho các sự kiện đã vận chuyển, vì bạn cần điền các trường này để nhóm các mặt hàng một cách chính xác trên trang "Đơn đặt hàng của tôi".
Đã giao đơn đặt hàng
Khi các mặt hàng trong đơn đặt hàng đã được giao.
Ví dụ (shipped và delivered): Ví dụ này cho thấy thông tin cập nhật về đơn đặt hàng sau khi mặt hàng đã được vận chuyển và giao hàng.
Tiêu đề bắt buộc:
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"
}
Ví dụ về đơn đặt hàng có nhiều mặt hàng
Các ví dụ sau đây minh hoạ cách cấu trúc thông tin cập nhật cho đơn đặt hàng có nhiều mặt hàng và lô hàng tách biệt. Để biết các quy tắc về cách xác định trạng thái gói hàng, hãy xem bài viết Cách xác định trạng thái gói hàng.
Đơn đặt hàng nhiều mặt hàng, giao hàng trong cùng một gói
Ví dụ này cho thấy thông tin cập nhật về đơn đặt hàng cho một gói duy nhất chứa nhiều mặt hàng. Tất cả các mục hàng đều được nhóm trong một sự kiện shipped duy nhất có cùng số vận đơn.
Tiêu đề bắt buộc:
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"
}
Đơn đặt hàng nhiều mặt hàng, giao hàng riêng
Ví dụ này cho thấy thông tin cập nhật về đơn đặt hàng đối với các lô hàng tách rời. Có nhiều sự kiện shipped, mỗi sự kiện tham chiếu đến line_items cụ thể trong gói tương ứng đó, với các số theo dõi riêng biệt. Vì mỗi gói hàng thể hiện một cam kết riêng biệt về việc thực hiện đơn hàng (ví dụ: tốc độ và chi phí khác nhau trong quy trình thanh toán nhiều nhóm), nên expectations cũng được chia tách.
Tiêu đề bắt buộc:
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"
}
Ví dụ về sự kiện điều chỉnh
Các ví dụ sau đây minh hoạ cách cấu trúc thông tin cập nhật cho việc hoàn tiền, trả lại và huỷ. Để biết danh sách các sự kiện được hỗ trợ và định nghĩa của các sự kiện đó, hãy xem Sự kiện điều chỉnh trong phần Tổng quan về vòng đời của đơn đặt hàng.
Huỷ đơn đặt hàng và hoàn tiền
Ví dụ này cho thấy một đơn đặt hàng đã bị huỷ và được hoàn tiền ngay sau khi được đặt.
Các thay đổi chính trong phiên bản này trong ví dụ này:
- Những mục hàng chịu ảnh hưởng của
cancellationhiện sử dụng"status": "removed"trong mảngline_itemschính. - Khi
line_items.statuslàremoved:line_items.quantity.totalđược đặt thành0.- Số lượng ban đầu được lưu trữ trong trường
line_items.quantity.originalmới.
Tiêu đề bắt buộc:
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"
}
Trả lại và hoàn tiền cho đơn đặt hàng
Ví dụ này cho thấy một đơn đặt hàng mà mặt hàng đã được vận chuyển, giao hàng, sau đó được trả lại và hoàn tiền.
Các thay đổi chính trong phiên bản này trong ví dụ này:
- Các mục hàng chịu ảnh hưởng của
returnhiện sử dụng"status": "removed"trong mảngline_itemschính. - Khi
line_items.statuslàremoved:line_items.quantity.totalđược đặt thành0.- Số lượng ban đầu được lưu trữ trong trường
line_items.quantity.originalmới.
- Trong
adjustmentsthuộc loạireturn, trườngline_items.quantitytrong mức điều chỉnh sử dụng giá trị âm (ví dụ:-1) để cho biết các mặt hàng đang được trả lại.
Tiêu đề bắt buộc:
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"
}