Dopo che un cliente ha inviato un ordine di cibo, puoi inviare un messaggio di aggiornamento dell'ordine al servizio Ordina con Google per informarci della modifica.
Ecco alcuni motivi comuni per l'invio degli aggiornamenti relativi agli ordini:
- Il tempo di evasione stimato per l'ordine diventa disponibile o cambia.
- Lo stato di un ordine cambia.
- L'ordine non può più essere evaso.
- Il prezzo di una voce di menu inclusa nell'ordine è cambiato.
- Il cliente ha un nuovo modo di gestire l'ordine, ad esempio l'assistenza clienti o il numero di telefono del ristorante.
- La ricevuta dell'ordine diventa disponibile.
Le sezioni successive forniscono dettagli su come affrontare questi diversi scenari utilizzando gli aggiornamenti degli ordini.
Stati di esecuzione della transizione
Un ordine può avere sei stati. Questi stati e le possibili transizioni sono descritti nel seguente diagramma:
Quando un cliente invia un ordine per la prima volta, l'ordine inizia con lo stato CREATED
, CONFIRMED
o REJECTED
. Puoi inviare un messaggio di aggiornamento dell'ordine per aggiornare lo stato di un ordine, purché la transizione dello stato sia valida. Lo stato CREATED
viene utilizzato quando la piattaforma del partner non può confermare o rifiutare immediatamente l'ordine. Un esempio di caso d'uso è quando un cliente ordina tramite un aggregatore di pubblicazione. L'aggregatore di consegne riceve i dati da Google e l'aggregatore invia le informazioni al ristorante. Una volta che il ristorante ha ricevuto e confermato la disponibilità dell'ordine, lo stato può ora essere CONFIRMED
, altrimenti REJECTED
.
Un ordine nello stato CONFIRMED
viene quindi spostato nello stato IN_PREPARATION
. A seconda che l'ordine sia con ritiro o consegna, utilizza lo stato READY_FOR_PICKUP
o IN_TRANSIT
. Quando il cibo è stato consegnato o ritirato, l'ordine è impostato sullo stato FULFILLED
.
Se consenti ai clienti di annullare gli ordini, puoi utilizzare lo stato CANCELLED
. Un ordine può essere annullato in stato CREATED
, CONFIRMED
, IN_PREPARATION
, READY_FOR_PICKUP
o IN_TRANSIT
.
Il servizio Ordina con Google deve emettere rimborsi in base alle tue norme relative all'annullamento e allo stato dei pagamenti al momento dell'annullamento.
Il tuo servizio Ordina con Google non deve supportare tutti gli stati e le transizioni disponibili. Tuttavia, lo stato finale dell'ordine deve essere FULFILLED
,
REJECTED
o CANCELLED
.
Fornire un tempo di evasione stimato
Puoi fornire agli utenti un intervallo di tempo stimato per il momento in cui il loro ordine sarà pronto per il ritiro (o la consegna). Utilizza il campo estimatedFulfillmentTimeIso8601
di FoodOrderUpdateExtension
per fornire un intervallo di tempo stimato per il momento in cui
l'ordine di un cliente sarà pronto per il ritiro o la consegna.
Invia estimatedFulfillmentTimeIso8601
nei seguenti orari:
- Quando il tempo stimato diventa disponibile, idealmente nell'ordine
CREATED
oCONFIRMED
. - Quando l'ora stimata cambia, ad esempio aggiornando l'ora stimata in modo che sia più precisa quando l'ordine è
IN_TRANSIT
.
Per gestire in modo efficace le aspettative degli utenti, adotta un approccio conservativo nelle stime e fornisci un intervallo di date e ore anziché una data e un'ora fisse. Quando è possibile, è consigliabile prendere in considerazione varianti come le condizioni di traffico. Ad esempio, puoi inviare una stima delle 12:45 (limite inferiore) alle 13:15 (limite superiore) per un ordine in cui il tempo di consegna stimato è 13:00.
Fornire azioni di gestione degli ordini.
Quando invii un aggiornamento dell'ordine, puoi fornire risorse ai clienti per aiutarli a gestire l'ordine sotto forma di OrderManagementAction
. Dopo che un cliente ha effettuato un ordine, potrebbe dover contattare te o il ristorante per evadere l'ordine per monitorare i progressi, apportare modifiche o annullare l'ordine.
Un OrderManagementAction
consente ai clienti di inviare email, chiamare o creare un link a un URL direttamente dal proprio dispositivo. Utilizza le stesse informazioni riportate in
OrderManagementAction
e nella conferma dell'ordine email che invii
all'utente.
Le azioni di gestione degli ordini includono i seguenti tipi:
CUSTOMER_SERVICE
: fornire ai clienti un'azione per contattare l'assistenza clienti. Questo tipo di azione di gestione è obbligatorio per gli aggiornamenti degli ordini.EMAIL
: fornisci ai clienti un'azione per inviare un'email all'indirizzo fornito.CALL
: fornisci ai clienti un'azione per chiamare il numero di telefono fornito.VIEW_DETAIL
: fornire ai clienti un'azione per visualizzare i dettagli del loro ordine.
Ogni aggiornamento dell'ordine deve contenere almeno un'azione di gestione degli ordini. Tuttavia, le azioni di gestione degli ordini fornite possono variare in base allo stato dell'ordine.
Ad esempio, quando un ordine è nello stato CONFIRMED
, l'azione CUSTOMER_SERVICE
può puntare al tuo numero di telefono dell'assistenza clienti. Quando lo stato di questo ordine viene aggiornato a IN_TRANSIT
, l'azione CUSTOMER_SERVICE
può indirizzare al numero di telefono del ristorante di evasione degli ordini.
Invio degli aggiornamenti sugli ordini
Utilizzi il tipo di messaggio AsyncOrderUpdateRequestMessage
per inviare un aggiornamento dell'ordine al servizio Ordina con Google. Google risponde con un
AsyncOrderUpdateResponseMessage
. Ad esempio, se vuoi comunicare a un cliente che il suo ordine è valido e accettato, puoi inviare un AsyncOrderUpdateRequestMessage
per modificare lo stato dell'ordine in CONFIRMED
con l'etichetta Accepted by restaurant
.
Impostare il messaggio di aggiornamento dell'ordine
Quando invii un elemento AsyncOrderUpdateRequestMessage
a Google, devi includere informazioni sullo stato dell'ordine utilizzando il campo OrderUpdate
.
I seguenti esempi mostrano un esempio AsyncOrderUpdateRequestMessage
per ogni stato dell'ordine:
CONFERMATO
Questo esempio mostra una richiesta di aggiornamento dell'ordine di esempio che notifica all'utente che l'ordine è confermato con una ricevuta e un tempo di consegna stimato.
{ "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" } } } }
RIFIUTATA
Questo esempio mostra una richiesta di aggiornamento dell'ordine di esempio che notifica all'utente che l'ordine è stato rifiutato con un motivo di rifiuto.
{ "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." } ] } } } }
CANCELLATO
Questo esempio mostra una richiesta di aggiornamento dell'ordine di esempio che notifica all'utente che l'ordine è stato annullato con un motivo dell'annullamento.
{ "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_PREPARAZIONE
Questo esempio mostra una richiesta di aggiornamento dell'ordine di esempio che notifica all'utente che il cibo è in fase di preparazione.
{ "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" } } } }
PRONTO_PER_RITIRO
Questo esempio mostra una richiesta di aggiornamento dell'ordine di esempio che notifica all'utente che il cibo è pronto per il ritiro.
{ "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" } } } }
TRANSITTA
Questo esempio mostra una richiesta di aggiornamento dell'ordine di esempio che notifica all'utente che l'ordine è in transito con un tempo di consegna stimato.
{ "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" } } } }
COMPLETATO
Questo esempio mostra una richiesta di aggiornamento dell'ordine di esempio che notifica all'utente che l'ordine è stato ritirato o consegnato:
{ "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" } } } ] } } }
Per altri esempi di richieste di aggiornamento dell'ordine in diversi casi d'uso, consulta Implementare gli aggiornamenti avanzati degli ordini.
Genera il token di autorizzazione e invia il messaggio
Gli aggiornamenti sugli ordini richiedono un token di autorizzazione per consentire al servizio Ordina con Google di verificare che il messaggio provenga dal tuo servizio web Ordina con Google.
Per implementare gli aggiornamenti sugli ordini per il tuo progetto:
- Genera un token di autorizzazione seguendo questa procedura:
- Utilizza la libreria di autenticazione Google per leggere le credenziali dal file dell'account di servizio.
- Richiedi token utilizzando il seguente ambito API:
https://www.googleapis.com/auth/actions.fulfillment.conversation
- Utilizza questo token per inviare una richiesta POST HTTP autenticata al seguente endpoint:
https://actions.googleapis.com/v2/conversations:send
- Imposta l'intestazione
Content-Type
suapplication/json
come parte della richiesta.
I seguenti esempi mostrano come implementare gli aggiornamenti degli ordini:
Node.js
Questo codice utilizza la libreria di autenticazione di Google per 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
Questo codice utilizza la libreria di autenticazione di Google per 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
Questo codice utilizza la libreria di autenticazione di Google per 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",); }
Per gli aggiornamenti riusciti degli ordini senza errori, Google restituisce una risposta HTTP 200 con un payload vuoto. Se si è verificato un problema, ad esempio se l'aggiornamento non è corretto, Google restituisce un errore.