Gdy klient złoży zamówienie na jedzenie, możesz wysłać wiadomość z aktualizacją zamówienia do usługi Zamawianie od początku do końca, aby powiadomić nas o zmianie.
Oto kilka najczęstszych przyczyn wysyłania aktualizacji zamówienia:
- Przewidywany czas realizacji zamówienia staje się dostępny lub zmienia się.
- Stan zamówienia ulega zmianie.
- Zamówienia nie można już zrealizować.
- zmieniła się cena pozycji menu zawartej w zamówieniu;
- Klient ma nowy sposób zarządzania zamówieniem, np. numer telefonu do obsługi klienta lub restauracji.
- potwierdzenie zamówienia stanie się dostępne.
W kolejnych sekcjach znajdziesz szczegółowe informacje o tym, jak rozwiązywać te różne scenariusze za pomocą aktualizacji zamówień.
Przechodzenie między stanami zamówienia
Zamówienie może mieć 6 możliwych stanów. Te stany i ich możliwe przejścia przedstawia diagram poniżej:
Gdy klient po raz pierwszy przesyła zamówienie, ma ono stan CREATED
, CONFIRMED
lub REJECTED
. Możesz wysłać wiadomość z aktualizacją zamówienia, aby zaktualizować jego stan, o ile zmiana stanu jest prawidłowa. CREATED
Stan ten jest używany, gdy platforma partnera nie może od razu potwierdzić ani odrzucić zamówienia. Przykładem takiego przypadku jest sytuacja, gdy klient składa zamówienie za pomocą agregatora dostaw. Agregator dostaw otrzymuje zamówienie od Google, a potem wysyła informacje do restauracji. Gdy restauracja otrzyma i potwierdzi dostępność zamówienia, stan może zostać zmieniony na CONFIRMED
. W przeciwnym razie będzie to REJECTED
.
Zamówienie w stanie CONFIRMED
przechodzi następnie do stanu IN_PREPARATION
. W zależności od tego, czy zamówienie jest przeznaczone do odbioru czy dostawy, użyj stanu READY_FOR_PICKUP
lub IN_TRANSIT
. Po dostarczeniu lub odbiorze jedzenia zamówienie ma stan FULFILLED
.
Jeśli zezwalasz klientom na anulowanie zamówień, możesz użyć stanu CANCELLED
. Zamówienie można anulować, gdy ma stan CREATED
, CONFIRMED
, IN_PREPARATION
, READY_FOR_PICKUP
lub IN_TRANSIT
.
Usługa kompleksowego zamawiania powinna zwracać środki zgodnie z zasadami anulowania i stanem płatności w momencie anulowania.
Usługa kompleksowego zamawiania nie musi obsługiwać wszystkich dostępnych stanów i przejść. Jednak ostateczny stan zamówienia musi być FULFILLED
,
REJECTED
lub CANCELLED
.
Podawanie przewidywanego czasu realizacji
Możesz podać użytkownikom przewidywany czas, kiedy ich zamówienie będzie gotowe do odbioru (lub dostarczone). Użyj pola estimatedFulfillmentTimeIso8601
w FoodOrderUpdateExtension
, aby podać przewidywany przedział czasu, w którym zamówienie klienta będzie gotowe do odbioru lub dostawy.
Wysyłaj estimatedFulfillmentTimeIso8601
o tych porach:
- Gdy przewidywany czas stanie się dostępny, najlepiej w stanie
CREATED
lubCONFIRMED
. - Gdy zmieni się szacowany czas, np. gdy zamówienie jest
IN_TRANSIT
, należy zaktualizować szacowany czas, aby był bardziej dokładny.
Aby skutecznie zarządzać oczekiwaniami użytkowników, podawaj ostrożne szacunki i okres dat i godzin zamiast stałych dat i godzin. O ile to możliwe, należy uwzględnić zmienne czynniki, takie jak warunki na drodze. Na przykład możesz wysłać szacowany czas dostawy 13:45 (wartość dolna) do 13:15 (wartość górna) dla zamówienia, którego przewidywany czas dostawy to 13:00.
Dostępność działań związanych z zarządzaniem zamówieniami
Podczas wysyłania aktualizacji zamówienia możesz udostępnić klientom zasoby, które pomogą im zarządzać zamówieniem w postaci OrderManagementAction
. Po złożeniu zamówienia przez klienta może on potrzebować kontaktu z Tobą lub restauracją, aby śledzić postępy, wprowadzić zmiany lub anulować zamówienie.
OrderManagementAction
umożliwia klientom wysyłanie e-maili, wykonywanie połączeń telefonicznych i dodawanie linków do adresów URL bezpośrednio z urządzenia. W polu OrderManagementAction
podawaj te same informacje co w e-mailu z potwierdzeniem zamówienia wysyłanym do użytkownika.
Działania związane z zarządzaniem zamówieniami obejmują te typy:
CUSTOMER_SERVICE
: umożliwić klientom skontaktowanie się z zespołem obsługi klienta. Ten typ działania administracyjnego jest wymagany w przypadku aktualizacji zamówień.EMAIL
: umożliwić klientom wysyłanie e-maili na podany adres e-mail.CALL
: umożliwić klientom wykonanie działania polegającego na wykonaniu połączenia na podany numer telefonu.VIEW_DETAIL
: podaj klientom działanie, które umożliwi im wyświetlenie szczegółów zamówienia.
Każda aktualizacja zamówienia musi zawierać co najmniej 1 działanie związane z zarządzaniem zamówieniem. Jednak dostępne działania związane z zarządzaniem zamówieniem mogą się różnić w zależności od jego stanu.
Jeśli np. zamówienie ma stan CONFIRMED
, działanie CUSTOMER_SERVICE
może wskazywać numer telefonu obsługi klienta. Gdy stan zamówienia zmieni się na IN_TRANSIT
, działanie CUSTOMER_SERVICE
może wskazywać numer telefonu restauracji realizującej zamówienie.
Wysyłanie aktualizacji zamówień
Używasz typu wiadomości AsyncOrderUpdateRequestMessage
, aby wysłać do usługi Zamawianie od początku do końca aktualizację zamówienia. Google odpowiada elementem AsyncOrderUpdateResponseMessage
. Jeśli na przykład chcesz poinformować klienta, że jego zamówienie zostało przyjęte, możesz wysłać AsyncOrderUpdateRequestMessage
, aby zmienić stan zamówienia na CONFIRMED
z etykietą Accepted by restaurant
.
Konfigurowanie wiadomości o zaktualizowanym zamówieniu
Wysyłając do Google AsyncOrderUpdateRequestMessage
, musisz podać informacje o stanie zamówienia, korzystając z pola OrderUpdate
.
Poniższe przykłady pokazują przykładową wartość AsyncOrderUpdateRequestMessage
dla każdego stanu zamówienia:
POTWIERDZONO
Ten przykład pokazuje prośbę o zmianę zamówienia, która informuje użytkownika o potwierdzenie zamówienia z potwierdzeniem odbioru i szacowanym czasem dostawy.
{ "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" } } } }
ODRZUCONE
Ten przykład pokazuje prośbę o zmianę zamówienia, która informuje użytkownika o odrzuceniu zamówienia wraz z odpowiednią przyczyną.
{ "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." } ] } } } }
ANULOWANO
Ten przykład pokazuje prośbę o zmianę zamówienia, która powiadamia użytkownika o anulowaniu zamówienia wraz z odpowiednim powodem.
{ "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
Ten przykład pokazuje prośbę o zmianę zamówienia, która informuje użytkownika, że posiłek jest obecnie przygotowywany.
{ "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
Ten przykład pokazuje prośbę o zmianę zamówienia, która informuje użytkownika, że posiłek jest gotowy do odbioru.
{ "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
Ten przykład pokazuje prośbę o zmianę zamówienia, która informuje użytkownika, że zamówienie jest w drodze, podając przybliżony czas dostawy.
{ "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
Ten przykład pokazuje prośbę o zmianę zamówienia, która powiadamia użytkownika o odbiorze lub dostawie zamówienia:
{ "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" } } } ] } } }
Więcej przykładów żądań aktualizacji zamówienia w różnych przypadkach użycia znajdziesz w artykule Wdrażanie zaawansowanych aktualizacji zamówienia.
Generowanie tokena autoryzacji i wysyłanie wiadomości
Aktualizacje zamówienia wymagają tokena autoryzacji, aby usługa kompleksowej pomocy w zamawianiu mogła zweryfikować, czy wiadomość pochodzi z Twojej usługi internetowej kompleksowej pomocy w zamawianiu.
Aby wdrożyć aktualizacje zamówień w projekcie:
- Aby wygenerować token autoryzacji:
- Użyj Google Auth Library, aby odczytać dane logowania z pliku konta usługi.
- Poproś o token, używając tego zakresu uprawnień API:
https://www.googleapis.com/auth/actions.fulfillment.conversation
- Użyj tego tokena, aby wysłać uwierzytelnione żądanie HTTP POST do tego punktu końcowego:
https://actions.googleapis.com/v2/conversations:send
- W żądaniu ustaw nagłówek
Content-Type
naapplication/json
.
Te przykłady pokazują, jak wdrażać aktualizacje zamówień:
Node.js
Ten kod używa biblioteki Google do uwierzytelniania w 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
Ten kod korzysta z biblioteki uwierzytelniania Google dla Pythona.
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
Ten kod korzysta z biblioteki Google do uwierzytelniania w Javie.
/** * 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",); }
W przypadku pomyślnych aktualizacji zamówień bez błędów Google zwraca odpowiedź HTTP 200 z pustym ładunkiem. Jeśli wystąpił problem, np. nieprawidłowa aktualizacja, Google zwraca błąd.