使用者建立購物車時,系統會叫用結帳程序。使用者購物車的內容和訂單詳細資料會傳送至你的訂購端到端網路服務。您的網路服務會驗證這項資訊,然後您可以視需要繼續操作或調整購物車。
網路服務的結帳處理程序必須回應 POST 要求。當消費者選擇結帳時,Google 會以 CheckoutRequestMessage
的形式,將 JSON 要求主體傳送至訂購端到端網路服務,其中包含消費者 Cart
的詳細資料。您的網路服務隨後會傳回 CheckoutResponseMessage
。下圖說明此程序。
收到結帳要求後,你的訂購端到端網路服務必須執行下列操作:
- 根據目前的商品價格、供應情形和供應商服務,檢查購物車的有效性。
- 計算總價 (包括任何折扣、稅金和運費)。
- 如果成功,請回傳未修改的購物車。
- 如果未成功,請回覆錯誤訊息和新的建議順序。
建議您在開始導入結帳功能前,先詳閱履行總覽說明文件。
結帳要求訊息
為了驗證客戶的購物車,當客戶選擇結帳時,Google 會傳送要求給您的網路服務,其中 JSON 主體的格式為 CheckoutRequestMessage
。在端對端訂購流程中,系統會稍後才提交客戶訂單。
CheckoutRequestMessage
中的資料包括:
- 意圖:每個結帳要求主體的
inputs[0].intent
欄位都包含actions.foodordering.intent.CHECKOUT
字串值。 - 購物車:結帳要求的
inputs[0].arguments[0].extension
欄位包含代表消費者購物車的Cart
物件。 - 外送或外帶:
Cart
物件的擴充功能欄位包含FoodCartExtension
物件,可指定外送或外帶的屬性:- 對於外送訂單,
FoodCartExtension
物件會包含運送地址。 - 對於外帶或外送訂單,
FoodCartExtension
物件不會包含任何位置資訊。
- 對於外送訂單,
- 沙箱:結帳要求的
isInSandbox
欄位包含布林值,用於指出交易是否使用沙箱付款。
結帳要求範例
以下是 CheckoutRequestMessage
的範例:
{
"user": {},
"conversation": {
"conversationId": "CTZbZfUlHCybEdcz_5PB3Ttf"
},
"inputs": [
{
"intent": "actions.foodordering.intent.CHECKOUT",
"arguments": [
{
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.Cart",
"merchant": {
"id": "restaurant/Restaurant/QWERTY",
"name": "Tep Tep Chicken Club"
},
"lineItems": [
{
"name": "Spicy Fried Chicken",
"type": "REGULAR",
"id": "299977679",
"quantity": 2,
"price": {
"type": "ESTIMATE",
"amount": {
"currencyCode": "AUD",
"units": "39",
"nanos": 600000000
}
},
"offerId": "MenuItemOffer/QWERTY/scheduleId/496/itemId/143",
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension"
}
}
],
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
"fulfillmentPreference": {
"fulfillmentInfo": {
"delivery": {
"deliveryTimeIso8601": "P0M"
}
}
},
"location": {
"coordinates": {
"latitude": -33.8376441,
"longitude": 151.0868736
},
"formattedAddress": "Killoola St, 1, Concord West NSW 2138",
"zipCode": "2138",
"city": "Concord West",
"postalAddress": {
"regionCode": "AU",
"postalCode": "2138",
"administrativeArea": "NSW",
"locality": "Concord West",
"addressLines": [
"Killoola St",
"1"
]
}
}
}
}
}
]
}
],
"directActionOnly": true,
"isInSandbox": true
}
結帳回應訊息
收到來自訂購端對端服務的要求後,您的結帳網站服務必須處理該要求,並以 CheckoutResponseMessage
回應。CheckoutResponseMessage
必須涵蓋成功或失敗的要求。
要求成功
如果結帳要求成功,CheckoutResponseMessage
就必須包含 ProposedOrder
和 PaymentOptions
:
ProposedOrder
cart
:與CheckoutRequestMessage
中提供的購物車相同的cart
物件。如果購物車的任何內容需要變更,CheckoutResponseMessage
應改為包含FoodErrorExtension
,並附上修正過的ProposedOrder
。otherItems
:供應商新增的項目,例如運費、稅金和其他費用。也可能包含使用者加的小費。totalPrice
:訂單的總價。extension
:定義訂單履行資訊 (例如運送時間) 的FoodOrderExtension
。
PaymentOptions
- 我們會在稍後的「設定 Google Pay」一節中說明如何設定付款處理程序。在準備好導入付款處理程序之前,您可以在
CheckoutResponseMessage
中使用預留位置 JSON。 - 如要在
CheckoutResponseMessage
中新增預留位置付款選項,請參考下方的範例,該範例使用PaymentOptions
的付款閘道範例。
- 我們會在稍後的「設定 Google Pay」一節中說明如何設定付款處理程序。在準備好導入付款處理程序之前,您可以在
成功回應範例
{
"finalResponse": {
"richResponse": {
"items": [
{
"structuredResponse": {
"checkoutResponse": {
"proposedOrder": {
"cart": {
"merchant": {
"id": "restaurant/Restaurant/QWERTY",
"name": "Tep Tep Chicken Club"
},
"lineItems": [
{
"name": "Spicy Fried Chicken",
"type": "REGULAR",
"id": "299977679",
"quantity": 2,
"price": {
"type": "ESTIMATE",
"amount": {
"currencyCode": "AUD",
"units": "39",
"nanos": 600000000
}
},
"offerId": "MenuItemOffer/QWERTY/scheduleId/496/itemId/143",
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension"
}
}
],
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
"fulfillmentPreference": {
"fulfillmentInfo": {
"delivery": {
"deliveryTimeIso8601": "P0M"
}
}
},
"location": {
"coordinates": {
"latitude": -33.8376441,
"longitude": 151.0868736
},
"formattedAddress": "Killoola St, 1, Concord West NSW 2138",
"zipCode": "2138",
"city": "Concord West",
"postalAddress": {
"regionCode": "AU",
"postalCode": "2138",
"administrativeArea": "NSW",
"locality": "Concord West",
"addressLines": [
"Killoola St",
"1"
]
}
}
}
},
"totalPrice": {
"type": "ESTIMATE",
"amount": {
"currencyCode": "AUD",
"units": "43",
"nanos": 100000000
}
},
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension",
"availableFulfillmentOptions": [
{
"fulfillmentInfo": {
"delivery": {
"deliveryTimeIso8601": "P0M"
}
}
}
]
},
"otherItems": [
{
"name": "Delivery fee",
"price": {
"type": "ESTIMATE",
"amount": {
"currencyCode": "AUD",
"units": "3",
"nanos": 500000000
}
},
"type": "DELIVERY"
}
]
},
"paymentOptions": {
"googleProvidedOptions": {
"facilitationSpecification": "{\"apiVersion\":2,\"apiVersionMinor\":0,\"merchantInfo\":{\"merchantName\":\"merchantName\"},\"allowedPaymentMethods\":[{\"type\":\"CARD\",\"parameters\":{\"allowedAuthMethods\":[\"PAN_ONLY\"],\"allowedCardNetworks\":[\"VISA\",\"MASTERCARD\"],\"billingAddressRequired\":true,\"cvcRequired\":false},\"tokenizationSpecification\":{\"type\":\"PAYMENT_GATEWAY\",\"parameters\":{\"gatewayMerchantId\":\"YOUR_MERCHANT_ID\",\"gateway\":\"cybersource\"}}}],\"transactionInfo\":{\"currencyCode\":\"AUD\",\"totalPriceStatus\":\"ESTIMATED\",\"totalPrice\":\"43.1\"}} "
}
},
"additionalPaymentOptions": [
{
"actionProvidedOptions": {
"paymentType": "ON_FULFILLMENT",
"displayName": "Pay when you get your food.",
"onFulfillmentPaymentData": {
"supportedPaymentOptions": []
}
}
}
]
}
}
}
]
}
}
}
要求失敗
如果結帳要求失敗,CheckoutResponseMessage
就必須包含 FoodErrorExtension
,其中包含 FoodOrderError
項目清單,說明發生的任何錯誤。如果訂單有可復原的錯誤 (例如購物車中商品價格變更),FoodErrorExtension
就必須包含 correctedProposedOrder
。
失敗回應範例
{
"expectUserResponse": false,
"finalResponse": {
"richResponse": {
"items": [
{
"structuredResponse": {
"error": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension",
"foodOrderErrors": [
{
"error": "CLOSED",
"description": "The restaurant is closed."
}
]
}
}
}
]
}
}
}
結帳流程導入
實作結帳功能時,請採取下列步驟。
驗證服務
針對找到的第一個服務錯誤情況,傳回 FoodOrderError。這些錯誤無法復原,因此應傳回遇到的第一個錯誤。請參閱「處理錯誤」,瞭解可復原錯誤的說明。
- 請讀取要求中的 FulfillmentOptionInfo 屬性,判斷是否為
delivery
或pickup
的交付類型。 視需要傳回下列錯誤類型:
錯誤類型 用途 INVALID 執行要求類型無效。 NOT_FOUND 找不到出貨類型。 已結束 - 訂單沒有 OperationHours 時間區間。
- 該訂單為 ASAP 訂單,目前沒有可用的 ASAP ServiceHours。
- 發生緊急關閉事件,或是服務
isDisabled
為 true。
UNAVAILABLE_SLOT 提前訂購的訂單無法完成。 NO_CAPACITY 餐廳目前忙於接待顧客,因此無法接受訂單。 OUT_OF_SERVICE_AREA 訂單無法送達使用者的地址。如需範例,請參閱運送地址驗證。 NO_COURIER_AVAILABLE 由於送貨人員有限,因此無法送達訂購商品。
驗證購物車並設定價格
查詢每個購物車.
lineItems
,並使用您或商家系統中的目前資料進行驗證。動態饋給實體中的 MenuItemOffer.sku
值會納入為 LineItem.offerId
。視需要為每個委刊項建立 FoodOrderError。每個項目最多只能建立一個錯誤。視需要傳回下列錯誤類型:錯誤類型 用途 可復原 INVALID 商品資料或任何選項資料無效。 否 NOT_FOUND 找不到項目或任何選項。 否 PRICE_CHANGED 商品或加購組合的價格已變更。這項錯誤可視為可復原。 是 AVAILABILITY_CHANGED 委刊項或任何選項要求的金額無效。 是 REQUIREMENTS_NOT_MET 未達到最低或最高訂單數量要求。如要判斷是否符合這項條件,請檢查購物車價格是否低於「費用」。 eligibleTransactionVolumeMin
或高於「費用」。eligibleTransactionVolumeMax
。請參閱最低訂單價值驗證中的範例。否 使用 LineItemType
REGULAR
傳回已驗證的 lineItems 清單。所有購物車委刊項價格的總和即為購物車價格或SUBTOTAL
。
請參閱購物車商品驗證中的範例。
計算服務費
- 根據
eligibleRegion
、validFrom
、validThrough
和priority
,找出服務的正確費用實體。 - 根據實體是否使用
price
、percentageOfCart
或pricePerMeter
屬性定義,計算費用金額。 - 請分別使用 LineItemType
DELIVERY
或FEE
,將外送或外帶服務費做為 LineItem 傳回。將費用新增至「Cart」.otherItems
清單。
套用促銷活動
- 根據促銷活動.
coupon
值與 交易.dealCode
比對結果,找出交易實體。 驗證交易,並視需要傳回 FoodOrderError。這些錯誤可視為可復原的錯誤。視需要傳回下列錯誤類型:
錯誤類型 用途 PROMO_NOT_RECOGNIZED 系統無法辨識優待券代碼。 PROMO_EXPIRED 優惠已過期。 PROMO_ORDER_INELIGIBLE 該訂單不符合優待券使用資格。 PROMO_NOT_APPLICABLE 其他原因。 根據特惠.
dealType
,使用購物車總額或費用總額套用特惠價格金額。傳回已套用促銷優惠的 Cart.
promotions
。使用 LineItemType
DISCOUNT
將宣傳活動傳回為 LineItem。將折扣加入Cart.otherItems
清單,並設為負價格。
傳回回應
- 建立 ProposedOrder。
cart
,如果驗證期間未發生任何錯誤,回應購物車就會與要求購物車相同。 - 傳回 ProposedOrder.
otherItems
清單,包括稅金、費用、小費和折扣 (如有)。如要進一步瞭解如何設定小費項目,請參閱「小費」。 - 加入ProposedOrder.
totalPrice
,方法是新增購物車價格、費用、折扣、稅金和小費。 - 傳回FoodOrderExtension.
availableFulfillmentOptions
和相應的 FulfillmentOption。將預估上車或送達時間更新為預期時間。 - 如果先前的驗證檢查產生 FoodOrderErrors:
- 在 FoodErrorExtension.
foodOrderErrors
中加入 StructuredResponse.error
和錯誤清單。 - 如果所有錯誤都能復原,請在
correctedProposedOrder
欄位中傳回 ProposedOrder。 - 如果所有錯誤都能復原,請在
paymentOptions
欄位中傳回 PaymentOptions。 - 如果有其他付款選項且所有錯誤都能復原,則可選擇加入
additionalPaymentOptions
。
- 在 FoodErrorExtension.
- 如果沒有驗證錯誤,請在 CheckoutResponse 物件中傳回
proposedOrder
paymentOptions
。如果有其他付款方式,您可以選擇加入additionalPaymentOptions
。