El proceso de confirmación de la compra se invoca cuando un usuario crea un carrito. El contenido del carrito del usuario y los detalles del pedido se envían a tu servicio web de extremo a extremo de pedidos. Tu servicio web valida esta información y, luego, puedes continuar o hacer ajustes en su carrito según sea necesario.
El controlador de confirmación de la compra para tu servicio web debe responder a las solicitudes POST. Cuando un cliente elige pagar, Google envía al servicio web de extremo a extremo de pedidos un cuerpo de solicitud JSON en forma de un CheckoutRequestMessage
, que contiene los detalles del Cart
de un cliente. Luego, tu servicio web responde con un CheckoutResponseMessage
. En el siguiente diagrama, se ilustra el proceso.
Cuando recibas una solicitud de confirmación de la compra, tu servicio web de extremo a extremo de pedidos debe hacer lo siguiente:
- Comprueba la validez del carrito según los precios actuales del artículo, la disponibilidad y el servicio del proveedor.
- Calcula el precio total (incluidos los descuentos, los impuestos y las tarifas de envío).
- Si el proceso es satisfactorio, responde con un carrito sin modificar.
- Si el problema persiste, responde con un mensaje de error y un nuevo pedido propuesto.
Antes de comenzar a implementar la confirmación de la compra, te recomendamos que revises la documentación de Descripción general de la entrega.
Mensaje de solicitud de confirmación de la compra
Para validar el carrito del cliente, cuando un cliente elige pagar, Google envía una solicitud a tu servicio web con un cuerpo JSON en forma de CheckoutRequestMessage
. El pedido del cliente no se envía hasta más adelante en el flujo de pedidos de extremo a extremo.
Entre los datos que se incluyen en un CheckoutRequestMessage
, se incluyen los siguientes:
- Intent: El campo
inputs[0].intent
del cuerpo de cada solicitud de confirmación de la compra contiene el valor de stringactions.foodordering.intent.CHECKOUT
. - Carrito: El campo
inputs[0].arguments[0].extension
de una solicitud de confirmación de la compra contiene un objetoCart
que representa el carrito del cliente. - Entrega o comida para llevar: El campo de extensión del objeto
Cart
contiene un objetoFoodCartExtension
que especifica las propiedades para la entrega o la exportación:- Para los pedidos de entrega, el objeto
FoodCartExtension
incluye la dirección de entrega. - En el caso de los pedidos para llevar o para llevar, el objeto
FoodCartExtension
no contiene información de ubicación.
- Para los pedidos de entrega, el objeto
- Zona de pruebas: El campo
isInSandbox
de una solicitud de confirmación de la compra contiene un valor booleano que indica si la transacción usa pagos de zona de pruebas.
Ejemplo de solicitud de confirmación de la compra
A continuación, se muestra un ejemplo de 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
}
Mensaje de respuesta de confirmación de la compra
Después de recibir una solicitud del servicio de pedidos de extremo a extremo, el servicio web de confirmación de la compra debe procesarla y responder con un CheckoutResponseMessage
. El CheckoutResponseMessage
debe cubrir una solicitud correcta o no.
Solicitud correcta
Si una solicitud de confirmación de la compra se realiza correctamente, CheckoutResponseMessage
debe incluir ProposedOrder
y PaymentOptions
:
ProposedOrder
cart
: Es un objetocart
idéntico al carrito que se proporciona enCheckoutRequestMessage
. Si es necesario cambiar algún contenido del carrito,CheckoutResponseMessage
debe incluir, en cambio, unaFoodErrorExtension
con unProposedOrder
corregido.otherItems
: Elementos que agrega el proveedor, como cargos de envío, impuestos y otras tarifas. También puede contener una propina agregada por el usuario.totalPrice
: Es el precio total del pedido.extension
: Es unFoodOrderExtension
que define la información de entrega del pedido, como el tiempo de entrega.
PaymentOptions
- La configuración del procesamiento de pagos se aborda más adelante en Configura Google Pay.
Puedes usar el marcador de posición JSON en tu
CheckoutResponseMessage
hasta que estés listo para implementar el procesamiento de pagos. - Para agregar opciones de pago de marcadores de posición en tu
CheckoutResponseMessage
, consulta el ejemplo a continuación, que usa una puerta de enlace de pagos de ejemplo paraPaymentOptions
.
- La configuración del procesamiento de pagos se aborda más adelante en Configura Google Pay.
Puedes usar el marcador de posición JSON en tu
Ejemplo de respuesta correcta
{
"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": []
}
}
}
]
}
}
}
]
}
}
}
Solicitud incorrecta
Si una solicitud de confirmación de la compra no es exitosa, CheckoutResponseMessage
debe incluir FoodErrorExtension
, que contiene una lista de elementos FoodOrderError
que describen los errores que se produjeron. Si hay errores recuperables en el pedido, como un cambio de precio de un elemento en el carrito, el FoodErrorExtension
debe incluir el correctedProposedOrder
.
Ejemplo de respuesta no exitosa
{
"expectUserResponse": false,
"finalResponse": {
"richResponse": {
"items": [
{
"structuredResponse": {
"error": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension",
"foodOrderErrors": [
{
"error": "CLOSED",
"description": "The restaurant is closed."
}
]
}
}
}
]
}
}
}
Implementación en la confirmación de la compra
Se deben seguir los siguientes pasos para implementar la confirmación de la compra.
Valida el servicio
Muestra un FoodOrderError para la primera condición de error de servicio que se encuentra. Estos errores no se pueden recuperar, por lo que debería mostrarse el primer error encontrado. Consulta Manejo de errores para obtener una descripción de los errores recuperables.
- Lee la propiedad FulfillmentOptionInfo en la solicitud a fin de determinar si el tipo de entrega es para
delivery
opickup
. Muestra los siguientes tipos de errores si es necesario:
Tipo de error Caso de uso INVALID El tipo de entrega no es válido. NOT_FOUND No se encontró el tipo de entrega. CERRADA - No hay períodos de OperationHours para el pedido.
- El pedido es lo antes posible y no hay ServiceHours disponibles para este momento.
- Se produjo un cierre de emergencia o el servicio
isDisabled
es verdadero.
UNAVAILABLE_SLOT No se puede completar el pedido con antelación. NO_CAPACITY El restaurante está ocupado y no toma pedidos en este momento. OUT_OF_SERVICE_AREA El pedido no se puede entregar a la dirección del usuario. Consulta Validación de la dirección de entrega para ver un ejemplo. NO_COURIER_AVAILABLE El pedido no se puede entregar porque el personal de entrega es limitado.
Valida el carrito y ponle un precio
Busca cada Carrito.
lineItems
y valídalo con los datos actuales en tu sistema o en el sistema del comercio. El valor MenuItemOffer.sku
de la entidad del feed se incluye como LineItem.offerId
. Crea un FoodOrderError para cada línea de pedido si es necesario. Crea un máximo de un error para cada elemento. Muestra los siguientes tipos de errores si es necesario:Tipo de error Caso de uso Recuperable INVALID Los datos del artículo o cualquiera de las opciones no son válidos. No NOT_FOUND No se encontró el elemento ni ninguna de las opciones. No PRICE_CHANGED Cambió el precio de un elemento o una combinación de complementos. Este error se puede tratar como recuperable. Sí AVAILABILITY_CHANGED El importe solicitado para las líneas de pedido o cualquiera de las opciones no está disponible. Sí REQUIREMENTS_NOT_MET No se cumple el pedido máximo o mínimo del pedido. Para ello, verifica si el precio del carrito es inferior a la tarifa. eligibleTransactionVolumeMin
o superior a la tarifa.eligibleTransactionVolumeMax
Consulta el ejemplo de validación del valor mínimo de pedido.No Muestra la lista validada de elementos de una sola línea con LineItemType
REGULAR
. La suma de todos los precios de elementos de una sola línea del carrito es el precio del carrito oSUBTOTAL
.
Consulta ejemplos en validación de artículos del carrito.
Calcula los cargos del servicio
- Encuentra la entidad Tarifa correcta para el servicio según
eligibleRegion
,validFrom
,validThrough
ypriority
. - Calcula el importe de la tarifa en función de si la entidad se definió con una propiedad
price
,percentageOfCart
opricePerMeter
. - Muestra los cargos del servicio de entrega o comida para llevar como un LineItem con LineItemType
DELIVERY
oFEE
, respectivamente. Agrega la tarifa a la lista del Carrito.otherItems
Aplica promociones
- Busca la entidad Deal según la coincidencia del valor Promoción.
coupon
con el Acuerdo.dealCode
. Valida el acuerdo y muestra un FoodOrderError si es necesario. Estos errores se pueden tratar como recuperables. Muestra los siguientes tipos de errores si es necesario:
Tipo de error Caso de uso PROMO_NOT_RECOGNIZED No se reconoció el código del cupón. PROMO_EXPIRED Venció la validez del acuerdo. PROMO_ORDER_INELIGIBLE El pedido no es apto para el cupón. PROMO_NOT_APPLICABLE Cualquier otro motivo Calcula el importe del precio del acuerdo según Acuerdo.
discount
o Acuerdo.discountPercentage
Aplica el importe del precio del acuerdo con el total del carrito o el total de la tarifa según el Acuerdo.
dealType
Devuelve el carrito.
promotions
con la promoción aplicada.Muestra la promoción como un LineItem con LineItemType
DISCOUNT
. Agrega el descuento a la lista del Carrito.otherItems
con un precio negativo.
Devuelve la respuesta
- Crea el ProposedOrder.
cart
, el carrito de respuestas es el mismo que el carrito de solicitudes si no se encuentran errores durante la validación. - Muestra la lista ProposedOrder.
otherItems
, incluidos los impuestos, las tarifas, las propinas y el descuento, si se aplican. Consulta Gratuidad para obtener más detalles sobre cómo configurar el elemento de propina. - Incluye el ProposedOrder.
totalPrice
si agregas el precio del carrito, las tarifas, el descuento, los impuestos y la propina. - Muestra FoodOrderExtension.
availableFulfillmentOptions
con la FulfillmentOption respectiva. Actualiza el tiempo estimado de retiro o entrega a la hora esperada. - Si se generaron FoodOrderErrors en las verificaciones de validación anteriores, haz lo siguiente:
- Incluye StructuredResponse.
error
y la lista de errores en FoodErrorExtension.foodOrderErrors
. - Muestra ProposedOrder en el campo
correctedProposedOrder
si todos los errores se pueden recuperar. - Muestra PaymentOptions en el campo
paymentOptions
si todos los errores se pueden recuperar. - De manera opcional, puedes incluir
additionalPaymentOptions
si hay otras opciones de pago disponibles y si todos los errores se pueden recuperar.
- Incluye StructuredResponse.
- Si no hay errores de validación, muestra
proposedOrder
ypaymentOptions
en el objeto CheckoutResponse. De manera opcional, puedes incluiradditionalPaymentOptions
si hay otras opciones de pago disponibles.