Mapowanie plików danych menu i elementów koszyka realizacji
Gdy klienci dodają pozycje z pliku danych z menu do koszyka i zapłacą za zakupy, Google wysyła te produkty do punktu końcowego realizacji zamówienia, aby zweryfikować ich cenę i dostępność. Po zweryfikowaniu cen i dostępności klient może złożyć zamówienie. W tej sekcji pokazujemy, jak mapować pozycje kanału menu na realizacji zamówień.
Przykłady w tej sekcji to skrócone wersje menu Menu i koszyka
schemat. Tylko pola istotne do zilustrowania mapowania między kanałem Menu a
wyświetlany jest obiekt koszyka. Pełne schematy znajdziesz na stronach Menu
i Cart
.
Produkty z pliku danych Menu
dodane do koszyka są wysyłane w Cart
w momencie płatności i przesłania zamówienia.
- Prosty
MenuItem
jest przedstawiony jakoLineItem
w elemencielineItems
. tablica, w którejofferId
jest wybraną wartościąoffer.id
elementu menu w menu kanału. - Parametr
MenuItem
z wymaganym atrybutemMenuItemOption
jest przedstawiany jakoLineItem
w tablicylineItems
z wybraną wartościąofferId
wartośćoffer.id
elementu menu. - Wartość
AddOnMenuItem
elementuLineItem
jest przedstawiona jakoFoodItemOption
w tablicyoptions
FoodItemExtension
. Każda opcja ma atrybutofferId
odpowiadający wybranemu menu dodatkuoffer.id
elementu z pliku menu. Pamiętaj, że element AddOnMenuItem może mieć również zagnieżdżone elementy AddOnMenuItem(s) reprezentowane w każdym z nich jakosubOptions
.
Poniższe przykłady mapują pozycje menu między plikiem danych menu a realizacją zamówienia koszyk.
JSON
Ten przykład zawiera listę prostych elementów menu.
Pozycje menu w pliku danych:
{ "@type": "Menu", "@id": "menu_id", "hasMenuItem": [ { "@type": "MenuItem", "@id": "menuitem_id_1", "offers": [ { "@type": "Offer", "@id": "menuitem_offer_id_1", "price": "p_1", "priceCurrency": "USD" } ] }, { "@type": "MenuItem", "@id": "menuitem_id_2", "offers": [ { "@type": "Offer", "@id": "menuitem_offer_id_2", "price": "p_2", "priceCurrency": "USD" } ] } ] }
Pozycje menu zmapowane na koszyk realizacji:
{ "@type": "Cart", "lineItems": [ { "offerId": "menuitem_offer_id_1", "price": { "amount": { "currencyCode": "USD", "units": "dollar(q_1*p_1)", "nanos": "cent(q_1*p_1)" } }, "quantity": "q_1" }, { "offerId": "menuitem_offer_id_2", "price": { "amount": { "currencyCode": "USD", "units": "dollar(q_2*p_2)", "nanos": "cent(q_2*p_2)" } }, "quantity": "q_2" } ] }
JSON
Ten przykład zawiera pozycję menu z co najmniej jednym elementem AddOnMenuItem.
Pozycje menu w pliku danych:
{ "@type": "Menu", "@id": "menu_id", "hasMenuItem": [ { "@type": "MenuItem", "@id": "menuitem_id_1", "offers": [ { "@type": "Offer", "@id": "menuitem_offer_id_1", "price": "p_1", "priceCurrency": "USD" } ], "menuAddOn": [ { "@type": "MenuAddOnSection", "@id": "menuaddon_section_id_1", "hasMenuItem": [ { "@type": "AddOnMenuItem", "@id": "menuitem_addon_id_1", "offers": [ { "@type": "Offer", "@id": "menuitem_addon_offer_id_1", "price": "addon_p_1", "priceCurrency": "USD" } ] }, { "@type": "AddOnMenuItem", "@id": "menuitem_addon_id_2", "offers": [ { "@type": "Offer", "@id": "menuitem_addon_offer_id_2", "price": "addon_p_2", "priceCurrency": "USD" } ] } ] } ] }, { "@type": "MenuItem", "@id": "menuitem_id_2", "offers": [ { "@type": "Offer", "@id": "menuitem_offer_id_2", "price": "p_2", "priceCurrency": "USD" } ] } ] }
Pozycje menu zmapowane na koszyk realizacji:
{ "@type": "Cart", "lineItems": [ { "offerId": "menuitem_offer_id_1", "price": { "amount": { "currencyCode": "USD", "units": "dollar(q_1*(p_1 + addon_q_1*addon_p_1 + addon_q_2*addon_p_2))", "nanos": "cent(q_1*(p_1 + addon_q_1*addon_p_1 + addon_q_2*addon_p_2))" } }, "quantity": "q_1", "extension": { "@type": "FoodItemExtension", "options": [ { "offerId": "menuitem_addon_offer_id_1", "price": { "currencyCode": "USD", "units": "dollar(addon_q_1*addon_p_1)", "nanos": "cent(addon_q_1*addon_p_1)" }, "quantity": "addon_q_1" }, { "offerId": "menuitem_addon_offer_id_2", "price": { "currencyCode": "USD", "units": "dollar(addon_q_2*addon_p_2)", "nanos": "cent(addon_q_2*addon_p_2)" }, "quantity": "addon_q_2" } ] } }, { "offerId": "menuitem_offer_id_2", "price": { "amount": { "currencyCode": "USD", "units": "dollar(q_2*p_2)", "nanos": "cent(q_2*p_2)" } }, "quantity": "q_2" } ] }
JSON
Ten przykład zawiera pozycję menu z opcjami pozycji, AddOnMenuItems, i zagnieżdżone elementy AddOnMenuItems
Pozycje menu w pliku danych:
{ "@type": "MenuItem", "@id": "menuitem_id_1", "hasMenuItemOptions": [ { "@type": "MenuItemOption", "value": { "@type": "PropertyValue", "name": "OPTION", "value": "Large", "offers": [ { "@type": "Offer", "@id": "menuitem_option_offer_id_1", "price": "p_1", "priceCurrency": "USD" } ], "menuAddOn": [ { "@type": "AddOnMenuSection", "@id": "menuitem_option_addon_section_id_1", "hasMenuItem": [ { "@type": "AddOnMenuItem", "@id": "menuitem_option_addon_id_1", "offers": [ { "@type": "Offer", "@id": "menuitem_option_addon_offer_id_1", "price": "addon_p_1", "priceCurrency": "USD" } ] }, { "@type": "AddOnMenuItem", "@id": "menuitem_option_addon_id_2", "offers": [ { "@type": "Offer", "@id": "menuitem_option_addon_offer_id_2", "price": "addon_p_2", "priceCurrency": "USD" } ], "menuAddOn": [ { "@type": "AddOnMenuSection", "@id": "menuitem_option_subaddon_section_id_1", "hasMenuItem": [ { "@type": "AddOnMenuItem", "@id": "menuitem_option_subaddon_id_1", "offers": [ { "@type": "Offer", "@id": "menuitem_option_subaddon_offer_id_1", "price": "subaddon_p_1", "priceCurrency": "USD" } ] } ] } ] } ] } ] } } ] }
Pozycje menu zmapowane na koszyk realizacji:
{ "@type": "Cart", "lineItems": [ { "offerId": "menuitem_option_offer_id_1", "price": { "amount": { "currencyCode": "USD", "units": "dollar(q_1*(p_1 + addon_q_1*addon_p_1 + addon_q_2*(addon_p_2 + subaddon_q_1*subaddon_p_1)))", "nanos": "cent(q_1*(p_1 + addon_q_1*addon_p_1 + addon_q_2*(addon_p_2 + subaddon_q_1*subaddon_p_1)))" } }, "quantity": "q_1", "extension": { "@type": "FoodItemExtension", "options": [ { "offerId": "menuitem_option_addon_offer_id_1", "price": { "currencyCode": "USD", "units": "dollar(addon_q_1*addon_p_1)", "nanos": "cent(addon_q_1*addon_p_1)" }, "quantity": "addon_q_1" }, { "offerId": "menuitem_option_addon_offer_id_2", "price": { "currencyCode": "USD", "units": "dollar(addon_q_2*(addon_p_2 + subaddon_q_1*subaddon_p_1))", "nanos": "cent(addon_q_2*(addon_p_2 + subaddon_q_1*subaddon_p_1))" }, "quantity": "addon_q_2", "subOptions": [ { "offerId": "menuitem_option_subaddon_offer_id_1", "price": { "currencyCode": "USD", "units": "dollar(subaddon_q_1*subaddon_p_1)", "nanos": "cent(subaddon_q_1*subaddon_p_1)" }, "quantity": "subaddon_q_1" } ] } ] } } ] }
Obsługa błędów
Jeśli podczas przetwarzania CheckoutRequestMessage
wystąpią problemy,
może odpowiedzieć, używając symbolu CheckoutResponseMessage
zawierającego
FoodErrorExtension
, a nie CheckoutResponse. Możesz użyć tej
aby zidentyfikować co najmniej 1 błąd, który wystąpił podczas przetwarzania.
Są 2 sposoby rozwiązywania tych błędów:
- Błędy możliwe do odzyskania: użytkownik nie musi edytować koszyka, aby przesłać
zamówienie. Jeśli na przykład ustalisz, że element w tagu
Cart
ma atrybut zmiana ceny, możesz odpowiedzieć, przesyłającFoodOrderError
typu błęduPRICE_CHANGED
wraz zcorrectedProposedOrder
ipaymentOptions
. Google informuje użytkownika o zmianie, ale zezwala użytkownikowi na przesłanie go wraz zcorrectedProposedOrder
Użytkownik może też wrócić i edytować koszyk, jeśli: pożądaną. Otrzymasz nowyCheckoutRequestMessage
lubSubmitOrderRequestMessage
- Błędy nieodwracalne: użytkownik musi edytować koszyk przed
złożenie zamówienia. Jeśli na przykład okaże się, że restauracja jest
zamknięte, możesz odpowiedzieć
FoodOrderError
z błędem typuCLOSED
. Google informuje użytkownika i zarządza interakcją, by zaktualizować ją do nowej restauracji. Otrzymasz nowyCheckoutRequestMessage
za nowy koszyk.
Ogólnie rzecz biorąc, błędy na poziomie koszyka mogą być nieodwracalne oraz błędy na poziomie produktu.
i da się je odzyskać. Pełną listę typów błędów i ich znaczeń znajdziesz w artykule
FoodOrderError
Obsługa zmian cen
Ceny zmieniają się w momencie płatności
Jeśli podczas przetwarzania płatności klienta wystąpi problem z ceną wykonaj te czynności:
- Wyślij odpowiedź na pytanie „
CheckoutRequestMessage
”,CheckoutResponseMessage
, który zawiera elementFoodErrorExtension
, na przykład opisane w artykule Obsługa błędów. - W odpowiedzi na błąd użyj pola
correctedProposedOrder.cart
, aby zaktualizować cenę na właściwą wartość. Google otrzyma poprawione zamówienie i może wystawić noweCheckoutRequestMessage
Po dokonaniu płatności Google wyświetla użytkownikowi stronę potwierdzenia zamówienia,
bez względu na to, czy pole ProposedOrder
zostało zmienione, czy nie.
Jeśli Proponowane zamówienie zostało poprawione, Google może wyświetlać dodatkowe ostrzeżenia
poinformować użytkownika o zmianach. Jeśli użytkownik wyrazi zgodę na złożenie zamówienia,
nie będą już wysyłać próśb o płatność. Proces składania zamówień jest kontynuowany,
poprawiony ProposedOrder
.
Użytkownik może jednak zawsze zmienić zdanie i ponownie edytować koszyk. Kiedy
aktualizacji koszyka w ten sposób, Google wysyła nowy CheckoutRequestMessage
.
Cena zmienia się podczas składania zamówienia
Jeśli podczas przetwarzania przesłania zamówienia napotkasz problem z ceną
(została aktywowana intencja actions.intent.TRANSACTION_DECISION
), nie odpowiadaj
zawiera błąd, lub zaktualizuj cenę w odpowiedzi. Jeśli ceny, ilości,
lub inne szczegóły w SubmitOrderRequestMessage
nie odpowiadają
danych, w odpowiedzi pole orderState
ustaw na REJECTED
, aby wskazać, że
nie można złożyć zamówienia zgodnie z żądaniem.
Następnie, jeśli zamówienie i dane do płatności są prawidłowe, ustaw orderState
na CREATED
lub CONFIRMED
. Dołącz też actionOrderId
reprezentujący identyfikator zamówienia w:
systemu. Tego identyfikatora należy używać przy wysyłaniu kolejnych aktualizacji.
Jeśli nie możesz przetworzyć płatności, a płatność została już wysłana
SubmitOrderRequestMessage
, możesz wysłać
AsyncOrderUpdateRequestMessage
z ustawieniem orderState
ustawionym na REJECTED
, aby zezwolić
użytkownik wie, że zamówienie nie zostanie zrealizowane.
Cena zmieni się po złożeniu zamówienia
Jeśli ustalisz, że cena zmieniła się od ceny podanej, gdy klient
przesłał(a) zamówienie, możesz wysłać AsyncOrderUpdateRequestMessage
,
opisane w artykule Wdrażanie asynchronicznych aktualizacji zamówień z nową ceną.
Aby zaktualizować ceny przy użyciu asynchronicznej aktualizacji zamówień:
- Zmień cenę w aplikacji
lineItemUpdates[x].price
. Ten odzwierciedla łączny koszt produktu z uwzględnieniem dodatków i pomnożeń według ilości. (Więcej informacji znajdziesz w opisieprice
LineItem
). - Wyjaśnienie wpisz w tym języku:
lineItemUpdates[x].reason
. - Ustaw
lineItemUpdates[x].orderState
do:CONFIRMED
.
Możesz podjąć próbę obciążenia instrumentu płatniczego przed wysłaniem
AsyncOrderUpdateRequestMessage według własnego uznania. Jeśli transakcja się nie powiedzie
(prawdopodobnie dlatego, że różnica ceny jest zbyt wysoka), wyślij
AsyncOrderUpdateRequestMessage z następującymi ustawieniami w
OrderUpdate
, aby poinformować Google o niepowodzeniu:
- Ustaw
orderState
naREJECTED
. - Opisz błąd w polu
label
.
Weryfikacja płatności
Jak wspomnieliśmy w kroku 4. Wdróż Google Checkout,
punkt końcowy realizacji powinien sprawdzać wszystkie przychodzące
CheckoutRequestMessage
i w odpowiedzi napisz CheckoutResponseMessage
.
Oto przykład CheckoutResponseMessage
odnoszącego się do udanego wyszukiwania
weryfikacja:
Przypadek użycia | Sposób implementacji |
---|---|
Przypadek użycia 1: weryfikacja zakończyła się powodzeniem | Zwróć: CheckoutResponse . Musi mieć
ProposedOrder i PaymentOptions .
ProposedOrder obejmuje podatek, opłaty i łączną cenę
koszyk. |
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "checkoutResponse": { "proposedOrder": { "id": "sample_proposed_order_id_1", "otherItems": [ { "name":"New customer discount", "price": { "type":"ESTIMATE", "amount": { "currencyCode":"USD", "units":"-5", "nanos": -500000000 } }, "type": "DISCOUNT" }, { "name": "Delivery fee", "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "3", "nanos": 500000000 } }, "type": "DELIVERY" }, { "name": "Tax", "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "1", "nanos": 500000000 } }, "type": "TAX" } ], "cart": { "merchant": { "id": "https://www.exampleprovider.com/merchant/id1", "name": "Falafel Bite" }, "lineItems": [ { "name": "Pita Chips", "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": "2", "nanos": 750000000 } }, "subLines": [ { "note": "Notes for this item." } ], "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension", "options": [ { "id": "sample_addon_offer_id_1", "offerId": "https://www.exampleprovider.com/menu/item/addon/offer/id1", "name": "Honey Mustard", "price": { "currencyCode": "USD" }, "quantity": 1 }, { "id": "sample_addon_offer_id_2", "offerId": "https://www.exampleprovider.com/menu/item/addon/offer/id2", "name": "BBQ Sauce", "price": { "currencyCode": "USD", "nanos": 500000000 }, "quantity": 1 } ] } }, { "name": "Chicken Shwarma Wrap", "type": "REGULAR", "id": "sample_item_offer_id_2", "offerId": "https://www.exampleprovider.com/menu/item/offer/id2", "quantity": 1, "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "8" } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension" } }, { "name": "Greek Salad", "type": "REGULAR", "id": "sample_item_offer_id_3", "offerId": "https://www.exampleprovider.com/menu/item/offer/id3", "quantity": 1, "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "9", "nanos": 990000000 } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension" } }, { "name": "Prawns Biryani", "type": "REGULAR", "id": "sample_item_offer_id_4", "offerId": "https://www.exampleprovider.com/menu/item/offer/id4", "quantity": 1, "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "15", "nanos": 990000000 } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension" } } ], "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension", "fulfillmentPreference": { "fulfillmentInfo": { "delivery": { "deliveryTimeIso8601": "P90M" } } }, "location": { "coordinates": { "latitude": 37.788783, "longitude": -122.41384 }, "formattedAddress": "1350 CHARLESTON ROAD, MOUNTAIN VIEW, CA, United States", "zipCode": "94043", "city": "Mountain View", "postalAddress": { "regionCode": "US", "postalCode": "94043", "administrativeArea": "CA", "locality": "Mountain View", "addressLines": [ "1350 Charleston Road" ] }, "notes": "Gate code is #111" } } }, "totalPrice": { "type": "ESTIMATE", "amount": { // Represents $36.73 "currencyCode": "USD", "units": "36", "nanos": 730000000 } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension", "availableFulfillmentOptions": [ { "fulfillmentInfo": { "delivery": { "deliveryTimeIso8601": "P90M" } }, "expiresAt": "2017-07-17T12:30:00Z" } ] } }, "paymentOptions": { "googleProvidedOptions": { "tokenizationParameters": { "tokenizationType": "PAYMENT_GATEWAY", "parameters": { "gateway": "stripe", "stripe:publishableKey": "pk_live_stripe_client_key", "stripe:version": "2017-04-06" } }, "supportedCardNetworks": [ "AMEX", "DISCOVER", "MASTERCARD", "JCB", "VISA" ], "prepaidCardDisallowed": true } } } } } ] } } }
Weryfikacja adresu dostawy
Twój punkt końcowy realizacji powinien weryfikować adres dostawy zawarty w każdym
CheckoutRequestMessage
Jeśli wystąpił problem z adresem dostawy (np. jest on poza zasięgiem)
usługę dostawy, CheckoutResponseMessage
zwrócony przez
realizacja powinna zawierać element FoodOrderError
odpowiedniego typu.
Przypadek użycia | Sposób implementacji |
---|---|
Przypadek użycia 1: weryfikacja nie udała się z powodu braku adresu dostawy mieści się w zakresie lub wystąpił problem z adresem dostawy | Zwróć FoodErrorExtension z: FoodOrderError
typu błędu OUT_OF_SERVICE_AREA . |
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "error": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension", "foodOrderErrors": [ { "error": "OUT_OF_SERVICE_AREA", "description": "Sorry, the restaurant cannot deliver to your address." } ] } } } ] } } }
Weryfikacja minimalnej wartości zamówienia
Punkt końcowy realizacji zamówień powinien weryfikować minimalną wartość zamówienia każdego
CheckoutRequestMessage
Jeśli minimalna wartość zamówienia nie zostanie osiągnięta, CheckoutResponseMessage
zwrócone przez Twoją realizację powinna zawierać FoodOrderError
typu błędu
REQUIREMENTS_NOT_MET
.
Przypadek użycia | Sposób implementacji |
---|---|
Przypadek użycia 1: weryfikacja nie powiodła się z powodu minimalnej wartości zamówienia nie jest spełniony | Zwróć FoodErrorExtension z: FoodOrderError
typu błędu REQUIREMENTS_NOT_MET . |
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "error": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension", "foodOrderErrors": [ { "error": "REQUIREMENTS_NOT_MET", "description": "The cart subtotal must be over $20." } ] } } } ] } } }
Weryfikacja okna sortowania
Punkt końcowy realizacji powinien sprawdzać wszystkie czynniki, które mogą mieć wpływ na
okres składania zamówień w przypadku każdego parametru CheckoutRequestMessage
.
Jeśli na przykład restauracja jest zamknięta lub nie przyjmuje już zamówień
momencie, wartość CheckoutResponseMessage
zwrócona przez Twoją realizację powinna
zawierają błąd FoodOrderError
typu CLOSED
lub NO_CAPACITY
,
.
Przypadek użycia | Sposób implementacji |
---|---|
Przypadek użycia 1. Weryfikacja nie powiodła się, ponieważ restauracja jest zamknięta lub już nieobsługiwane | Zwróć FoodErrorExtension z: FoodOrderError
typu błędu CLOSED . |
Przypadek użycia 2. Weryfikacja nie powiodła się, ponieważ restauracja jest zajęta w tej chwili nie przyjmuje zamówień | Zwróć FoodErrorExtension z: FoodOrderError
typu błędu NO_CAPACITY . |
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "error": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension", "foodOrderErrors": [ { "error": "CLOSED", "description": "The restaurant is closed." } ] } } } ] } } }
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "error": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension", "foodOrderErrors": [ { "error": "NO_CAPACITY", "description": "Sorry, the restaurant is busy at the moment." } ] } } } ] } } }
Weryfikacja produktów w koszyku
Punkt końcowy realizacji zamówień powinien weryfikować ceny i dostępność każdego
elementu koszyka zawartego w elemencie CheckoutRequestMessage
.
Jeśli dostępność lub cena uległa zmianie, CheckoutResponseMessage
zwrócone przez Twoją realizację powinna zawierać FoodOrderError
typu błędu
AVAILABILITY_CHANGED
lub PRICE_CHANGED
.
Przypadek użycia | Sposób implementacji |
---|---|
Przypadek użycia 1: weryfikacja się nie udała, ponieważ niektóre pozycje menu lub ich dostosowania są nieprawidłowe lub niedostępne | Zwróć użytkownika FoodErrorExtension z: correctedProposedOrder ,
PaymentOptions i FoodOrderError typu błędu
AVAILABILITY_CHANGED . Nieprawidłowe elementy należy usunąć z:
CorrectedProposedOrder |
Przypadek użycia 2: weryfikacja się nie udała, ponieważ niektóre pozycje menu lub ich dostosowania są nieprawidłowe lub są niedostępne. Poprawiony koszyk, nie spełnia już wymagań dotyczących minimalnej wartości zamówienia. | Zwróć FoodErrorExtension z: FoodOrderError
typów błędów AVAILABILITY_CHANGED i
REQUIREMENTS_NOT_MET |
Przypadek użycia 3. Weryfikacja się nie udała, ponieważ jakiś element menu lub ceny dostosowania uległy zmianie | Zwróć użytkownika FoodErrorExtension z: correctedProposedOrder ,
PaymentOptions i FoodOrderError typu błędu
PRICE_CHANGED . Nieaktualne ceny należy zaktualizować w
CorrectedProposedOrder |
Przypadek użycia 4. Weryfikacja się nie udała, ponieważ jakiś element menu lub ceny w usłudze personalizacji uległy zmianie. Poprawiony koszyk nie spełnia już wymagań wymagana minimalna wartość zamówienia | Zwróć FoodErrorExtension z: FoodOrderError
typów błędów PRICE_CHANGED i
REQUIREMENTS_NOT_MET |
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "error": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension", "foodOrderErrors": [ { "error": "AVAILABILITY_CHANGED", "id": "sample_item_offer_id_1", "description": "The item is no longer available." }, { "error": "AVAILABILITY_CHANGED", "id": "sample_item_offer_id_2", "description": "The item is no longer available." } ], "correctedProposedOrder": { "id": "sample_corrected_proposed_order_id_1", "otherItems": [ { "name":"New customer discount", "price": { "type":"ESTIMATE", "amount": { "currencyCode":"USD", "units":"-5", "nanos": -500000000 } }, "type": "DISCOUNT" }, { "name": "Delivery fee", "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "3", "nanos": 500000000 } }, "type": "DELIVERY" }, { "name": "Tax", "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "1", "nanos": 500000000 } }, "type": "TAX" } ], "cart": { "merchant": { "id": "https://www.exampleprovider.com/merchant/id1", "name": "Falafel Bite" }, "lineItems": [ { "name": "Greek Salad", "type": "REGULAR", "id": "sample_item_offer_id_3", "offerId": "https://www.exampleprovider.com/menu/item/offer/id3", "quantity": 1, "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "9", "nanos": 990000000 } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension" } }, { "name": "Prawns Biryani", "type": "REGULAR", "id": "sample_item_offer_id_4", "offerId": "https://www.exampleprovider.com/menu/item/offer/id4", "quantity": 1, "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "15", "nanos": 990000000 } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension" } } ], "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension", "fulfillmentPreference": { "fulfillmentInfo": { "delivery": { "deliveryTimeIso8601": "P90M" } } }, "location": { "coordinates": { "latitude": 37.788783, "longitude": -122.41384 }, "formattedAddress": "1350 CHARLESTON ROAD, MOUNTAIN VIEW, CA, United States", "zipCode": "94043", "city": "Mountain View", "postalAddress": { "regionCode": "US", "postalCode": "94043", "administrativeArea": "CA", "locality": "Mountain View", "addressLines": [ "1350 Charleston Road" ] }, "notes": "Gate code is #111" } } }, "totalPrice": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "36", "nanos": 730000000 } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension", "availableFulfillmentOptions": [ { "fulfillmentInfo": { "delivery": { "deliveryTimeIso8601": "P90M" } }, "expiresAt": "2017-07-17T12:30:00Z" } ] } }, "paymentOptions": { "googleProvidedOptions": { "tokenizationParameters": { "tokenizationType": "PAYMENT_GATEWAY", "parameters": { "gateway": "stripe", "stripe:publishableKey": "pk_live_stripe_client_key", "stripe:version": "2017-04-06" } }, "supportedCardNetworks": [ "AMEX", "DISCOVER", "MASTERCARD", "JCB", "VISA" ], "prepaidCardDisallowed": true } } } } } ] } } }
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "error": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension", "foodOrderErrors": [ { "error": "REQUIREMENTS_NOT_MET", "description": "The cart subtotal must be over $20." }, { "error": "AVAILABILITY_CHANGED", "id": "cart_lineitem_id" "description": "cart_lineitem_id is no longer available." } ] } } } ] } } }
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "error": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension", "foodOrderErrors": [ { "error": "PRICE_CHANGED", "id": "sample_item_offer_id_1", "description": "The price has changed.", "updatedPrice": { "currencyCode": "USD", "units": "2", "nanos": 750000000 } }, { "error": "PRICE_CHANGED", "id": "sample_item_offer_id_2", "description": "The price has changed.", "updatedPrice": { "currencyCode": "USD", "units": "8" } } ], "correctedProposedOrder": { "id": "sample_corrected_proposed_order_id_1", "otherItems": [ { "name":"New customer discount", "price": { "type":"ESTIMATE", "amount": { "currencyCode":"USD", "units":"-5", "nanos": -500000000 } }, "type": "DISCOUNT" }, { "name": "Delivery fee", "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "3", "nanos": 500000000 } }, "type": "DELIVERY" }, { "name": "Tax", "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "1", "nanos": 500000000 } }, "type": "TAX" } ], "cart": { "merchant": { "id": "https://www.exampleprovider.com/merchant/id1", "name": "Falafel Bite" }, "lineItems": [ { "name": "Pita Chips", "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": "2", "nanos": 750000000 } }, "subLines": [ { "note": "Notes for this item." } ], "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension", "options": [ { "id": "sample_addon_offer_id_1", "offerId": "https://www.exampleprovider.com/menu/item/addon/offer/id1", "name": "Honey Mustard", "price": { "currencyCode": "USD" }, "quantity": 1 }, { "id": "sample_addon_offer_id_2", "offerId": "https://www.exampleprovider.com/menu/item/addon/offer/id2", "name": "BBQ Sauce", "price": { "currencyCode": "USD", "nanos": 500000000 }, "quantity": 1 } ] } }, { "name": "Chicken Shwarma Wrap", "type": "REGULAR", "id": "sample_item_offer_id_2", "offerId": "https://www.exampleprovider.com/menu/item/offer/id2", "quantity": 1, "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "8" } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension" } }, { "name": "Greek Salad", "type": "REGULAR", "id": "sample_item_offer_id_3", "offerId": "https://www.exampleprovider.com/menu/item/offer/id3", "quantity": 1, "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "9", "nanos": 990000000 } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension" } }, { "name": "Prawns Biryani", "type": "REGULAR", "id": "sample_item_offer_id_4", "offerId": "https://www.exampleprovider.com/menu/item/offer/id4", "quantity": 1, "price": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "15", "nanos": 990000000 } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension" } } ], "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension", "fulfillmentPreference": { "fulfillmentInfo": { "delivery": { "deliveryTimeIso8601": "P90M" } } }, "location": { "coordinates": { "latitude": 37.788783, "longitude": -122.41384 }, "formattedAddress": "1350 CHARLESTON ROAD, MOUNTAIN VIEW, CA, United States", "zipCode": "94043", "city": "Mountain View", "postalAddress": { "regionCode": "US", "postalCode": "94043", "administrativeArea": "CA", "locality": "Mountain View", "addressLines": [ "1350 Charleston Road" ] }, "notes": "Gate code is #111" } } }, "totalPrice": { "type": "ESTIMATE", "amount": { "currencyCode": "USD", "units": "36", "nanos": 730000000 } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension", "availableFulfillmentOptions": [ { "fulfillmentInfo": { "delivery": { "deliveryTimeIso8601": "P90M" } }, "expiresAt": "2017-07-17T12:30:00Z" } ] } }, "paymentOptions": { "googleProvidedOptions": { "tokenizationParameters": { "tokenizationType": "PAYMENT_GATEWAY", "parameters": { "gateway": "stripe", "stripe:publishableKey": "pk_live_stripe_client_key", "stripe:version": "2017-04-06" } }, "supportedCardNetworks": [ "AMEX", "DISCOVER", "MASTERCARD", "JCB", "VISA" ], "prepaidCardDisallowed": true } } } } } ] } } }
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "error": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension", "foodOrderErrors": [ { "error": "REQUIREMENTS_NOT_MET", "description": "The cart subtotal must be over $20." }, { "error": "PRICE_CHANGED", "id": "cart_lineitem_id" "description": "cart_lineitem_id price has been updated." "updatedPrice": { "currencyCode": "USD", "units": "2", "nanos": 750000000 } } ] } } } ] } } }
Prześlij weryfikację zamówienia
Jak omówiliśmy w sekcji Krok 7. Wdróż przesyłanie zamówienia,
punkt końcowy realizacji powinien sprawdzać wszystkie przychodzące
SubmitOrderRequestMessage
i wyślij odpowiedź
SubmitOrderResponseMessage
Oto przykład SubmitOrderResponseMessage
odnoszącego się do udanego wyszukiwania
weryfikacja:
Przypadek użycia | Sposób implementacji |
---|---|
Przypadek użycia nr 1: zamówienie zostało utworzone | Zamówienie SubmitOrderResponseMessage z CREATED
stanu. Musi zawierać te wartości: actionOrderId ,
userVisibleId , orderManagementActions i
estimatedFulfillmentTime |
Przypadek użycia 2: zamówienie zostało odrzucone z powodu problemów z płatnością | Zamówienie SubmitOrderResponseMessage z REJECTED
stanu. Musi zawierać te wartości: actionOrderId ,
userVisibleId , orderManagementActions i
rejectionInfo typu PAYMENT_DECLINED . |
Przypadek użycia 3: zamówienie odrzucone dla użytkownika jest oznaczone jako zablokowane | Zamówienie SubmitOrderResponseMessage z REJECTED
stanu. Musi zawierać te wartości: actionOrderId ,
userVisibleId , orderManagementActions i
rejectionInfo typu INELIGIBLE . |
Przypadek użycia 4: zamówienie zostało odrzucone, ponieważ informacje o użytkowniku niekompletna lub nieprawidłowa | Zamówienie SubmitOrderResponseMessage z REJECTED
stanu. Musi zawierać te wartości: actionOrderId ,
userVisibleId , orderManagementActions i
rejectionInfo typu INELIGIBLE . |
Przypadek użycia 5: zamówienie zostało odrzucone z nieznanej przyczyny | Zamówienie SubmitOrderResponseMessage z REJECTED
stanu. Musi zawierać te wartości: actionOrderId ,
userVisibleId , orderManagementActions i
rejectionInfo typu UNKNOWN . |
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "CREATED", "label": "Order received" }, "updateTime": "2017-05-10T02:30:00.000Z", "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "VIEW_DETAILS", "button": { "title": "View order", "openUrlAction": { "url": "https://orderview.partner.com?orderid=sample_action_order_id" } } } ] } } } ] } } }
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "REJECTED", "label": "Order rejected" }, "updateTime": "2017-05-10T02:30:00.000Z", "rejectionInfo": { "type": "PAYMENT_DECLINED", "reason": "Insufficient funds" }, "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "VIEW_DETAILS", "button": { "title": "View order", "openUrlAction": { "url": "https://orderview.partner.com?orderid=sample_action_order_id" } } } ] } } } ] } } }
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "REJECTED", "label": "Order rejected" }, "updateTime": "2017-05-10T02:30:00.000Z", "rejectionInfo": { "type": "INELIGIBLE", "reason": "Sorry, we are not able to take orders from this user" }, "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "VIEW_DETAILS", "button": { "title": "View order", "openUrlAction": { "url": "https://orderview.partner.com?orderid=sample_action_order_id" } } } ] } } } ] } } }
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "REJECTED", "label": "Order rejected" }, "updateTime": "2017-05-10T02:30:00.000Z", "rejectionInfo": { "type": "INELIGIBLE", "reason": "Sorry, the phone number must not be blank" }, "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "VIEW_DETAILS", "button": { "title": "View order", "openUrlAction": { "url": "https://orderview.partner.com?orderid=sample_action_order_id" } } } ] } } } ] } } }
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "REJECTED", "label": "Order rejected" }, "updateTime": "2017-05-10T02:30:00.000Z", "rejectionInfo": { "type": "UNKNOWN", "reason": "Sorry, there is something wrong with this order." }, "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "VIEW_DETAILS", "button": { "title": "View order", "openUrlAction": { "url": "https://orderview.partner.com?orderid=sample_action_order_id" } } } ] } } } ] } } }