使用者建立購物車時,系統會叫用結帳程序。使用者購物車的內容和訂單詳細資料會傳送至「訂購端對端網路服務」。您的網路服務會驗證這些資訊,然後您就可以繼續視需要調整購物車或進行調整。
網路服務的結帳處理常式必須回應 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
:cart
物件與CheckoutRequestMessage
中提供的購物車相同。如果購物車中的任何內容需要變更,CheckoutResponseMessage
應改為加入含有修正ProposedOrder
的FoodErrorExtension
。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 時段。
- 訂單是「盡快」的訂單,且目前時間沒有 SAP 的「ServiceHours」ServiceHours可用。
- 發生緊急關閉狀況,或服務
isDisabled
為正確資訊。
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
傳回通過驗證的明細項目清單。所有購物車明細項目的價格總和為購物車價格或SUBTOTAL
。
請參閱購物車商品驗證中的範例。
計算服務費
- 根據
eligibleRegion
、validFrom
、validThrough
和priority
,找出服務的正確費用實體。 - 根據實體是透過
price
、percentageOfCart
或pricePerMeter
屬性定義計算費用金額。 - 使用 LineItemType
DELIVERY
或FEE
的 LineItem 傳回外送或匯出服務費。將費用新增至「Cart」.otherItems
清單。
套用促銷優惠
- 根據與 Promotion 相符的
coupon
值尋找 Deal 實體。coupon
值和 Deal。dealCode
驗證交易,並視需要傳回 FoodOrderError。 這些錯誤可能會視為可復原。視需要傳回下列錯誤類型:
錯誤類型 用途 PROMO_NOT_RECOGNIZED 無法識別優待券代碼。 PROMO_EXPIRED 交易有效期限已過。 PROMO_ORDER_INELIGIBLE 訂單不符合優待券的使用資格。 PROMO_NOT_APPLICABLE 其他原因。 使用購物車總金額或費用總額套用交易價格,具體取決於特惠。
dealType
退回購物車。
promotions
已套用促銷優惠。使用 LineItemType
DISCOUNT
,以 LineItem 傳回促銷活動。將折扣新增至購物車otherItems
清單,並將價格設為負值。
傳回回應
- 建立 ProposedOrder.
cart
,如果驗證期間未發生錯誤,回應購物車會與要求購物車相同。 - 傳回 ProposedOrder。
otherItems
清單,其中包含稅金、費用、免費折扣和折扣 (如有)。如要進一步瞭解如何設定祝賀項目,請參閱「Gratuity」。 - 加入 ProposedOrder,
totalPrice
即可加入購物車價格、費用、折扣、稅金和申請費。 - 使用個別的 FulfillmentOption 傳回 FoodOrderExtension.
availableFulfillmentOptions
。請將預估取貨或運送時間更新為預期時間。 - 如果先前的驗證檢查結果產生 FoodOrderErrors:
- 加入 StructuredResponse.
error
,並在 FoodErrorExtension 中列出錯誤清單。foodOrderErrors
。 - 如果所有錯誤都可以復原,請在
correctedProposedOrder
欄位中傳回 ProposedOrder。 - 如果所有錯誤都可以復原,請傳回
paymentOptions
欄位中的 PaymentOptions。 - 或者,如果有其他可用的付款選項,且所有錯誤都可復原,則請加入
additionalPaymentOptions
。
- 加入 StructuredResponse.
- 如果沒有驗證錯誤,請在 CheckoutResponse 物件中傳回
proposedOrder
、paymentOptions
。如有其他可用的付款方式,也可以加入additionalPaymentOptions
。