メニュー フィードとフルフィルメント カート項目のマッピング
ユーザーがメニュー フィードから商品をカートに追加して購入手続きを済ませると、 Google はこれらの商品をフルフィルメント エンドポイントに送信して価格を確認し、 可用性。料金と可用性を確認したら、お客様は 注文します。このセクションでは、メニューのフィード項目を フルフィルメント カートの商品アイテム。
このセクションのサンプルは、メニュー フィードとカートをシンプルにしたものです。
説明します。メニュー フィードと
Cart オブジェクトが表示されます。完全なスキーマについては、Menu
と Cart
をご覧ください。
Menu
フィード内の商品アイテムがカートに追加された場合、Cart
で送信されます。
決済と注文送信の両方に使用されます。
- 単純な
MenuItem
は、lineItems
ではLineItem
として表されます。offerId
がメニュー内で選択されたメニュー項目のoffer.id
の配列 できます。 - 必須の
MenuItemOption
を持つMenuItem
は、次のように表されます。lineItems
配列のLineItem
(offerId
が選択されている) メニュー フィードのoffer.id
というメニュー項目のオプションです。 LineItem
のAddOnMenuItem
は次のように表されます。FoodItemExtension
のoptions
配列内のFoodItemOption
各オプションには、選択したアドオン メニューに対応するofferId
があります メニュー フィードのアイテムのoffer.id
。AddOnMenuItem には それぞれの内部にsubOptions
として表される、ネストされた AddOnMenuItem(s) があります。 選択します。
次の例では、メニュー フィードとフルフィルメントの間でメニュー項目をマッピングしています 表示されます。
JSON
この例には、シンプルなメニュー項目のリストが含まれています。
メニュー フィードのメニュー項目:
{ "@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" } ] } ] }
フルフィルメント カートにマッピングされたメニュー項目:
{ "@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
この例には、1 つ以上の AddOnMenuItems を持つメニュー項目が含まれています。
メニュー フィードのメニュー項目:
{ "@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" } ] } ] }
フルフィルメント カートにマッピングされたメニュー項目:
{ "@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
この例には、AddOnMenuItems というメニュー項目のオプションを含むメニュー項目が含まれています。 ネストされた AddOnMenuItems
メニュー フィードのメニュー項目:
{ "@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" } ] } ] } ] } ] } ] } } ] }
フルフィルメント カートにマッピングされたメニュー項目:
{ "@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" } ] } ] } } ] }
エラー処理
CheckoutRequestMessage
の処理中に問題が発生した場合は、
次の値を含む CheckoutResponseMessage
で応答できます:
CheckoutResponse ではなく FoodErrorExtension
を使用します。こちらの
レスポンスを使用して、処理中に発生した 1 つ以上のエラーを特定します。
エラーを処理する方法は 2 つあります。
- 復元可能なエラー: ユーザーはカートを編集しなくても、
できます。たとえば、
Cart
のアイテムに 価格の変更については、エラータイプのFoodOrderError
で応答できますPRICE_CHANGED
とcorrectedProposedOrder
およびpaymentOptions
。 Google はユーザーに変更を通知しますが、ユーザーはcorrectedProposedOrder
。次の場合は、前の画面に戻ってカートを編集することもできます。 あります。新しいCheckoutRequestMessage
またはSubmitOrderRequestMessage
。 - 回復不能なエラー: ユーザーは事前にカートを編集する必要があります。
注文を送信します。たとえば、レストランがレストランで
エラータイプ
CLOSED
のFoodOrderError
で応答できます。 Google がユーザーに通知し、インタラクションを管理して新しい 説明します。新しいCheckoutRequestMessage
として 表示されます。
通常、カート単位のエラーは回復不能なエラー、商品アイテム単位のエラーは復元不可にします。
復元可能です。エラーの種類とその意味の完全なリストについては、
FoodOrderError
。
価格変更の処理
購入手続き中に価格が変更される
お客様の購入手続きの処理中に価格に関する問題が発生した場合 次の操作を行います。
CheckoutRequestMessage
に対して、次を使用して応答します:FoodErrorExtension
を含むCheckoutResponseMessage
(エラーの処理を参照)- エラー レスポンスで、
correctedProposedOrder.cart
を使用して価格を更新します。 必要があります。修正された注文を Google が受領すると、Google が新しいCheckoutRequestMessage
。
購入手続き後、Google はエンドユーザーに注文確認ページを表示します。
ProposedOrder
が変更されたかどうかに関係なく保持されます。
ProposedOrder が修正されると、Google は以下に対して追加の警告を表示することがあります
ユーザーに変更を通知します。ユーザーが注文に同意した場合は、
購入手続きのリクエストは行われなくなりますフローは注文の送信を続行し、
修正された ProposedOrder
。
ただし、カートはいつでも再編集できます。日時
カートが更新されたら、Google は新しい CheckoutRequestMessage
を送信します。
注文の送信中に価格を変更
注文の送信の処理中に価格に関する問題が発生した場合
(actions.intent.TRANSACTION_DECISION
インテントがトリガーされた)、応答しない
価格を更新するか、ご自身の回答で修正してください。価格、在庫数、
SubmitOrderRequestMessage
内のその他の詳細が
orderState
を REJECTED
に設定して応答し、
リクエストどおりに注文できません。
注文とお支払いの詳細が有効な場合は、orderState
を CREATED
に設定します。
または CONFIRMED
。また、注文の ID を表す actionOrderId
を含めます。
できます。この ID は、その後のアップデートを送信する際に使用する必要があります。
お支払いを処理できず、
SubmitOrderRequestMessage
さん、
AsyncOrderUpdateRequestMessage
で orderState
を REJECTED
に設定して、
注文が処理されないことをお客様に知らせます。
注文送信後の価格変更
お客様が
注文を送信した場合は、次のように AsyncOrderUpdateRequestMessage
を発行できます。
に記載されている新しい料金での、非同期注文更新の実装をご覧ください。
注文を非同期で更新して価格を更新するには:
lineItemUpdates[x].price
で価格を変更します。この は、アイテムの合計費用を表します。これにはアドオンと 割った数値です(詳細については、このモジュールのLineItem
のprice
フィールド)。lineItemUpdates[x].reason
に説明を入力してください。lineItemUpdates[x].orderState
を設定 宛先:CONFIRMED
お支払い方法への請求は、
AsyncOrderUpdateRequestMessage を自身の裁量で呼び出します。トランザクションが失敗した場合
(おそらく、価格の差分が高すぎるため)は、
AsyncOrderUpdateRequestMessage を次のように設定して、
OrderUpdate
で Google に失敗を通知します。
orderState
をREJECTED
に設定する。label
フィールドで失敗を説明します。
購入手続きの検証
ステップ 4: 決済機能を実装するで説明したとおり、
フルフィルメント エンドポイントは、すべての受信に対して検証を実行する必要がある
CheckoutRequestMessage
、CheckoutResponseMessage
で応答します。
以下は、成功したリクエストの CheckoutResponseMessage
の例です。
検証:
ユースケース | 導入方法 |
---|---|
ユースケース 1: 検証が成功する | CheckoutResponse を返します。以下が必要です。
ProposedOrder と PaymentOptions 。
ProposedOrder には、税金、手数料、合計金額が含まれます
表示されます。 |
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 } } } } } ] } } }
配送先住所の検証
フルフィルメント エンドポイントは、各リクエストに含まれる配送先住所を検証する必要があります。
CheckoutRequestMessage
。
範囲外など、配送先住所に問題がある場合は、
配送サービス、つまり商品アイテムによって返される CheckoutResponseMessage
フルフィルメントには適切なタイプの FoodOrderError
を含める必要があります。
ユースケース | 導入方法 |
---|---|
ユースケース 1: 配送先住所がないことが原因で検証に失敗した 範囲外または配送先住所に問題があります | FoodOrderError で FoodErrorExtension を返却
(エラータイプ 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." } ] } } } ] } } }
最低注文額の検証
フルフィルメント エンドポイントでは、各商品の最低注文額を検証する必要があります。
CheckoutRequestMessage
。
最低注文額に達していない場合、CheckoutResponseMessage
フルフィルメントから返される値に、エラータイプの FoodOrderError
が含まれていること
REQUIREMENTS_NOT_MET
。
ユースケース | 導入方法 |
---|---|
ユースケース 1: 最低注文額が原因で検証に失敗した 不適合 | FoodOrderError で FoodErrorExtension を返却
(エラータイプ 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." } ] } } } ] } } }
注文期間の検証
フルフィルメント エンドポイントでは、
注文期間内であることが確認されます。CheckoutRequestMessage
たとえば、レストランが閉業している場合や、
フルフィルメントから返される CheckoutResponseMessage
は
エラータイプが CLOSED
または NO_CAPACITY
の FoodOrderError
が含まれている
できます。
ユースケース | 導入方法 |
---|---|
ユースケース 1: レストランが閉業したか、 サポートは終了しました | FoodOrderError で FoodErrorExtension を返却
(エラータイプ CLOSED )。 |
ユースケース 2: レストランが混雑していて、かつ 現在注文を受け付けていない | FoodOrderError で FoodErrorExtension を返却
(エラータイプ 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." } ] } } } ] } } }
カートのアイテムの検証
フルフィルメント エンドポイントでは、それぞれの価格と在庫状況を検証する必要があります。
CheckoutRequestMessage
に含まれるカート商品アイテム。
在庫状況または価格が変更された場合の CheckoutResponseMessage
フルフィルメントから返される値に、エラータイプの FoodOrderError
が含まれていること
それぞれ AVAILABILITY_CHANGED
、PRICE_CHANGED
です。
ユースケース | 導入方法 |
---|---|
ユースケース 1: 一部のメニュー項目や カスタマイズが無効か、在庫切れの場合 | correctedProposedOrder で FoodErrorExtension を返品する。
PaymentOptions 、およびエラータイプの FoodOrderError
AVAILABILITY_CHANGED 。無効なアイテムは
CorrectedProposedOrder 。 |
ユースケース 2: 一部のメニュー項目や カスタマイズが無効であるか、在庫切れです。修正されたカート 最低注文額の要件を満たさなくなった場合 | FoodOrderError で FoodErrorExtension を返却
エラータイプ AVAILABILITY_CHANGED と
REQUIREMENTS_NOT_MET 。 |
ユースケース 3: 一部のメニュー項目が原因で検証に失敗した カスタマイズ料金が変更されました | correctedProposedOrder で FoodErrorExtension を返品する。
PaymentOptions 、およびエラータイプの FoodOrderError
PRICE_CHANGED 。古い価格の更新が必要です
CorrectedProposedOrder 。 |
ユースケース 4: 一部のメニュー項目が原因で検証に失敗した カスタマイズ料金が変更されました。修正されたカートが 最低注文額の要件 | FoodOrderError で FoodErrorExtension を返却
エラータイプ PRICE_CHANGED と
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 } } ] } } } ] } } }
注文の検証を送信する
ステップ 7: 注文送信を実装するで説明したとおり、
フルフィルメント エンドポイントは、すべての受信に対して検証を実行する必要がある
SubmitOrderRequestMessage
、
SubmitOrderResponseMessage
。
以下は、成功したリクエストの SubmitOrderResponseMessage
の例です。
検証:
ユースケース | 導入方法 |
---|---|
ユースケース 1: 注文が正常に作成される | SubmitOrderResponseMessage (注文が CREATED )
あります。actionOrderId が必要です。
userVisibleId 、orderManagementActions 、
estimatedFulfillmentTime 。 |
ユースケース 2: 支払いの問題により注文が拒否された | SubmitOrderResponseMessage (注文が REJECTED )
あります。actionOrderId が必要です。
userVisibleId 、orderManagementActions 、
PAYMENT_DECLINED 型の rejectionInfo 。 |
ユースケース 3: ユーザーのために注文が拒否され、禁止フラグが付けられている | SubmitOrderResponseMessage (注文が REJECTED )
ステータスです。actionOrderId が必要です。
userVisibleId 、orderManagementActions 、
INELIGIBLE 型の rejectionInfo 。 |
ユースケース 4: ユーザー情報が 不完全または無効 | SubmitOrderResponseMessage (注文が REJECTED )
あります。actionOrderId が必要です。
userVisibleId 、orderManagementActions 、
INELIGIBLE 型の rejectionInfo 。 |
ユースケース 5: 不明な理由により注文が拒否された | SubmitOrderResponseMessage (注文が REJECTED )
あります。actionOrderId が必要です。
userVisibleId 、orderManagementActions 、
UNKNOWN 型の rejectionInfo 。 |
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" } } } ] } } } ] } } }