Memetakan feed menu dan item keranjang pemenuhan
Saat pelanggan menambahkan item dari feed Menu Anda ke keranjang dan melakukan check out, Google akan mengirimkan item tersebut ke endpoint fulfillment Anda untuk memverifikasi harga dan ketersediaannya. Setelah harga dan ketersediaan divalidasi, pelanggan dapat melakukan pemesanan. Bagian ini menggambarkan cara memetakan item feed menu ke item keranjang pemenuhan.
Contoh di bagian ini adalah versi feed Menu dan skema
Keranjang yang disederhanakan. Hanya kolom yang relevan untuk menggambarkan pemetaan antara feed Menu dan
objek Keranjang yang ditampilkan. Untuk skema lengkap, lihat Menu
dan Cart
.
Item dalam feed Menu
yang ditambahkan ke keranjang akan dikirim di objek Cart
untuk pengiriman pesanan dan checkout.
MenuItem
sederhana direpresentasikan sebagaiLineItem
dalam arraylineItems
denganofferId
menjadioffer.id
item menu yang dipilih di feed Menu.MenuItem
denganMenuItemOption
wajib direpresentasikan sebagaiLineItem
dalam arraylineItems
denganofferId
menjadioffer.id
opsi item menu yang dipilih dari feed Menu.AddOnMenuItem
dariLineItem
direpresentasikan sebagaiFoodItemOption
dalam arrayoptions
dariFoodItemExtension
. Setiap opsi memilikiofferId
yang sesuai denganoffer.id
item menu add-on yang dipilih dari feed Menu. Perhatikan bahwa AddOnMenuItem juga dapat memiliki AddOnMenuItem bertingkat yang direpresentasikan sebagaisubOptions
di dalam setiap opsi.
Contoh item menu peta berikut antara feed menu dan keranjang pemenuhan pesanan.
JSON
Contoh ini berisi daftar item menu sederhana.
Item menu di feed Menu:
{ "@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" } ] } ] }
Item menu yang dipetakan ke keranjang pemenuhan:
{ "@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
Contoh ini berisi item menu dengan satu atau beberapa AddOnMenuItems.
Item menu di feed Menu:
{ "@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" } ] } ] }
Item menu yang dipetakan ke keranjang pemenuhan:
{ "@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
Contoh ini berisi item menu dengan opsi item menu, AddOnMenuItems, dan AddOnMenuItems bertingkat
Item menu di feed Menu:
{ "@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" } ] } ] } ] } ] } ] } } ] }
Item menu yang dipetakan ke keranjang pemenuhan:
{ "@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" } ] } ] } } ] }
Menangani error
Jika mengalami masalah saat memproses CheckoutRequestMessage
, Anda
dapat merespons dengan CheckoutResponseMessage
yang berisi
FoodErrorExtension
, bukan CheckoutResponse. Anda dapat menggunakan respons ini untuk mengidentifikasi satu atau beberapa error yang terjadi selama pemrosesan.
Ada 2 cara untuk menangani error:
- Error yang dapat dipulihkan: Pengguna tidak perlu mengedit keranjang untuk mengirimkan
pesanan. Misalnya, jika Anda menentukan bahwa item dalam
Cart
memiliki perubahan harga, Anda dapat merespons denganFoodOrderError
jenis errorPRICE_CHANGED
, besertacorrectedProposedOrder
danpaymentOptions
. Google akan memberi tahu pengguna tentang perubahan ini, tetapi mengizinkan pengguna mengirim dengancorrectedProposedOrder
. Pengguna juga dapat kembali dan mengedit keranjangnya jika diinginkan. Anda akan menerimaCheckoutRequestMessage
baru atauSubmitOrderRequestMessage
. - Error yang tidak dapat dipulihkan: Pengguna harus mengedit keranjang sebelum
mengirim pesanan. Misalnya, jika menentukan bahwa restoran sudah tutup, Anda dapat merespons dengan
FoodOrderError
dari jenis errorCLOSED
. Google memberi tahu pengguna dan mengelola interaksi untuk diperbarui ke restoran baru. Anda akan menerimaCheckoutRequestMessage
baru untuk keranjang baru.
Secara umum, buat error tingkat keranjang tidak dapat dipulihkan dan error tingkat item
dapat dipulihkan. Untuk mengetahui daftar lengkap jenis error dan artinya, lihat
FoodOrderError
.
Menangani perubahan harga
Perubahan harga saat checkout
Jika Anda mengalami masalah harga saat memproses permintaan checkout pelanggan, lakukan hal berikut:
- Respons
CheckoutRequestMessage
denganCheckoutResponseMessage
yang berisiFoodErrorExtension
, seperti yang dijelaskan dalam Menangani error. - Dalam respons error, gunakan
correctedProposedOrder.cart
untuk memperbarui harga ke nilai yang benar. Google menerima pesanan yang telah dikoreksi dan dapat menerbitkanCheckoutRequestMessage
baru.
Setelah checkout, Google akan menampilkan halaman konfirmasi pesanan kepada pengguna akhir,
terlepas dari apakah ProposedOrder
telah diubah atau tidak.
Jika ProposaldOrder telah diperbaiki, Google dapat menampilkan peringatan tambahan untuk memberi tahu pengguna tentang perubahan ini. Jika pengguna setuju untuk melakukan pemesanan, tidak akan ada lagi permintaan checkout. Alur ini akan terus mengurutkan pengiriman, dengan
ProposedOrder
yang dikoreksi.
Namun, pengguna dapat berubah pikiran dan mengedit keranjangnya lagi kapan saja. Saat
keranjang mereka diperbarui dengan cara ini, Google akan mengirimkan CheckoutRequestMessage
baru.
Perubahan harga selama pengiriman pesanan
Jika Anda mengalami masalah harga saat memproses pengiriman pesanan
(intent actions.intent.TRANSACTION_DECISION
dipicu), jangan merespons
dengan error atau memperbarui harga dalam respons Anda. Jika harga, jumlah,
atau detail lainnya dalam SubmitOrderRequestMessage
tidak sesuai dengan
data Anda, tanggapi dengan orderState
yang disetel ke REJECTED
untuk menunjukkan bahwa
pesanan tidak dapat dilakukan sesuai permintaan.
Kemudian, jika detail pesanan dan pembayaran valid, tetapkan orderState
ke CREATED
atau CONFIRMED
. Selain itu, sertakan actionOrderId
untuk merepresentasikan ID pesanan dalam
sistem Anda. ID ini harus digunakan saat mengirim update berikutnya.
Jika Anda tidak dapat memproses pembayaran dan sudah mengirim
SubmitOrderRequestMessage
, Anda dapat mengirim
AsyncOrderUpdateRequestMessage
dengan orderState
ditetapkan ke REJECTED
untuk memberi tahu
pengguna bahwa pesanan tidak akan berhasil.
Perubahan harga setelah mengirim pesanan
Jika menentukan bahwa harga telah berubah dari harga yang digunakan saat pelanggan
mengirimkan pesanannya, Anda dapat menerbitkan AsyncOrderUpdateRequestMessage
, seperti
yang dijelaskan dalam Menerapkan Pembaruan Pesanan Asinkron, dengan harga baru.
Untuk memperbarui harga menggunakan pembaruan pesanan asinkron:
- Ubah harga dalam
lineItemUpdates[x].price
. Nilai ini mencerminkan total biaya item, termasuk add-on dan dikalikan dengan kuantitas. (Untuk informasi selengkapnya, lihat deskripsi kolomprice
dariLineItem
.) - Masukkan penjelasan dalam bahasa
lineItemUpdates[x].reason
. - Tetapkan
lineItemUpdates[x].orderState
keCONFIRMED
.
Anda dapat mencoba menagih instrumen pembayaran sebelum atau sesudah mengirim AsyncOrderUpdateRequestMessage, sesuai kebijaksanaan Anda. Jika transaksi gagal (mungkin karena delta harga terlalu tinggi), kirim AsyncOrderUpdateRequestMessage dengan setelan berikut di OrderUpdate
untuk memberi tahu Google tentang kegagalan tersebut:
- Tetapkan
orderState
keREJECTED
. - Jelaskan kegagalan di kolom
label
.
Validasi checkout
Seperti yang dibahas dalam Langkah 4: Implementasikan Checkout, endpoint
fulfillment Anda harus melakukan validasi pada setiap
CheckoutRequestMessage
yang masuk, dan merespons dengan CheckoutResponseMessage
.
Berikut adalah contoh CheckoutResponseMessage
untuk validasi
yang berhasil:
Kasus penggunaan | Cara menerapkan |
---|---|
Kasus penggunaan 1: Validasi berhasil | Kembalikan CheckoutResponse . File ini harus memiliki
ProposedOrder dan PaymentOptions .
ProposedOrder termasuk pajak, biaya, dan harga total keranjang. |
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 } } } } } ] } } }
Validasi alamat pengiriman
Endpoint fulfillment Anda harus memvalidasi alamat pengiriman yang ada di setiap
CheckoutRequestMessage
.
Jika ada masalah dengan alamat pengiriman, seperti berada di luar jangkauan
layanan pengiriman, CheckoutResponseMessage
yang ditampilkan oleh
fulfillment Anda harus berisi FoodOrderError
dari jenis yang sesuai.
Kasus penggunaan | Cara menerapkan |
---|---|
Kasus penggunaan 1: Validasi gagal karena alamat pengiriman berada di luar jangkauan atau ada masalah dengan alamat pengiriman | Tampilkan FoodErrorExtension dengan FoodOrderError jenis error 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." } ] } } } ] } } }
Validasi nilai pesanan minimum
Endpoint fulfillment Anda harus memvalidasi nilai pesanan minimum setiap
CheckoutRequestMessage
.
Jika nilai pesanan minimum tidak terpenuhi, CheckoutResponseMessage
yang ditampilkan oleh fulfillment Anda harus berisi FoodOrderError
jenis error
REQUIREMENTS_NOT_MET
.
Kasus penggunaan | Cara menerapkan |
---|---|
Kasus penggunaan 1: Validasi gagal karena nilai pesanan minimum tidak terpenuhi | Tampilkan FoodErrorExtension dengan FoodOrderError jenis error 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." } ] } } } ] } } }
Validasi periode pemesanan
Endpoint fulfillment Anda harus memvalidasi faktor apa pun yang dapat memengaruhi
periode pengurutan setiap CheckoutRequestMessage
.
Misalnya, jika restoran tutup atau tidak lagi menerima pesanan pada
saat ini, CheckoutResponseMessage
yang ditampilkan oleh fulfillment Anda harus
berisi FoodOrderError
jenis error CLOSED
atau
NO_CAPACITY
.
Kasus penggunaan | Cara menerapkan |
---|---|
Kasus penggunaan 1: Validasi gagal karena restoran tutup atau tidak didukung lagi | Tampilkan FoodErrorExtension dengan FoodOrderError jenis error CLOSED . |
Kasus penggunaan 2: Validasi gagal karena restoran sedang sibuk dan tidak menerima pesanan saat ini | Tampilkan FoodErrorExtension dengan FoodOrderError jenis error 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." } ] } } } ] } } }
Validasi item keranjang
Endpoint fulfillment Anda harus memvalidasi harga dan ketersediaan setiap
item keranjang yang terdapat dalam CheckoutRequestMessage
.
Jika ketersediaan atau harga telah berubah, CheckoutResponseMessage
yang ditampilkan oleh fulfillment Anda harus berisi FoodOrderError
jenis error
AVAILABILITY_CHANGED
atau PRICE_CHANGED
.
Kasus penggunaan | Cara menerapkan |
---|---|
Kasus penggunaan 1: Validasi gagal karena beberapa item menu dan/atau penyesuaiannya tidak valid atau habis stoknya | Tampilkan FoodErrorExtension dengan correctedProposedOrder ,
PaymentOptions , dan FoodOrderError dari jenis error
AVAILABILITY_CHANGED . Item yang tidak valid harus dihapus dari
CorrectedProposedOrder . |
Kasus penggunaan 2: Validasi gagal karena beberapa item menu dan/atau penyesuaiannya tidak valid atau habis. Keranjang yang dikoreksi tidak lagi memenuhi persyaratan nilai pesanan minimum. | Tampilkan FoodErrorExtension dengan FoodOrderError jenis error AVAILABILITY_CHANGED dan REQUIREMENTS_NOT_MET . |
Kasus penggunaan 3: Validasi gagal karena beberapa item menu dan/atau harga penyesuaian telah berubah | Tampilkan FoodErrorExtension dengan correctedProposedOrder ,
PaymentOptions , dan FoodOrderError dari jenis error
PRICE_CHANGED . Harga lama harus diperbarui dalam
CorrectedProposedOrder . |
Kasus penggunaan 4: Validasi gagal karena beberapa item menu dan/atau harga penyesuaian telah berubah. Keranjang yang dikoreksi tidak lagi memenuhi persyaratan nilai pesanan minimum | Tampilkan FoodErrorExtension dengan FoodOrderError jenis error PRICE_CHANGED dan 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 } } ] } } } ] } } }
Mengirimkan validasi pesanan
Seperti yang dibahas dalam Langkah 7: Terapkan Pengiriman Pesanan, endpoint fulfillment Anda harus melakukan validasi pada setiap
SubmitOrderRequestMessage
yang masuk, dan merespons dengan
SubmitOrderResponseMessage
.
Berikut adalah contoh SubmitOrderResponseMessage
untuk validasi
yang berhasil:
Kasus penggunaan | Cara menerapkan |
---|---|
Kasus penggunaan 1: Pesanan berhasil dibuat | SubmitOrderResponseMessage dengan status pesanan
CREATED . File harus memiliki actionOrderId ,
userVisibleId , orderManagementActions , dan
estimatedFulfillmentTime . |
Kasus penggunaan 2: Pesanan ditolak karena masalah pembayaran | SubmitOrderResponseMessage dengan status pesanan
REJECTED . File harus memiliki actionOrderId ,
userVisibleId , orderManagementActions , dan
rejectionInfo dari jenis PAYMENT_DECLINED . |
Kasus penggunaan 3: Pesanan ditolak untuk pengguna ditandai sebagai diblokir | SubmitOrderResponseMessage dengan status pesanan
REJECTED . File harus memiliki actionOrderId ,
userVisibleId , orderManagementActions , dan
rejectionInfo dari jenis INELIGIBLE . |
Kasus penggunaan 4: Pesanan ditolak karena informasi pengguna tidak lengkap atau tidak valid | SubmitOrderResponseMessage dengan status pesanan
REJECTED . File harus memiliki actionOrderId ,
userVisibleId , orderManagementActions , dan
rejectionInfo dari jenis INELIGIBLE . |
Kasus penggunaan 5: Pesanan ditolak karena alasan yang tidak diketahui | SubmitOrderResponseMessage dengan status pesanan
REJECTED . File harus memiliki actionOrderId ,
userVisibleId , orderManagementActions , dan
rejectionInfo dari jenis UNKNOWN . |
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "CREATED", "label": "Order received" }, "updateTime": "2017-05-10T02:30:00.000Z", "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "VIEW_DETAILS", "button": { "title": "View order", "openUrlAction": { "url": "https://orderview.partner.com?orderid=sample_action_order_id" } } } ] } } } ] } } }
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "REJECTED", "label": "Order rejected" }, "updateTime": "2017-05-10T02:30:00.000Z", "rejectionInfo": { "type": "PAYMENT_DECLINED", "reason": "Insufficient funds" }, "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "VIEW_DETAILS", "button": { "title": "View order", "openUrlAction": { "url": "https://orderview.partner.com?orderid=sample_action_order_id" } } } ] } } } ] } } }
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "REJECTED", "label": "Order rejected" }, "updateTime": "2017-05-10T02:30:00.000Z", "rejectionInfo": { "type": "INELIGIBLE", "reason": "Sorry, we are not able to take orders from this user" }, "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "VIEW_DETAILS", "button": { "title": "View order", "openUrlAction": { "url": "https://orderview.partner.com?orderid=sample_action_order_id" } } } ] } } } ] } } }
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "REJECTED", "label": "Order rejected" }, "updateTime": "2017-05-10T02:30:00.000Z", "rejectionInfo": { "type": "INELIGIBLE", "reason": "Sorry, the phone number must not be blank" }, "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "VIEW_DETAILS", "button": { "title": "View order", "openUrlAction": { "url": "https://orderview.partner.com?orderid=sample_action_order_id" } } } ] } } } ] } } }
JSON
{ "expectUserResponse": false, "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "REJECTED", "label": "Order rejected" }, "updateTime": "2017-05-10T02:30:00.000Z", "rejectionInfo": { "type": "UNKNOWN", "reason": "Sorry, there is something wrong with this order." }, "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Contact customer service", "openUrlAction": { "url": "mailto:support@example.com" } } }, { "type": "EMAIL", "button": { "title": "Email restaurant", "openUrlAction": { "url": "mailto:person@example.com" } } }, { "type": "CALL", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "VIEW_DETAILS", "button": { "title": "View order", "openUrlAction": { "url": "https://orderview.partner.com?orderid=sample_action_order_id" } } } ] } } } ] } } }