客戶提交訂餐後,您可以傳送訂單更新訊息給 「訂單端對端服務」回報變更。
以下是傳送訂單更新的常見原因:
- 訂單的預估出貨時間有現貨或變更。
- 訂單狀態會變更。
- 訂單已無法履行。
- 訂單中包含的菜單品項價格已變更。
- 客戶可透過新的方式管理訂單,例如客戶服務人員 或餐廳的電話號碼
- 訂單收據可供查看。
以下各節將詳細說明如何因應這些不同情況 來更新訂單內容
轉換訂單狀態
訂單有六種可能的狀態。這些狀態及其可能的轉換 ,如下圖所示:
當客戶初次提交訂單時,訂單會從
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 (下限) 傳送至晚上 1:15 (上下限) 規定)。
提供訂單管理動作
傳送訂單最新狀態時,你可以為客戶提供實用資源
他們可以使用 OrderManagementAction
格式管理訂單執行
客戶下訂單後,可能要聯絡你或餐廳
履行訂單以便追蹤進度、變更或取消訂單。
OrderManagementAction
能讓客戶透過電子郵件、電話或連結
直接透過自己的裝置存取網址。在
OrderManagementAction
,必須與您傳送給
內容。
訂單管理動作如下:
CUSTOMER_SERVICE
:為客戶提供聯絡客戶的動作 課程中也會快速介紹 Memorystore 這是 Google Cloud 的全代管 Redis 服務這個管理動作類型是更新訂單的必要項目。EMAIL
:讓客戶採取行動,傳送電子郵件至提供的 建立一個 Fitbit 帳戶。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" } } } }
READY_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" } } } }
IN_TRANSIT
本例顯示會通知使用者的訂單更新要求範例 訂單商品正在運送途中,以及預計送達時間。
{ "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 驗證程式庫讀取服務的憑證
- 使用以下 API 範圍要求權杖:
https://www.googleapis.com/auth/actions.fulfillment.conversation
- 使用此憑證將經過驗證的 HTTP POST 要求傳送至
以下端點:
https://actions.googleapis.com/v2/conversations:send
- 在要求中將
Content-Type
標頭設為application/json
。
以下範例說明如何實作訂單更新:
Node.js
這個程式碼使用 Node.js 適用的 Google 驗證程式庫。
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
這段程式碼使用 Python 適用的 Google 驗證程式庫。
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
這個程式碼使用 Java 適用的 Google 驗證程式庫。
/** * 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 會傳回錯誤。