Depois que um cliente envia um pedido de comida, você pode enviar uma mensagem de atualização de pedido para o serviço de pedidos de ponta a ponta para nos notificar sobre a alteração.
Confira alguns motivos comuns para enviar atualizações de pedidos:
- O tempo estimado de atendimento do pedido fica disponível ou muda.
- O estado de um pedido muda.
- Não é mais possível atender o pedido.
- O preço de um item do menu incluído no pedido mudou.
- O cliente tem uma nova maneira de gerenciar o pedido, como um número de telefone de restaurante ou de suporte ao cliente.
- O recibo do pedido fica disponível.
As próximas seções fornecem detalhes sobre como resolver esses diferentes cenários usando atualizações de pedidos.
Estados de transição do pedido
Um pedido tem seis estados possíveis. Esses estados e as possíveis transições são descritos no diagrama a seguir:
Quando um cliente envia um pedido pela primeira vez, ele começa com um estado de
CREATED
, CONFIRMED
ou REJECTED
. Você pode enviar uma mensagem de atualização de pedido para
atualizar o estado de um pedido, desde que a transição de estado seja válida. O estado CREATED
é usado quando a plataforma do parceiro não pode confirmar ou rejeitar o pedido
imediatamente. Um exemplo de caso de uso é quando um cliente faz um pedido por um agregador
de entregas. O agregador de entregas recebe a entrega do Google e envia as informações ao restaurante. Depois que o restaurante receber
e confirmar a disponibilidade do pedido, o estado poderá ser CONFIRMED
. Caso contrário, será
REJECTED
.
Um pedido no estado CONFIRMED
passa para o estado IN_PREPARATION
. Dependendo se o pedido é para retirada ou entrega, use o estado READY_FOR_PICKUP
ou IN_TRANSIT
. Quando a comida é entregue ou retirada, o pedido é definido como o estado FULFILLED
.
Se você permitir que os clientes cancelem pedidos, use o estado CANCELLED
. Um pedido pode ser cancelado enquanto estiver no estado CREATED
, CONFIRMED
, IN_PREPARATION
, READY_FOR_PICKUP
ou IN_TRANSIT
.
O serviço de atendimento completo de pedidos precisa emitir reembolsos de acordo com sua
política de cancelamento e o estado dos pagamentos no momento do cancelamento.
O serviço de pedidos de ponta a ponta não precisa oferecer suporte a todos os estados e transições
disponíveis. No entanto, o estado final do pedido precisa ser FULFILLED
,
REJECTED
ou CANCELLED
.
Como informar um tempo de atendimento estimado
Você pode informar aos usuários um intervalo de tempo estimado para quando o pedido estará
pronto para retirada (ou entrega). Use o campo estimatedFulfillmentTimeIso8601
de FoodOrderUpdateExtension
para fornecer um intervalo de tempo estimado para quando o
pedido de um cliente estará pronto para retirada ou entregue.
Envie o estimatedFulfillmentTimeIso8601
nos seguintes horários:
- Quando o tempo estimado estiver disponível, idealmente no estado
CREATED
ouCONFIRMED
do pedido. - Quando o tempo estimado muda, como atualizar o tempo estimado para ser
mais preciso quando o pedido é
IN_TRANSIT
.
Para gerenciar as expectativas dos usuários de maneira eficaz, seja conservador nas estimativas e forneça um período de datas e horários em vez de uma data e um horário fixos. É preciso considerar variações, como condições de trânsito, sempre que possível. Por exemplo, é possível enviar uma estimativa de 12h45 (limite inferior) a 13h15 (limite superior) para um pedido em que o tempo de entrega estimado é 13h.
Como realizar ações de gerenciamento de pedidos
Ao enviar uma atualização de pedido, você pode fornecer recursos aos clientes que os ajudam
a gerenciar o pedido na forma de um OrderManagementAction
. Depois que um
cliente faz um pedido, ele pode precisar entrar em contato com você ou com o restaurante
que está realizando o pedido para acompanhar o progresso, fazer alterações ou cancelar o pedido.
Um OrderManagementAction
permite que os clientes enviem e-mails, liguem ou vinculem a um
URL diretamente do dispositivo. Use as mesmas informações em
OrderManagementAction
que no e-mail de confirmação do pedido enviado ao
usuário.
As ações de gerenciamento de pedidos incluem os seguintes tipos:
CUSTOMER_SERVICE
: oferecer aos clientes uma ação para entrar em contato com o atendimento ao cliente. Esse tipo de ação de gerenciamento é obrigatório para atualizações de pedidos.EMAIL
: oferecer aos clientes uma ação para enviar um e-mail para o endereço fornecido.CALL
: oferecer aos clientes uma ação para ligar para o número de telefone fornecido.VIEW_DETAIL
: ofereça aos clientes uma ação para conferir os detalhes do pedido.
Cada atualização de pedido precisa conter pelo menos uma ação de gerenciamento de pedidos. No entanto,
as ações de gerenciamento de pedidos fornecidas podem variar de acordo com o estado do pedido.
Por exemplo, quando um pedido está no estado CONFIRMED
, a ação CUSTOMER_SERVICE
pode apontar para o número de telefone do seu atendimento ao cliente. Quando o estado do pedido
é atualizado para IN_TRANSIT
, a ação CUSTOMER_SERVICE
pode apontar para o
número de telefone do restaurante de atendimento.
Como enviar atualizações de pedidos
Você usa o tipo de mensagem AsyncOrderUpdateRequestMessage
para enviar uma atualização
de pedido ao serviço de pedidos de ponta a ponta. O Google responde com um
AsyncOrderUpdateResponseMessage
. Por exemplo, se você quiser informar a um
cliente que o pedido foi validado e aceito, envie um
AsyncOrderUpdateRequestMessage
para mudar o estado do pedido para CONFIRMED
com o rótulo Accepted by restaurant
.
Como definir a mensagem de atualização do pedido
Ao enviar uma AsyncOrderUpdateRequestMessage
ao Google, é necessário incluir
informações sobre o estado do pedido usando o campo OrderUpdate
.
Os exemplos a seguir mostram um AsyncOrderUpdateRequestMessage
de exemplo para
cada estado de pedido:
CONFIRMADO
Este exemplo mostra uma solicitação de atualização de pedido que notifica o usuário de que o pedido foi confirmado com um recibo e um tempo de entrega estimado.
{ "isInSandbox": true, "customPushMessage": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "CONFIRMED", "label": "Provider confirmed" }, "receipt": { "userVisibleOrderId": "userVisibleId1234" }, "updateTime": "2017-07-17T12:00:00Z", "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_RESTAURANT", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "CALL_DRIVER", "button": { "title": "Call driver", "openUrlAction": { "url": "tel:+16505554681" } } } ], "infoExtension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension", "estimatedFulfillmentTimeIso8601": "2017-07-17T13:00:00Z/2017-07-17T13:30:00Z" } } } }
REJEITADO
Este exemplo mostra uma solicitação de atualização de pedido que notifica o usuário de que o pedido foi rejeitado com um motivo de rejeição.
{ "isInSandbox": true, "customPushMessage": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "REJECTED", "label": "Order rejected" }, "updateTime": "2017-05-10T02:30:00.000Z", "rejectionInfo": { "type": "UNKNOWN", "reason": "Sorry, the restaurant cannot take your order right now." }, "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_RESTAURANT", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "CALL_DRIVER", "button": { "title": "Call driver", "openUrlAction": { "url": "tel:+16505554681" } } } ], "infoExtension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension", "foodOrderErrors": [ { "error": "NO_CAPACITY", "description": "Sorry, the restaurant cannot take your order right now." } ] } } } }
CANCELADO
Este exemplo mostra uma solicitação de atualização de pedido que notifica o usuário de que o pedido foi cancelado com um motivo de cancelamento.
{ "isInSandbox": true, "customPushMessage": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "CANCELLED", "label": "Order cancelled" }, "updateTime": "2017-05-10T02:30:00.000Z", "cancellationInfo": { "reason": "Customer requested" }, "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_RESTAURANT", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "CALL_DRIVER", "button": { "title": "Call driver", "openUrlAction": { "url": "tel:+16505554681" } } } ] } } }
IN_PREPARATION
Este exemplo mostra um pedido de atualização de pedido que notifica o usuário de que a comida está sendo preparada.
{ "isInSandbox":true, "customPushMessage":{ "orderUpdate":{ "actionOrderId":"sample_action_order_id", "orderState":{ "state":"IN_PREPARATION", "label":"Order is being prepared" }, "receipt": { "userVisibleOrderId": "userVisibleId1234" }, "updateTime":"2018-04-15T11:30:00Z", "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_RESTAURANT", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "CALL_DRIVER", "button": { "title": "Call driver", "openUrlAction": { "url": "tel:+16505554681" } } } ], "infoExtension":{ "@type":"type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension", "estimatedFulfillmentTimeIso8601":"PT20M" } } } }
READY_FOR_PICKUP
Este exemplo mostra um pedido de atualização de pedido que notifica o usuário de que a comida está pronta para retirada.
{ "isInSandbox": true, "customPushMessage": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "READY_FOR_PICKUP", "label": "Order is ready for pickup" }, "receipt": { "userVisibleOrderId": "userVisibleId1234" }, "updateTime": "2018-04-15T12:00:00Z", "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_RESTAURANT", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "CALL_DRIVER", "button": { "title": "Call driver", "openUrlAction": { "url": "tel:+16505554681" } } } ], "infoExtension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension", "estimatedFulfillmentTimeIso8601": "PT20M" } } } }
IN_TRANSIT
Este exemplo mostra uma solicitação de atualização de pedido que notifica o usuário de que o pedido está em trânsito com um tempo de entrega estimado.
{ "isInSandbox": true, "customPushMessage": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "IN_TRANSIT", "label": "Order is on the way" }, "inTransitInfo": { "updatedTime": "2017-07-17T12:00:00Z" }, "updateTime": "2017-07-17T12:00:00Z", "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_RESTAURANT", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "CALL_DRIVER", "button": { "title": "Call driver", "openUrlAction": { "url": "tel:+16505554681" } } } ], "infoExtension": { "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension", "estimatedFulfillmentTimeIso8601": "PT20M" } } } }
FULFILLED
Este exemplo mostra um pedido de atualização de exemplo que notifica o usuário de que o pedido foi retirado ou entregue:
{ "isInSandbox": true, "customPushMessage": { "orderUpdate": { "actionOrderId": "sample_action_order_id", "orderState": { "state": "FULFILLED", "label": "Order delivered" }, "updateTime": "2017-05-10T02:30:00.000Z", "fulfillmentInfo": { "deliveryTime": "2017-05-10T02:30:00.000Z" }, "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_RESTAURANT", "button": { "title": "Call restaurant", "openUrlAction": { "url": "tel:+16505554679" } } }, { "type": "CALL_DRIVER", "button": { "title": "Call driver", "openUrlAction": { "url": "tel:+16505554681" } } } ] } } }
Para mais exemplos de solicitações de atualização de pedidos em diferentes casos de uso, leia Implementar atualizações avançadas de pedidos.
Gerar token de autorização e enviar a mensagem
As atualizações de pedidos exigem um token de autorização para que o serviço de pedidos de ponta a ponta possa verificar se a mensagem é do seu serviço da Web de pedidos de ponta a ponta.
Para implementar atualizações de pedidos no seu projeto, siga estas etapas:
- Para gerar um token de autorização, siga estas etapas:
- Use a Biblioteca Auth do Google para ler as credenciais do arquivo da conta de serviço.
- Solicite o token usando o seguinte escopo da API:
https://www.googleapis.com/auth/actions.fulfillment.conversation
- Use esse token para enviar uma solicitação POST HTTP autenticada para o
seguinte endpoint:
https://actions.googleapis.com/v2/conversations:send
- Defina o cabeçalho
Content-Type
comoapplication/json
como parte da solicitação.
Os exemplos a seguir demonstram como implementar atualizações de pedidos:
Node.js
Este código usa a biblioteca de autenticação do Google para Node.js.
const {auth} = require('google-auth-library') const request = require('request'); // The service account client secret file downloaded from the Google Cloud Console const serviceAccountJson = require('./service-account.json') // order-update.json is a file that contains the payload const jsonBody = require('./order-update.json') /** * Get the authorization token using a service account. */ async function getAuthToken() { let client = auth.fromJSON(serviceAccountJson) client.scopes = ['https://www.googleapis.com/auth/actions.fulfillment.conversation'] const tokens = await client.authorize() return tokens.access_token; } /** * Send an order update request */ async function sendOrderUpdate() { const token = await getAuthToken() request.post({ headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, url: 'https://actions.googleapis.com/v2/conversations:send', body: jsonBody, json: true }, (err, res, body) => { if (err) { return console.log(err); } console.log(`Response: ${JSON.stringify(res)}`) }) }
Python
Esse código usa a biblioteca de autenticação do Google para Python.
from google.oauth2 import service_account from google.auth.transport.requests import AuthorizedSession import json # service-account.json is the service account client secret file downloaded from the # Google Cloud Console credentials = service_account.Credentials.from_service_account_file( 'service-account.json') scoped_credentials = credentials.with_scopes( ['https://www.googleapis.com/auth/actions.fulfillment.conversation']) authed_session = AuthorizedSession(scoped_credentials) # order-update.json is a file that contains the payload json_payload=json.load(open('order-update.json')) response = authed_session.post( 'https://actions.googleapis.com/v2/conversations:send', json=json_payload)
Java
Esse código usa a biblioteca de autenticação do Google para Java.
/** * Get the authorization token using a service account. */ private static String getAuthToken() { InputStream serviceAccountFile = Example.class.getClassLoader().getResourceAsStream("service-account.json"); ServiceAccountCredentials.Builder credentialsSimpleBuilder = ServiceAccountCredentials.fromStream(serviceAccountFile).toBuilder(); credentialsSimpleBuilder.setScopes(ImmutableList.of("https://www.googleapis.com/auth/actions.fulfillment.conversation")); AccessToken accessToken = credentialsSimpleBuilder.build().refreshAccessToken(); return accessToken.getTokenValue(); } /** * Send an order update request */ public void sendOrderUpdate() { String authToken = getAuthToken(); // Execute POST request executePostRequest("https://actions.googleapis.com/v2/conversations:send", authToken, "update_order_example.json",); }
Para atualizações de pedidos bem-sucedidas sem erros, o Google retorna uma resposta HTTP 200 com um payload vazio. Se houver um problema, como a atualização estar com formato incorreto, o Google vai retornar um erro.