Bạn có thể hỗ trợ phương thức thực hiện đơn hàng để người dùng lên lịch đến lấy hàng và
giao đồ ăn trước. Trước khi triển khai tính năng hỗ trợ này trong
thực hiện đơn hàng, hãy tạo nguồn cấp dữ liệu kho hàng cung cấp dịch vụ để chỉ định giờ làm việc cho người dùng
để đặt hàng trước, như được mô tả trong giản đồ nguồn cấp dữ liệu kho hàng
(AdvanceServiceDeliveryHoursSpecification
).
Khung giờ đặt hàng trước
Google đề xuất khung giờ đặt hàng trước theo gia số 15 phút, cho tối đa 7 ngày
dựa trên thời gian thực hiện đơn hàng cho một nhà hàng hoặc dịch vụ (như được xác định trong
AdvanceServiceDeliveryHoursSpecification
).
Để truy xuất vị trí đơn đặt hàng trước được đề xuất, hãy sử dụng các giá trị sau từ
Trường fulfillmentPreference
của đối tượng FoodCartExtension
khi thanh toán:
PickupInfo.pickupTimeIso8601
DeliveryInfo.deliveryTimeIso8601
Triển khai đơn đặt hàng trước khi thanh toán
Bảng dưới đây liệt kê những cách mà bạn có thể triển khai phương thức thực hiện đơn hàng phản hồi tại thời điểm thanh toán khi người dùng cố gắng đặt hàng.
Trường hợp | Hành vi thực hiện đơn hàng |
---|---|
Có thể thực hiện đơn đặt hàng trước cho khung giờ được yêu cầu. | Chấp nhận P0M ("càng sớm càng tốt") hoặc
FUTURE_SLOT giỏ hàng bằng cách tạo một ProposedOrder với
cùng một vị trí. Để xem ví dụ về phản hồi thanh toán chấp nhận khung giờ nhận đặt quảng cáo, hãy xem
đoạn mã này. |
Không thể thực hiện đơn đặt hàng trước cho khung giờ được yêu cầu. | Phương thức thực hiện của bạn cần thực hiện như sau:
Để xem ví dụ về phản hồi của quy trình thanh toán đề xuất các vị trí thay thế, hãy xem đoạn mã này. |
Vị trí thay thế để thực hiện đơn hàng
Khi thanh toán, nếu khung giờ đặt hàng trước do Google đề xuất không phù hợp,
phương thức thực hiện có thể đề xuất phương án thay thế bằng cách sử dụng CheckoutResponseMessage
.
Để chỉ định khung giờ đặt hàng trước thay thế, hãy phản hồi yêu cầu thanh toán bằng
FoodErrorExtension
rồi đặt các giá trị sau:
- Trong tham số
foodOrderErrors
, hãy chỉ định loại lỗi (nhưUNAVAILABLE_SLOT
,NO_CAPACITY
hoặcCLOSED
). - Trong tham số
correctedProposedOrder
, hãy cung cấpP0M
hoặc Các giá trịFUTURE_SLOT
quaavailableFulfillmentOptions
.
Các khung giờ thay thế phải trong vòng 7 ngày tiếp theo kể từ thời điểm đặt hàng và bao gồm tất cả các vị trí mà giỏ hàng được yêu cầu của người dùng có thể sẽ được thực hiện.
Ví dụ: giả sử bữa trưa đặc biệt chỉ có sẵn từ thứ Hai đến thứ Sáu từ 11 giờ sáng đến 1 giờ chiều. Sau đó, người dùng thử thêm bữa trưa đặc biệt vào giỏ hàng, nhưng khung giờ mà họ đã chọn không có sẵn. Trong trường hợp này, phương thức thực hiện của bạn phải giữ lại các món đặc biệt cho bữa trưa trong giỏ hàng và chỉ trả lại vào khung giờ từ 11 giờ sáng đến 1 giờ chiều trong 7 ngày tới
Bạn nên bỏ qua đối tượng correctedProposedOrder.Cart.fulfillmentPreference
trong câu trả lời của bạn.
Nếu không còn chỗ trống hoặc nếu nhà hàng hoặc dịch vụ không
hỗ trợ đơn đặt hàng trước, thì bạn không cần cung cấp
correctedProposedOrder
.
Hãy xem ví dụ dưới đây về các thông báo JSON giữa phương thức thực hiện của bạn và Google trong quy trình yêu cầu thanh toán và phản hồi cho một đơn đặt hàng trước, khi nhà hàng hoặc dịch vụ có sẵn để đặt hàng trước.
Ví dụ: CheckoutRequest có vị trí giao hàng
Đoạn mã dưới đây là ví dụ về một yêu cầu thanh toán có đơn đặt hàng trước vùng phân phối.
{
"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": {
...
}
}
}
}
]
}
]
}
Ví dụ: CheckoutResponse chấp nhận vị trí
Đoạn mã dưới đây cho thấy ví dụ về một phản hồi thanh toán trong đó thực hiện đơn hàng chấp nhận khung giờ đặt hàng trước được đề xuất.
{
"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": {
...
}
}
}
}
]
}
}
}
Ví dụ: CheckoutResponse có các ô thay thế
Đoạn mã dưới đây cho thấy ví dụ về một phản hồi thanh toán trong đó thực hiện đơn hàng
đề xuất khung giờ đặt hàng trước thay thế. Lưu ý rằng
Phải bỏ qua đối tượng correctedProposedOrder.Cart.fulfillmentPreference
trong
phản hồi của bạn.
{
"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": {
...
}
}
}
}
]
}
}
}
Triển khai đơn đặt hàng trước khi gửi đơn đặt hàng
Khi gửi đơn đặt hàng, nếu có vấn đề với khung giờ đặt hàng trước,
SubmitOrderResponseMessage
phải bao gồm lý do (chẳng hạn như
UNAVAILABLE_SLOT
hoặc UNKNOWN
) trong đối tượng RejectionInfo
.
Cập nhật trạng thái của đơn đặt hàng từ CREATED
thành CONFIRMED
trong
OrderState
đối tượng khi nhà cung cấp chấp nhận đơn gọi món. Bao gồm
khung giờ đã chọn trong email xác nhận gửi cho người dùng.
Nếu phương thức thực hiện đơn hàng của bạn gửi đơn đặt hàng đến nhà hàng sau đó, hãy gửi cho Google cập nhật bằng Thao tác cập nhật thứ tự không đồng bộ.
Trong đối tượng OrderUpdate
của phản hồi gửi đơn đặt hàng của bạn hoặc
các bản cập nhật đơn đặt hàng không đồng bộ tiếp theo, bao gồm
estimatedFulfillmentTimeIso8601
với giá trị được đặt như sau:
- Khi trạng thái đơn đặt hàng là
CREATED
hoặcCONFIRMED
, hãy đặt giá trị thành giao hàng hoặc thời gian nhận hàng mà người dùng đã lên lịch cho đơn đặt hàng trước của họ. - Khi có thời gian giao hàng dự kiến chính xác hơn từ nhà hàng hoặc dịch vụ, hãy đặt giá trị thành thời gian giao hàng hoặc thời gian đến lấy hàng dự kiến.
Ví dụ: SubmitOrderRequest có khung giờ giao hàng
Đoạn mã dưới đây cho thấy ví dụ về một yêu cầu gửi đơn đặt hàng cho biết vùng đơn đặt hàng trước mà người dùng đã chọn.
{
"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": {
...
}
}
}
}
]
}
]
}
Ví dụ: SubmitOrderResponse chấp nhận đơn đặt hàng
Đoạn mã dưới đây minh hoạ một ví dụ về phản hồi khi gửi đơn đặt hàng, trong đó phương thức thực hiện đơn hàng xác nhận rằng đã chấp nhận đơn đặt hàng trước của người dùng.
{
"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"
}
}
}
}
]
}
}
}
Ví dụ: SubmitOrderResponse từ chối đơn đặt hàng do không có chỗ trống
Đoạn mã dưới đây minh hoạ một ví dụ về phản hồi khi gửi đơn đặt hàng, trong đó thực hiện đơn hàng từ chối đơn đặt hàng trước của người dùng do không còn khung giờ.
{
"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": [
...
]
}
}
}
]
}
}
}
Ví dụ về đơn đặt hàng trước
Bạn có thể sử dụng loại AdvanceServiceDeliveryHoursSpecification
để chỉ định
giờ giao hàng hoặc đến lấy hàng để người dùng lên lịch trước cho đơn đặt hàng của họ.
Lưu ý: Có hai khoảng thời gian riêng biệt mà bạn phải chỉ định
để thực hiện dịch vụ: cửa sổ sắp xếp chỉ định thời điểm người dùng có thể đặt một
đơn đặt hàng và cửa sổ thực hiện đơn hàng chỉ định thời điểm thực hiện đơn đặt hàng. Chiến lược phát hành đĩa đơn
Đối tượng
xác định thời điểm người dùng
có thể đặt hàng. Thời gian thực hiện nhiệm vụ con của mục này (OpeningHoursSpecification
hoặc ServiceDeliveryHoursSpecification
) xác định thời điểm đơn đặt hàng có thể được
đã thực hiện.AdvanceServiceDeliveryHoursSpecification
Ví dụ sau đây xác định giờ mở cửa của một dịch vụ chấp nhận đơn đặt hàng trước, trong khoảng thời gian bảo dưỡng là 15 phút.
{ "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" } } ] } ] }
Ví dụ sau cho thấy cách bạn có thể chỉ định rằng dịch vụ được mở cho các đơn đặt hàng cùng ngày vào ngày Giáng sinh nhưng đóng đối với các đơn đặt hàng nâng cao được lên lịch vào ngày hôm đó. Ví dụ này hỗ trợ các trường hợp sau:
- Người dùng có thể đặt hàng vào ngày 25 tháng 12 để được giao hàng trong cùng ngày.
- Người dùng có thể đặt hàng trước vào ngày 25 tháng 12 để được lên lịch giao hàng vào ngày 27 tháng 12.
- Người dùng không thể đặt hàng trước vào ngày 22 tháng 12 để được lên lịch giao hàng vào ngày 25 tháng 12.
{ "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" } }
Ví dụ sau cho thấy cách bạn có thể chỉ định đóng dịch vụ đối với đơn đặt hàng trong cùng ngày hoặc đơn đặt hàng trước được lên lịch vào ngày Giáng sinh, nhưng mở trong các đơn đặt hàng nâng cao được lên lịch cho một ngày sau đó. Ví dụ này hỗ trợ: trường hợp:
- Người dùng không thể đặt hàng vào ngày 25 tháng 12 để được giao hàng trong cùng ngày.
- Người dùng có thể đặt hàng trước vào ngày 25 tháng 12 để được lên lịch giao hàng vào ngày 27 tháng 12.
- Người dùng không thể đặt hàng trước vào ngày 22 tháng 12 để được lên lịch giao hàng vào ngày 25 tháng 12.
{ "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" } ] }
Dịch vụ mẫu sau đây chấp nhận đơn đặt hàng 24x7 và giao hàng từ 10:00 – 2:59:59 vào các ngày trong tuần:
... { "@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" } } } ...
Dịch vụ mẫu sau đây chấp nhận đơn đặt hàng mỗi ngày từ 8 SA-4:59:59 CH, và khách hàng có thể chọn giao hàng trong vòng một giờ hoặc chọn một trong vị trí:
... { "@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" } } ] } ...
Mẫu sau đây cho thấy trường hợp cửa hàng mở cửa từ 8:00 đến 16:59:59 vào các ngày trong tuần nhưng từ 8:00 đến 18:59 vào cuối tuần. Không chấp nhận đơn đặt hàng 24x7.
... { // 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" } } ] } ...