Możesz dodać obsługę w ramach realizacji zamówienia, aby użytkownicy mogli z wyprzedzeniem zaplanować odbiór i dostawę jedzenia. Zanim wdrożysz tę funkcję w ramach realizacji, utwórz plik danych o asortymencie usługi, który określa godziny, w których użytkownicy mogą składać zamówienia z wyprzedzeniem, zgodnie ze schematem pliku danych o asortymencie (AdvanceServiceDeliveryHoursSpecification
).
Terminy składania zamówień z wyprzedzeniem
Google proponuje terminy składania zamówień z wyprzedzeniem w odstępach 15-minutowych do 7 dni w oparciu o czas realizacji zamówienia w restauracji lub usługi (zgodnie z definicją w AdvanceServiceDeliveryHoursSpecification
).
Aby pobrać proponowane terminy dostawy, użyj tych wartości z pola fulfillmentPreference
obiektu FoodCartExtension
podczas płatności:
PickupInfo.pickupTimeIso8601
DeliveryInfo.deliveryTimeIso8601
Wprowadzanie zamówień w przedsprzedaży podczas płatności
Tabela poniżej zawiera możliwe sposoby implementacji odpowiedzi usługi realizacji zamówienia w momencie płatności, gdy użytkownicy próbują złożyć zamówienie.
Scenariusz | Sposób realizacji |
---|---|
Zamówienie wstępne może zostać zrealizowane w wybranym terminie. | Zaakceptuj P0M („jak najszybciej”) lub FUTURE_SLOT , tworząc ProposedOrder w tym samym miejscu. Przykład odpowiedzi z akceptacją rezerwacji znajdziesz w tym fragmentie kodu. |
Nie można zrealizować zamówienia z wyprzedzeniem w wybranym czasie. | Proces realizacji zamówienia powinien:
Przykład odpowiedzi z płatnością proponującej alternatywne sloty znajdziesz w tym fragmencie kodu. |
alternatywne sloty na realizację zamówień,
Jeśli podczas płatności proponowane przez Google terminy dostawy nie są odpowiednie, usługa realizacji zamówienia może zaproponować alternatywne terminy za pomocą obiektu CheckoutResponseMessage
.
Aby określić alternatywne terminy składania zamówienia z wyprzedzeniem, odpowiedz na żądanie płatności parametrem FoodErrorExtension
i ustaw te wartości:
- W parametrze
foodOrderErrors
określ typ błędu (np.UNAVAILABLE_SLOT
,NO_CAPACITY
lubCLOSED
). - W parametrze
correctedProposedOrder
podaj alternatywne wartościP0M
lubFUTURE_SLOT
za pomocąavailableFulfillmentOptions
.
Alternatywny termin dostawy powinien obejmować 7 dni od daty złożenia zamówienia i wszystkie terminy, w których można zrealizować żądaną przez użytkownika koszyk.
Załóżmy, że specjalne menu obiadowe jest dostępne tylko od poniedziałku do piątku w godzinach 11:00–13:00. Użytkownik próbuje dodać do koszyka specjalne oferty lunchowe, ale wybrany przez niego slot jest niedostępny. W tym przypadku Twoje usługi powinny obejmować specjalne oferty na lunch w koszyku i powinny być dostępne w ciągu najbliższych 7 dni w godzinach 11:00–13:00.
W odpowiedzi pomiń obiekt correctedProposedOrder.Cart.fulfillmentPreference
.
Jeśli nie ma dostępnych terminów lub restauracja lub usługa nie obsługuje zamówień z wyprzedzeniem, nie musisz podawać informacji o correctedProposedOrder
.
Poniżej znajdziesz przykłady wiadomości JSON przesyłanych między Twoją firmą a Google w trakcie procesu składania zamówienia i odpowiedzi na żądanie dotyczące płatności, gdy restauracja lub usługa umożliwiają składanie zamówień w przedsprzedaży.
Przykład: CheckoutRequest z oknem dostawy
Fragment poniżej pokazuje przykład żądania płatności z zamówieniem z dostawą w określonym terminie.
{
"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": {
...
}
}
}
}
]
}
]
}
Przykład: CheckoutResponse akceptujący slot
Fragment poniżej pokazuje przykład odpowiedzi na proces płatności, w którym usługa realizacji zamówień akceptuje zaproponowane terminy zamówienia z wyprzedzeniem.
{
"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": {
...
}
}
}
}
]
}
}
}
Przykład: CheckoutResponse z alternatywnymi slotami
Fragment poniżej pokazuje przykład odpowiedzi na proces płatności, w którym usługa realizacji proponuje alternatywne terminy zamówienia z wyprzedzeniem. Pamiętaj, że w odpowiedzi nie należy pomijać obiektu 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": {
...
}
}
}
}
]
}
}
}
Wdrażanie zamówień z wyprzedzeniem podczas przesyłania zamówienia
Jeśli podczas przesyłania zamówienia wystąpi problem z miejscami na zamówienia z wyprzedzeniem, obiekt SubmitOrderResponseMessage
powinien zawierać w obiekcie RejectionInfo
przyczynę (np. UNAVAILABLE_SLOT
lub UNKNOWN
).
Po zaakceptowaniu zamówienia przez dostawcę zaktualizuj stan zamówienia z CREATED
na CONFIRMED
w obiekcie OrderState
. W e-mailu z potwierdzeniem dla użytkownika podaj wybrany przedział czasu.
Jeśli usługa wysyłki wyśle zamówienie do restauracji później, wyślij do Google aktualizację za pomocą asymetrycznego działania aktualizacji zamówienia.
W obiekcie OrderUpdate
w odpowiedzi na przesłanie zamówienia przez usługę realizacji lub w kolejnych asynchronicznych aktualizacjach zamówienia dodaj obiekt estimatedFulfillmentTimeIso8601
z wartością ustawioną w ten sposób:
- Jeśli stan zamówienia to
CREATED
lubCONFIRMED
, ustaw wartość na czas dostawy lub odbioru, który użytkownik zaplanował dla zamówienia z wyprzedzeniem. - Jeśli restauracja lub usługa podaje dokładniejszy szacowany czas dostawy, ustaw wartość na szacowany czas dostawy lub odbioru.
Przykład: SubmitOrderRequest z oknem dostawy
Fragment poniżej pokazuje przykład prośby o przesłanie zamówienia z wyznaczonym przez użytkownika slotem zamówienia z wyprzedzeniem.
{
"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": {
...
}
}
}
}
]
}
]
}
Przykład: odpowiedź SubmitOrderResponse z zaakceptowanym zamówieniem
Poniżej znajduje się fragment kodu, który pokazuje przykład odpowiedzi na przesłanie zamówienia, w którym usługa realizacji potwierdza, że zaakceptowała wstępny zakup użytkownika.
{
"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"
}
}
}
}
]
}
}
}
Przykład: odpowiedź SubmitOrderResponse z odrzuceniem zamówienia z powodu braku dostępności slotu
Fragment poniżej pokazuje przykład odpowiedzi na przesłanie zamówienia, w którym usługa odrzuca zamówienie z wyprzedzeniem z powodu niedostępnego przedziału czasowego.
{
"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": [
...
]
}
}
}
]
}
}
}
Przykłady zamówień w przedsprzedaży
Typ AdvanceServiceDeliveryHoursSpecification
może służyć do określania godzin dostawy lub odbioru, aby użytkownicy mogli z wyprzedzeniem zaplanować swoje zamówienie.
Uwaga: aby zrealizować usługę, musisz określić 2 okresy czasowe: okres składania zamówień, który określa, kiedy użytkownicy mogą składać zamówienia, oraz okres realizacji, który określa, kiedy zamówienie ma zostać zrealizowane. Obiekt
określa, kiedy użytkownik może złożyć zamówienie. Czasy realizacji zamówienia (OpeningHoursSpecification
lub ServiceDeliveryHoursSpecification
) określają, kiedy zamówienie może zostać zrealizowane.AdvanceServiceDeliveryHoursSpecification
W tym przykładzie definiujemy godziny przyjmowania zamówień z wyprzedzeniem z interwałem 15 minut.
{ "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" } } ] } ] }
Poniższy przykład pokazuje, jak określić, że usługa jest dostępna w dniu Bożego Narodzenia na potrzeby zamówień tego samego dnia, ale zamknięta dla zamówień złożonych wcześniej i zaplanowanych na ten dzień. Ten przykład obsługuje te scenariusze:
- Użytkownicy mogą złożyć zamówienie 25 grudnia, aby otrzymać je tego samego dnia.
- Użytkownicy mogą złożyć zamówienie z dostawą zaplanowaną na 27 grudnia.
- Użytkownicy nie mogą złożyć zamówienia z dostawa w 22 grudnia na 25 grudnia.
{ "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" } }
Na przykładzie poniżej możesz zobaczyć, jak określić, że usługa jest zamknięta dla zamówień tego samego dnia lub zamówień z wyprzedzeniem zaplanowanych na dzień Bożego Narodzenia, ale otwarta dla zamówień z wyprzedzeniem zaplanowanych na późniejszy dzień. Ten przykład obsługuje te scenariusze:
- Nie można złożyć zamówienia 25 grudnia z dostawą tego samego dnia.
- Użytkownicy mogą złożyć zamówienie z dostawą zaplanowaną na 27 grudnia.
- Użytkownicy nie mogą złożyć zamówienia z wyprzedzeniem 22 grudnia z dostawą zaplanowaną na 25 grudnia.
{ "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" } ] }
Przykładowa usługa przyjmuje zamówienia przez całą dobę, a dostarcza je od 10:00 do 23:59:59 w dni robocze:
... { "@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" } } } ...
Przykładowa usługa przyjmuje zamówienia codziennie w godzinach 8:00–16:59:59. Klienci mogą wybrać dostawę w ciągu godziny lub jeden z tych slotów:
... { "@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" } } ] } ...
Przykład poniżej pokazuje przypadek, w którym sklep jest otwarty od 8:00 do 16:59:59 w dni powszednie, a w weekendy od 8:00 do 18:59:59. Zamówienia nie są przyjmowane przez całą dobę.
... { // 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" } } ] } ...