Memetakan feed menu dan item keranjang fulfillment
Saat pelanggan menambahkan item dari feed Menu ke keranjang dan melakukan checkout, Google akan mengirimkan item tersebut ke endpoint fulfillment Anda untuk memverifikasi harga dan ketersediaannya. Setelah harga dan ketersediaan divalidasi, pelanggan dapat membuat pesanan. Bagian ini mengilustrasikan cara memetakan item feed menu ke item keranjang fulfillment.
Contoh di bagian ini adalah versi ringkas feed Menu dan skema
Keranjang. Hanya kolom yang relevan untuk mengilustrasikan pemetaan antara feed Menu dan
objek Keranjang yang ditampilkan. Untuk skema lengkap, lihat Menu
dan Cart
.
Item dalam feed Menu
yang ditambahkan ke keranjang dikirim dalam objek Cart
untuk checkout dan pengiriman pesanan.
MenuItem
sederhana direpresentasikan sebagaiLineItem
dalam arraylineItems
denganofferId
sebagaioffer.id
item menu yang dipilih di feed Menu.MenuItem
denganMenuItemOption
yang diperlukan direpresentasikan sebagaiLineItem
dalam arraylineItems
denganofferId
sebagaioffer.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 berikut memetakan item menu antara feed menu dan keranjang fulfillment.
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 fulfillment:
{ "@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" } ] }
Contoh ini berisi item menu dengan satu atau beberapa AddOnMenuItem.
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 fulfillment:
{ "@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" } ] }
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 fulfillment:
{ "@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 diwajibkan untuk mengedit keranjangnya guna mengirimkan
pesanan. Misalnya, jika Anda menentukan bahwa item di
Cart
memiliki perubahan harga, Anda dapat merespons denganFoodOrderError
dari jenis errorPRICE_CHANGED
, bersama dengancorrectedProposedOrder
danpaymentOptions
. Google akan memberi tahu pengguna tentang perubahan tersebut, tetapi mengizinkan pengguna mengirimkan dengancorrectedProposedOrder
. Pengguna juga dapat kembali dan mengedit keranjang jika ingin. Anda akan menerimaCheckoutRequestMessage
baru atauSubmitOrderRequestMessage
. - Error yang tidak dapat dipulihkan: Pengguna diwajibkan untuk mengedit keranjang sebelum
mengirim pesanan. Misalnya, jika Anda menentukan bahwa restoran
tertutup, Anda dapat merespons dengan
FoodOrderError
dari jenis errorCLOSED
. Google memberi tahu pengguna dan mengelola interaksi untuk memperbarui 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 beserta artinya, lihat
FoodOrderError
.
Menangani perubahan harga
Perubahan harga selama checkout
Jika Anda mengalami masalah harga saat memproses permintaan checkout pelanggan, lakukan tindakan 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 perintah yang dikoreksi dan dapat menerbitkanCheckoutRequestMessage
baru.
Setelah checkout, Google akan menampilkan halaman konfirmasi pesanan kepada pengguna akhir,
terlepas dari apakah ProposedOrder
diubah atau tidak.
Jika ProposedOrder dikoreksi, Google dapat menampilkan peringatan tambahan untuk
memberi tahu pengguna tentang perubahan tersebut. Jika pengguna setuju untuk melakukan pemesanan, tidak
akan ada lagi permintaan checkout. Alur ini akan melanjutkan pengiriman pesanan, dengan
ProposedOrder
yang telah dikoreksi.
Namun, pengguna dapat mengubah keputusannya kapan saja dan mengedit keranjangnya lagi. 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 di SubmitOrderRequestMessage
tidak sesuai dengan
data Anda, respons dengan orderState
yang ditetapkan ke REJECTED
untuk menunjukkan bahwa
pesanan tidak dapat dilakukan seperti yang diminta.
Kemudian, jika detail pesanan dan pembayaran valid, tetapkan orderState
ke CREATED
atau CONFIRMED
. Selain itu, sertakan actionOrderId
untuk mewakili ID pesanan di
sistem Anda. ID ini harus digunakan saat mengirim update berikutnya.
Jika tidak dapat memproses pembayaran dan telah mengirim
SubmitOrderRequestMessage
, Anda dapat mengirim
AsyncOrderUpdateRequestMessage
dengan orderState
disetel ke REJECTED
untuk memberi tahu
pengguna bahwa pesanan tidak akan berhasil.
Perubahan harga setelah mengirim pesanan
Jika Anda menentukan bahwa harga telah berubah dari harga yang digunakan saat pelanggan
mengirimkan pesanan, Anda dapat menerbitkan AsyncOrderUpdateRequestMessage
, seperti
yang dijelaskan dalam Menerapkan Pembaruan Pesanan Asinkron, dengan harga baru.
Untuk memperbarui harga menggunakan pembaruan pesanan asinkron:
- Ubah harga di
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 di
lineItemUpdates[x].reason
. - Tetapkan
lineItemUpdates[x].orderState
keCONFIRMED
.
Anda dapat mencoba menagih instrumen pembayaran sebelum atau setelah 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 telah dibahas di Langkah 4: Menerapkan 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 . Harus memiliki
ProposedOrder dan PaymentOptions .
ProposedOrder mencakup pajak, biaya, dan harga total
keranjang. |
{ "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 terdapat dalam 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 rentang atau ada masalah dengan alamat pengiriman | Tampilkan FoodErrorExtension dengan FoodOrderError
dari jenis error OUT_OF_SERVICE_AREA . |
{ "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 dari setiap
CheckoutRequestMessage
.
Jika nilai pesanan minimum tidak terpenuhi, CheckoutResponseMessage
yang ditampilkan oleh fulfillment Anda harus berisi FoodOrderError
dari jenis error
REQUIREMENTS_NOT_MET
.
Kasus penggunaan | Cara menerapkan |
---|---|
Kasus penggunaan 1: Validasi gagal karena nilai pesanan minimum tidak terpenuhi | Tampilkan FoodErrorExtension dengan FoodOrderError
dari jenis error REQUIREMENTS_NOT_MET . |
{ "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 jendela pengurutan
Endpoint fulfillment Anda harus memvalidasi faktor apa pun yang dapat memengaruhi
periode pemesanan setiap CheckoutRequestMessage
.
Misalnya, jika restoran tutup atau tidak lagi menerima pesanan saat ini,
CheckoutResponseMessage
yang ditampilkan oleh fulfillment Anda harus
berisi FoodOrderError
dari jenis error CLOSED
atau NO_CAPACITY
.
Kasus penggunaan | Cara menerapkan |
---|---|
Kasus penggunaan 1: Validasi gagal karena restoran tutup atau tidak lagi didukung | Tampilkan FoodErrorExtension dengan FoodOrderError
dari jenis error CLOSED . |
Kasus penggunaan 2: Validasi gagal karena restoran sedang sibuk dan tidak menerima pesanan saat ini | Tampilkan FoodErrorExtension dengan FoodOrderError
dari jenis error NO_CAPACITY . |
{ "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." } ] } } } ] } } }
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
dari 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 stoknya habis | 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 stoknya habis. Keranjang yang dikoreksi tidak lagi memenuhi persyaratan nilai pesanan minimum. | Tampilkan FoodErrorExtension dengan FoodOrderError
dari 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 yang sudah tidak berlaku harus diperbarui di
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
dari jenis error PRICE_CHANGED dan
REQUIREMENTS_NOT_MET . |
{ "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 } } ] } } } ] } } }
Mengirim validasi pesanan
Seperti yang telah dibahas di Langkah 7: Mengimplementasikan Kirim 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 . Harus memiliki actionOrderId ,
userVisibleId , orderManagementActions , dan
estimatedFulfillmentTime . |
Kasus penggunaan 2: Pesanan ditolak karena masalah pembayaran | SubmitOrderResponseMessage dengan status pesanan
REJECTED . Harus memiliki actionOrderId ,
userVisibleId , orderManagementActions , dan
rejectionInfo dari jenis PAYMENT_DECLINED . |
Kasus penggunaan 3: Pesanan ditolak karena pengguna ditandai sebagai diblokir | SubmitOrderResponseMessage dengan status pesanan
REJECTED . 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 . 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 . Harus memiliki actionOrderId ,
userVisibleId , orderManagementActions , dan
rejectionInfo dari jenis UNKNOWN . |
{ "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" } } } ] } } } ] } } }