Speisekartenfeeds und Warenkorbartikel für die Auftragsausführung zuordnen
Wenn Kunden Artikel aus Ihrem Menüfeed in den Einkaufswagen legen und bezahlen, sendet Google diese Artikel an Ihren Endpunkt für die Auftragsausführung, um Preis und Verfügbarkeit zu prüfen. Sobald Preise und Verfügbarkeit überprüft wurden, kann der Kunde die Bestellung aufgeben. In diesem Abschnitt wird veranschaulicht, wie Menü-Feedelemente den Warenkorbartikeln für die Auftragsausführung zugeordnet werden.
Die Beispiele in diesem Abschnitt sind reduzierte Versionen des Menüfeeds und des Warenkorbschemas. Es werden nur Felder angezeigt, die für die Zuordnung zwischen dem Menüfeed und dem Warenkorbobjekt relevant sind. Vollständige Schemas finden Sie unter Menu
und Cart
.
Artikel im Menu
-Feed, die in einen Einkaufswagen gelegt wurden, werden im Cart
-Objekt sowohl zum Bezahlen als auch zum Senden der Bestellung gesendet.
- Ein einfaches
MenuItem
wird im ArraylineItems
alsLineItem
dargestellt, wobeiofferId
demoffer.id
des ausgewählten Menüpunkts im Menüfeed entspricht. - Ein
MenuItem
mit einem erforderlichenMenuItemOption
wird imlineItems
-Array alsLineItem
dargestellt, wobeiofferId
deroffer.id
der ausgewählten Menüoption im Menüfeed ist. - Ein
AddOnMenuItem
einerLineItem
wird alsFoodItemOption
imoptions
-Array vonFoodItemExtension
dargestellt. Jede Option hat einofferId
, das demoffer.id
des ausgewählten Add-on-Menüelements aus dem Menüfeed entspricht. Ein AddOnMenuItem kann auch verschachtelte AddOnMenuItem(s) enthalten, die in jeder Option alssubOptions
dargestellt werden.
In den folgenden Beispielen werden Menüelemente zwischen Menüfeed und Einkaufswagen für die Auftragsausführung zugeordnet.
JSON
Dieses Beispiel enthält eine Liste mit einfachen Menüpunkten.
Speisekarten in einem Speisekartenfeed:
{ "@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" } ] } ] }
Speisekartenartikel, die einem Einkaufswagen für Auftragsausführung zugeordnet sind:
{ "@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
Dieses Beispiel enthält einen Menüpunkt mit einem oder mehreren AddOnMenuItems.
Speisekarten in einem Speisekartenfeed:
{ "@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" } ] } ] }
Speisekartenartikel, die einem Einkaufswagen für Auftragsausführung zugeordnet sind:
{ "@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
Dieses Beispiel enthält einen Menüpunkt mit Menüpunktoptionen, AddOnMenuItems und verschachtelten AddOnMenuItems
Speisekarten in einem Speisekartenfeed:
{ "@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" } ] } ] } ] } ] } ] } } ] }
Speisekartenartikel, die einem Einkaufswagen für Auftragsausführung zugeordnet sind:
{ "@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" } ] } ] } } ] }
Fehlerbehebung
Wenn bei der Verarbeitung eines CheckoutRequestMessage
Probleme auftreten, kannst du mit einer CheckoutResponseMessage
antworten, die eine FoodErrorExtension
anstelle einer CheckoutResponse enthält. Anhand dieser Antwort können Sie einen oder mehrere Fehler identifizieren, die während der Verarbeitung aufgetreten sind.
Es gibt zwei Möglichkeiten, die Fehler zu beheben:
- Wiederherstellbare Fehler: Der Nutzer muss seinen Einkaufswagen nicht bearbeiten, um die Bestellung zu senden. Wenn Sie beispielsweise feststellen, dass ein Artikel in der
Cart
eine Preisänderung aufweist, können Sie mit einerFoodOrderError
des FehlertypsPRICE_CHANGED
zusammen mitcorrectedProposedOrder
undpaymentOptions
antworten. Google informiert den Nutzer über die Änderung, lässt ihn aber mitcorrectedProposedOrder
einreichen. Der Nutzer kann auch zurückgehen und seinen Einkaufswagen bearbeiten. Sie erhalten entweder eine neueCheckoutRequestMessage
oder eineSubmitOrderRequestMessage
. - Nicht behebbare Fehler: Der Nutzer muss seinen Einkaufswagen bearbeiten, bevor er die Bestellung aufgibt. Wenn Sie beispielsweise feststellen, dass das Restaurant geschlossen ist, können Sie mit einem
FoodOrderError
vom FehlertypCLOSED
antworten. Google informiert den Nutzer und verwaltet die Interaktion, um auf ein neues Restaurant zu aktualisieren. Sie erhalten ein neuesCheckoutRequestMessage
für einen neuen Einkaufswagen.
Im Allgemeinen sollten Fehler auf Warenkorbebene nicht behebbar und Fehler auf Artikelebene wiederherstellbar sein. Eine vollständige Liste der Fehlertypen und ihrer Bedeutungen finden Sie unter FoodOrderError
.
Umgang mit Preisänderungen
Preisänderungen an der Kasse
Wenn bei der Bearbeitung der Zahlungsanfrage eines Kunden ein Preisproblem auftritt, gehe so vor:
- Antworten Sie auf die
CheckoutRequestMessage
mit einemCheckoutResponseMessage
, dasFoodErrorExtension
enthält, wie unter Umgang mit Fehlern beschrieben. - Verwenden Sie in der Fehlerantwort
correctedProposedOrder.cart
, um den Preis auf den richtigen Wert zu aktualisieren. Google erhält die korrigierte Bestellung und stellt möglicherweise eine neueCheckoutRequestMessage
aus.
Nach dem Bezahlvorgang zeigt Google dem Endnutzer eine Bestellbestätigungsseite an, unabhängig davon, ob ProposedOrder
geändert wurde oder nicht.
Wenn die vorgeschlagene Bestellung korrigiert wurde, kann Google zusätzliche Warnungen anzeigen, um den Nutzer über die Änderungen zu informieren. Wenn der Nutzer der Aufgabe zustimmt, gibt es keine Zahlungsanfragen mehr. Der Ablauf fährt mit der Reihenfolge der Einreichung mit dem korrigierten ProposedOrder
fort.
Der Nutzer kann seine Meinung jedoch jederzeit ändern und seinen Einkaufswagen erneut bearbeiten. Wenn der Einkaufswagen auf diese Weise aktualisiert wird, sendet Google ein neues CheckoutRequestMessage
.
Preisänderungen beim Absenden der Bestellung
Wenn bei der Verarbeitung der Bestellungsübermittlung ein Preisproblem auftritt (der Intent actions.intent.TRANSACTION_DECISION
wurde ausgelöst), antworten Sie nicht mit einem Fehler und aktualisieren Sie den Preis in Ihrer Antwort nicht. Wenn die Preise, Mengen oder andere Details in SubmitOrderRequestMessage
nicht mit Ihren Daten übereinstimmen, antworten Sie mit orderState
auf REJECTED
, um anzugeben, dass die Bestellung nicht wie angefordert aufgegeben werden kann.
Wenn dann die Bestellung und die Zahlungsdetails gültig sind, setze orderState
auf CREATED
oder CONFIRMED
. Füge auch ein actionOrderId
ein, um die ID der Bestellung in deinem System darzustellen. Diese ID muss beim Senden nachfolgender Aktualisierungen verwendet werden.
Wenn du die Zahlung nicht verarbeiten kannst und die SubmitOrderRequestMessage
bereits gesendet hast, kannst du eine AsyncOrderUpdateRequestMessage
senden, bei der orderState
auf REJECTED
gesetzt ist, um den Nutzer zu informieren, dass die Bestellung nicht ausgeführt wird.
Preisänderungen nach Absenden der Bestellung
Wenn Sie feststellen, dass sich ein Preis von dem Preis geändert hat, der beim Einreichen der Bestellung des Kunden verwendet wurde, können Sie mit dem neuen Preis einen AsyncOrderUpdateRequestMessage
ausgeben, wie unter Asynchrone Bestellaktualisierungen implementieren beschrieben.
So aktualisieren Sie Preise mithilfe von asynchronen Bestellaktualisierungen:
- Ändere den Preis in
lineItemUpdates[x].price
. Dieser Wert entspricht den Gesamtkosten des Artikels, einschließlich Add-ons, multipliziert mit der Menge. Weitere Informationen finden Sie in der Beschreibung des Feldsprice
vonLineItem
. - Gib eine Erklärung in
lineItemUpdates[x].reason
ein. - Legen Sie
lineItemUpdates[x].orderState
aufCONFIRMED
fest.
Sie können nach eigenem Ermessen versuchen, das Zahlungsmittel vor oder nach dem Senden der AsyncOrderUpdateRequestMessage zu belasten. Wenn die Transaktion fehlschlägt (möglicherweise, weil das Preisdelta zu hoch ist), sende eine AsyncOrderUpdateRequestMessage mit den folgenden Einstellungen in OrderUpdate
, um Google über den Fehler zu informieren:
- Setzen Sie
orderState
aufREJECTED
. - Beschreiben Sie den Fehler im Feld
label
.
Validierung an der Kasse
Wie in Schritt 4: Checkout implementieren beschrieben, sollte der Auftragsausführungsendpunkt bei jedem eingehenden CheckoutRequestMessage
eine Validierung durchführen und mit einem CheckoutResponseMessage
antworten.
Hier ist ein Beispiel für einen CheckoutResponseMessage
für eine erfolgreiche Validierung:
Anwendungsfall | Implementierung |
---|---|
Anwendungsfall 1: Validierung ist erfolgreich | Rückflug: CheckoutResponse . Er muss ProposedOrder und PaymentOptions enthalten.
ProposedOrder enthält Steuern, Gebühren und den Gesamtpreis des Einkaufswagens. |
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 } } } } } ] } } }
Überprüfung der Lieferadresse
Der Endpunkt für die Auftragsausführung sollte die in jedem CheckoutRequestMessage
enthaltene Lieferadresse validieren.
Wenn es ein Problem mit der Lieferadresse gibt, z. B. wenn sie außerhalb des Bereichs des Lieferdienstes liegt, sollte das von der Auftragsausführung zurückgegebene CheckoutResponseMessage
einen FoodOrderError
des entsprechenden Typs enthalten.
Anwendungsfall | Implementierung |
---|---|
Anwendungsfall 1: Die Validierung ist fehlgeschlagen, weil die Lieferadresse außerhalb des zulässigen Bereichs liegt oder ein Problem mit der Lieferadresse vorliegt | Gibt FoodErrorExtension mit FoodOrderError vom Fehlertyp OUT_OF_SERVICE_AREA zurück. |
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." } ] } } } ] } } }
Überprüfung des Mindestbestellwerts
Der Mindestbestellwert jedes CheckoutRequestMessage
sollte vom Endpunkt für die Auftragsausführung validiert werden.
Wenn der Mindestbestellwert nicht erreicht wird, sollte das von der Auftragsausführung zurückgegebene CheckoutResponseMessage
einen FoodOrderError
vom Fehlertyp REQUIREMENTS_NOT_MET
enthalten.
Anwendungsfall | Implementierung |
---|---|
Anwendungsfall 1: Validierung fehlgeschlagen, da der Mindestbestellwert nicht erreicht wurde | Gibt FoodErrorExtension mit FoodOrderError vom Fehlertyp REQUIREMENTS_NOT_MET zurück. |
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." } ] } } } ] } } }
Validierung von Bestellfenstern
Der Auftragsausführungsendpunkt sollte alle Faktoren validieren, die das Bestellfenster jedes CheckoutRequestMessage
beeinflussen können.
Wenn das Restaurant beispielsweise geschlossen ist oder derzeit keine Bestellungen mehr entgegennimmt, sollte das von der Auftragsausführung zurückgegebene CheckoutResponseMessage
einen FoodOrderError
vom Fehlertyp CLOSED
bzw. NO_CAPACITY
enthalten.
Anwendungsfall | Implementierung |
---|---|
Anwendungsfall 1: Validierung fehlgeschlagen, da das Restaurant geschlossen ist oder nicht mehr unterstützt wird | Gibt FoodErrorExtension mit FoodOrderError vom Fehlertyp CLOSED zurück. |
Anwendungsfall 2: Validierung fehlgeschlagen, weil das Restaurant voll ist und derzeit keine Bestellungen entgegennimmt | Gibt FoodErrorExtension mit FoodOrderError vom Fehlertyp NO_CAPACITY zurück. |
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." } ] } } } ] } } }
Validierung von Warenkorbartikeln
Der Auftragsausführungsendpunkt sollte die Preise und die Verfügbarkeit aller Einkaufswagenpositionen in einem CheckoutRequestMessage
validieren.
Wenn sich die Verfügbarkeit oder der Preis geändert hat, sollte das von der Auftragsausführung zurückgegebene CheckoutResponseMessage
einen FoodOrderError
vom Fehlertyp AVAILABILITY_CHANGED
bzw. PRICE_CHANGED
enthalten.
Anwendungsfall | Implementierung |
---|---|
Anwendungsfall 1: Validierung fehlgeschlagen, da einige Menüpunkte und/oder ihre Anpassungen ungültig oder nicht auf Lager sind | Gibt FoodErrorExtension mit correctedProposedOrder , PaymentOptions und FoodOrderError vom Fehlertyp AVAILABILITY_CHANGED zurück. Ungültige Elemente müssen aus CorrectedProposedOrder entfernt werden. |
Anwendungsfall 2:Die Validierung ist fehlgeschlagen, da einige Menüpunkte und/oder ihre Anpassungen ungültig oder nicht auf Lager sind. Der korrigierte Einkaufswagen erfüllt nicht mehr den Mindestbestellwert. | Gibt FoodErrorExtension mit FoodOrderError der Fehlertypen AVAILABILITY_CHANGED und REQUIREMENTS_NOT_MET zurück. |
Anwendungsfall 3: Die Validierung ist fehlgeschlagen, da sich einige Menüpunkte und/oder Anpassungspreise geändert haben | Gibt FoodErrorExtension mit correctedProposedOrder , PaymentOptions und FoodOrderError vom Fehlertyp PRICE_CHANGED zurück. Veraltete Preise müssen in CorrectedProposedOrder aktualisiert werden. |
Anwendungsfall 4:Die Validierung ist fehlgeschlagen, da sich einige Menüpunkte und/oder Anpassungspreise geändert haben. Der korrigierte Einkaufswagen erfüllt nicht mehr den Mindestbestellwert. | Gibt FoodErrorExtension mit FoodOrderError der Fehlertypen PRICE_CHANGED und REQUIREMENTS_NOT_MET zurück. |
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 } } ] } } } ] } } }
Bestellbestätigung senden
Wie in Schritt 7: Übermittlung der Bestellung implementieren erläutert, sollte der Auftragsausführungsendpunkt bei jedem eingehenden SubmitOrderRequestMessage
eine Validierung durchführen und mit einer SubmitOrderResponseMessage
antworten.
Hier ist ein Beispiel für einen SubmitOrderResponseMessage
für eine erfolgreiche Validierung:
Anwendungsfall | Implementierung |
---|---|
Anwendungsfall 1: Auftrag wurde erstellt | Ein SubmitOrderResponseMessage mit dem Bestellstatus CREATED . Er muss actionOrderId , userVisibleId , orderManagementActions und estimatedFulfillmentTime enthalten. |
Anwendungsfall 2: Bestellung wird aufgrund von Zahlungsproblemen abgelehnt | Ein SubmitOrderResponseMessage mit dem Bestellstatus REJECTED . Er muss actionOrderId , userVisibleId , orderManagementActions und rejectionInfo vom Typ PAYMENT_DECLINED enthalten. |
Anwendungsfall 3: Bestellung wurde abgelehnt, weil der Nutzer als gesperrt gekennzeichnet ist | Ein SubmitOrderResponseMessage mit dem Bestellstatus REJECTED . Er muss actionOrderId , userVisibleId , orderManagementActions und rejectionInfo vom Typ INELIGIBLE enthalten. |
Anwendungsfall 4:Die Bestellung wurde abgelehnt, weil die Nutzerinformationen unvollständig oder ungültig sind. | Ein SubmitOrderResponseMessage mit dem Bestellstatus REJECTED . Er muss actionOrderId , userVisibleId , orderManagementActions und rejectionInfo vom Typ INELIGIBLE enthalten. |
Anwendungsfall 5: Bestellung wurde aus unbekanntem Grund abgelehnt | Ein SubmitOrderResponseMessage mit dem Bestellstatus REJECTED . Er muss actionOrderId , userVisibleId , orderManagementActions und rejectionInfo vom Typ UNKNOWN enthalten. |
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" } } } ] } } } ] } } }