Você pode adicionar suporte à sua entrega para que os usuários programem a retirada e
a entrega de pedidos de comida com antecedência. Antes de implementar esse suporte no
atendimento, crie um feed de inventário de serviço que especifique os horários em que os usuários
podem fazer pedidos antecipados, conforme descrito no esquema do feed de inventário
(AdvanceServiceDeliveryHoursSpecification
).
Horários de pedidos antecipados
O Google propõe horários de pedidos antecipados em incrementos de 15 minutos, com até sete dias
de antecedência, com base nos tempos de atendimento de um restaurante ou serviço (conforme definido em
AdvanceServiceDeliveryHoursSpecification
).
Para recuperar os horários de agendamento de pedidos antecipados propostos, use os seguintes valores do campo fulfillmentPreference
do objeto FoodCartExtension
na finalização da compra:
PickupInfo.pickupTimeIso8601
DeliveryInfo.deliveryTimeIso8601
Implementar pedidos antecipados na finalização da compra
A tabela abaixo lista as maneiras possíveis de implementar a resposta da sua conclusão no momento do pagamento quando os usuários tentam fazer pedidos.
Cenário | Comportamento de fulfillment |
---|---|
O pedido antecipado pode ser atendido no horário solicitado. | Aceite o P0M ("assim que possível") ou
o carrinho FUTURE_SLOT criando um ProposedOrder com o
mesmo slot. Para conferir um exemplo de uma resposta de finalização de compra que aceita um slot, consulte
este snippet de código. |
O pedido antecipado não pode ser atendido no horário solicitado. | Sua entrega precisa fazer o seguinte:
Para conferir um exemplo de resposta de finalização de compra que propõe horários alternativos, consulte este snippet de código. |
Horários alternativos para atendimento do pedido
Na finalização da compra, se os horários de pedido antecipado propostos pelo Google não forem adequados, o
atendimento poderá sugerir alternativas usando o objeto
CheckoutResponseMessage
.
Para especificar horários de reserva antecipada alternativos, responda à solicitação de finalização de compra com um
FoodErrorExtension
e defina os seguintes valores:
- No parâmetro
foodOrderErrors
, especifique o tipo de erro (comoUNAVAILABLE_SLOT
,NO_CAPACITY
ouCLOSED
). - No parâmetro
correctedProposedOrder
, forneça valores alternativos deP0M
ouFUTURE_SLOT
usandoavailableFulfillmentOptions
.
Os slots alternativos devem ser para os próximos sete dias a partir do momento do pedido e incluir todos os slots em que o carrinho solicitado pelo usuário pode ser atendido.
Por exemplo, digamos que os pratos do dia só estão disponíveis de segunda a sexta-feira, das 11h às 13h. O usuário tenta adicionar itens especiais de almoço ao carrinho, mas o horário selecionado não está disponível. Nesse caso, o atendimento precisa manter os itens especiais de almoço no carrinho e retornar apenas os horários de 11h às 13h nos próximos sete dias.
O objeto correctedProposedOrder.Cart.fulfillmentPreference
precisa ser omitido
na resposta.
Se não houver horários disponíveis ou se o restaurante ou serviço não
aceitar pedidos antecipados, não será necessário fornecer um
correctedProposedOrder
.
Confira os exemplos abaixo das mensagens JSON entre seu fulfillment e o Google durante o fluxo de solicitação e resposta de finalização de compra de um pedido antecipado, quando o restaurante ou serviço está disponível para receber encomendas antecipadas.
Exemplo: CheckoutRequest com slot de entrega
O snippet abaixo mostra um exemplo de uma solicitação de finalização de compra com um horário de entrega de pedido antecipado.
{
"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": {
...
}
}
}
}
]
}
]
}
Exemplo: CheckoutResponse aceitando o slot
O snippet abaixo mostra um exemplo de resposta de finalização de compra em que a entrega aceita os horários de pedidos antecipados propostos.
{
"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": {
...
}
}
}
}
]
}
}
}
Exemplo: CheckoutResponse com slots alternativos
O snippet abaixo mostra um exemplo de resposta de finalização de compra em que a fulfillment
propõe horários alternativos de pedidos antecipados. O objeto
correctedProposedOrder.Cart.fulfillmentPreference
precisa ser omitido na
resposta.
{
"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": {
...
}
}
}
}
]
}
}
}
Implementar pedidos antecipados ao enviar o pedido
No envio do pedido, se houver um problema com os horários de reserva antecipada, o
SubmitOrderResponseMessage
precisará incluir o motivo (como
UNAVAILABLE_SLOT
ou UNKNOWN
) no objeto RejectionInfo
.
Atualize o estado do pedido de CREATED
para CONFIRMED
no
objeto OrderState
quando o pedido for aceito pelo provedor. Inclua o
horário selecionado no e-mail de confirmação enviado ao usuário.
Se o fulfillment enviar o pedido ao restaurante mais tarde, envie uma atualização ao Google usando a ação de atualização de pedido assíncrono.
No objeto OrderUpdate
da resposta de envio de pedido do fulfillment ou
nas atualizações assíncronas subsequentes do pedido, inclua um
estimatedFulfillmentTimeIso8601
com o valor definido da seguinte maneira:
- Quando o status do pedido for
CREATED
ouCONFIRMED
, defina o valor como o horário de entrega ou retirada que o usuário programou para o pedido antecipado. - Quando houver um tempo de entrega estimado mais preciso do restaurante ou serviço, defina o valor como o tempo estimado de entrega ou retirada.
Exemplo: enviar uma solicitação de pedido com horário de entrega
O snippet abaixo mostra um exemplo de solicitação de envio de pedido indicando o horário de pedido antecipado que o usuário selecionou.
{
"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": {
...
}
}
}
}
]
}
]
}
Exemplo: SubmitOrderResponse aceitando o pedido
O snippet abaixo mostra um exemplo de resposta de envio de pedido em que o atendimento confirma que aceitou o pedido antecipado do usuário.
{
"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"
}
}
}
}
]
}
}
}
Exemplo: SubmitOrderResponse recusando o pedido devido à indisponibilidade de slot
O snippet abaixo mostra um exemplo de uma resposta de envio de pedido em que o atendimento recusa o pedido antecipado de um usuário devido a um horário indisponível.
{
"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": [
...
]
}
}
}
]
}
}
}
Exemplos de pedidos antecipados
O tipo AdvanceServiceDeliveryHoursSpecification
pode ser usado para especificar
os horários de entrega ou retirada para que os usuários programem o pedido com antecedência.
Observação : há duas janelas de tempo separadas que precisam ser especificadas
para a realização do serviço: a janela de pedidos, que especifica quando os usuários podem fazer um
pedido, e a janela de fulfillment, que especifica quando o pedido é realizado. O
objeto
define quando o usuário
pode fazer o pedido. Os tempos de atendimento das crianças (OpeningHoursSpecification
ou ServiceDeliveryHoursSpecification
) definem quando o pedido pode ser
cumprido.AdvanceServiceDeliveryHoursSpecification
O exemplo a seguir define os horários de um serviço para aceitar pedidos antecipados, com intervalos 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" } } ] } ] }
O exemplo a seguir mostra como especificar que o serviço está aberto para pedidos no mesmo dia no Natal, mas fechado para pedidos avançados programados para esse dia. Este exemplo é compatível com os seguintes cenários:
- Os usuários podem fazer um pedido em 25 de dezembro para entrega no mesmo dia.
- Os usuários podem fazer um pedido antecipado em 25 de dezembro para entrega programada em 27 de dezembro.
- Os usuários não podem fazer um pedido antecipado em 22 de dezembro para entrega programada em 25 de dezembro.
{ "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" } }
O exemplo a seguir mostra como especificar que o serviço está fechado para pedidos no mesmo dia ou pedidos antecipados programados para o dia de Natal, mas aberto para pedidos antecipados programados para um dia posterior. Este exemplo oferece suporte aos seguintes cenários:
- Os usuários não podem fazer um pedido em 25 de dezembro para entrega no mesmo dia.
- Os usuários podem fazer um pedido antecipado em 25 de dezembro para entrega programada em 27 de dezembro.
- Os usuários não podem fazer um pedido antecipado em 22 de dezembro para entrega programada em 25 de dezembro.
{ "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" } ] }
O exemplo de serviço a seguir aceita pedidos 24 horas por dia e faz entregas das 10h às 16h59 (horário local) nos dias úteis:
... { "@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" } } } ...
O exemplo de serviço a seguir aceita pedidos todos os dias das 8h às 16h59, e os clientes podem optar por uma entrega em até uma hora ou escolher um dos horários:
... { "@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" } } ] } ...
O exemplo a seguir mostra um caso em que a loja abre das 8h às 16h59:59 nos dias úteis, mas das 8h às 18h59 nos fins de semana. Pedidos não são aceitos 24 horas por dia, sete dias por semana.
... { // 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" } } ] } ...