您可以在執行要求中加入支援,讓使用者預先安排自取和外送餐點訂單。在執行要求導入這項支援功能之前,請先建立服務商品目錄動態饋給,指定使用者的提前訂購時數,如商品目錄動態饋給結構定義 (AdvanceServiceDeliveryHoursSpecification
) 所述。
提前訂購運算單元
Google 會根據餐廳或服務的出貨時間 (如 AdvanceServiceDeliveryHoursSpecification
所定義),以 15 分鐘為遞增單位提前安排預訂時段,最多提前 7 天。
如要擷取提議的預訂運算單元,請在結帳時使用 FoodCartExtension
物件的 fulfillmentPreference
欄位中的下列值:
PickupInfo.pickupTimeIso8601
DeliveryInfo.deliveryTimeIso8601
在結帳時導入提前訂單功能
下表列出了當使用者嘗試下單時,在結帳時間實作執行要求回應的方法。
情境 | 出貨行為 |
---|---|
可針對要求的時段提前完成訂單。 | 使用同一個版位建立 ProposedOrder ,接受 P0M (「越快越好」) 或 FUTURE_SLOT 購物車。如需接受運算單元的結帳回應範例,請參閱這個程式碼片段。 |
系統無法針對要求的時段完成提前訂單。 | 執行要求應執行以下操作:
如需提供替代版位的結帳回應範例,請參閱這篇程式碼片段。 |
訂單履行的替代運算單元
在結帳時,如果 Google 提出的預先預訂訂單不適合,您的執行要求可以使用 CheckoutResponseMessage
物件建議替代方案。
如要指定其他提前訂單時段,請使用 FoodErrorExtension
回應結帳要求,並設定下列值:
- 在
foodOrderErrors
參數中指定錯誤類型 (例如UNAVAILABLE_SLOT
、NO_CAPACITY
或CLOSED
)。 - 在
correctedProposedOrder
參數中,透過availableFulfillmentOptions
提供替代的P0M
或FUTURE_SLOT
值。
替代運算單元應是訂單下單後的未來 7 天,且應包含使用者要求購物車的所有運算單元。
舉例來說,午餐特惠僅限週一至週五上午 11 點到下午 1 點。接著,使用者嘗試將午餐優惠加入購物車,但所選時段無法購買。在這種情況下,您的執行要求應保留購物車中的午餐優惠,並且只傳回接下來 7 天的上午 11 點到下午 1 點的時段
回應中應省略 correctedProposedOrder.Cart.fulfillmentPreference
物件。
如果沒有可預約的時段,或是餐廳或服務不支援提前訂購,您就不需要提供 correctedProposedOrder
。
請參閱以下範例,瞭解在預訂餐廳或服務進行預購的結帳要求與回應流程期間,執行要求與 Google 之間的 JSON 訊息。
範例:包含放送時段的「CheckRequest」要求
下方程式碼片段是含提前訂單送達時段的結帳要求範例。
{
"inputs": [
{
"intent": "actions.foodordering.intent.CHECKOUT",
"arguments": [
{
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.Cart",
"merchant": {
"id": "https://www.exampleprovider.com/merchant/id1",
"name": "Cucina Venti"
},
"lineItems": [
{
"name": "Sizzling Prawns Dinner",
"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": "16",
"nanos": 750000000
}
},
}
],
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
"fulfillmentPreference": {
"fulfillmentInfo": {
"delivery": {
// Deliver at 6:30PM.
"deliveryTimeIso8601": "2017-12-14T18:30:00-07:00"
}
}
},
"location": {
...
}
}
}
}
]
}
]
}
範例:CheckResponse 接受版位
以下程式碼片段是結帳回應範例,您的執行要求接受建議的提前訂購時段。
{
"expectUserResponse": false,
"finalResponse": {
"richResponse": {
"items": [
{
"structuredResponse": {
"checkoutResponse": {
"proposedOrder": {
"id": "sample_proposed_order_id_1",
"cart": {
"merchant": {
"id": "https://www.exampleprovider.com/merchant/id1",
"name": "Falafel Bite"
},
"lineItems": [
{
"name": "Sizzling Prawns Dinner",
"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": "16",
"nanos": 750000000
}
},
}
],
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
"fulfillmentPreference": {
"fulfillmentInfo": {
"delivery": {
// Same as the time in the request.
"deliveryTimeIso8601": "2017-12-14T18:30:00-07:00"
}
}
},
"location": {
...
}
}
},
"totalPrice": {
"type": "ESTIMATE",
"amount": {
// Represents $16.75
"currencyCode": "USD",
"units": "16",
"nanos": 750000000
}
},
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension",
// Send whole proposed order back.
"availableFulfillmentOptions": [
"fulfillmentInfo": {
"delivery": {
// Same as the time in the request.
"deliveryTimeIso8601": "2017-12-14T18:30:00-07:00"
}
}
]
}
},
"paymentOptions": {
...
}
}
}
}
]
}
}
}
範例:包含備用版位的 CheckoutResponse
以下程式碼片段是結帳回應的範例,您的執行要求會提議替代的提前訂購時段。請注意,回應中應省略 correctedProposedOrder.Cart.fulfillmentPreference
物件。
{
"expectUserResponse": false,
"finalResponse": {
"richResponse": {
"items": [
{
"structuredResponse": {
"error": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension",
"foodOrderErrors": [
{
"error": "UNAVAILABLE_SLOT", // Cart level error
"description": "The restaurant is closed."
}
],
"correctedProposedOrder": {
// Send whole original cart back,
// without the fulfillmentPreference.
"cart": {
...
},
"otherItems": {
...
},
"totalPrice": {
...
},
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension",
"availableFulfillmentOptions": [
"fulfillmentInfo": {
"delivery": {
"deliveryTimeIso8601": "2017-12-14T19:00:00-07:00"
}
},
"fulfillmentInfo": {
"delivery": {
"deliveryTimeIso8601": "2017-12-14T19:30:00-07:00"
}
},
"fulfillmentInfo": {
"delivery": {
"deliveryTimeIso8601": "2017-12-14T20:00:00-07:00"
}
}
]
}
},
"paymentOptions": {
...
}
}
}
}
]
}
}
}
在提交訂單時導入提前訂單功能
提交訂單時,如果提前訂單時段有問題,SubmitOrderResponseMessage
應在 RejectionInfo
物件中附上原因 (例如 UNAVAILABLE_SLOT
或 UNKNOWN
)。
當供應商接受訂單後,請將 OrderState
物件中的訂單狀態從 CREATED
更新為 CONFIRMED
。請在要傳送給使用者的確認電子郵件中,加入所選時段。
如果執行要求稍後將訂單傳送給餐廳,請使用非同步訂單更新動作將更新傳送給 Google。
在執行要求提交訂單回應或後續非同步訂單更新的 OrderUpdate
物件中,加入 estimatedFulfillmentTimeIso8601
並設定以下值:
- 當訂單狀態為
CREATED
或CONFIRMED
時,請將值設為使用者提前訂購的外送或取貨時間。 - 如果餐廳或服務的預估送達時間更準確,請將值設為外送或取貨時間的預計時間。
範例:SubmitOrderRequest 包含放送時段
以下程式碼片段是提交訂單要求的範例,指出使用者選取的提前訂購時段。
{
"inputs": [
{
"intent": "actions.intent.TRANSACTION_DECISION",
"arguments": [
{
"transactionDecisionValue": {
"order": {
"finalOrder": {
"cart": {
"notes": "Guest prefers their food to be hot when it is delivered.",
"merchant": {
"id": "https://www.exampleprovider.com/merchant/id1",
"name": "Cucina Venti"
},
"lineItems": [
{
"name": "Sizzling Prawns Dinner",
"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": "16",
"nanos": 750000000
}
}
}
],
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
"fulfillmentPreference": {
"fulfillmentInfo": {
"delivery": {
"deliveryTimeIso8601": "2017-12-14T18:30:00-07:00"
}
}
}
"contact": {
...
}
}
},
"totalPrice": {
"type": "ESTIMATE",
"amount": {
"currencyCode": "USD",
"units": "16",
"nanos": 750000000
}
},
"id": "sample_final_order_id",
"extension": {
// Send whole proposed order back.
"availableFulfillmentOptions": [
"fulfillmentInfo": {
"delivery": {
"deliveryTimeIso8601": "2017-12-14T18:30:00-07:00"
}
]
}
},
"googleOrderId": "sample_google_order_id",
"orderDate": "2017-07-17T12:00:00Z",
"paymentInfo": {
...
}
}
}
}
]
}
]
}
例如:SubmitOrderResponse 接受訂單
以下程式碼片段是提交訂單回應的範例,在執行要求確認其已接受使用者的提前訂單。
{
"expectUserResponse": false,
"finalResponse": {
"richResponse": {
"items": [
{
"structuredResponse": {
"orderUpdate": {
"actionOrderId": "sample_action_order_id",
"orderState": {
"state": "CREATED",
"label": "Order placed"
},
"receipt": {
"userVisibleOrderId": "userVisibleId1234"
},
"updateTime": "2017-07-17T12:00:00Z",
"orderManagementActions": [
...
],
"infoExtension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension",
// Same as the user selected time.
"estimatedFulfillmentTimeIso8601": "2017-12-14T18:30:00-07:00"
}
}
}
}
]
}
}
}
例如:SubmitOrderResponse 因無法供應時段而拒絕訂單
以下程式碼片段是提交訂單回應的範例,其中執行要求因無法使用的時段而拒絕使用者的提前訂單。
{
"expectUserResponse": false,
"finalResponse": {
"richResponse": {
"items": [
{
"structuredResponse": {
"orderUpdate": {
"actionOrderId": "sample_action_order_id",
"orderState": {
"state": "REJECTED",
"label": "Unavailable slot"
},
"rejectionInfo": {
// Note that this UNAVAILABLE_SLOT is different from the enum
// with the same name proposed for FoodOrderError.
"state": "UNAVAILABLE_SLOT",
"label": "Unavailable slot"
},
"updateTime": "2017-07-17T12:00:00Z",
"orderManagementActions": [
...
]
}
}
}
]
}
}
}
提前訂單範例
AdvanceServiceDeliveryHoursSpecification
類型可用來指定外送或取貨時間,讓使用者能提前安排訂單。
注意: 您必須針對服務執行要求指定兩個不同的時間範圍:訂購期 (指定使用者下單的時間),以及指定訂單完成時間的執行要求期。
物件會定義使用者可下單的時機。子項執行時間 (OpeningHoursSpecification
或 ServiceDeliveryHoursSpecification
) 會定義訂單可履行的時間。AdvanceServiceDeliveryHoursSpecification
以下範例定義接受提前訂單的服務時數 (15 分鐘服務間隔)。
{ "hoursAvailable": [ { "@type": "OpeningHoursSpecification", "opens": "T00:00:00", // Ordering available 24 hours "closes": "T23:59:59", "deliveryHours": [ { "@type": "ServiceDeliveryHoursSpecification", "opens": "T09:00:00", // ASAP orders b/w 9am and 8:59:59pm "closes": "T21:00:00", "deliveryLeadTime": { "value": "60", "unitCode": "MIN" } }, { "@type": "AdvanceServiceDeliveryHoursSpecification", "opens": "T10:00:00", // Delivery between 10AM and 7:59:59PM "closes": "T20:00:00", "serviceTimeInterval": "PT15M", // in slots spaced 15 minutes apart (ISO8601) "advanceBookingRequirement": { "minValue": 60, // The slot should be at least 60 mins away "maxValue": 8640, // but not more than 6 days away "unitCode": "MIN" } } ] } ] }
以下範例說明如何指定在聖誕節當天營業,但針對當天排定的進階訂單關閉服務。本範例支援下列情況:
- 使用者可以在 12 月 25 日下單,當天到貨服務。
- 使用者「可以」在 12 月 25 日預先下單,並排定在 12 月 27 日送達。
- 使用者無法在 12 月 22 日事先下單,並安排在 12 月 25 日送達。
{ "specialOpeningHoursSpecification": { "@type": "AdvanceServiceDeliveryHoursSpecification", "validFrom": "2018-12-25T00:00:00-07:00", "validThrough": "2018-12-26T00:00:00-07:00", "opens": "T00:00:00", // No advance ordering "closes": "T00:00:00" } }
以下範例說明如何指定在聖誕節當天關閉服務,或排定在聖誕節前透過提前預訂服務關閉服務,但這種訂單會在稍晚的隔日營業。本例支援下列情境:
- 使用者無法在 12 月 25 日下單,訂購當天到貨服務。
- 使用者「可以」在 12 月 25 日預先下單,並排定在 12 月 27 日送達。
- 使用者無法在 12 月 22 日事先下單,並安排在 12 月 25 日送達。
{ "specialOpeningHoursSpecification": [ { "@type": "ServiceDeliveryHoursSpecification", "validFrom": "2018-12-25T00:00:00-07:00", "validThrough": "2018-12-26T00:00:00-07:00", "opens": "T00:00:00", // No ASAP ordering on Christmas "closes": "T00:00:00" }, { "@type": "AdvanceServiceDeliveryHoursSpecification", "validFrom": "2018-12-25T00:00:00-07:00", "validThrough": "2018-12-26T00:00:00-07:00", "opens": "T00:00:00", // Orders cannot be scheduled for Christmas "closes": "T00:00:00" } ] }
下列服務範例服務可接受 24 小時全年無休的訂單,並在平日的上午 10 點到 2:59:59 之間遞送:
... { "@type": "OpeningHoursSpecification", "opens": "T00:00:00", "closes": "T23:59:59", "deliveryHours": { "@type": "AdvanceServiceDeliveryHoursSpecification", "opens": "T10:00:00", // Delivery starts at 10:00AM "closes": "T15:00:00", // Delivery ends at 3:00PM. Delivery from 10AM-2:59:59PM. "dayOfWeek": [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" ], "serviceTimeInterval": "PT15M", // in slots spaced 15 minutes apart "advanceBookingRequirement": { "minValue": 60, // The slot should be at least 60 mins away "maxValue": 8640, // but not more than 6 days away "unitCode": "MIN" } } } ...
下列服務範例服務接受每天上午 8 點至下午 4 點 59 分 59 分的訂單,客戶可以選擇在一小時內送達,或是選擇其中一個時段:
... { "@type": "OpeningHoursSpecification", "opens": "T08:00:00", // Ordering opens at 8:00AM "closes": "T17:00:00", // Ordering closes at 5:00PM, last order at 4:59:59PM "deliveryHours": [ { "@type": "ServiceDeliveryHoursSpecification", "opens": "T08:00:00", "closes": "T17:00:00", "deliveryLeadTime": { "@type": "QuantitativeValue", "value": "60", // If no exact deliveryLeadTime, put a maximum time "unitCode": "MIN" } }, { "@type": "AdvanceServiceDeliveryHoursSpecification", "opens": "T08:00:00", "closes": "T17:00:00", "serviceTimeInterval": "PT15M", // in slots spaced 15 minutes apart "advanceBookingRequirement": { "minValue": 90, // The slot should be at least 90 mins away "maxValue": 8640, // but not more than 6 days away "unitCode": "MIN" } } ] } ...
以下範例顯示商店於平日上午 8 點至下午 4 點 59 分 59 分,但週末晚上 8 點至 6 點 59 分。我們不提供全年無休的訂單。
... { // On weekdays, ordering open from 8AM-4:59:59PM. "@type": "OpeningHoursSpecification", "opens": "T08:00:00", "closes": "T17:00:00", "dayOfWeek": [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" ], "deliveryHours": [ { // Fulfillment between 8AM-4:59:59PM on weekdays. "@type": "AdvanceServiceDeliveryHoursSpecification", "opens": "T08:00:00", "closes": "T17:00:00", "dayOfWeek": [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" ], "serviceTimeInterval": "PT15M", "advanceBookingRequirement": { "minValue": 60, "maxValue": 8640, "unitCode": "MIN" } }, { // Fulfillment between 8AM-6:59:59PM on weekends (even for orders placed on a // weekday). "@type": "AdvanceServiceDeliveryHoursSpecification", "opens": "T08:00:00", "closes": "T19:00:00", "dayOfWeek": [ "Saturday", "Sunday" ], "serviceTimeInterval": "PT15M", "advanceBookingRequirement": { "minValue": 60, "maxValue": 8640, "unitCode": "MIN" } } ] }, { // On weekends, one can place orders upto 6:59:59PM. "@type": "OpeningHoursSpecification", "opens": "T08:00:00", "closes": "T19:00:00", "dayOfWeek": [ "Saturday", "Sunday" ], "deliveryHours": [ { // But fulfillment on weekdays is only till 4:59:59PM. "@type": "AdvanceServiceDeliveryHoursSpecification", "opens": "T08:00:00", "closes": "T17:00:00", "dayOfWeek": [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" ], "serviceTimeInterval": "PT15M", "advanceBookingRequirement": { "minValue": 60, "maxValue": 8640, "unitCode": "MIN" } }, { // Fulfillment on weekends is till 6:59:59PM. "@type": "AdvanceServiceDeliveryHoursSpecification", "opens": "T08:00:00", "closes": "T19:00:00", "dayOfWeek": [ "Saturday", "Sunday" ], "serviceTimeInterval": "PT15M", "advanceBookingRequirement": { "minValue": 60, "maxValue": 8640, "unitCode": "MIN" } } ] } ...