對應菜單動態饋給和出貨購物車商品
當客戶將菜單品項中的商品加入購物車並結帳時,Google 會將這些商品傳送至您的執行要求端點,以確認他們的價格與供應情形。價格和供應情形通過驗證後,客戶即可下單。本節說明如何將選單動態饋給項目對應至出貨購物車項目。
本節中的範例是精簡的菜單動態饋給和購物車結構定義版本。系統只會顯示與選單動態饋給和購物車物件之間的對應關係相關的欄位。如需完整的結構定義,請參閱 Menu
和 Cart
。
Cart
加入購物車的 Menu
動態饋給商品會同時傳送到 Cart
物件,用於結帳及提交訂單。
lineItems
陣列中的簡易MenuItem
會以LineItem
表示,offerId
則是選單動態饋給中所選選單項目的offer.id
。- 含有必要
MenuItemOption
的MenuItem
會以LineItem
表示,其中offerId
是選單動態饋給中所選選單項目選項的offer.id
。lineItems
LineItem
的AddOnMenuItem
會在FoodItemExtension
的options
陣列中表示FoodItemOption
。每個選項都有offerId
,對應至選單動態饋給中所選外掛程式選單項目的offer.id
。請注意,AddOnMenuItem 也可以包含巢狀 AddOnMenuItem(s),在每個選項中以subOptions
表示。
下列範例對應選單動態饋給和出貨購物車之間的選單項目範例。
JSON
此範例包含簡易選單項目清單。
菜單動態饋給中的選單項目:
{ "@type": "Menu", "@id": "menu_id", "hasMenuItem": [ { "@type": "MenuItem", "@id": "menuitem_id_1", "offers": [ { "@type": "Offer", "@id": "menuitem_offer_id_1", "price": "p_1", "priceCurrency": "USD" } ] }, { "@type": "MenuItem", "@id": "menuitem_id_2", "offers": [ { "@type": "Offer", "@id": "menuitem_offer_id_2", "price": "p_2", "priceCurrency": "USD" } ] } ] }
對應至出貨購物車的選單項目:
{ "@type": "Cart", "lineItems": [ { "offerId": "menuitem_offer_id_1", "price": { "amount": { "currencyCode": "USD", "units": "dollar(q_1*p_1)", "nanos": "cent(q_1*p_1)" } }, "quantity": "q_1" }, { "offerId": "menuitem_offer_id_2", "price": { "amount": { "currencyCode": "USD", "units": "dollar(q_2*p_2)", "nanos": "cent(q_2*p_2)" } }, "quantity": "q_2" } ] }
JSON
此範例包含的選單項目具有一或多個 AddOnMenuItems。
菜單動態饋給中的選單項目:
{ "@type": "Menu", "@id": "menu_id", "hasMenuItem": [ { "@type": "MenuItem", "@id": "menuitem_id_1", "offers": [ { "@type": "Offer", "@id": "menuitem_offer_id_1", "price": "p_1", "priceCurrency": "USD" } ], "menuAddOn": [ { "@type": "MenuAddOnSection", "@id": "menuaddon_section_id_1", "hasMenuItem": [ { "@type": "AddOnMenuItem", "@id": "menuitem_addon_id_1", "offers": [ { "@type": "Offer", "@id": "menuitem_addon_offer_id_1", "price": "addon_p_1", "priceCurrency": "USD" } ] }, { "@type": "AddOnMenuItem", "@id": "menuitem_addon_id_2", "offers": [ { "@type": "Offer", "@id": "menuitem_addon_offer_id_2", "price": "addon_p_2", "priceCurrency": "USD" } ] } ] } ] }, { "@type": "MenuItem", "@id": "menuitem_id_2", "offers": [ { "@type": "Offer", "@id": "menuitem_offer_id_2", "price": "p_2", "priceCurrency": "USD" } ] } ] }
對應至出貨購物車的選單項目:
{ "@type": "Cart", "lineItems": [ { "offerId": "menuitem_offer_id_1", "price": { "amount": { "currencyCode": "USD", "units": "dollar(q_1*(p_1 + addon_q_1*addon_p_1 + addon_q_2*addon_p_2))", "nanos": "cent(q_1*(p_1 + addon_q_1*addon_p_1 + addon_q_2*addon_p_2))" } }, "quantity": "q_1", "extension": { "@type": "FoodItemExtension", "options": [ { "offerId": "menuitem_addon_offer_id_1", "price": { "currencyCode": "USD", "units": "dollar(addon_q_1*addon_p_1)", "nanos": "cent(addon_q_1*addon_p_1)" }, "quantity": "addon_q_1" }, { "offerId": "menuitem_addon_offer_id_2", "price": { "currencyCode": "USD", "units": "dollar(addon_q_2*addon_p_2)", "nanos": "cent(addon_q_2*addon_p_2)" }, "quantity": "addon_q_2" } ] } }, { "offerId": "menuitem_offer_id_2", "price": { "amount": { "currencyCode": "USD", "units": "dollar(q_2*p_2)", "nanos": "cent(q_2*p_2)" } }, "quantity": "q_2" } ] }
JSON
此範例包含的選單項目包含選單項目選項、AddOnMenuItems 和巢狀 AddOnMenuItems
菜單動態饋給中的選單項目:
{ "@type": "MenuItem", "@id": "menuitem_id_1", "hasMenuItemOptions": [ { "@type": "MenuItemOption", "value": { "@type": "PropertyValue", "name": "OPTION", "value": "Large", "offers": [ { "@type": "Offer", "@id": "menuitem_option_offer_id_1", "price": "p_1", "priceCurrency": "USD" } ], "menuAddOn": [ { "@type": "AddOnMenuSection", "@id": "menuitem_option_addon_section_id_1", "hasMenuItem": [ { "@type": "AddOnMenuItem", "@id": "menuitem_option_addon_id_1", "offers": [ { "@type": "Offer", "@id": "menuitem_option_addon_offer_id_1", "price": "addon_p_1", "priceCurrency": "USD" } ] }, { "@type": "AddOnMenuItem", "@id": "menuitem_option_addon_id_2", "offers": [ { "@type": "Offer", "@id": "menuitem_option_addon_offer_id_2", "price": "addon_p_2", "priceCurrency": "USD" } ], "menuAddOn": [ { "@type": "AddOnMenuSection", "@id": "menuitem_option_subaddon_section_id_1", "hasMenuItem": [ { "@type": "AddOnMenuItem", "@id": "menuitem_option_subaddon_id_1", "offers": [ { "@type": "Offer", "@id": "menuitem_option_subaddon_offer_id_1", "price": "subaddon_p_1", "priceCurrency": "USD" } ] } ] } ] } ] } ] } } ] }
對應至出貨購物車的選單項目:
{ "@type": "Cart", "lineItems": [ { "offerId": "menuitem_option_offer_id_1", "price": { "amount": { "currencyCode": "USD", "units": "dollar(q_1*(p_1 + addon_q_1*addon_p_1 + addon_q_2*(addon_p_2 + subaddon_q_1*subaddon_p_1)))", "nanos": "cent(q_1*(p_1 + addon_q_1*addon_p_1 + addon_q_2*(addon_p_2 + subaddon_q_1*subaddon_p_1)))" } }, "quantity": "q_1", "extension": { "@type": "FoodItemExtension", "options": [ { "offerId": "menuitem_option_addon_offer_id_1", "price": { "currencyCode": "USD", "units": "dollar(addon_q_1*addon_p_1)", "nanos": "cent(addon_q_1*addon_p_1)" }, "quantity": "addon_q_1" }, { "offerId": "menuitem_option_addon_offer_id_2", "price": { "currencyCode": "USD", "units": "dollar(addon_q_2*(addon_p_2 + subaddon_q_1*subaddon_p_1))", "nanos": "cent(addon_q_2*(addon_p_2 + subaddon_q_1*subaddon_p_1))" }, "quantity": "addon_q_2", "subOptions": [ { "offerId": "menuitem_option_subaddon_offer_id_1", "price": { "currencyCode": "USD", "units": "dollar(subaddon_q_1*subaddon_p_1)", "nanos": "cent(subaddon_q_1*subaddon_p_1)" }, "quantity": "subaddon_q_1" } ] } ] } } ] }
處理錯誤
如果您在處理 CheckoutRequestMessage
時遇到問題,可以回應包含 FoodErrorExtension
的 CheckoutResponseMessage
,而非 CheckoutResponse。您可以使用這個回應來識別處理期間發生的一或多個錯誤。
處理錯誤的方式有 2 種:
- 可復原錯誤:使用者無須編輯購物車即可提交訂單。舉例來說,如果您判定
Cart
中的某個項目價格有異動,可以使用PRICE_CHANGED
錯誤類型為PRICE_CHANGED
的回應,以及correctedProposedOrder
和paymentOptions
。FoodOrderError
Google 會通知使用者相關變更,但允許使用者透過correctedProposedOrder
提交變更。如有需要,使用者也可以返回編輯購物車。您會收到新的CheckoutRequestMessage
或SubmitOrderRequestMessage
。 - 無法復原的錯誤:使用者必須先編輯購物車,才能提交訂單。舉例來說,如果您確定餐廳已停業,可以用
CLOSED
錯誤類型的FoodOrderError
回應。Google 會通知使用者及管理新餐廳的互動情形。您將會獲得新購物車的CheckoutRequestMessage
。
一般而言,請確保購物車層級的錯誤無法復原,商品層級的錯誤也要復原。如需錯誤類型及其意義的完整清單,請參閱 FoodOrderError
。
處理價格異動
結帳時價格有所變動
如果您在處理客戶的結帳要求時遇到價格問題,請執行以下操作:
- 使用包含
FoodErrorExtension
的CheckoutResponseMessage
回應CheckoutRequestMessage
,詳情請參閱處理錯誤。 - 請在錯誤回應中,使用
correctedProposedOrder.cart
將價格更新為正確的值。Google 收到修正後的訂單,並可能會發出新的CheckoutRequestMessage
。
結帳後,Google 會向使用者顯示訂單確認頁面,無論 ProposedOrder
是否變更。
如果 ProposedOrder 已修正,Google 可能會顯示額外警告,以通知使用者變更。如果使用者同意下單,就不會有其他結帳要求。流程會持續提交訂單,並使用正確的 ProposedOrder
。
不過,使用者隨時可以改變心意,重新編輯購物車內容。以這種方式更新購物車時,Google 會傳送新的 CheckoutRequestMessage
。
提交訂單時的價格異動
如果您在處理訂單提交時遇到價格問題 (觸發 actions.intent.TRANSACTION_DECISION
意圖),請不要傳回錯誤或更新回應中的價格。如果 SubmitOrderRequestMessage
中的價格、數量或其他詳細資料與您的資料不符,請回應 orderState
設為 REJECTED
,表示無法按照要求下單。
接著,如果訂單和付款資料有效,請將 orderState
設為 CREATED
或 CONFIRMED
。此外,請加入 actionOrderId
來代表系統中的訂單 ID。傳送後續更新時必須使用這組 ID。
如果您無法處理付款,且已經傳送 SubmitOrderRequestMessage
,可以傳送將 orderState
設為 REJECTED
的 AsyncOrderUpdateRequestMessage
傳送 AsyncOrderUpdateRequestMessage
,讓使用者瞭解無法完成訂單。
提交訂單後價格異動
如果您確定客戶提交訂單時使用的價格已經變更,可以發出 AsyncOrderUpdateRequestMessage
,詳情請參閱「導入非同步訂單更新」一文,瞭解新的價格。
如何透過非同步訂單更新來更新價格:
- 變更
lineItemUpdates[x].price
的價格。這個值反映了商品總費用,包括外掛程式乘以數量。(詳情請參閱LineItem
的price
欄位說明)。 - 在
lineItemUpdates[x].reason
中輸入說明。 - 將
lineItemUpdates[x].orderState
設為CONFIRMED
。
您可自行決定在傳送 AsyncOrderUpdateRequestMessage 之前或之後,嘗試透過付款方式收費。如果交易失敗 (可能是因為價格差異過高),請在 OrderUpdate
中使用下列設定傳送 AsyncOrderUpdateRequestMessage,通知 Google 失敗:
- 將
orderState
設為REJECTED
。 - 說明
label
欄位中的失敗情形。
結帳驗證
如步驟 4:實作結帳一節所述,執行要求端點應對每個傳入的 CheckoutRequestMessage
執行驗證,並使用 CheckoutResponseMessage
回應。
以下是驗證成功的 CheckoutResponseMessage
範例:
用途 | 實作方式 |
---|---|
用途 1:驗證成功 | 回程日期:CheckoutResponse 。元件必須包含 ProposedOrder 和 PaymentOptions 。ProposedOrder 包含購物車的稅金、相關費用和總價。 |
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "checkoutResponse": { "proposedOrder": { "id": "sample_proposed_order_id_1", "otherItems": [ { "name":"New customer discount", "price": { "type":"ESTIMATE", "amount": { "currencyCode":"USD", "units":"-5", "nanos": -500000000 } }, "type": "DISCOUNT" }, { "name": "Delivery fee", "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "3", "nanos": 500000000 } }, "type": "DELIVERY" }, { "name": "Tax", "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "1", "nanos": 500000000 } }, "type": "TAX" } ], "cart": { "merchant": { "id": "https://www.exampleprovider.com/merchant/id1", "name": "Falafel Bite" }, "lineItems": [ { "name": "Pita Chips", "type": "REGULAR", "id": "sample_item_offer_id_1", "offerId": "https://www.exampleprovider.com/menu/item/offer/id1", "quantity": 1, "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "2", "nanos": 750000000 } }, "subLines": [ { "note": "Notes for this item." } ], "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension", "options": [ { "id": "sample_addon_offer_id_1", "offerId": "https://www.exampleprovider.com/menu/item/addon/offer/id1", "name": "Honey Mustard", "price": { "currencyCode": "USD" }, "quantity": 1 }, { "id": "sample_addon_offer_id_2", "offerId": "https://www.exampleprovider.com/menu/item/addon/offer/id2", "name": "BBQ Sauce", "price": { "currencyCode": "USD", "nanos": 500000000 }, "quantity": 1 } ] } }, { "name": "Chicken Shwarma Wrap", "type": "REGULAR", "id": "sample_item_offer_id_2", "offerId": "https://www.exampleprovider.com/menu/item/offer/id2", "quantity": 1, "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "8" } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension" } }, { "name": "Greek Salad", "type": "REGULAR", "id": "sample_item_offer_id_3", "offerId": "https://www.exampleprovider.com/menu/item/offer/id3", "quantity": 1, "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "9", "nanos": 990000000 } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension" } }, { "name": "Prawns Biryani", "type": "REGULAR", "id": "sample_item_offer_id_4", "offerId": "https://www.exampleprovider.com/menu/item/offer/id4", "quantity": 1, "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "15", "nanos": 990000000 } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension" } } ], "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension", "fulfillmentPreference": { "fulfillmentInfo": { "delivery": { "deliveryTimeIso8601": "P90M" } } }, "location": { "coordinates": { "latitude": 37.788783, "longitude": -122.41384 }, "formattedAddress": "1350 CHARLESTON ROAD, MOUNTAIN VIEW, CA, United States", "zipCode": "94043", "city": "Mountain View", "postalAddress": { "regionCode": "US", "postalCode": "94043", "administrativeArea": "CA", "locality": "Mountain View", "addressLines": [ "1350 Charleston Road" ] }, "notes": "Gate code is #111" } } }, "totalPrice": { "type": "ESTIMATE", "amount": { // Represents $36.73 "currencyCode": "USD", "units": "36", "nanos": 730000000 } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension", "availableFulfillmentOptions": [ { "fulfillmentInfo": { "delivery": { "deliveryTimeIso8601": "P90M" } }, "expiresAt": "2017-07-17T12:30:00Z" } ] } }, "paymentOptions": { "googleProvidedOptions": { "tokenizationParameters": { "tokenizationType": "PAYMENT_GATEWAY", "parameters": { "gateway": "stripe", "stripe:publishableKey": "pk_live_stripe_client_key", "stripe:version": "2017-04-06" } }, "supportedCardNetworks": [ "AMEX", "DISCOVER", "MASTERCARD", "JCB", "VISA" ], "prepaidCardDisallowed": true } } } } } ] } } }
寄送地址驗證
執行要求端點應驗證每個 CheckoutRequestMessage
中包含的寄送地址。
如果寄送地址有問題 (例如超出送貨服務範圍),則執行要求傳回的 CheckoutResponseMessage
應包含適當類型的 FoodOrderError
。
用途 | 實作方式 |
---|---|
用途 1:由於寄送地址超出範圍或寄送地址有問題,導致驗證失敗 | 傳回 FoodErrorExtension ,FoodOrderError 錯誤類型為 OUT_OF_SERVICE_AREA 。 |
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "error": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension", "foodOrderErrors": [ { "error": "OUT_OF_SERVICE_AREA", "description": "Sorry, the restaurant cannot deliver to your address." } ] } } } ] } } }
最低訂單價值驗證
執行要求端點應驗證每個 CheckoutRequestMessage
的最低訂單價值。
如果未達到最低訂單價值,執行要求傳回的CheckoutResponseMessage
便應包含錯誤類型的FoodOrderError
錯誤類型REQUIREMENTS_NOT_MET
。
用途 | 實作方式 |
---|---|
用途 1:不符合最低訂單價值,導致驗證失敗 | 傳回 FoodErrorExtension ,FoodOrderError 錯誤類型為 REQUIREMENTS_NOT_MET 。 |
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "error": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension", "foodOrderErrors": [ { "error": "REQUIREMENTS_NOT_MET", "description": "The cart subtotal must be over $20." } ] } } } ] } } }
訂購期驗證
執行要求端點應驗證可能影響每個 CheckoutRequestMessage
排序期的任何因素。
舉例來說,如果餐廳正休息或不再接受訂單,執行要求傳回的 CheckoutResponseMessage
應分別包含錯誤類型的 FoodOrderError
或 CLOSED
或 NO_CAPACITY
。
用途 | 實作方式 |
---|---|
用途 1:餐廳已停業或不再支援,導致驗證失敗 | 傳回 FoodErrorExtension ,FoodOrderError 錯誤類型為 CLOSED 。 |
用途 2:因為餐廳繁忙且目前未接受訂單,導致驗證失敗 | 傳回 FoodErrorExtension ,FoodOrderError 錯誤類型為 NO_CAPACITY 。 |
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "error": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension", "foodOrderErrors": [ { "error": "CLOSED", "description": "The restaurant is closed." } ] } } } ] } } }
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "error": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension", "foodOrderErrors": [ { "error": "NO_CAPACITY", "description": "Sorry, the restaurant is busy at the moment." } ] } } } ] } } }
購物車商品驗證
您的執行要求端點應驗證 CheckoutRequestMessage
中每個購物車商品的價格和供應情形。
如果供應情形或價格有所變更,執行要求傳回的 CheckoutResponseMessage
應包含錯誤類型 AVAILABILITY_CHANGED
或 PRICE_CHANGED
的 FoodOrderError
。
用途 | 實作方式 |
---|---|
用途 1:部分選單項目和/或自訂項目無效或缺貨中,因此驗證失敗 | 傳回 correctedProposedOrder 、PaymentOptions 和 FoodOrderError 錯誤類型為 AVAILABILITY_CHANGED 的 FoodErrorExtension 。您必須從「CorrectedProposedOrder 」中移除無效項目。 |
用途 2:部分選單項目和/或自訂項目無效或缺貨中,因此驗證失敗。修正後的購物車不再符合最低訂單價值規定。 | 傳回 FoodErrorExtension ,其中 FoodOrderError 錯誤類型為 AVAILABILITY_CHANGED 和 REQUIREMENTS_NOT_MET 。 |
用途 3:部分選單項目和/或自訂價格已變更,導致驗證失敗 | 傳回 correctedProposedOrder 、PaymentOptions 和 FoodOrderError 錯誤類型為 PRICE_CHANGED 的 FoodErrorExtension 。您必須在 CorrectedProposedOrder 內更新過時價格。 |
用途 4:部分選單項目和/或自訂價格已變更,導致驗證失敗。修正後的購物車不再符合最低訂單價值規定 | 傳回 FoodErrorExtension ,其中 FoodOrderError 錯誤類型為 PRICE_CHANGED 和 REQUIREMENTS_NOT_MET 。 |
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "error": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension", "foodOrderErrors": [ { "error": "AVAILABILITY_CHANGED", "id": "sample_item_offer_id_1", "description": "The item is no longer available." }, { "error": "AVAILABILITY_CHANGED", "id": "sample_item_offer_id_2", "description": "The item is no longer available." } ], "correctedProposedOrder": { "id": "sample_corrected_proposed_order_id_1", "otherItems": [ { "name":"New customer discount", "price": { "type":"ESTIMATE", "amount": { "currencyCode":"USD", "units":"-5", "nanos": -500000000 } }, "type": "DISCOUNT" }, { "name": "Delivery fee", "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "3", "nanos": 500000000 } }, "type": "DELIVERY" }, { "name": "Tax", "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "1", "nanos": 500000000 } }, "type": "TAX" } ], "cart": { "merchant": { "id": "https://www.exampleprovider.com/merchant/id1", "name": "Falafel Bite" }, "lineItems": [ { "name": "Greek Salad", "type": "REGULAR", "id": "sample_item_offer_id_3", "offerId": "https://www.exampleprovider.com/menu/item/offer/id3", "quantity": 1, "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "9", "nanos": 990000000 } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension" } }, { "name": "Prawns Biryani", "type": "REGULAR", "id": "sample_item_offer_id_4", "offerId": "https://www.exampleprovider.com/menu/item/offer/id4", "quantity": 1, "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "15", "nanos": 990000000 } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension" } } ], "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension", "fulfillmentPreference": { "fulfillmentInfo": { "delivery": { "deliveryTimeIso8601": "P90M" } } }, "location": { "coordinates": { "latitude": 37.788783, "longitude": -122.41384 }, "formattedAddress": "1350 CHARLESTON ROAD, MOUNTAIN VIEW, CA, United States", "zipCode": "94043", "city": "Mountain View", "postalAddress": { "regionCode": "US", "postalCode": "94043", "administrativeArea": "CA", "locality": "Mountain View", "addressLines": [ "1350 Charleston Road" ] }, "notes": "Gate code is #111" } } }, "totalPrice": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "36", "nanos": 730000000 } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension", "availableFulfillmentOptions": [ { "fulfillmentInfo": { "delivery": { "deliveryTimeIso8601": "P90M" } }, "expiresAt": "2017-07-17T12:30:00Z" } ] } }, "paymentOptions": { "googleProvidedOptions": { "tokenizationParameters": { "tokenizationType": "PAYMENT_GATEWAY", "parameters": { "gateway": "stripe", "stripe:publishableKey": "pk_live_stripe_client_key", "stripe:version": "2017-04-06" } }, "supportedCardNetworks": [ "AMEX", "DISCOVER", "MASTERCARD", "JCB", "VISA" ], "prepaidCardDisallowed": true } } } } } ] } } }
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "error": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension", "foodOrderErrors": [ { "error": "REQUIREMENTS_NOT_MET", "description": "The cart subtotal must be over $20." }, { "error": "AVAILABILITY_CHANGED", "id": "cart_lineitem_id" "description": "cart_lineitem_id is no longer available." } ] } } } ] } } }
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "error": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension", "foodOrderErrors": [ { "error": "PRICE_CHANGED", "id": "sample_item_offer_id_1", "description": "The price has changed.", "updatedPrice": { "currencyCode": "USD", "units": "2", "nanos": 750000000 } }, { "error": "PRICE_CHANGED", "id": "sample_item_offer_id_2", "description": "The price has changed.", "updatedPrice": { "currencyCode": "USD", "units": "8" } } ], "correctedProposedOrder": { "id": "sample_corrected_proposed_order_id_1", "otherItems": [ { "name":"New customer discount", "price": { "type":"ESTIMATE", "amount": { "currencyCode":"USD", "units":"-5", "nanos": -500000000 } }, "type": "DISCOUNT" }, { "name": "Delivery fee", "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "3", "nanos": 500000000 } }, "type": "DELIVERY" }, { "name": "Tax", "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "1", "nanos": 500000000 } }, "type": "TAX" } ], "cart": { "merchant": { "id": "https://www.exampleprovider.com/merchant/id1", "name": "Falafel Bite" }, "lineItems": [ { "name": "Pita Chips", "type": "REGULAR", "id": "sample_item_offer_id_1", "offerId": "https://www.exampleprovider.com/menu/item/offer/id1", "quantity": 1, "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "2", "nanos": 750000000 } }, "subLines": [ { "note": "Notes for this item." } ], "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension", "options": [ { "id": "sample_addon_offer_id_1", "offerId": "https://www.exampleprovider.com/menu/item/addon/offer/id1", "name": "Honey Mustard", "price": { "currencyCode": "USD" }, "quantity": 1 }, { "id": "sample_addon_offer_id_2", "offerId": "https://www.exampleprovider.com/menu/item/addon/offer/id2", "name": "BBQ Sauce", "price": { "currencyCode": "USD", "nanos": 500000000 }, "quantity": 1 } ] } }, { "name": "Chicken Shwarma Wrap", "type": "REGULAR", "id": "sample_item_offer_id_2", "offerId": "https://www.exampleprovider.com/menu/item/offer/id2", "quantity": 1, "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "8" } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension" } }, { "name": "Greek Salad", "type": "REGULAR", "id": "sample_item_offer_id_3", "offerId": "https://www.exampleprovider.com/menu/item/offer/id3", "quantity": 1, "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "9", "nanos": 990000000 } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension" } }, { "name": "Prawns Biryani", "type": "REGULAR", "id": "sample_item_offer_id_4", "offerId": "https://www.exampleprovider.com/menu/item/offer/id4", "quantity": 1, "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "15", "nanos": 990000000 } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension" } } ], "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension", "fulfillmentPreference": { "fulfillmentInfo": { "delivery": { "deliveryTimeIso8601": "P90M" } } }, "location": { "coordinates": { "latitude": 37.788783, "longitude": -122.41384 }, "formattedAddress": "1350 CHARLESTON ROAD, MOUNTAIN VIEW, CA, United States", "zipCode": "94043", "city": "Mountain View", "postalAddress": { "regionCode": "US", "postalCode": "94043", "administrativeArea": "CA", "locality": "Mountain View", "addressLines": [ "1350 Charleston Road" ] }, "notes": "Gate code is #111" } } }, "totalPrice": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "36", "nanos": 730000000 } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension", "availableFulfillmentOptions": [ { "fulfillmentInfo": { "delivery": { "deliveryTimeIso8601": "P90M" } }, "expiresAt": "2017-07-17T12:30:00Z" } ] } }, "paymentOptions": { "googleProvidedOptions": { "tokenizationParameters": { "tokenizationType": "PAYMENT_GATEWAY", "parameters": { "gateway": "stripe", "stripe:publishableKey": "pk_live_stripe_client_key", "stripe:version": "2017-04-06" } }, "supportedCardNetworks": [ "AMEX", "DISCOVER", "MASTERCARD", "JCB", "VISA" ], "prepaidCardDisallowed": true } } } } } ] } } }
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "error": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension", "foodOrderErrors": [ { "error": "REQUIREMENTS_NOT_MET", "description": "The cart subtotal must be over $20." }, { "error": "PRICE_CHANGED", "id": "cart_lineitem_id" "description": "cart_lineitem_id price has been updated." "updatedPrice": { "currencyCode": "USD", "units": "2", "nanos": 750000000 } } ] } } } ] } } }
提交訂單驗證
如步驟 7:實作提交訂單所述,執行要求端點應對每個傳入的 SubmitOrderRequestMessage
執行驗證,並以 SubmitOrderResponseMessage
回應。
以下是驗證成功的 SubmitOrderResponseMessage
範例:
用途 | 實作方式 |
---|---|
用途 1:訂單已成功建立 | 具有 CREATED 訂單狀態的 SubmitOrderResponseMessage 。必須與 actionOrderId 、userVisibleId 、orderManagementActions 和 estimatedFulfillmentTime 相同。 |
用途 2:訂單因付款問題而遭拒 | 具有 REJECTED 訂單狀態的 SubmitOrderResponseMessage 。它必須包含 PAYMENT_DECLINED 類型的 actionOrderId 、userVisibleId 、orderManagementActions 和 rejectionInfo 。 |
用途 3:使用者將訂單商品標記為已停權,因而遭拒 | 含有 REJECTED 訂單狀態的 SubmitOrderResponseMessage 。它必須包含 INELIGIBLE 類型的 actionOrderId 、userVisibleId 、orderManagementActions 和 rejectionInfo 。 |
用途 4:使用者資訊不完整或無效,導致訂單遭拒 | 具有 REJECTED 訂單狀態的 SubmitOrderResponseMessage 。它必須包含 INELIGIBLE 類型的 actionOrderId 、userVisibleId 、orderManagementActions 和 rejectionInfo 。 |
用途 5:訂單因不明原因遭拒 | 具有 REJECTED 訂單狀態的 SubmitOrderResponseMessage 。它必須包含 UNKNOWN 類型的 actionOrderId 、userVisibleId 、orderManagementActions 和 rejectionInfo 。 |
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "CREATED", "label": "Order received" }, "updateTime": "2017-05-10T02:30:00.000Z", "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "VIEW_DETAILS", "button": { "title": "View order", "openUrlAction": { "url": "https://orderview.partner.com?orderid=sample_action_order_id" } } } ] } } } ] } } }
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "REJECTED", "label": "Order rejected" }, "updateTime": "2017-05-10T02:30:00.000Z", "rejectionInfo": { "type": "PAYMENT_DECLINED", "reason": "Insufficient funds" }, "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "VIEW_DETAILS", "button": { "title": "View order", "openUrlAction": { "url": "https://orderview.partner.com?orderid=sample_action_order_id" } } } ] } } } ] } } }
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "REJECTED", "label": "Order rejected" }, "updateTime": "2017-05-10T02:30:00.000Z", "rejectionInfo": { "type": "INELIGIBLE", "reason": "Sorry, we are not able to take orders from this user" }, "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "VIEW_DETAILS", "button": { "title": "View order", "openUrlAction": { "url": "https://orderview.partner.com?orderid=sample_action_order_id" } } } ] } } } ] } } }
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "REJECTED", "label": "Order rejected" }, "updateTime": "2017-05-10T02:30:00.000Z", "rejectionInfo": { "type": "INELIGIBLE", "reason": "Sorry, the phone number must not be blank" }, "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "VIEW_DETAILS", "button": { "title": "View order", "openUrlAction": { "url": "https://orderview.partner.com?orderid=sample_action_order_id" } } } ] } } } ] } } }
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "REJECTED", "label": "Order rejected" }, "updateTime": "2017-05-10T02:30:00.000Z", "rejectionInfo": { "type": "UNKNOWN", "reason": "Sorry, there is something wrong with this order." }, "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "VIEW_DETAILS", "button": { "title": "View order", "openUrlAction": { "url": "https://orderview.partner.com?orderid=sample_action_order_id" } } } ] } } } ] } } }