本指南將逐步引導您使用 Actionss API 開發 Actions 專案,以便進行預訂。
交易流程
當動作專案處理保留項目時,它會使用以下流程:
- 驗證交易需求 (選填) - 在對話開始時使用交易需求輔助程式,以確保使用者能夠進行交易。
- 建構訂單 - 引導使用者進行「購物車組合」,建立預訂詳細資料。
- 建議訂單 - 「購物車」完成後,向使用者建議預訂「訂單」,以便確認訂單是否正確。如果保留項目已確認,您會收到包含保留項目詳細資料的回應。
- 確認訂單並傳送收據:確認訂單後,更新您的預訂系統並傳送收據給使用者。
- 傳送訂單更新 - 在保留項目的效期內,傳送 PATCH 要求至 Orders API 以提供使用者預訂狀態更新。
限制和審查規範
請注意,其他使用交易和 Orders API 的動作皆適用其他政策。我們最多需要六週的時間來檢視與交易相關的動作,因此在規劃發布時間表時,請將時間納入考量。為了簡化審查程序,請先確認您遵守交易政策和規範,再將動作送交審查。
您只能在下列國家/地區部署使用 Orders API 的動作:
澳洲 巴西 加拿大 印尼 |
日本 墨西哥 卡達 俄羅斯 |
新加坡 瑞士 泰國 土耳其 英國 美國 |
建置您的專案
如需交易對話的廣泛範例,請參閱 Node.js 交易範例。
設定
建立動作時,您必須在動作主控台中指定您要執行交易。
設定專案和執行要求的方式如下:
- 建立新專案或匯入現有專案。
- 前往 [部署] > [目錄資訊]。
在「其他資訊 > 交易」下方,勾選「您的動作是否使用交易 API 執行實體商品的交易?」方塊。
驗證交易要求 (選填)
使用者表示他們想要設定預訂後,應確認對方是否能要求預訂。例如,叫用時您的動作可能會詢問「您要預訂座位嗎?」如果使用者說出「yes」,您應確保他們能夠繼續進行並修正任何設定,以防止他們繼續完成交易。如要這麼做,請轉換至執行交易需求檢查的場景。
建立交易規定檢查情境
- 在「Scenes」(場景) 分頁中,新增名為
TransactionRequirementsCheck
的新場景。 - 在「運算單元填充」下方,按一下 [+] 來新增運算單元。
- 在「Select type」(選取類型) 下方,選取
actions.type.TransactionRequirementsCheckResult
做為運算單元類型。 - 在運算單元名稱欄位中,為運算單元命名
TransactionRequirementsCheck
。 - 勾選 [自訂版位值寫入] 核取方塊 (預設為啟用)。
按一下「儲存」。
交易需求檢查會產生下列結果:
- 如果符合條件,則工作階段參數會設定成功條件,而您可以繼續建立使用者訂單。
- 如果無法滿足一或多項條件,則工作階段參數會設定失敗,在這種情況下,您應該針對交易體驗進行對話透視,或結束對話。
- 如果造成故障狀態的錯誤可以由使用者修正,系統會提示他們在裝置上解決這些問題。如果在僅限語音的表面上進行對話,系統會啟動使用者的手機。
處理交易需求檢查結果
- 在「Scenes」(場景) 分頁中,選取新建立的
TransactionRequirementsCheck
場景。 - 在「條件」下方按一下「+」來新增條件。
在文字欄位中輸入下列條件語法,檢查是否成功:
scene.slots.status == "FINAL" && session.params.TransactionRequirementsCheck.resultType == "CAN_TRANSACT"
將遊標懸停在剛新增的條件上,然後按一下向上箭頭,將其放在
if scene.slots.status == "FINAL"
之前。啟用 [Send 提示] 並提供簡單的提示,告訴使用者他們已準備好進行交易:
candidates: - first_simple: variants: - speech: >- Looks like you're good to go!.
在「Transition」底下,選取另一個情境,讓使用者繼續進行對話並繼續交易。
選取條件
else if scene.slots.status == "FINAL"
。啟用 [Send 提示] 並提供簡單的提示,讓使用者知道無法進行交易:
candidates: - first_simple: variants: - speech: Transaction requirements check failed.
選取「轉換」下方的「結束對話」,如果使用者無法進行交易,即可結束對話。
建立訂單
擁有所需的使用者資訊後,請建立「購物車組」體驗,引導使用者建立預訂。每個動作都會根據自身的服務,採用稍微不同的購物車組件。
在基本的購物車組裝服務中,使用者可從清單中選擇要新增至保留項目的選項,不過您可以設計對話來簡化使用者體驗。例如,建立購物車組合體驗,讓使用者能夠以簡單或非問題的方式安排每月預訂。您也可以將輪轉介面或清單資訊卡提供給「推薦」保留項目。
我們建議使用豐富回應,以視覺化方式呈現使用者的選項,同時設計對話,讓使用者只需透過語音建構購物車。如需關於購物車組裝的最佳做法和範例,請參閱設計指南。
建立一個訂單
在整個對話中,收集使用者的保留項目詳細資料,然後建構 Order
物件。
您的 Order
至少必須包含:
buyerInfo
- 購買使用者的相關資訊。transactionMerchant
:協助下單的商家相關資訊。contents
- 列為lineItems
訂單的實際內容。
請參閱 Order
回應說明文件來建構您的購物車。請注意,您可能需要依據保留項目包含不同的欄位。
下列程式碼範例顯示完整的預訂順序,包含選用欄位:
const order = {
createTime: '2019-09-24T18:00:00.877Z',
lastUpdateTime: '2019-09-24T18:00:00.877Z',
merchantOrderId: orderId, // A unique ID String for the order
userVisibleOrderId: orderId,
transactionMerchant: {
id: 'http://www.example.com',
name: 'Example Merchant',
},
contents: {
lineItems: [
{
id: 'LINE_ITEM_ID',
name: 'Dinner reservation',
description: 'A world of flavors all in one destination.',
reservation: {
status: 'PENDING',
userVisibleStatusLabel: 'Reservation is pending.',
type: 'RESTAURANT',
reservationTime: {
timeIso8601: '2020-01-16T01:30:15.01Z',
},
userAcceptableTimeRange: {
timeIso8601: '2020-01-15/2020-01-17',
},
partySize: 6,
staffFacilitators: [
{
name: 'John Smith',
},
],
location: {
zipCode: '94086',
city: 'Sunnyvale',
postalAddress: {
regionCode: 'US',
postalCode: '94086',
administrativeArea: 'CA',
locality: 'Sunnyvale',
addressLines: [
'222, Some other Street',
],
},
},
},
},
],
},
buyerInfo: {
email: 'janedoe@gmail.com',
firstName: 'Jane',
lastName: 'Doe',
displayName: 'Jane Doe',
},
followUpActions: [
{
type: 'VIEW_DETAILS',
title: 'View details',
openUrlAction: {
url: 'http://example.com',
},
},
{
type: 'CALL',
title: 'Call us',
openUrlAction: {
url: 'tel:+16501112222',
},
},
{
type: 'EMAIL',
title: 'Email us',
openUrlAction: {
url: 'mailto:person@example.com',
},
},
],
termsOfServiceUrl: 'http://www.example.com'
};
建立訂單和簡報選項
const orderOptions = {
'requestDeliveryAddress': false,
};
const presentationOptions = {
'actionDisplayName': 'RESERVE'
};
在工作階段參數中儲存訂單資料
根據您的出貨要求,將訂單資料儲存至工作階段參數。這個順序物件將用於同一工作階段的情境。
conv.session.params.order = {
'@type': 'type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValueSpec',
order: order,
orderOptions: orderOptions,
presentationOptions: presentationOptions
};
建議訂單
建立預訂訂單後,您必須向使用者顯示該訂單, 才能確認或拒絕。如要這麼做,請轉換至執行交易決策的場景。
建立交易決策場景
- 在「場景」分頁中,新增名為
TransactionDecision
的新場景。 - 在「運算單元填充」下方,按一下 [+] 來新增運算單元。
- 在「Select type」(選取類型) 下方,選取
actions.type.TransactionDecisionValue
做為運算單元類型。 - 在運算單元名稱欄位中,為運算單元命名
TransactionDecision
。 - 勾選 [自訂版位值寫入] 核取方塊 (預設為啟用)。
- 在「Configure slot」(設定版位) 下方的下拉式選單中,選取 [使用工作階段參數]。
- 在「Configure slot」(設定版位) 下方,在文字欄位中,輸入用於儲存訂單的工作階段參數名稱 (即
$session.params.order
)。 按一下「儲存」。
為了嘗試填入 TransactionDecisionValue
位置,Google 助理會啟動內建體驗,您傳遞的 Order
會直接顯示在「購物車預覽卡」上。使用者可以說出「安排預約」、拒絕交易,或要求變更保留項目詳細資料。
此時,使用者也可以要求變更訂單。在這種情況下,您應確保在完成購物車組合體驗後,您的出貨要求可以處理訂單變更要求。
處理交易決策結果
填入 TransactionDecisionValue
運算單元時,使用者對交易決策的答案會儲存在工作階段參數中。這個值包含下列項目:
ORDER_ACCEPTED
、ORDER_REJECTED
、CART_CHANGE_REQUESTED
USER_CANNOT_TRANSACT
。
如何處理交易決策結果:
- 在「場景」分頁中,選取新建立的
TransactionDecision
場景。 - 在「條件」下方按一下「+」來新增條件。
在文字欄位中輸入下列條件語法,檢查是否成功:
scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_ACCEPTED"
將遊標懸停在您剛剛新增的條件上,然後按一下向上箭頭,將其放在
if scene.slots.status == "FINAL"
之前。啟用 [Send 提示] 並提供簡單的提示,讓使用者知道他們的預約已完成:
candidates: - first_simple: variants: - speech: >- Transaction completed! Your reservation $session.params.TransactionDecision.order.merchantOrderId is all set!
在「轉換」底下選取「結束對話」即可結束對話。
在「條件」下方按一下「+」來新增條件。
在文字欄位中輸入下列條件語法,檢查是否失敗:
scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_REJECTED"
將遊標懸停在您剛剛新增的條件上,然後按一下向上箭頭,將其放在
if scene.slots.status == "FINAL"
之前。啟用 [Send 提示] 並提供簡單的提示,讓使用者知道訂單遭拒:
candidates: - first_simple: variants: - speech: Looks like you don't want to set up a reservation. Goodbye.
在「轉換」底下選取「結束對話」即可結束對話。
選取條件
else if scene.slots.status == "FINAL"
。啟用「Send 提示」並提供簡單的提示,讓使用者知道無法進行交易:
candidates: - first_simple: variants: - speech: >- Transaction failed with status $session.params.TransactionDecision.transactionDecision
在「Transition」(轉換) 下方,選取 [End 對話] 以結束使用者無法進行交易的對話。
完成預訂並傳送收據
當 TransactionDecisionValue
運算單元傳回 ORDER_ACCEPTED
的結果時,您必須立即執行排定保留項目所需的任何處理作業 (例如在自己的資料庫中保留保留項目)。
傳送簡單回應來維持對話的動機。使用者會收到您的回應「已收合的收據」卡片。
如何傳送初始訂單更新:
- 在「Scenes」(場景) 分頁中選取您的
TransactionDecision
場景。 在「Condition」(條件) 之下,選取檢查成功結果的條件
ORDER_ACCEPTED
:scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_ACCEPTED"
啟用 Call Webhook 並提供意圖處理常式名稱,例如
update_order
。在 Webhook 程式碼中,新增用於傳送初始訂單更新的意圖處理常式:
app.handle('update_order', conv => { const currentTime = new Date().toISOString(); let order = conv.session.params.TransactionDecision.order; conv.add(new OrderUpdate({ 'updateMask': { 'paths': [ 'reservation.status', 'reservation.user_visible_status_label', 'reservation.confirmation_code' ] }, 'order': { 'merchantOrderId': order.merchantOrderId, 'lastUpdateTime': currentTime, 'reservation': { 'status': 'CONFIRMED', 'userVisibleStatusLabel': 'Reservation confirmed', 'confirmationCode': '123ABCDEFGXYZ', }, }, 'reason': 'Reason string' })); });
傳送訂單動態
保留項目在生命週期內會有所變動。使用 HTTP PATCH 要求將使用者預訂更新傳送至 Orders API,並提供訂單狀態和詳細資料。
設定向 Orders API 發出的非同步要求
向 Orders API 發出的訂單更新要求將獲得存取權杖的授權。若要向 Orders API 提交訂單更新,請下載與您的 Actions 主控台專案相關聯的 JSON 服務帳戶金鑰,然後為服務帳戶權杖交換可於 HTTP 要求 Authorization
標頭中持有的不記名憑證。
如要擷取您的服務帳戶金鑰,請執行下列步驟:
- 在 Google Cloud 控制台中,依序前往 [Menu] 選單 > [API 和服務] > [憑證] > [建立憑證] > [服務帳戶金鑰]。
- 在「Service Account」(服務帳戶) 之下選取 [New Service Account] (新增服務帳戶)。
- 將服務帳戶設為
service-account
。 - 將「Role」(角色) 設為「Project」>「Owner」(擁有者)。
- 將金鑰類型設為「JSON」。
- 選取「建立」。
- 私密 JSON 服務帳戶金鑰會下載到您的本機電腦上。
在訂單更新程式碼中,使用 Google API 用戶端程式庫和 "https://www.googleapis.com/auth/actions.order.developer" 範圍,將服務金鑰交換給不記名憑證。您可以在 API 用戶端程式庫的 GitHub 頁面中找到安裝步驟和範例。
如需金鑰交換範例,請參閱 Node.js 範例中的 order-update.js
。
傳送訂單動態
使用服務帳戶將 OAuth 持有人權杖交換之後,請將訂單更新做為授權的 PATCH 要求傳送至 Orders API。
Orders API 網址:
PATCH https://actions.googleapis.com/v3/orders/${orderId}
在要求中提供下列標頭:
"Authorization: Bearer token"
替換為您交換服務帳戶金鑰的 OAuth 持有者權杖。"Content-Type: application/json"
。
PATCH 要求應採用下列格式的 JSON 主體:
{ "orderUpdate": OrderUpdate }
OrderUpdate
物件由下列頂層欄位組成:
updateMask
:您要更新的訂單的欄位。如要更新保留項目狀態,請將值設為reservation.status, reservation.userVisibleStatusLabel
。order
:更新的內容。如果您要更新保留項目的內容,請將值設為更新的Order
物件。如果只是要更新保留項目的狀態 (例如從"PENDING"
到"FULFILLED"
),則物件會包含以下欄位:merchantOrderId
- 您在Order
物件中設定的 ID。lastUpdateTime
:本次更新的時間戳記。purchase
- 包含以下項目的物件:status
- 訂單狀態,以ReservationStatus
表示,例如「CONFIRMED
」或「CANCELLED
」。userVisibleStatusLabel
- 向使用者顯示的標籤,提供訂單狀態的詳細資料,例如「您的預訂已確認」。
userNotification
(選用) -userNotification
物件,在傳送這項更新時,可以在使用者的裝置上顯示。請注意,包含這個物件並不保證通知在使用者的裝置上會顯示。
下列程式碼範例顯示 OrderUpdate
範例,可將預訂訂單的狀態更新為 FULFILLED
:
// Import the 'googleapis' module for authorizing the request.
const {google} = require('googleapis');
// Import the 'request-promise' module for sending an HTTP POST request.
const request = require('request-promise');
// Import the OrderUpdate class from the client library.
const {OrderUpdate} = require('@assistant/conversation');
// Import the service account key used to authorize the request.
// Replacing the string path with a path to your service account key.
// i.e. const serviceAccountKey = require('./service-account.json')
// Create a new JWT client for the Actions API using credentials
// from the service account key.
let jwtClient = new google.auth.JWT(
serviceAccountKey.client_email,
null,
serviceAccountKey.private_key,
['https://www.googleapis.com/auth/actions.order.developer'],
null,
);
// Authorize the client
let tokens = await jwtClient.authorize();
// Declare the ID of the order to update.
const orderId = '<UNIQUE_MERCHANT_ORDER_ID>';
// Declare order update
const orderUpdate = new OrderUpdate({
updateMask: {
paths: [
'contents.lineItems.reservation.status',
'contents.lineItems.reservation.userVisibleStatusLabel'
]
},
order: {
merchantOrderId: orderId, // Specify the ID of the order to update
lastUpdateTime: new Date().toISOString(),
contents: {
lineItems: [
{
reservation: {
status: 'FULFILLED',
userVisibleStatusLabel: 'Reservation fulfilled',
},
}
]
},
},
reason: 'Reservation status was updated to fulfilled.',
});
// Set up the PATCH request header and body,
// including the authorized token and order update.
let options = {
method: 'PATCH',
uri: `https://actions.googleapis.com/v3/orders/${orderId}`,
auth: {
bearer: tokens.access_token,
},
body: {
header: {
isInSandbox: true,
},
orderUpdate,
},
json: true,
};
// Send the PATCH request to the Orders API.
try {
await request(options);
} catch (e) {
console.log(`Error: ${e}`);
}
設定預訂狀態
訂單更新的 ReservationStatus
必須能夠描述訂單目前的狀態。在更新的 order.ReservationStatus
欄位中,請使用下列其中一個值:
PENDING
- 動作是由您的動作「建立」,但需要在後端進行額外處理。CONFIRMED
- 預約時間已確認。CANCELLED
- 使用者取消預訂。FULFILLED
- 使用者的預約是由服務完成。CHANGE_REQUESTED
- 使用者提出了變更要求,且正在處理變更。REJECTED
:如果您無法處理或以其他方式確認保留項目。
請針對與保留項目相關的各個狀態,傳送訂單更新資訊。例如,如果您的保留項目需要手動處理,以便在提出要求後確認保留項目,請傳送 PENDING
訂單更新,直到完成其他處理作業為止。並非所有預訂都需要每個狀態值,
測試專案
測試專案時,您可以在動作主控台中啟用沙箱模式,以便測試動作而不收費。如要啟用沙箱模式,請按照下列步驟操作:
- 在動作控制台中,按一下導覽中的 [測試]。
- 按一下「設定」。
- 啟用 [Development Sandbox] 選項。
對於實體交易,您也可以在範例中將 isInSandbox
欄位設定為 true
。這個動作相當於在「動作」控制台中啟用沙箱模式設定。如要查看使用 isInSandbox
的程式碼片段,請參閱傳送訂單更新一節。
疑難排解
如果您在測試期間遇到任何問題,請參閱交易的疑難排解步驟。