The checkout process is invoked when a user creates a cart. The contents of the user's cart and details about the order are sent to your Ordering End-to-End web service. This information is validated by your web service, and then you can either proceed or make adjustments to their cart as needed.
The checkout handler for your web service must respond to POST requests. When a
customer chooses to check out, Google sends the Ordering End-to-End web service a
JSON request body in the form of a CheckoutRequestMessage
, which contains the
details of a customer's Cart
. Your web service then responds back with a
CheckoutResponseMessage
. The following diagram illustrates the process.
Upon receiving a checkout request, your Ordering End-to-End web service must do the following:
- Check the cart's validity based on the current item prices, availability, and provider service.
- Calculate the total price (including any discounts, taxes, and delivery fees).
- If successful, respond with an unmodified cart.
- If unsuccessful, respond with an error message and a new proposed order.
Before you begin implementing checkout, we recommend reviewing the Fulfillment overview documentation.
Checkout Request Message
In order to validate the customer's cart, when a customer chooses to check out,
Google sends a request to your web service with a JSON body in the form of a
CheckoutRequestMessage
. The customer order is not submitted until later in the
Ordering End-to-End flow.
Data contained in a
CheckoutRequestMessage
includes the following:
- Intent: The
inputs[0].intent
field of every checkout request body contains theactions.foodordering.intent.CHECKOUT
string value. - Cart: The
inputs[0].arguments[0].extension
field of a checkout request contains aCart
object that represents the customer's cart. - Delivery or takeout: The
Cart
object's extension field contains aFoodCartExtension
object that specifies properties for delivery or takeout:- For delivery orders, the
FoodCartExtension
object includes the delivery address. - For pickup or takeout orders, the
FoodCartExtension
object doesn't contain any location information.
- For delivery orders, the
- Sandbox: The
isInSandbox
field of a checkout request contains a boolean value that indicates whether the transaction uses sandbox payments.
Checkout request example
Below is an example of a CheckoutRequestMessage
:
{
"user": {},
"conversation": {
"conversationId": "CTZbZfUlHCybEdcz_5PB3Ttf"
},
"inputs": [
{
"intent": "actions.foodordering.intent.CHECKOUT",
"arguments": [
{
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.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"
]
}
}
}
}
}
]
}
],
"directActionOnly": true,
"isInSandbox": true
}
Checkout Response Message
After receiving a request from the Ordering End-to-End service, your checkout web
service must process it and respond with a CheckoutResponseMessage
. The
CheckoutResponseMessage
needs to cover either a successful or unsuccessful
request.
Successful request
If a check out request is successful, CheckoutResponseMessage
needs to include
ProposedOrder
and
PaymentOptions
:
ProposedOrder
cart
: Acart
object identical to the cart provided in theCheckoutRequestMessage
. If any of the contents of the cart need to be changed, theCheckoutResponseMessage
should instead include aFoodErrorExtension
with a correctedProposedOrder
.otherItems
: Items added by the provider, such as delivery charges, taxes, and other fees. May also contain gratuity added by the user.totalPrice
: The total price of the order.extension
: AFoodOrderExtension
that defines fulfillment information for the order, such as delivery time.
PaymentOptions
- Setting up payment processing is covered later in Set up Google
Pay.
You can use placeholder JSON in your
CheckoutResponseMessage
until you're ready to implement payment processing. - To add placeholder payment options in your
CheckoutResponseMessage
, refer to the example below, which uses an example payment gateway forPaymentOptions
.
- Setting up payment processing is covered later in Set up Google
Pay.
You can use placeholder JSON in your
Successful response example
{
"finalResponse": {
"richResponse": {
"items": [
{
"structuredResponse": {
"checkoutResponse": {
"proposedOrder": {
"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"
]
}
}
}
},
"totalPrice": {
"type": "ESTIMATE",
"amount": {
"currencyCode": "AUD",
"units": "43",
"nanos": 100000000
}
},
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension",
"availableFulfillmentOptions": [
{
"fulfillmentInfo": {
"delivery": {
"deliveryTimeIso8601": "P0M"
}
}
}
]
},
"otherItems": [
{
"name": "Delivery fee",
"price": {
"type": "ESTIMATE",
"amount": {
"currencyCode": "AUD",
"units": "3",
"nanos": 500000000
}
},
"type": "DELIVERY"
}
]
},
"paymentOptions": {
"googleProvidedOptions": {
"facilitationSpecification": "{\"apiVersion\":2,\"apiVersionMinor\":0,\"merchantInfo\":{\"merchantName\":\"merchantName\"},\"allowedPaymentMethods\":[{\"type\":\"CARD\",\"parameters\":{\"allowedAuthMethods\":[\"PAN_ONLY\"],\"allowedCardNetworks\":[\"VISA\",\"MASTERCARD\"],\"billingAddressRequired\":true,\"cvcRequired\":false},\"tokenizationSpecification\":{\"type\":\"PAYMENT_GATEWAY\",\"parameters\":{\"gatewayMerchantId\":\"YOUR_MERCHANT_ID\",\"gateway\":\"cybersource\"}}}],\"transactionInfo\":{\"currencyCode\":\"AUD\",\"totalPriceStatus\":\"ESTIMATED\",\"totalPrice\":\"43.1\"}} "
}
},
"additionalPaymentOptions": [
{
"actionProvidedOptions": {
"paymentType": "ON_FULFILLMENT",
"displayName": "Pay when you get your food.",
"onFulfillmentPaymentData": {
"supportedPaymentOptions": []
}
}
}
]
}
}
}
]
}
}
}
Unsuccessful request
If a checkout request is unsuccessful, CheckoutResponseMessage
needs to
include FoodErrorExtension
, which contains a list of
FoodOrderError
items that describe any errors that occurred. If there are any recoverable
errors to the order, like a price change of an item in the cart, the
FoodErrorExtension
must include the correctedProposedOrder
.
Unsuccessful response example
{
"expectUserResponse": false,
"finalResponse": {
"richResponse": {
"items": [
{
"structuredResponse": {
"error": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension",
"foodOrderErrors": [
{
"error": "CLOSED",
"description": "The restaurant is closed."
}
]
}
}
}
]
}
}
}
Checkout implementation
The following steps should be taken when implementing checkout.
Validate the service
Return a FoodOrderError for the first service error condition found. These errors are not recoverable so the first error encountered should be returned. See Handling errors for a description of recoverable errors.
- Read the FulfillmentOptionInfo property in the
request to determine if the fulfillment type is for
delivery
orpickup
. Return the following error types if needed:
Error type Use case INVALID The fulfillment type is invalid. NOT_FOUND The fulfillment type is not found. CLOSED - There are no OperationHours windows for the order.
- The order is an ASAP order and there are no ASAP ServiceHours available for the current time.
- There is an emergency closure or the service
isDisabled
is true.
UNAVAILABLE_SLOT The order ahead time cannot be fulfilled. NO_CAPACITY The restaurant is busy and not taking orders at the moment. OUT_OF_SERVICE_AREA The order cannot be delivered to the user's address. See Delivery address validation for an example. NO_COURIER_AVAILABLE The order cannot be delivered because of limited delivery personnel.
Validate and price the cart
Look up each Cart.
lineItems
and validate with the current data in your system or in the merchant's system. The MenuItemOffer.sku
value from the feed entity is included as the LineItem.offerId
. Create a FoodOrderError for each line item if needed. Create a maximum of one error for each item. Return the following error types if needed:Error type Use case Recoverable INVALID The item data or any of the options data are invalid. No NOT_FOUND The item or any of the options are not found. No PRICE_CHANGED The price of an item or add-on combination has changed. This error can be treated as recoverable. Yes AVAILABILITY_CHANGED The amount requested for the line items or any of the options are not available. Yes REQUIREMENTS_NOT_MET The order minimum or order maximum is not met. This can be determined by checking if the cart price is below the Fee. eligibleTransactionVolumeMin
or above the Fee.eligibleTransactionVolumeMax
. See the example in minimum order value validation.No Return the validated list of lineItems with LineItemType
REGULAR
. The sum of all the cart line item prices is the cart price orSUBTOTAL
.
See examples in cart items validation.
Calculate the service fees
- Find the correct Fee entity for the service based on the
eligibleRegion
,validFrom
,validThrough
andpriority
. - Calculate the fee amount based on if the entity was defined with a
price
,percentageOfCart
orpricePerMeter
property. - Return the delivery or takeout service fee as a LineItem with
LineItemType
DELIVERY
orFEE
respectively. Add the fee to the Cart.otherItems
list.
Apply promotions
- Find the Deal entity based on matching the
Promotion.
coupon
value with the Deal.dealCode
. Validate the deal and return a FoodOrderError if needed. These errors can be treated as recoverable. Return the following error types if needed:
Error type Use case PROMO_NOT_RECOGNIZED The coupon code was not recognized. PROMO_EXPIRED The deal validity is expired. PROMO_ORDER_INELIGIBLE The order is not eligible for the coupon. PROMO_NOT_APPLICABLE Any other reason. Calculate the deal price amount based on Deal.
discount
or Deal.discountPercentage
.Apply deal price amount using the cart total or fee total depending on the Deal.
dealType
.Return the Cart.
promotions
with applied promotion.Return the promotion as a LineItem with LineItemType
DISCOUNT
. Add the discount to the Cart.otherItems
list with a negative price.
Return the response
- Create the ProposedOrder.
cart
, the response cart is the same as the request cart if no errors are encountered during validation. - Return the ProposedOrder.
otherItems
list including the tax, fees, gratuity and discount if applied. See Gratuity for more details on how to configure the gratuity item. - Include the ProposedOrder.
totalPrice
by adding the cart price, fees, discount, taxes and gratuity. - Return the
FoodOrderExtension.
availableFulfillmentOptions
with the respective FulfillmentOption. Update the estimated pickup or delivery time to the expected time. - If there are FoodOrderErrors generated from the previous validation checks:
- Include StructuredResponse.
error
and the list of errors in FoodErrorExtension.foodOrderErrors
. - Return the ProposedOrder in the
correctedProposedOrder
field if all errors are recoverable. - Return the PaymentOptions in the
paymentOptions
field if all errors are recoverable. - Optionally, include the
additionalPaymentOptions
if there are other payment options available and all errors are recoverable.
- Include StructuredResponse.
- If there are no validation errors, return the
proposedOrder
,paymentOptions
in the CheckoutResponse object. Optionally, include theadditionalPaymentOptions
if there are other payment options available.