После того как клиент отправит заказ на еду, вы можете отправить сообщение об обновлении заказа в службу сквозного заказа, чтобы уведомить нас об изменении.
Вот некоторые распространенные причины отправки обновлений заказов:
- Ориентировочный срок выполнения заказа становится доступным или изменяется.
- Статус заказа меняется.
- Заказ больше не может быть выполнен.
- Изменилась цена позиции меню, включенной в заказ.
- У клиента появился новый способ управления своим заказом, например, служба поддержки или номер телефона ресторана.
- Квитанция о заказе становится доступной.
В следующих разделах представлена подробная информация о том, как решать эти различные сценарии с помощью обновлений заказов.
Переходные состояния порядка
Заказ имеет шесть возможных состояний. Эти состояния и их возможные переходы показаны на следующей диаграмме:
Когда клиент впервые отправляет заказ, заказ начинается с состояния CREATED
, CONFIRMED
или REJECTED
. Вы можете отправить сообщение об обновлении заказа, чтобы обновить состояние заказа, если переход состояния действителен. Состояние CREATED
используется, когда платформа партнера не может немедленно подтвердить или отклонить заказ. Пример использования: клиент заказывает через агрегатор доставки. Агрегатор доставки получает доставку от Google и отправляет информацию в ресторан. После того, как ресторан получил и подтвердил наличие заказа, состояние теперь может быть CONFIRMED
, в противном случае — REJECTED
.
Заказ в состоянии CONFIRMED
затем переходит в состояние IN_PREPARATION
. В зависимости от того, предназначен ли заказ для самовывоза или доставки, затем используйте состояние READY_FOR_PICKUP
или IN_TRANSIT
. Когда еда доставлена или забрана, заказ переходит в состояние FULFILLED
.
Если вы разрешаете клиентам отменять заказы, вы можете использовать состояние CANCELLED
. Заказ можно отменить, находясь в состоянии CREATED
, CONFIRMED
, IN_PREPARATION
, READY_FOR_PICKUP
или IN_TRANSIT
. Служба комплексного оформления заказов должна возвращать средства в зависимости от вашей политики отмены и состояния платежей на момент отмены.
Служба сквозного заказа заказов не обязательно должна поддерживать все доступные состояния и переходы. Однако окончательное состояние заказа должно быть FULFILLED
, REJECTED
или CANCELLED
.
Указание примерного срока выполнения
Вы можете предоставить пользователям приблизительный диапазон времени, когда их заказ будет готов к выдаче (или доставлен). Используйте поле estimatedFulfillmentTimeIso8601
FoodOrderUpdateExtension
, чтобы указать предполагаемый диапазон времени, когда заказ клиента будет готов к самовывозу или доставке.
Отправляйте estimatedFulfillmentTimeIso8601
в следующее время:
- Когда расчетное время станет доступным, в идеале заказ в состоянии
CREATED
илиCONFIRMED
. - При изменении расчетного времени, например, при обновлении расчетного времени для большей точности при заказе
IN_TRANSIT
.
Чтобы эффективно управлять ожиданиями пользователей, будьте консервативны в своих оценках и указывайте диапазон дат и времени, а не фиксированную дату и время. По возможности вам следует учитывать такие вариации, как условия дорожного движения. Например, вы можете отправить расчетное время от 12:45 (нижняя граница) до 13:15 (верхняя граница) для заказа, расчетное время доставки которого составляет 13:00.
Обеспечение действий по управлению заказами
Отправляя обновление заказа, вы можете предоставить клиентам ресурсы, которые помогут им управлять своим заказом, в форме OrderManagementAction
. После того как клиент разместит заказ, ему может потребоваться связаться с вами или рестораном, выполняющим заказ, чтобы отслеживать ход выполнения, внести изменения или отменить заказ.
OrderManagementAction
позволяет клиентам отправлять электронные письма, звонить или ссылаться на URL-адрес непосредственно со своего устройства. Используйте в OrderManagementAction
ту же информацию, что и в подтверждении заказа по электронной почте, которое вы отправляете пользователю.
Действия по управлению заказами включают в себя следующие виды:
-
CUSTOMER_SERVICE
: предоставить клиентам возможность связаться со службой поддержки. Этот тип действия управления необходим для обновления заказов. -
EMAIL
: Предоставьте клиентам возможность отправить электронное письмо на указанный адрес электронной почты. -
CALL
: Предоставьте клиентам возможность позвонить по указанному номеру телефона. -
VIEW_DETAIL
: Предоставьте клиентам действие для просмотра деталей их заказа.
Каждое обновление заказа должно содержать хотя бы одно действие по управлению заказом. Однако предоставляемые действия по управлению заказами могут различаться в зависимости от состояния заказа. Например, когда заказ находится в состоянии CONFIRMED
, действие CUSTOMER_SERVICE
может указывать на номер телефона вашей службы поддержки клиентов. Когда состояние заказа обновляется до IN_TRANSIT
, действие CUSTOMER_SERVICE
может указывать на номер телефона ресторана, где осуществляется выполнение заказов.
Отправка обновлений заказа
Тип сообщения AsyncOrderUpdateRequestMessage
используется для отправки обновления заказа в службу сквозного заказа заказов. Google отвечает в ответ AsyncOrderUpdateResponseMessage
. Например, если вы хотите сообщить клиенту, что его заказ действителен и принят, вы можете отправить сообщение AsyncOrderUpdateRequestMessage
чтобы изменить состояние заказа на CONFIRMED
с меткой Accepted by restaurant
.
Настройка сообщения об обновлении заказа
Когда вы отправляете сообщение AsyncOrderUpdateRequestMessage
в Google, вы должны включить информацию о состоянии заказа, используя поле OrderUpdate
.
В следующих примерах показан образец AsyncOrderUpdateRequestMessage
для каждого состояния заказа:
ПОДТВЕРЖДЕННЫЙ
В этом примере показан пример запроса на обновление заказа, который уведомляет пользователя о том, что заказ подтвержден квитанцией и расчетным временем доставки.
{ "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" } } } }
ОТКЛОНЕННЫЙ
В этом примере показан пример запроса на обновление заказа, который уведомляет пользователя о том, что заказ отклонен с указанием причины отклонения.
{ "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." } ] } } } }
ОТМЕНЕНО
В этом примере показан пример запроса на обновление заказа, который уведомляет пользователя об отмене заказа с указанием причины отмены.
{ "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
В этом примере показан пример запроса на обновление заказа, который уведомляет пользователя о том, что еда в данный момент готовится.
{ "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" } } } }
ГОТОВО_FOR_PICKUP
В этом примере показан пример запроса на обновление заказа, который уведомляет пользователя о том, что еда готова к самовывозу.
{ "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" } } } }
В ПУТИ
В этом примере показан пример запроса на обновление заказа, который уведомляет пользователя о том, что заказ находится в пути, и указывает расчетное время доставки.
{ "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" } } } }
ВЫПОЛНЕНО
В этом примере показан пример запроса на обновление заказа, который уведомляет пользователя о том, что заказ получен или доставлен:
{ "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" } } } ] } } }
Дополнительные примеры запросов на обновление заказов в различных вариантах использования см. в статье Реализация расширенных обновлений заказов .
Сгенерируйте токен авторизации и отправьте сообщение
Для обновлений заказов требуется токен авторизации, чтобы сквозная служба заказов могла проверить, что сообщение пришло от вашей сквозной веб-службы заказов.
Чтобы реализовать обновления заказов для вашего проекта, выполните следующие действия:
- Создайте токен авторизации, выполнив следующие действия:
- Используйте библиотеку Google Auth, чтобы прочитать учетные данные из файла вашей учетной записи службы.
- Запросите токен, используя следующую область API:
https://www.googleapis.com/auth/actions.fulfillment.conversation
- Используйте этот токен для отправки аутентифицированного запроса HTTP POST на следующую конечную точку:
https://actions.googleapis.com/v2/conversations:send
- Установите для заголовка
Content-Type
значениеapplication/json
как часть вашего запроса.
Следующие примеры демонстрируют, как реализовать обновления заказов:
Node.js
Этот код использует библиотеку аутентификации Google для 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)}`) }) }
Питон
Этот код использует библиотеку аутентификации Google для 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)
Ява
Этот код использует библиотеку аутентификации Google для 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",); }
При успешном обновлении заказа без ошибок Google возвращает ответ HTTP 200 с пустой полезной нагрузкой. Если возникла проблема, например неверный формат обновления, Google возвращает ошибку.