開啟互動式對話方塊

本頁面說明 Chat 應用程式如何開啟對話方塊 回覆使用者

對話方塊採用視窗式的卡片式介面 從 Chat 聊天室或訊息開啟的連結對話方塊及其 只有開啟該頁面的使用者看得見。

即時通訊應用程式可以使用對話方塊,要求及收集 即時通訊使用者,包括多步驟表單。瞭解詳情 請參閱「收集及處理使用者提供的資訊」一文。

必要條件

Node.js

  • 已啟用互動功能的 Google Chat 應用程式。如要建立 請使用 HTTP 服務互動式即時通訊應用程式,請完成快速入門導覽課程

Python

  • 已啟用互動功能的 Google Chat 應用程式。如要建立 請使用 HTTP 服務互動式即時通訊應用程式,請完成快速入門導覽課程

Apps Script

開啟對話方塊

顯示各種不同小工具的對話方塊。
圖 1:收集聯絡資訊的對話方塊。

本節說明如何按照下列步驟回應及設定對話方塊:

  1. 透過使用者互動觸發對話方塊要求。
  2. 傳回並開啟對話方塊來處理要求。
  3. 使用者提交資訊後,請透過關閉 或傳回其他對話方塊

觸發對話方塊要求

Chat 應用程式只能開啟回覆使用者的對話方塊 互動,例如斜線指令或點選資訊卡訊息中的按鈕。

如要透過對話方塊回覆使用者,Chat 應用程式必須 建構可觸發對話方塊要求的互動,如以下所示:

  • 回應斜線指令。如要透過斜線指令觸發要求, 在設定指令時,請務必勾選「開啟對話方塊」核取方塊。
  • 回應按鈕點擊的 訊息、 資訊卡或訊息底部如要觸發 要求從訊息中的按鈕提出要求 按鈕的 onClick 方法是將 interaction 設為 OPEN_DIALOG
  • 在 Chat 應用程式首頁中按一下回應按鈕。 如要瞭解如何從首頁開啟對話方塊,請參閱: 為 Google Chat 應用程式打造首頁
,瞭解如何調查及移除這項存取權。
觸發對話方塊的按鈕
圖 2:Chat 應用程式會傳送訊息,提示使用者使用 /addContact 斜線指令。
訊息中還提供按鈕,讓使用者點選後觸發指令。

下列 JSON 說明如何透過 資訊卡訊息。如要開啟對話方塊, button.interaction敬上 欄位設為 OPEN_DIALOG

{
  "buttonList": { "buttons": [{
    "text": "BUTTON_TEXT",
    "onClick": { "action": {
      "function": "FUNCTION_NAME",
      "interaction": "OPEN_DIALOG"
    }}
  }]}
}

其中 BUTTON_TEXT 是按鈕中顯示的文字 而 FUNCTION_NAME 則是執行以開啟初始 對話方塊

開啟初始對話方塊

當使用者觸發對話方塊要求時,您的 Chat 應用程式 收到的互動事件; event 是 Chat API。如果互動觸發對話方塊要求, dialogEventType 欄位已設為 REQUEST_DIALOG

如要開啟對話方塊,Chat 應用程式可以回應 並傳回 actionResponse敬上 type 設為 DIALOGMessage 物件。如要指定對話方塊內容,請加入以下內容 物件:

  • actionResponse 物件,而且其 type 設為 DIALOG
  • dialogAction 物件。body 欄位包含以下項目的使用者介面 (UI) 元素: 包括一則或多則在資訊卡中 sections 小工具。 若要收集使用者的資訊,您可以指定表單輸入小工具和 按鈕小工具。如要進一步瞭解如何設計表單輸入功能,請參閱 收集及處理使用者提供的資訊

下列 JSON 顯示 Chat 應用程式如何回傳 會開啟對話方塊的回應:

{ "actionResponse": {
  "type": "DIALOG",
  "dialogAction": { "dialog": { "body": { "sections": [{
    "widgets": [{
      WIDGETS,
      { "buttonList": { "buttons": [{
        "text": "BUTTON_TEXT",
        "onClick": {
          "action": {"function": "FUNCTION_NAME"}
        }
      }]}}
    }]
  }]}}}
}}

