结账流程会在用户创建购物车时调用。系统会将用户购物车的内容和订单详情发送给“Google 订餐”网络服务。您的网络服务会验证这些信息,然后您便可以根据需要继续调整或调整购物车。
网络服务的结账处理程序必须响应 POST 请求。当客户选择结帐时,Google 会以 CheckoutRequestMessage
的形式向 Order with Google 网络服务发送一个 JSON 请求正文,其中包含该客户的 Cart
的详细信息。然后,您的 Web 服务会返回 CheckoutResponseMessage
。下图说明了该流程。
收到结账请求后,您的“Google 订餐”网络服务必须执行以下操作:
- 根据当前商品价格、库存状况和提供商服务检查购物车的有效性。
- 计算总价(包括所有折扣、税费和运费)。
- 如果成功,请使用未经修改的购物车进行回复。
- 如果不成功,可回复错误消息,并显示新的建议订单。
在开始实现结账流程之前,我们建议您先查看 Fulfillment 概览文档。
结账请求消息
为了验证客户的购物车,当客户选择结帐时,Google 会使用 CheckoutRequestMessage
形式的 JSON 正文向您的网络服务发送请求。客户订单稍后才会在“Google 订餐”流程中提交。
CheckoutRequestMessage
中包含的数据包括:
- Intent:每个结账请求正文的
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
}
结账响应消息
收到“Google 订餐”服务的请求后,您的结账网络服务必须处理该请求并返回 CheckoutResponseMessage
。CheckoutResponseMessage
需要包含成功或失败的请求。
请求成功
如果检出请求成功,CheckoutResponseMessage
需要包含 ProposedOrder
和 PaymentOptions
:
ProposedOrder
cart
:与CheckoutRequestMessage
中提供的购物车完全相同的cart
对象。如果购物车中的任何内容需要更改,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."
}
]
}
}
}
]
}
}
}