對話動作將於 2023 年 6 月 13 日淘汰。詳情請參閱對話動作停用

建立保留項目

透過集合功能整理內容 你可以依據偏好儲存及分類內容。

本指南將逐步引導您使用 Actionss API 開發 Actions 專案,以便進行預訂。

交易流程

當動作專案處理保留項目時,它會使用以下流程:

  1. 驗證交易需求 (選填) - 在對話開始時使用交易需求輔助程式,以確保使用者能夠進行交易。
  2. 建構訂單 - 引導使用者進行「購物車組合」,建立預訂詳細資料。
  3. 建議訂單 - 「購物車」完成後,向使用者建議預訂「訂單」,以便確認訂單是否正確。如果保留項目已確認,您會收到包含保留項目詳細資料的回應。
  4. 確認訂單並傳送收據:確認訂單後,更新您的預訂系統並傳送收據給使用者。
  5. 傳送訂單更新 - 在保留項目的效期內,傳送 PATCH 要求至 Orders API 以提供使用者預訂狀態更新。

限制和審查規範

請注意,其他使用交易和 Orders API 的動作皆適用其他政策。我們最多需要六週的時間來檢視與交易相關的動作,因此在規劃發布時間表時,請將時間納入考量。為了簡化審查程序,請先確認您遵守交易政策和規範,再將動作送交審查。

您只能在下列國家/地區部署使用 Orders API 的動作:

澳洲
巴西
加拿大
印尼
日本
墨西哥
卡達
俄羅斯
新加坡
瑞士
泰國
土耳其
英國
美國

建置您的專案

如需交易對話的廣泛範例,請參閱 Node.js 交易範例

設定

建立動作時,您必須在動作主控台中指定您要執行交易。

設定專案和執行要求的方式如下:

  1. 建立新專案或匯入現有專案。
  2. 前往 [部署] > [目錄資訊]。
  3. 在「其他資訊 > 交易」下方,勾選「您的動作是否使用交易 API 執行實體商品的交易?」方塊。

驗證交易要求 (選填)

使用者表示他們想要設定預訂後,應確認對方是否能要求預訂。例如,叫用時您的動作可能會詢問「您要預訂座位嗎?」如果使用者說出「yes」,您應確保他們能夠繼續進行並修正任何設定,以防止他們繼續完成交易。如要這麼做,請轉換至執行交易需求檢查的場景。

建立交易規定檢查情境

  1. 在「Scenes」(場景) 分頁中,新增名為 TransactionRequirementsCheck 的新場景。
  2. 在「運算單元填充」下方,按一下 [+] 來新增運算單元。
  3. 在「Select type」(選取類型) 下方,選取 actions.type.TransactionRequirementsCheckResult 做為運算單元類型。
  4. 在運算單元名稱欄位中,為運算單元命名 TransactionRequirementsCheck
  5. 勾選 [自訂版位值寫入] 核取方塊 (預設為啟用)。
  6. 按一下「儲存」

交易需求檢查會產生下列結果:

  • 如果符合條件,則工作階段參數會設定成功條件,而您可以繼續建立使用者訂單。
  • 如果無法滿足一或多項條件,則工作階段參數會設定失敗,在這種情況下,您應該針對交易體驗進行對話透視,或結束對話。
    • 如果造成故障狀態的錯誤可以由使用者修正,系統會提示他們在裝置上解決這些問題。如果在僅限語音的表面上進行對話,系統會啟動使用者的手機。

處理交易需求檢查結果

  1. 在「Scenes」(場景) 分頁中,選取新建立的 TransactionRequirementsCheck 場景。
  2. 在「條件」下方按一下「+」來新增條件。
  3. 在文字欄位中輸入下列條件語法,檢查是否成功:

    scene.slots.status == "FINAL" && session.params.TransactionRequirementsCheck.resultType == "CAN_TRANSACT"
    
  4. 將遊標懸停在剛新增的條件上,然後按一下向上箭頭,將其放在 if scene.slots.status == "FINAL" 之前。

  5. 啟用 [Send 提示] 並提供簡單的提示,告訴使用者他們已準備好進行交易:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Looks like you're good to go!.
    
  6. 在「Transition」底下,選取另一個情境,讓使用者繼續進行對話並繼續交易。

  7. 選取條件 else if scene.slots.status == "FINAL"

  8. 啟用 [Send 提示] 並提供簡單的提示,讓使用者知道無法進行交易:

    candidates:
      - first_simple:
          variants:
            - speech: Transaction requirements check failed.
    
  9. 選取「轉換」下方的「結束對話」,如果使用者無法進行交易,即可結束對話。

建立訂單

擁有所需的使用者資訊後,請建立「購物車組」體驗,引導使用者建立預訂。每個動作都會根據自身的服務,採用稍微不同的購物車組件。

在基本的購物車組裝服務中,使用者可從清單中選擇要新增至保留項目的選項,不過您可以設計對話來簡化使用者體驗。例如,建立購物車組合體驗,讓使用者能夠以簡單或非問題的方式安排每月預訂。您也可以將輪轉介面或清單資訊卡提供給「推薦」保留項目。

我們建議使用豐富回應,以視覺化方式呈現使用者的選項,同時設計對話,讓使用者只需透過語音建構購物車。如需關於購物車組裝的最佳做法和範例,請參閱設計指南

建立一個訂單

在整個對話中,收集使用者的保留項目詳細資料,然後建構 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
};

建議訂單

