After the checkout call, the user reviews the updated cart with taxes, delivery fees, discounts, and other charges that you return. The user confirms and submits the order and Google sends your fulfillment endpoint a JSON request that contains the information for the order. Your web service must receive this order, process it, and respond back to Google with the state of the order.
This section describes the order request message format sent by Google,
called the SubmitOrderRequestMessage
, and the format of the response message
you must provide, called the
SubmitOrderResponseMessage
.
For more information about the order fulfillment lifecycle, see the
Fulfillment overview.
Order fulfillment implementation
The Ordering End-to-End web service you build to work with Ordering End-to-End must
include a URL endpoint for receiving order messages from Google. For order
processing, your web service receives a SubmitOrderRequestMessage
in JSON
format as a POST request from Google. This request contains a customer order,
including taxes, fees, and payment information. Upon receiving a submit order
request, your web service must do the following:
- Check transaction eligibility, such as card verification or fraud detection.
- Create an order in your system.
- Authorize the payment method and call the charge API of your payment processor when applicable.
- Respond with the appropriate state of the order:
CREATED
,CONFIRMED
, orREJECTED
.
After processing the order, your fulfillment code must provide a response
in the form of a SubmitOrderResponseMessage
JSON message back to Google.
For more information about the Ordering End-to-End fulfillment web service implementation requirements, see the Fulfillment overview.
Order request message
When a customer chooses to place an order during the Ordering End-to-End flow,
Google sends a request to your web service with a JSON message called a
SubmitOrderRequestMessage
that contains the following data:
- Intent: The
inputs[0].intent
field of every submit order request body contains theactions.intent.TRANSACTION_DECISION
string value. - Order: The
inputs[0].arguments[0].transactionDecisionValue
field of a submit order request contains anOrder
object that represents the customer's order to be placed, along with payment details. - Sandbox flag: The
isInSandbox
field of a submit order request indicates whether the transaction uses sandbox payments.
Order request example
The following is an example SubmitOrderRequestMessage
:
JSON
{ "user": {}, "conversation": { "conversationId": "CTKbKfUlHCyDEdcz_5PBJTtf" }, "inputs": [ { "intent": "actions.intent.TRANSACTION_DECISION", "arguments": [ { "transactionDecisionValue": { "order": { "finalOrder": { "cart": { "merchant": { "id": "restaurant/Restaurant/QWERTY", "name": "Tep Tep Chicken Club" }, "lineItems": [ { "name": "Spicy Fried Chicken", "type": "REGULAR", "id": "299977679", "quantity": 2, "price": { "type": "ESTIMATE", "amount": { "currencyCode": "AUD", "units": "39", "nanos": 600000000 } }, "offerId": "MenuItemOffer/QWERTY/scheduleId/496/itemId/143", "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension" } } ], "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension", "fulfillmentPreference": { "fulfillmentInfo": { "delivery": { "deliveryTimeIso8601": "P0M" } } }, "location": { "coordinates": { "latitude": -33.8376441, "longitude": 151.0868736 }, "formattedAddress": "Killoola St, 1, Concord West NSW 2138", "zipCode": "2138", "city": "Concord West", "postalAddress": { "regionCode": "AU", "postalCode": "2138", "administrativeArea": "NSW", "locality": "Concord West", "addressLines": [ "Killoola St", "1" ] } }, "contact": { "displayName": "Hab Sy", "email": "hab9878.sy@gmail.com", "phoneNumber": "+61000000000", "firstName": "Hab", "lastName": "Sy" } } }, "otherItems": [ { "name": "Delivery fee", "type": "DELIVERY", "price": { "type": "ESTIMATE", "amount": { "currencyCode": "AUD", "units": "3", "nanos": 500000000 } } }, { "name": "Subtotal", "type": "SUBTOTAL", "price": { "type": "ESTIMATE", "amount": { "currencyCode": "AUD", "units": "39", "nanos": 600000000 } } } ], "totalPrice": { "type": "ESTIMATE", "amount": { "currencyCode": "AUD", "units": "43", "nanos": 100000000 } }, "extension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension" } }, "googleOrderId": "01412971004192156198", "orderDate": "2020-10-22T09:02:06.173Z", "paymentInfo": { "displayName": "Pay when you get your food", "paymentType": "ON_FULFILLMENT" } } } } ] } ], "directActionOnly": true, "isInSandbox": true }
Order response message
After receiving a request, your Ordering End-to-End web service processes the
request and sends back a SubmitOrderResponseMessage
that includes the
following data:
OrderUpdate
: An object containing the state of the order, and any post-order actions available to the user, such as contacting support and viewing order details, which you define in thefinalResponse.richResponse.items[0].structuredResponse.orderUpdate
field of the response.
Order update field
When your web service sends a SubmitOrderResponseMessage
, it contains an
OrderUpdate
field that includes the following fields:
actionOrderId
: The unique ID of the order, which is used to uniquely identify the order in your system and refer to it when sending subsequent order updates.orderState
: AnOrderState
object representing the state of the order.orderManagementActions
: Post-order actions available to the user, such as contacting customer support and viewing order details.totalPrice
: The total price of the order. This is optional. Only send if the total price of the order has changed after the order is submitted.
An order can be in one of the following states:
CREATED
: Your fulfillment endpoint processed the order successfully, but the provider has not yet confirmed the order.CONFIRMED
: Your fulfillment endpoint processed the order successfully, and the provider has confirmed the order.REJECTED
: There was a problem and your fulfillment endpoint could not create or confirm the order, which can include problems with payment.
If you set an order to a REJECTED
state, specify the reason in the
rejectionInfo
field of OrderUpdate
. Use
FoodOrderUpdateExtension.FoodOrderErrors
values in conjunction with
rejectionInfo
of type UNKNOWN
and provide a description.
Order response example
The following is an example SubmitOrderResponseMessage
:
JSON
{ "finalResponse": { "richResponse": { "items": [ { "structuredResponse": { "orderUpdate": { "actionOrderId": "1603357328160", "orderState": { "state": "CONFIRMED", "label": "Pending" }, "updateTime": "2020-10-22T02:02:08-07:00", "orderManagementActions": [ { "type": "CUSTOMER_SERVICE", "button": { "title": "Call customer service", "openUrlAction": { "url": "tel:+61234561000" } } }, { "type": "VIEW_DETAILS", "button": { "title": "View order details", "openUrlAction": { "url": "https://partner.com/view/orderstatus" } } } ], "receipt": { "userVisibleOrderId": "BXZ-1603357328" } } } } ] } } }
Unsuccessful request
If a submit request is unsuccessful, SubmitOrderResponseMessage
needs to set
the OrderState.state
to REJECTED
. The response must also
include the RejectionInfo, which contains a RejectionType
object to describe the error type.
Unsuccessful response example
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" } } } ] } } } ] } } }
Submit order implementation
The following steps should be taken when implementing the submit order API.
Validation
- Perform service, cart and promotion validations as done in Set up Checkout.
- Return RejectionInfo with one of the following types if needed:
RejectionInfoType | Use case |
---|---|
UNAVAILABLE_SLOT |
The fulfillment time is no longer valid. |
PROMO_USER_INELIGIBLE |
Use the Email in the Contact object in the request to validate the promotion eligibility for the user. See the example in implement submit order with promotions. |
INELIGIBLE |
|
PAYMENT_DECLINED |
The payment can't be processed. For example, this could be due to insufficient funds. |
UNKNOWN |
For any other validation error. |
Set the OrderState.state
to REJECTED
if there are validation
errors encountered. Optionally, you can provide a specific rejection reason
using the FoodOrderUpdateExtension.foodOrderErrors
. See examples in
Submit Order validation.
Process the payment
- Compute the
totalPrice
by adding the cart price, fees, discount, taxes and gratuity. ThetotalPrice
should be the same as thetotalPrice
returned in the CheckoutResponseMessage plus the change in the gratuity amount if the gratuity can be modified by the user. See Price changes during submit order for more details. - Process the order and payment if you return a response with an order state
of
CREATED
orCONFIRMED
. - Ensure that a valid response format is returned by using generated types created from the schema as described in generate client libraries.
- Use the
GoogleProvidedPaymentInstrument.
instrumentToken
to process the payment. Return RejectionInfo with typePAYMENT_DECLINED
if the payment can't be processed. See Process payments for more details. - Notify the user immediately after the order is processed by Email and or SMS.
Return the response
- Set the OrderState.
state
toCREATED
orCONFIRMED
if there are no errors. - Set the OrderState.
state
toREJECTED
if there are errors encountered and include the RejectionInfo object with the corresponding RejectionInfoType. - Set the OrderUpdate.
orderManagementActions
.