其中 BUTTON_TEXT 是按鈕中顯示的文字 (例如 NextSubmit),WIDGETS 代表一或多個 表單輸入小工具,以及 FUNCTION_NAME 是使用者點選按鈕時執行的函式。

處理對話方塊提交作業

當使用者按下提交對話方塊的按鈕時, Chat 應用程式獲得 CARD_CLICKED 互動 事件中,dialogEventTypeSUBMIT_DIALOG

Chat 應用程式必須透過下列方式處理互動事件: 執行下列其中一項操作:

選用:傳回其他對話方塊

使用者提交初始對話方塊後,即時通訊應用程式可以 傳回一或多個其他對話方塊,協助使用者事先查看資訊 提交、完成多步驟表單,或動態填入表單內容。

如要載入使用者從初始對話方塊輸入的任何資料,您必須新增 參數傳送至開啟下一個對話方塊的按鈕,或將原始 初始對話方塊的 CARD_CLICKED 互動事件。詳情請參閱 將資料轉移至其他卡片

在此範例中,Chat 應用程式會開啟對話方塊 才會在提交前傳回第二個對話方塊如要載入輸入資料, 即時通訊應用程式通過 CARD_CLICKED 互動事件 做為開啟下一個對話方塊的函式參數:

Node.js

// Respond to button clicks on attached cards
if (event.type === "CARD_CLICKED") {

  // Open the first dialog.
  if (event.common.invokedFunction === "openDialog") {
    openDialog(event);
  }

  // Open the second dialog.
  if (event.common.invokedFunction === "openNextDialog") {
    openNextDialog(event);
  }
}

/**
* Opens and starts a dialog that lets users add details about a contact.
*
* @param {object} event the event object from Google Chat.
*
* @return {object} open a dialog.
*/
function openDialog(event) {
  res.json({ "actionResponse": {
    "type": "DIALOG",
    "dialogAction": { "dialog": { "body": { "sections": [{ "widgets": [
      WIDGETS,
      { "buttonList": { "buttons": [{
        "text": "Next",
        "onClick": { "action": {
          "function": "openNextDialog"
        }}
      }]}}
    ]}]}}}
  }});
};

/**
* Opens a second dialog that lets users add more contact details.
*
* @param {object} event the event object from Google Chat.
*
* @return {object} open a dialog.
*/
function openNextDialog(event) {
  res.json({ "actionResponse": {
    "type": "DIALOG",
    "dialogAction": { "dialog": { "body": { "sections": [{ "widgets": [
      WIDGETS,
      {
        "horizontalAlignment": "END",
        "buttonList": { "buttons": [{
          "text": "Submit",
          "onClick": { "action": {
            "function": "submitDialog"
          }}
        }]}
      }
    ]}]}}}
  }});
}

Python

from typing import Any, Mapping

import flask
import functions_framework

@functions_framework.http
def main(req: flask.Request) -> Mapping[str, Any]:
  """Responds to a MESSAGE event in Google Chat that includes the /createContact
     slash command by opening a dialog.

  Args:
      req (flask.Request): the event object from Chat API.

  Returns:
      Mapping[str, Any]: open a Dialog in response to a card's button click.
  """

  if req.method == 'GET':
    return 'Sorry, this function must be called from a Google Chat.'

  request = req.get_json(silent=True)

  if request.get('type') == 'CARD_CLICKED':
    if invoked_function := request.get('common', dict()).get('invokedFunction'):
      if invoked_function == 'open_dialog':
        return open_dialog(request)

      elif invoked_function == 'open_next_dialog':
        return open_dialog(request)

def open_dialog(request: Mapping[str, Any]) -> Mapping[str, Any]:
  """Opens a dialog in Google Chat.

  Args:
      request (Mapping[str, Any]): the event object from Chat API.

  Returns:
      Mapping[str, Any]: open a Dialog in response to a card's button click.
  """
  return { "actionResponse": {
    "type": "DIALOG",
    "dialogAction": { "dialog": { "body": { "sections": [{ "widgets": [
      WIDGETS,
      { "buttonList": { "buttons": [{
        "text": "Next",
        "onClick": { "action": {
          "function": "open_next_dialog"
        }}
      }]}}
    ]}]}}}
  }}