建立預訂訂單後,您必須向使用者顯示該訂單, 才能確認或拒絕。如要這麼做,請轉換至執行交易決策的場景。

建立交易決策場景

  1. 在「場景」分頁中,新增名為 TransactionDecision 的新場景。
  2. 在「運算單元填充」下方,按一下 [+] 來新增運算單元。
  3. 在「Select type」(選取類型) 下方,選取 actions.type.TransactionDecisionValue 做為運算單元類型。
  4. 在運算單元名稱欄位中,為運算單元命名 TransactionDecision
  5. 勾選 [自訂版位值寫入] 核取方塊 (預設為啟用)。
  6. 在「Configure slot」(設定版位) 下方的下拉式選單中,選取 [使用工作階段參數]
  7. 在「Configure slot」(設定版位) 下方,在文字欄位中,輸入用於儲存訂單的工作階段參數名稱 (即 $session.params.order)。
  8. 按一下「儲存」

為了嘗試填入 TransactionDecisionValue 位置,Google 助理會啟動內建體驗,您傳遞的 Order 會直接顯示在「購物車預覽卡」上。使用者可以說出「安排預約」、拒絕交易,或要求變更保留項目詳細資料。

此時,使用者也可以要求變更訂單。在這種情況下,您應確保在完成購物車組合體驗後,您的出貨要求可以處理訂單變更要求。

處理交易決策結果

填入 TransactionDecisionValue 運算單元時,使用者對交易決策的答案會儲存在工作階段參數中。這個值包含下列項目:

  • ORDER_ACCEPTED
  • ORDER_REJECTED
  • CART_CHANGE_REQUESTED
  • USER_CANNOT_TRANSACT

如何處理交易決策結果:

  1. 在「場景」分頁中,選取新建立的 TransactionDecision 場景。
  2. 在「條件」下方按一下「+」來新增條件。
  3. 在文字欄位中輸入下列條件語法,檢查是否成功:

    scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_ACCEPTED"
    
  4. 將遊標懸停在您剛剛新增的條件上,然後按一下向上箭頭,將其放在 if scene.slots.status == "FINAL" 之前。

  5. 啟用 [Send 提示] 並提供簡單的提示,讓使用者知道他們的預約已完成:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Transaction completed! Your reservation
                $session.params.TransactionDecision.order.merchantOrderId is all
                set!
    
  6. 在「轉換」底下選取「結束對話」即可結束對話。

  7. 在「條件」下方按一下「+」來新增條件。

  8. 在文字欄位中輸入下列條件語法,檢查是否失敗:

      scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_REJECTED"
    
  9. 將遊標懸停在您剛剛新增的條件上,然後按一下向上箭頭,將其放在 if scene.slots.status == "FINAL" 之前。

  10. 啟用 [Send 提示] 並提供簡單的提示,讓使用者知道訂單遭拒:

    candidates:
      - first_simple:
          variants:
            - speech: Looks like you don't want to set up a reservation. Goodbye.
    
  11. 在「轉換」底下選取「結束對話」即可結束對話。

  12. 選取條件 else if scene.slots.status == "FINAL"

  13. 啟用「Send 提示」並提供簡單的提示,讓使用者知道無法進行交易:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Transaction failed with status
                $session.params.TransactionDecision.transactionDecision
    
  14. 在「Transition」(轉換) 下方,選取 [End 對話] 以結束使用者無法進行交易的對話。

完成預訂並傳送收據

TransactionDecisionValue 運算單元傳回 ORDER_ACCEPTED 的結果時,您必須立即執行排定保留項目所需的任何處理作業 (例如在自己的資料庫中保留保留項目)。

傳送簡單回應來維持對話的動機。使用者會收到您的回應「已收合的收據」卡片。

如何傳送初始訂單更新:

  1. 在「Scenes」(場景) 分頁中選取您的 TransactionDecision 場景。
  2. 在「Condition」(條件) 之下,選取檢查成功結果的條件 ORDER_ACCEPTED

    scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_ACCEPTED"
    
  3. 啟用 Call Webhook 並提供意圖處理常式名稱,例如 update_order

  4. 在 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 標頭中持有的不記名憑證。

如要擷取您的服務帳戶金鑰,請執行下列步驟:

  1. Google Cloud 控制台中,依序前往 [Menu] 選單 > [API 和服務] > [憑證] > [建立憑證] > [服務帳戶金鑰]。
  2. 在「Service Account」(服務帳戶) 之下選取 [New Service Account] (新增服務帳戶)
  3. 將服務帳戶設為 service-account
  4. 將「Role」(角色) 設為「Project」>「Owner」(擁有者)
  5. 將金鑰類型設為「JSON」
  6. 選取「建立」
  7. 私密 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 訂單更新,直到完成其他處理作業為止。並非所有預訂都需要每個狀態值,

測試專案

測試專案時,您可以在動作主控台中啟用沙箱模式,以便測試動作而不收費。如要啟用沙箱模式,請按照下列步驟操作:

  1. 在動作控制台中,按一下導覽中的 [測試]
  2. 按一下「設定」。
  3. 啟用 [Development Sandbox] 選項。

對於實體交易,您也可以在範例中將 isInSandbox 欄位設定為 true。這個動作相當於在「動作」控制台中啟用沙箱模式設定。如要查看使用 isInSandbox 的程式碼片段,請參閱傳送訂單更新一節。

疑難排解

如果您在測試期間遇到任何問題,請參閱交易的疑難排解步驟