Menüfeeds und Artikel im Auftragswagen abgleichen
Wenn Kunden Artikel aus Ihrem Menüfeed in ihren Einkaufswagen legen und zur Kasse gehen, sendet Google diese Artikel an Ihren Fulfillment-Endpunkt, um deren Preis und Verfügbarkeit zu prüfen. Sobald Preise und Verfügbarkeit bestätigt sind, kann der Kunde die Bestellung aufgeben. In diesem Abschnitt wird beschrieben, wie Sie Menüfeedelemente den Artikeln im Auftragswagen zuordnen.
Die Beispiele in diesem Abschnitt sind reduzierte Versionen des Menüfeeds und des Einkaufswagenschemas. Es werden nur Felder angezeigt, die für die Zuordnung zwischen dem Menüfeed und dem Einkaufswagenobjekt relevant sind. Die vollständigen Schemas finden Sie unter Menu
und Cart
.
Artikel im Menu
-Feed, die einem Einkaufswagen hinzugefügt werden, werden sowohl für den Bezahlvorgang als auch für die Bestelleinreichung im Objekt Cart
gesendet.
- Ein einfaches
MenuItem
wird imlineItems
-Array alsLineItem
dargestellt. Dabei istofferId
dieoffer.id
des ausgewählten Menüelements im Menüfeed. - Ein
MenuItem
mit einer erforderlichenMenuItemOption
wird imlineItems
-Array alsLineItem
dargestellt. Dabei istofferId
dieoffer.id
der ausgewählten Menüpunktoption aus dem Menüfeed. - Ein
AddOnMenuItem
vonLineItem
wird alsFoodItemOption
imoptions
-Array derFoodItemExtension
dargestellt. Jede Option hat eineofferId
, die deroffer.id
des ausgewählten Menüpunkts aus dem Menüfeed entspricht. Ein AddOnMenuItem kann auch verschachtelte AddOnMenuItems haben, die in jeder Option alssubOptions
dargestellt werden.
In den folgenden Beispielen werden Menüelemente zwischen dem Menüfeed und dem Einkaufswagen für die Auftragsausführung zugeordnet.
Dieses Beispiel enthält eine Liste einfacher Menüpunkte.
Menüpunkte in einem Menüfeed:
{ "@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" } ] } ] }
Menüpunkte, die einem Auftragswagen 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" } ] }
Dieses Beispiel enthält einen Menüpunkt mit einem oder mehreren AddOnMenuItems.
Menüpunkte in einem Menüfeed:
{ "@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" } ] } ] }
Menüpunkte, die einem Auftragswagen 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" } ] }
Dieses Beispiel enthält ein Menüelement mit Menüelementoptionen, AddOnMenuItems und verschachtelten AddOnMenuItems.
Menüpunkte in einem Menüfeed:
{ "@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" } ] } ] } ] } ] } ] } } ] }
Menüpunkte, die einem Auftragswagen 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 einer 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 ermitteln, die bei der Verarbeitung aufgetreten sind.
Es gibt zwei Möglichkeiten, mit den Fehlern umzugehen:
- Wiederherstellbare Fehler: Der Nutzer muss seinen Einkaufswagen nicht bearbeiten, um die Bestellung aufzugeben. Wenn Sie beispielsweise feststellen, dass ein Artikel im
Cart
eine Preisänderung hat, können Sie mit einemFoodOrderError
vom FehlertypPRICE_CHANGED
antworten und diecorrectedProposedOrder
undpaymentOptions
angeben. Google informiert den Nutzer über die Änderung, lässt ihn aber die Meldung mit dercorrectedProposedOrder
einreichen. Der Nutzer kann auch zurückgehen und seinen Einkaufswagen bearbeiten. Sie erhalten entweder eine neueCheckoutRequestMessage
oder eineSubmitOrderRequestMessage
. - Nicht wiederherstellbare Fehler: Der Nutzer muss seinen Einkaufswagen bearbeiten, bevor er die Bestellung aufgeben kann. Wenn Sie beispielsweise feststellen, dass das Restaurant geschlossen ist, können Sie mit einer
FoodOrderError
vom FehlertypCLOSED
antworten. Google informiert den Nutzer und verwaltet die Interaktion, um auf ein neues Restaurant umzustellen. Sie erhalten eine neueCheckoutRequestMessage
für einen neuen Einkaufswagen.
Im Allgemeinen sollten Fehler auf Warenkorbebene nicht wiederhergestellt werden können, Fehler auf Artikelebene hingegen schon. 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 Kasse eines Kunden ein Preisproblem auftritt, gehe so vor:
- Antworten Sie auf die
CheckoutRequestMessage
mit einerCheckoutResponseMessage
, die eineFoodErrorExtension
enthält, wie unter Fehler behandeln beschrieben. - Aktualisieren Sie in der Fehlerantwort den Preis mit
correctedProposedOrder.cart
auf den richtigen Wert. Google erhält die korrigierte Bestellung und kann eine neueCheckoutRequestMessage
ausstellen.
Nach dem Bezahlvorgang zeigt Google dem Endnutzer eine Bestellbestätigungsseite an, unabhängig davon, ob die ProposedOrder
geändert wurde oder nicht.
Wenn die vorgeschlagene Verfügung korrigiert wurde, zeigt Google möglicherweise zusätzliche Warnungen an, um den Nutzer über die Änderungen zu informieren. Wenn der Nutzer der Bestellung zustimmt, werden keine weiteren Zahlungsanfragen gesendet. Der Ablauf wird mit der korrigierten ProposedOrder
fortgesetzt.
Der Nutzer kann seine Meinung jedoch jederzeit ändern und seinen Einkaufswagen noch einmal bearbeiten. Wenn der Einkaufswagen auf diese Weise aktualisiert wird, sendet Google eine neue CheckoutRequestMessage
.
Preisänderungen während der Bestellung
Wenn bei der Verarbeitung der Bestellaufgabe ein Preisproblem auftritt (die actions.intent.TRANSACTION_DECISION
-Intention wurde ausgelöst), antworte nicht mit einem Fehler und aktualisiere den Preis nicht in deiner Antwort. Wenn die Preise, Stückzahlen oder anderen Details in der SubmitOrderRequestMessage
nicht mit Ihren Daten übereinstimmen, antworten Sie mit orderState
auf REJECTED
, um anzugeben, dass die Bestellung nicht wie gewünscht aufgegeben werden kann.
Wenn die Bestell- und Zahlungsdetails gültig sind, setzen Sie orderState
auf CREATED
oder CONFIRMED
. Fügen Sie außerdem eine actionOrderId
für die ID der Bestellung in Ihrem System hinzu. Diese ID muss beim Senden nachfolgender Updates verwendet werden.
Wenn Sie die Zahlung nicht verarbeiten können und bereits die SubmitOrderRequestMessage
gesendet haben, können Sie eine AsyncOrderUpdateRequestMessage
mit orderState
auf REJECTED
senden, um den Nutzer darüber zu informieren, dass die Bestellung nicht ausgeführt wird.
Preisänderungen nach dem Senden der Bestellung
Wenn du feststellst, dass sich ein Preis gegenüber dem Preis geändert hat, der verwendet wurde, als ein Kunde seine Bestellung aufgegeben hat, kannst du eine AsyncOrderUpdateRequestMessage
mit dem neuen Preis senden, wie im Hilfeartikel Implementierung asynchroner Bestellaktualisierungen beschrieben.
So aktualisieren Sie Preise mithilfe von asynchronen Bestellaktualisierungen:
- Ändern Sie den Preis in
lineItemUpdates[x].price
. Dieser Wert entspricht den Gesamtkosten des Artikels, einschließlich der Add-ons, multipliziert mit der Stückzahl. Weitere Informationen finden Sie in der Beschreibung des Feldsprice
vonLineItem
. - Geben Sie in
lineItemUpdates[x].reason
eine Erklärung ein. - Legen Sie
lineItemUpdates[x].orderState
aufCONFIRMED
fest.
Sie können 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 der OrderUpdate
, um Google über den Fehler zu informieren:
- Setzen Sie
orderState
aufREJECTED
. - Beschreiben Sie den Fehler im Feld
label
.
Zahlungsbestätigung
Wie in Schritt 4: Direktkauf implementieren erläutert, sollte Ihr Fulfillment-Endpunkt jede eingehende CheckoutRequestMessage
validieren und mit einer CheckoutResponseMessage
antworten.
Hier ein Beispiel für eine CheckoutResponseMessage
nach erfolgreicher Validierung:
Anwendungsfall | Implementierung |
---|---|
Anwendungsfall 1:Validierung erfolgreich | Gib CheckoutResponse zurück. Es muss ProposedOrder und PaymentOptions haben.
ProposedOrder enthält Steuern, Gebühren und den Gesamtpreis des Einkaufswagens. |
{ "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 } } } } } ] } } }
Bestätigung der Lieferadresse
Ihr Fulfillment-Endpunkt muss die in jeder CheckoutRequestMessage
enthaltene Lieferadresse prüfen.
Wenn es ein Problem mit der Lieferadresse gibt, z. B. dass sie nicht im Lieferbereich des Lieferservice liegt, sollte die von Ihrem Fulfillment-Anbieter zurückgegebene CheckoutResponseMessage
einen FoodOrderError
des entsprechenden Typs enthalten.
Anwendungsfall | Implementierung |
---|---|
Use Case 1:Die Validierung ist fehlgeschlagen, weil die Lieferadresse nicht im zulässigen Bereich liegt oder ein Problem mit der Lieferadresse vorliegt. | Gibt FoodErrorExtension mit FoodOrderError vom Fehlertyp OUT_OF_SERVICE_AREA zurück. |
{ "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
Ihr Fulfillment-Endpunkt sollte den Mindestbestellwert für jede CheckoutRequestMessage
prüfen.
Wenn der Mindestbestellwert nicht erreicht wird, muss die von deinem Fulfillment-Anbieter zurückgegebene CheckoutResponseMessage
einen FoodOrderError
vom Fehlertyp REQUIREMENTS_NOT_MET
enthalten.
Anwendungsfall | Implementierung |
---|---|
Beispiel 1:Die Validierung ist fehlgeschlagen, weil der Mindestbestellwert nicht erreicht wurde. | Gibt FoodErrorExtension mit FoodOrderError vom Fehlertyp REQUIREMENTS_NOT_MET zurück. |
{ "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 des Bestellfensters
Ihr Fulfillment-Endpunkt sollte alle Faktoren prüfen, die sich auf das Bestellfenster jeder CheckoutRequestMessage
auswirken können.
Wenn das Restaurant beispielsweise geschlossen ist oder derzeit keine Bestellungen entgegennimmt, sollte die von deinem Fulfillment-Anbieter zurückgegebene CheckoutResponseMessage
einen FoodOrderError
vom Fehlertyp CLOSED
oder NO_CAPACITY
enthalten.
Anwendungsfall | Implementierung |
---|---|
Use Case 1:Die Überprüfung ist fehlgeschlagen, weil das Restaurant geschlossen ist oder nicht mehr unterstützt wird | Gibt FoodErrorExtension mit FoodOrderError vom Fehlertyp CLOSED zurück. |
Use Case 2:Die Validierung ist fehlgeschlagen, weil das Restaurant gerade sehr beschäftigt ist und keine Bestellungen entgegennimmt. | Gibt FoodErrorExtension mit FoodOrderError vom Fehlertyp NO_CAPACITY zurück. |
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "error": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension", "foodOrderErrors": [ { "error": "CLOSED", "description": "The restaurant is closed." } ] } } } ] } } }
{ "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
Ihr Fulfillment-Endpunkt sollte die Preise und die Verfügbarkeit jedes Artikels im Einkaufswagen in einer CheckoutRequestMessage
prüfen.
Wenn sich die Verfügbarkeit oder die Preise geändert haben, sollte die von deinem Fulfillment-Anbieter zurückgegebene CheckoutResponseMessage
einen FoodOrderError
vom Fehlertyp AVAILABILITY_CHANGED
oder PRICE_CHANGED
enthalten.
Anwendungsfall | Implementierung |
---|---|
Beispiel 1:Die Validierung ist fehlgeschlagen, weil einige Menüpunkte und/oder ihre Anpassungen ungültig sind 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. |
Use Case 2:Die Validierung ist fehlgeschlagen, weil einige Menüpunkte und/oder ihre Anpassungen ungültig sind oder nicht auf Lager sind. Der korrigierte Einkaufswagen erfüllt nicht mehr den Mindestbestellwert. | Gibt FoodErrorExtension mit FoodOrderError von den Fehlertypen AVAILABILITY_CHANGED und REQUIREMENTS_NOT_MET zurück. |
Anwendungsfall 3:Die Validierung ist fehlgeschlagen, weil sich die Preise für einige Menüpunkte und/oder Anpassungen geändert haben. | Gibt FoodErrorExtension mit correctedProposedOrder , PaymentOptions und FoodOrderError vom Fehlertyp PRICE_CHANGED zurück. Veraltete Preise müssen in CorrectedProposedOrder aktualisiert werden. |
Use Case 4:Die Validierung ist fehlgeschlagen, weil sich die Preise für einige Menüpunkte und/oder Anpassungen geändert haben. Der korrigierte Einkaufswagen erfüllt nicht mehr den Mindestbestellwert | Gibt FoodErrorExtension mit FoodOrderError von den Fehlertypen PRICE_CHANGED und REQUIREMENTS_NOT_MET zurück. |
{ "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 } } } } } ] } } }
{ "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." } ] } } } ] } } }
{ "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 } } } } } ] } } }
{ "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 } } ] } } } ] } } }
Bestätigung der Bestellung einreichen
Wie in Schritt 7: „Senden Bestellung“ implementieren erläutert, sollte Ihr Fulfillment-Endpunkt jede eingehende SubmitOrderRequestMessage
validieren und mit einer SubmitOrderResponseMessage
antworten.
Hier ein Beispiel für eine SubmitOrderResponseMessage
nach erfolgreicher Validierung:
Anwendungsfall | Implementierung |
---|---|
Fallbeispiel 1:Bestellung wird erfolgreich erstellt | Eine SubmitOrderResponseMessage mit dem Bestellstatus CREATED Sie müssen actionOrderId , userVisibleId , orderManagementActions und estimatedFulfillmentTime haben. |
Anwendungsfall 2:Bestellung wird aufgrund von Zahlungsproblemen abgelehnt | Eine SubmitOrderResponseMessage mit dem Bestellstatus REJECTED Sie muss actionOrderId , userVisibleId , orderManagementActions und rejectionInfo vom Typ PAYMENT_DECLINED enthalten. |
Use Case 3:Bestellung wird abgelehnt, da der Nutzer als gesperrt gekennzeichnet ist | Eine SubmitOrderResponseMessage mit dem Bestellstatus REJECTED Sie muss actionOrderId , userVisibleId , orderManagementActions und rejectionInfo vom Typ INELIGIBLE enthalten. |
Use Case 4:Bestellung wird abgelehnt, weil Nutzerinformationen unvollständig oder ungültig sind | Ein SubmitOrderResponseMessage mit dem Bestellstatus REJECTED . Sie muss actionOrderId , userVisibleId , orderManagementActions und rejectionInfo vom Typ INELIGIBLE enthalten. |
Use Case 5:Bestellung wird aus unbekanntem Grund abgelehnt | Eine SubmitOrderResponseMessage mit dem Bestellstatus REJECTED Es muss actionOrderId , userVisibleId , orderManagementActions und rejectionInfo vom Typ UNKNOWN enthalten. |
{ "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" } } } ] } } } ] } } }
{ "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" } } } ] } } } ] } } }
{ "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" } } } ] } } } ] } } }
{ "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" } } } ] } } } ] } } }
{ "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" } } } ] } } } ] } } }