def open_next_dialog(request: Mapping[str, Any]) -> Mapping[str, Any]:
  """Opens a second dialog that lets users add more contact details.

  Args:
      request (Mapping[str, Any]): the event object from Chat API.

  Returns:
      Mapping[str, Any]: open a Dialog in response to a card's button click.
  """
  return { "actionResponse": {
    "type": "DIALOG",
    "dialogAction": { "dialog": { "body": { "sections": [{ "widgets": [
      WIDGETS,
      {
        "horizontalAlignment": "END",
        "buttonList": { "buttons": [{
          "text": "Submit",
          "onClick": { "action": {
            "function": "submit_dialog"
          }}
        }]}
      }
    ]}]}}}
  }}

Apps Script

此範例會透過 資訊卡 JSON。 您也可以使用 Apps Script Card 服務

/**
* Responds to a CARD_CLICKED event in Google Chat.
*
* @param {Object} event the event object from Google Chat
*/
function onCardClick(event) {

  // When a user clicks a card, the Chat app checks to see which function to run.
  if (event.common.invokedFunction === "openDialog") {
    return openDialog(event);
  }

  if (event.common.invokedFunction === "openNextDialog") {
    return openNextDialog(event);
  }
}

/**
* Opens and starts a dialog that lets users add details about a contact.
*
* @param {object} event the event object from Google Chat.
*
* @return {object} open a dialog.
*/
function openDialog(event) {
  return { "actionResponse": {
    "type": "DIALOG",
    "dialogAction": { "dialog": { "body": { "sections": [{ "widgets": [
      WIDGETS,
      { "buttonList": { "buttons": [{
        "text": "Next",
        "onClick": { "action": {
          "function": "openNextDialog"
        }}
      }]}}
    ]}]}}}
  }};
}

/**
* Opens a second dialog that lets users add more contact details.
*
* @param {object} event the event object from Google Chat.
*
* @return {object} open a dialog.
*/
function openNextDialog(event) {
  return { "actionResponse": {
    "type": "DIALOG",
    "dialogAction": { "dialog": { "body": { "sections": [{ "widgets": [
      WIDGETS,
      {
        "horizontalAlignment": "END",
        "buttonList": { "buttons": [{
          "text": "Submit",
          "onClick": { "action": {
            "function": "submitDialog"
          }}
        }]}
      }
    ]}]}}}
  }};
}

其中 WIDGETS 代表一或多個 表單輸入小工具

關閉對話方塊

當使用者點選對話方塊中的按鈕時, Chat 應用程式收到與 以下資訊:

以下各節將說明如何驗證使用者輸入的資料,以及 關閉對話方塊。

驗證使用者輸入資料並關閉對話方塊

為了處理使用者輸入的資料,Chat 應用程式 採用 event.common.formInputs敬上 物件。如要進一步瞭解如何從輸入小工具擷取值,請參閱 收集及處理使用者提供的資訊

如果使用者省略必填欄位,或是輸入的值不正確, 即時通訊應用程式會傳回 ActionResponse敬上 其中包含 "actionStatus": "ERROR MESSAGE"

以下範例會檢查使用者是否已為小工具輸入值 接受字串 (stringInputs),例如 textInput 小工具。如果沒有, 即時通訊應用程式傳回錯誤。如果有的話 Chat 應用程式確認使用者提交對話方塊後 關閉對話方塊:

Node.js

/**
* Checks for a form input error, the absence of
* a "name" value, and returns an error if absent.
* Otherwise, confirms successful receipt of a dialog.
*
* Confirms successful receipt of a dialog.
*
* @param {Object} event the event object from Chat API.
*
* @return {Object} open a Dialog in Google Chat.
*/
function submitDialog(event) {

  // Checks to make sure the user entered a value
  // in a dialog. If no value detected, returns
  // an error message. Any "actionStatus" value other than "OK"
  // gets returned as an error.
  if (event.common.formInputs.WIDGET_NAME.stringInputs.value[0] === "") {
    res.json({
      "actionResponse": {
        "type": "DIALOG",
        "dialogAction": {
          "actionStatus": "ERROR_MESSAGE"
        }
      }
    });

    // Otherwise the Chat app indicates that it received
    // form data from the dialog. An "actionStatus" of "OK" is
    // interpreted as code 200, and the dialog closes.
  } else {
    res.json({
      "actionResponse": {
        "type": "DIALOG",
        "dialogAction": {
          "actionStatus": "OK"
        }
      }
    });
  }
}

