Puedes agregar compatibilidad en tu entrega para que los usuarios programen pedidos de comida para retirar y entregar con anticipación. Antes de implementar esta compatibilidad en la entrega, crea un feed de inventario de servicios que especifique las horas en las que los usuarios pueden realizar pedidos anticipados, como se describe en el esquema del feed de inventario (AdvanceServiceDeliveryHoursSpecification
).
Ranuras para pedidos anticipados
Google propone horarios disponibles para pedidos en incrementos de 15 minutos, hasta 7 días antes, según los tiempos de entrega de un restaurante o servicio (como se define en AdvanceServiceDeliveryHoursSpecification
).
Para recuperar los horarios propuestos de pedido por adelantado, usa los siguientes valores del campo fulfillmentPreference
del objeto FoodCartExtension
cuando confirmes la compra:
PickupInfo.pickupTimeIso8601
DeliveryInfo.deliveryTimeIso8601
Implementa pedidos anticipados en la confirmación de la compra
En la siguiente tabla, se enumeran las posibles formas en que puedes implementar la respuesta de tu entrega en el momento de la confirmación de la compra cuando los usuarios intentan realizar pedidos.
Situación | Comportamiento de entrega |
---|---|
Se puede completar el pedido anticipado para el horario disponible. | Para aceptar el carrito de P0M ("lo antes posible") o
FUTURE_SLOT , crea un objeto ProposedOrder con el
mismo espacio. Para ver un ejemplo de una respuesta de confirmación de la compra que acepta un espacio, consulta este fragmento de código. |
No se puede completar el pedido anticipado para el horario disponible solicitado. | La entrega debe hacer lo siguiente:
Para ver un ejemplo de una respuesta de confirmación de la compra que propone ranuras alternativas, consulta este fragmento de código. |
Ranuras alternativas para la entrega de pedidos
Durante la confirmación de la compra, si el pedido por adelantado propuesto por Google no es adecuado, tu entrega puede sugerir alternativas con el objeto CheckoutResponseMessage
.
Para especificar horarios alternativos para pedidos anticipados, responde a la solicitud de confirmación de la compra con un FoodErrorExtension
y establece los siguientes valores:
- En el parámetro
foodOrderErrors
, especifica el tipo de error (comoUNAVAILABLE_SLOT
,NO_CAPACITY
oCLOSED
). - En el parámetro
correctedProposedOrder
, proporciona valores alternativos deP0M
oFUTURE_SLOT
a través deavailableFulfillmentOptions
.
Las ranuras alternativas deben ser para los próximos 7 días a partir del momento de la realización del pedido y deben incluir todas las ranuras en las que se puede entregar el carrito solicitado por el usuario.
Por ejemplo, supongamos que los especiales de almuerzo solo están disponibles de lunes a viernes, de 11 a.m. a 1 p.m. Luego, el usuario intenta agregar especiales de almuerzo a su carrito, pero el horario seleccionado no está disponible. En este caso, tu entrega debe retener los especiales de almuerzo en el carrito y devolver solo los horarios disponibles de 11 a.m. a 1 p.m. durante los siguientes 7 días.
Debes omitir el objeto correctedProposedOrder.Cart.fulfillmentPreference
en tu respuesta.
Si no hay horarios disponibles o si el restaurante o servicio no admite pedidos anticipados, no es necesario que proporciones un correctedProposedOrder
.
Consulta los siguientes ejemplos para ver los mensajes JSON entre tu entrega y Google durante la solicitud de confirmación de la compra y el flujo de respuesta de un pedido anticipado, cuando el restaurante o servicio está disponible para aceptar pedidos por adelantado.
Ejemplo: CheckoutRequest con horario disponible
En el siguiente fragmento, se muestra un ejemplo de una solicitud de confirmación de la compra con un horario disponible para la entrega de pedidos anticipados.
{
"inputs": [
{
"intent": "actions.foodordering.intent.CHECKOUT",
"arguments": [
{
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.Cart",
"merchant": {
"id": "https://www.exampleprovider.com/merchant/id1",
"name": "Cucina Venti"
},
"lineItems": [
{
"name": "Sizzling Prawns Dinner",
"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": "16",
"nanos": 750000000
}
},
}
],
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
"fulfillmentPreference": {
"fulfillmentInfo": {
"delivery": {
// Deliver at 6:30PM.
"deliveryTimeIso8601": "2017-12-14T18:30:00-07:00"
}
}
},
"location": {
...
}
}
}
}
]
}
]
}
Ejemplo: Respuesta de confirmación de la compra acepta el horario disponible
En el siguiente fragmento, se muestra un ejemplo de una respuesta de confirmación de la compra en la que tu entrega acepta los espacios para pedidos anticipados propuestos.
{
"expectUserResponse": false,
"finalResponse": {
"richResponse": {
"items": [
{
"structuredResponse": {
"checkoutResponse": {
"proposedOrder": {
"id": "sample_proposed_order_id_1",
"cart": {
"merchant": {
"id": "https://www.exampleprovider.com/merchant/id1",
"name": "Falafel Bite"
},
"lineItems": [
{
"name": "Sizzling Prawns Dinner",
"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": "16",
"nanos": 750000000
}
},
}
],
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
"fulfillmentPreference": {
"fulfillmentInfo": {
"delivery": {
// Same as the time in the request.
"deliveryTimeIso8601": "2017-12-14T18:30:00-07:00"
}
}
},
"location": {
...
}
}
},
"totalPrice": {
"type": "ESTIMATE",
"amount": {
// Represents $16.75
"currencyCode": "USD",
"units": "16",
"nanos": 750000000
}
},
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension",
// Send whole proposed order back.
"availableFulfillmentOptions": [
"fulfillmentInfo": {
"delivery": {
// Same as the time in the request.
"deliveryTimeIso8601": "2017-12-14T18:30:00-07:00"
}
}
]
}
},
"paymentOptions": {
...
}
}
}
}
]
}
}
}
Ejemplo: CheckoutResponse con ranuras alternativas
En el siguiente fragmento, se muestra un ejemplo de una respuesta de confirmación de la compra en la que tu entrega propone ranuras para pedidos anticipados alternativas. Ten en cuenta que el objeto correctedProposedOrder.Cart.fulfillmentPreference
debe omitirse en tu respuesta.
{
"expectUserResponse": false,
"finalResponse": {
"richResponse": {
"items": [
{
"structuredResponse": {
"error": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension",
"foodOrderErrors": [
{
"error": "UNAVAILABLE_SLOT", // Cart level error
"description": "The restaurant is closed."
}
],
"correctedProposedOrder": {
// Send whole original cart back,
// without the fulfillmentPreference.
"cart": {
...
},
"otherItems": {
...
},
"totalPrice": {
...
},
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension",
"availableFulfillmentOptions": [
"fulfillmentInfo": {
"delivery": {
"deliveryTimeIso8601": "2017-12-14T19:00:00-07:00"
}
},
"fulfillmentInfo": {
"delivery": {
"deliveryTimeIso8601": "2017-12-14T19:30:00-07:00"
}
},
"fulfillmentInfo": {
"delivery": {
"deliveryTimeIso8601": "2017-12-14T20:00:00-07:00"
}
}
]
}
},
"paymentOptions": {
...
}
}
}
}
]
}
}
}
Implementa pedidos anticipados en el momento de envío
Cuando se envía un pedido, si hay un problema con los horarios disponibles del pedido anticipado, tu SubmitOrderResponseMessage
debe incluir el motivo (como UNAVAILABLE_SLOT
o UNKNOWN
) en el objeto RejectionInfo
.
Actualiza el estado del pedido de CREATED
a CONFIRMED
en el objeto OrderState
cuando el proveedor acepte el pedido. Incluye el horario seleccionado en el correo electrónico de confirmación que enviarás al usuario.
Si tu entrega envía el pedido al restaurante más tarde, envía una actualización a Google con la acción de actualización de pedido asíncrona.
En el objeto OrderUpdate
de la respuesta de pedido de envío de tu entrega o de las actualizaciones de pedido asíncronas posteriores, incluye un estimatedFulfillmentTimeIso8601
con el valor establecido de la siguiente manera:
- Cuando el estado del pedido sea
CREATED
oCONFIRMED
, establece el valor en la hora de entrega o retiro que el usuario programó para su pedido anticipado. - Cuando haya un tiempo de entrega estimado más preciso del restaurante o servicio, establece el valor en la hora estimada de entrega o retiro.
Ejemplo: SubmitOrderRequest con el horario disponible para la entrega
En el siguiente fragmento, se muestra un ejemplo de una solicitud de envío de pedido que indica el horario disponible que seleccionó el usuario.
{
"inputs": [
{
"intent": "actions.intent.TRANSACTION_DECISION",
"arguments": [
{
"transactionDecisionValue": {
"order": {
"finalOrder": {
"cart": {
"notes": "Guest prefers their food to be hot when it is delivered.",
"merchant": {
"id": "https://www.exampleprovider.com/merchant/id1",
"name": "Cucina Venti"
},
"lineItems": [
{
"name": "Sizzling Prawns Dinner",
"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": "16",
"nanos": 750000000
}
}
}
],
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
"fulfillmentPreference": {
"fulfillmentInfo": {
"delivery": {
"deliveryTimeIso8601": "2017-12-14T18:30:00-07:00"
}
}
}
"contact": {
...
}
}
},
"totalPrice": {
"type": "ESTIMATE",
"amount": {
"currencyCode": "USD",
"units": "16",
"nanos": 750000000
}
},
"id": "sample_final_order_id",
"extension": {
// Send whole proposed order back.
"availableFulfillmentOptions": [
"fulfillmentInfo": {
"delivery": {
"deliveryTimeIso8601": "2017-12-14T18:30:00-07:00"
}
]
}
},
"googleOrderId": "sample_google_order_id",
"orderDate": "2017-07-17T12:00:00Z",
"paymentInfo": {
...
}
}
}
}
]
}
]
}
Ejemplo: SubmitOrderResponse que acepta el pedido
En el siguiente fragmento, se muestra un ejemplo de una respuesta de pedido de envío en la que tu entrega confirma que aceptó el pedido por adelantado del usuario.
{
"expectUserResponse": false,
"finalResponse": {
"richResponse": {
"items": [
{
"structuredResponse": {
"orderUpdate": {
"actionOrderId": "sample_action_order_id",
"orderState": {
"state": "CREATED",
"label": "Order placed"
},
"receipt": {
"userVisibleOrderId": "userVisibleId1234"
},
"updateTime": "2017-07-17T12:00:00Z",
"orderManagementActions": [
...
],
"infoExtension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension",
// Same as the user selected time.
"estimatedFulfillmentTimeIso8601": "2017-12-14T18:30:00-07:00"
}
}
}
}
]
}
}
}
Ejemplo: SubmitOrderResponse rechaza el pedido debido a que el horario disponible no está disponible
En el siguiente fragmento, se muestra un ejemplo de una respuesta de pedido de envío en la que tu entrega rechaza el pedido anticipado de un usuario debido a un horario disponible.
{
"expectUserResponse": false,
"finalResponse": {
"richResponse": {
"items": [
{
"structuredResponse": {
"orderUpdate": {
"actionOrderId": "sample_action_order_id",
"orderState": {
"state": "REJECTED",
"label": "Unavailable slot"
},
"rejectionInfo": {
// Note that this UNAVAILABLE_SLOT is different from the enum
// with the same name proposed for FoodOrderError.
"state": "UNAVAILABLE_SLOT",
"label": "Unavailable slot"
},
"updateTime": "2017-07-17T12:00:00Z",
"orderManagementActions": [
...
]
}
}
}
]
}
}
}
Ejemplos de pedidos anticipados
El tipo AdvanceServiceDeliveryHoursSpecification
se puede usar para especificar las horas de entrega o retiro a fin de que los usuarios programen su pedido con anticipación.
Nota: Hay dos períodos separados que debes especificar para la entrega del servicio: el período de pedido, que especifica cuándo los usuarios pueden realizar un pedido, y el período de entrega, que especifica cuándo se debe entregar el pedido. El objeto
define cuándo el usuario puede realizar el pedido. Sus tiempos de entrega secundarios (OpeningHoursSpecification
o ServiceDeliveryHoursSpecification
) definen cuándo se puede entregar el pedido.AdvanceServiceDeliveryHoursSpecification
En el siguiente ejemplo, se definen las horas de un servicio para aceptar pedidos por adelantado, con intervalos de servicio de 15 minutos.
{ "hoursAvailable": [ { "@type": "OpeningHoursSpecification", "opens": "T00:00:00", // Ordering available 24 hours "closes": "T23:59:59", "deliveryHours": [ { "@type": "ServiceDeliveryHoursSpecification", "opens": "T09:00:00", // ASAP orders b/w 9am and 8:59:59pm "closes": "T21:00:00", "deliveryLeadTime": { "value": "60", "unitCode": "MIN" } }, { "@type": "AdvanceServiceDeliveryHoursSpecification", "opens": "T10:00:00", // Delivery between 10AM and 7:59:59PM "closes": "T20:00:00", "serviceTimeInterval": "PT15M", // in slots spaced 15 minutes apart (ISO8601) "advanceBookingRequirement": { "minValue": 60, // The slot should be at least 60 mins away "maxValue": 8640, // but not more than 6 days away "unitCode": "MIN" } } ] } ] }
En el siguiente ejemplo, se muestra cómo podrías especificar que el servicio está abierto para pedidos el mismo día el día de Navidad, pero cerrado para pedidos avanzados programados para ese día. En este ejemplo, se admiten las siguientes situaciones:
- Los usuarios pueden hacer un pedido el 25 de diciembre con entrega en el mismo día.
- Los usuarios pueden hacer un pedido por adelantado el 25 de diciembre con la entrega programada para el 27 de diciembre.
- Los usuarios no pueden hacer un pedido por adelantado el 22 de diciembre para la entrega programada para el 25 de diciembre.
{ "specialOpeningHoursSpecification": { "@type": "AdvanceServiceDeliveryHoursSpecification", "validFrom": "2018-12-25T00:00:00-07:00", "validThrough": "2018-12-26T00:00:00-07:00", "opens": "T00:00:00", // No advance ordering "closes": "T00:00:00" } }
En el siguiente ejemplo, se muestra cómo especificar que el servicio está cerrado para pedidos el mismo día o pedidos anticipados programados para Navidad, pero abierto para pedidos avanzados programados para un día posterior. En este ejemplo, se admiten las siguientes situaciones:
- Los usuarios no pueden hacer un pedido el 25 de diciembre para la entrega el mismo día.
- Los usuarios pueden hacer un pedido por adelantado el 25 de diciembre con la entrega programada para el 27 de diciembre.
- Los usuarios no pueden hacer un pedido por adelantado el 22 de diciembre para la entrega programada para el 25 de diciembre.
{ "specialOpeningHoursSpecification": [ { "@type": "ServiceDeliveryHoursSpecification", "validFrom": "2018-12-25T00:00:00-07:00", "validThrough": "2018-12-26T00:00:00-07:00", "opens": "T00:00:00", // No ASAP ordering on Christmas "closes": "T00:00:00" }, { "@type": "AdvanceServiceDeliveryHoursSpecification", "validFrom": "2018-12-25T00:00:00-07:00", "validThrough": "2018-12-26T00:00:00-07:00", "opens": "T00:00:00", // Orders cannot be scheduled for Christmas "closes": "T00:00:00" } ] }
El siguiente servicio de muestra acepta pedidos las 24 horas, todos los días, con entregas de 10:00 a.m. a 2:59:59 p.m. los días de semana:
... { "@type": "OpeningHoursSpecification", "opens": "T00:00:00", "closes": "T23:59:59", "deliveryHours": { "@type": "AdvanceServiceDeliveryHoursSpecification", "opens": "T10:00:00", // Delivery starts at 10:00AM "closes": "T15:00:00", // Delivery ends at 3:00PM. Delivery from 10AM-2:59:59PM. "dayOfWeek": [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" ], "serviceTimeInterval": "PT15M", // in slots spaced 15 minutes apart "advanceBookingRequirement": { "minValue": 60, // The slot should be at least 60 mins away "maxValue": 8640, // but not more than 6 days away "unitCode": "MIN" } } } ...
El siguiente servicio de muestra acepta pedidos todos los días de 8:00 a.m. a 4:59:59 p.m., y los clientes pueden optar por una entrega dentro de una hora o elegir uno de los horarios disponibles:
... { "@type": "OpeningHoursSpecification", "opens": "T08:00:00", // Ordering opens at 8:00AM "closes": "T17:00:00", // Ordering closes at 5:00PM, last order at 4:59:59PM "deliveryHours": [ { "@type": "ServiceDeliveryHoursSpecification", "opens": "T08:00:00", "closes": "T17:00:00", "deliveryLeadTime": { "@type": "QuantitativeValue", "value": "60", // If no exact deliveryLeadTime, put a maximum time "unitCode": "MIN" } }, { "@type": "AdvanceServiceDeliveryHoursSpecification", "opens": "T08:00:00", "closes": "T17:00:00", "serviceTimeInterval": "PT15M", // in slots spaced 15 minutes apart "advanceBookingRequirement": { "minValue": 90, // The slot should be at least 90 mins away "maxValue": 8640, // but not more than 6 days away "unitCode": "MIN" } } ] } ...
En el siguiente ejemplo, se muestra un caso en el que la tienda abre de 8:00 a.m. a 4:59:59 p.m. los días de semana, pero de 8:00 a.m. a 6:59 p.m. los fines de semana. No se aceptan pedidos las 24 horas, todos los días.
... { // On weekdays, ordering open from 8AM-4:59:59PM. "@type": "OpeningHoursSpecification", "opens": "T08:00:00", "closes": "T17:00:00", "dayOfWeek": [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" ], "deliveryHours": [ { // Fulfillment between 8AM-4:59:59PM on weekdays. "@type": "AdvanceServiceDeliveryHoursSpecification", "opens": "T08:00:00", "closes": "T17:00:00", "dayOfWeek": [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" ], "serviceTimeInterval": "PT15M", "advanceBookingRequirement": { "minValue": 60, "maxValue": 8640, "unitCode": "MIN" } }, { // Fulfillment between 8AM-6:59:59PM on weekends (even for orders placed on a // weekday). "@type": "AdvanceServiceDeliveryHoursSpecification", "opens": "T08:00:00", "closes": "T19:00:00", "dayOfWeek": [ "Saturday", "Sunday" ], "serviceTimeInterval": "PT15M", "advanceBookingRequirement": { "minValue": 60, "maxValue": 8640, "unitCode": "MIN" } } ] }, { // On weekends, one can place orders upto 6:59:59PM. "@type": "OpeningHoursSpecification", "opens": "T08:00:00", "closes": "T19:00:00", "dayOfWeek": [ "Saturday", "Sunday" ], "deliveryHours": [ { // But fulfillment on weekdays is only till 4:59:59PM. "@type": "AdvanceServiceDeliveryHoursSpecification", "opens": "T08:00:00", "closes": "T17:00:00", "dayOfWeek": [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" ], "serviceTimeInterval": "PT15M", "advanceBookingRequirement": { "minValue": 60, "maxValue": 8640, "unitCode": "MIN" } }, { // Fulfillment on weekends is till 6:59:59PM. "@type": "AdvanceServiceDeliveryHoursSpecification", "opens": "T08:00:00", "closes": "T19:00:00", "dayOfWeek": [ "Saturday", "Sunday" ], "serviceTimeInterval": "PT15M", "advanceBookingRequirement": { "minValue": 60, "maxValue": 8640, "unitCode": "MIN" } } ] } ...