메뉴 피드 및 처리 장바구니 항목 매핑
고객이 메뉴 피드의 항목을 장바구니에 추가하고 결제하면 Google은 이러한 항목을 처리 엔드포인트로 전송하여 가격 및 제공되어야 합니다 가격 및 재고가 검증되면 고객은 다음을 수행할 수 있습니다. 주문할 수 있습니다. 이 섹션에서는 메뉴 피드 항목을 처리 장바구니 상품을 말합니다
이 섹션의 샘플은 메뉴 피드와 장바구니의 간단한 버전입니다.
사용할 수 있습니다 메뉴 피드와
장바구니 객체가 표시됩니다. 전체 스키마는 Menu
및 Cart
을 참고하세요.
장바구니에 추가된 Menu
피드의 상품은 Cart
로 전송됩니다.
결제 및 주문 제출 모두에 사용합니다.
- 간단한
MenuItem
는lineItems
에서LineItem
로 표시됩니다. 메뉴에서 선택된 메뉴 항목의offer.id
인offerId
를 포함하는 배열 있습니다. - 필수
MenuItemOption
가 있는MenuItem
은 다음과 같이 표현됩니다.offerId
이(가) 선택된lineItems
배열의LineItem
메뉴 항목 옵션의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
이 예에는 하나 이상의 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
를 사용해야 합니다. 이
응답을 사용하여 처리 중에 발생한 하나 이상의 오류를 식별합니다.
다음 두 가지 방법으로 오류를 처리할 수 있습니다.
- 복구 가능한 오류: 사용자가
있습니다. 예를 들어
Cart
의 항목에 가격 변경 시 오류 유형의FoodOrderError
로 응답할 수 있습니다.PRICE_CHANGED
및correctedProposedOrder
및paymentOptions
Google은 사용자에게 변경사항을 알리지만 사용자가correctedProposedOrder
다음과 같은 경우 사용자는 돌아가서 장바구니를 수정할 수도 있습니다. 있습니다. 새CheckoutRequestMessage
또는SubmitOrderRequestMessage
- 복구할 수 없는 오류: 사용자가 장바구니를 수정해야 합니다.
주문을 제출할 수 있습니다. 예를 들어 음식점이
닫힌 경우 오류 유형
CLOSED
의FoodOrderError
로 응답할 수 있습니다. Google은 새 버전으로 업데이트하도록 사용자에게 알리고 상호작용을 관리합니다. 있습니다. 새CheckoutRequestMessage
을(를) 받게 됩니다. 있습니다.
일반적으로 장바구니 수준 오류를 복구할 수 없도록 하고 상품 수준의 오류로 만듭니다.
있습니다 오류 유형과 그 의미에 대한 전체 목록은 다음을 참고하세요.
FoodOrderError
가격 변경 처리
결제 중 가격 변경
고객의 결제를 처리하는 중에 가격 문제가 발생하는 경우 다음을 수행합니다.
- 다음과 같이
CheckoutRequestMessage
에 응답합니다.CheckoutResponseMessage
-FoodErrorExtension
를 포함합니다. 오류 처리에 설명되어 있습니다. - 오류 응답에서
correctedProposedOrder.cart
를 사용하여 가격을 업데이트합니다. 올바른 값으로 변경합니다. Google은 수정된 주문을 접수하고 새 주문을CheckoutRequestMessage
결제가 완료되면 Google에서 최종 사용자에게 주문 확인 페이지를 표시합니다.
ProposedOrder
의 변경 여부와 상관없이
제안 주문이 수정되면 Google은
사용자에게 변경사항을 알립니다. 사용자가 주문에 동의하면
더 이상 결제 요청이 발생하지 않습니다. 이 절차에서는 계속해서 제출이 진행되며
수정된 ProposedOrder
하지만 사용자는 언제든지 마음이 바뀌어 장바구니를 다시 수정할 수 있습니다. 날짜
장바구니가 업데이트되면 Google에서는 새 CheckoutRequestMessage
를 전송합니다.
주문 제출 중 가격 변경
주문 제출을 처리하는 중에 가격 문제가 발생하는 경우
(actions.intent.TRANSACTION_DECISION
인텐트가 트리거됨) 응답하지 마세요.
하거나 응답에서 가격을 업데이트하세요. 가격, 수량, 비용이
SubmitOrderRequestMessage
의 기타 세부정보가
orderState
를 REJECTED
로 설정하여 응답하면
요청한 대로 주문할 수 없습니다.
그런 다음 주문 및 결제 세부정보가 유효하면 orderState
를 CREATED
로 설정합니다.
또는 CONFIRMED
. 또한 다음과 같이 주문 ID를 나타내는 actionOrderId
를 포함합니다.
있습니다. 이 ID는 후속 업데이트를 전송할 때 사용해야 합니다.
결제를 처리할 수 없고
SubmitOrderRequestMessage
,
orderState
가 REJECTED
로 설정된 AsyncOrderUpdateRequestMessage
사용자는 주문이 처리되지 않는다는 것을 알고 있습니다.
주문 제출 후 가격 변경
고객이 사용했을 때와 비교하여 가격이 변경되었다고 판단되는 경우
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
을(를) 반품한 배송 서비스
fulfillment에는 적절한 유형의 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
이
FoodOrderError
오류 유형 CLOSED
또는 NO_CAPACITY
포함
각각 1개의 값으로 사용합니다.
사용 사례 | 구현 방법 |
---|---|
사용 사례 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: 주문이 생성됨 | CREATED 주문이 있는 SubmitOrderResponseMessage
있습니다. actionOrderId 가 있어야 합니다.
userVisibleId , orderManagementActions ,
estimatedFulfillmentTime 입니다. |
사용 사례 2: 결제 문제로 인해 주문이 거부된 경우 | REJECTED 주문이 있는 SubmitOrderResponseMessage
있습니다. actionOrderId 가 있어야 합니다.
userVisibleId , orderManagementActions ,
PAYMENT_DECLINED 유형의 rejectionInfo 입니다. |
사용 사례 3: 차단된 것으로 표시되어 사용자의 주문이 거부됨 | REJECTED 주문이 있는 SubmitOrderResponseMessage
있습니다. actionOrderId 가 있어야 합니다.
userVisibleId , orderManagementActions ,
INELIGIBLE 유형의 rejectionInfo 입니다. |
사용 사례 4: 사용자 정보가 불완전하거나 잘못됨 | REJECTED 주문이 있는 SubmitOrderResponseMessage
있습니다. actionOrderId 가 있어야 합니다.
userVisibleId , orderManagementActions ,
INELIGIBLE 유형의 rejectionInfo 입니다. |
사용 사례 5: 알 수 없는 이유로 주문이 거부되었습니다. | REJECTED 주문이 있는 SubmitOrderResponseMessage
있습니다. 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" } } } ] } } } ] } } }