Python

def receive_dialog(event: Mapping[str, Any]) -> Mapping[str, Any]:
  """Checks for a form input error, the absence of a "name" value, and returns
     an error if absent. Otherwise, confirms successful receipt of a dialog.

  Args:
      event (Mapping[str, Any]): the event object from Chat API.

  Returns:
      Mapping[str, Any]: the response.
  """

  if common := event.get('common'):
    if form_inputs := common.get('formInputs'):
      if contact_name := form_inputs.get('WIDGET_NAME'):
        if string_inputs := contact_name.get('stringInputs'):
          if name := string_inputs.get('value')[0]:
            return {
              'actionResponse': {
                'type': 'DIALOG',
                'dialogAction': {
                  'actionStatus': 'OK'
                }
              }
            }
          else:
            return {
              'actionResponse': {
                'type': 'DIALOG',
                'dialogAction': {
                  'actionStatus': 'ERROR_MESSAGE'
                }
              }
            }

Apps Script

此範例會透過 資訊卡 JSON。 您也可以使用 Apps Script Card 服務

/**
* Checks for a form input error, the absence of
* a "name" value, and returns an error if absent.
* Otherwise, confirms successful receipt of a dialog.
*
* Confirms successful receipt of a dialog.
*
* @param {Object} event the event object from Chat API.
*
* @return {object} open a Dialog in Google Chat.
*/
function submitDialog(event) {

  // Checks to make sure the user entered a value
  // in a dialog. If no value detected, returns
  // an error message. Any "actionStatus" value other than "OK"
  // gets returned as an error.
  if (event.common.formInputs.WIDGET_NAME[""].stringInputs.value[0] === "") {
    return {
      "actionResponse": {
        "type": "DIALOG",
        "dialogAction": {
          "actionStatus": "ERROR_MESSAGE"
        }
      }
    };

    // Otherwise the Chat app indicates that it received
    // form data from the dialog. An "actionStatus" of "OK" is
    // interpreted as code 200, and the dialog closes.
  } else {
    return {
      "actionResponse": {
        "type": "DIALOG",
        "dialogAction": {
          "actionStatus": "OK"
        }
      }
    };
  }
}

在本例中,WIDGET_NAME 代表name 小工具 (例如 contactName),而 ERROR_MESSAGE 則代表 錯誤訊息的內容 (例如 Don't forget to name your contact)。 如要進一步瞭解如何處理小工具的輸入資料,請參閱 接收互動式小工具的資料

選用:傳送確認訊息

關閉對話方塊後,你也可以傳送新訊息 現有的連結

如要傳送新訊息,請回傳 ActionResponse敬上 type 設為 NEW_MESSAGE 的物件。例如關閉對話方塊 傳送簡訊,則傳回以下內容:

  {
    "actionResponse": {
      "type": "NEW_MESSAGE",
    },
    "text": "Your information has been submitted."
  }

若要更新訊息,請傳回包含 actionResponse 物件 已更新訊息,並將 type 設為下列其中一種狀態:

  • UPDATE_MESSAGE:更新訊息 觸發對話方塊要求
  • UPDATE_USER_MESSAGE_CARDS:從 連結預覽

疑難排解

Google Chat 應用程式或 card 會傳回錯誤, 即時通訊介面顯示「發生錯誤」的訊息。 或「無法處理你的要求」。有時使用 Chat UI 不會顯示任何錯誤訊息,但 Chat 應用程式或 資訊卡產生非預期的結果例如資訊卡訊息 顯示。

雖然 Chat UI 中可能不會顯示錯誤訊息, 提供描述性錯誤訊息和記錄資料,協助您修正錯誤 。如需觀看說明, 偵錯及修正錯誤,請參閱 疑難排解並修正 Google Chat 錯誤