本页介绍了 Chat 应用如何打开对话框 来响应用户
对话框是基于卡片的窗口式界面 通过 Chat 聊天室或消息打开的应用。该对话框及其 内容仅对打开它的用户可见。
聊天应用可以使用对话框向以下对象请求信息并从中收集信息: Chat 用户,包括多步骤表单。了解详情 如需了解如何构建表单输入,请参阅收集和处理用户信息。
前提条件
Node.js
- 一款已启用互动功能的 Google Chat 应用。要创建 交互式 Chat 应用,请完成此快速入门。
Python
- 一款已启用互动功能的 Google Chat 应用。要创建 交互式 Chat 应用,请完成此快速入门。
Apps 脚本
- 一款已启用互动功能的 Google Chat 应用。要创建 交互式聊天应用,请完成此快速入门。
打开对话框
本部分介绍了如何通过执行以下操作来响应和设置对话框:
- 通过用户互动触发对话请求。
- 通过返回并打开一个对话框来处理请求。
- 用户提交信息后,通过关闭 对话框或返回另一个对话框。
触发对话请求
Chat 应用只能打开对话框来回复用户 互动,例如斜杠命令或点击卡片消息中的按钮。
如要使用对话框回复用户,Chat 应用必须 构建可触发对话框请求的交互,例如:
- 响应斜杠命令。若要通过斜杠命令触发请求,请执行以下操作: 配置此命令时,您必须选中打开对话框复选框。
- 在
消息、
以卡片形式显示或在邮件底部显示要触发
请求,您可以配置
按钮的
onClick
操作(将其interaction
设置为OPEN_DIALOG
)。 - 响应 Chat 应用首页中的按钮点击。 要了解如何从首页打开对话框,请参阅 为 Google Chat 应用构建首页。
以下 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
设置为 DIALOG
;
Message
对象。要指定对话框的内容,请添加以下内容
对象:
actionResponse
该对象的type
设置为DIALOG
。dialogAction
对象。body
字段包含 卡片中显示的内容,sections
的 widget。 要从用户处收集信息,您可以指定表单输入微件和 按钮微件。如需详细了解如何设计表单输入,请参阅 收集和处理用户信息。
以下 JSON 展示了 Chat 应用如何返回 打开对话框的响应:
{ "actionResponse": {
"type": "DIALOG",
"dialogAction": { "dialog": { "body": { "sections": [{
"widgets": [{
WIDGETS,
{ "buttonList": { "buttons": [{
"text": "BUTTON_TEXT",
"onClick": {
"action": {"function": "FUNCTION_NAME"}
}
}]}}
}]
}]}}}
}}
其中 BUTTON_TEXT 是在按钮中显示的文本(例如
Next
或 Submit
),WIDGETS 表示一个或多个
表单输入 widget 以及
FUNCTION_NAME 是在用户点击按钮时运行的函数。
处理对话框提交
当用户点击用于提交对话框的按钮时,您的
Chat 应用接收
CARD_CLICKED
互动
事件,其中 dialogEventType
为 SUBMIT_DIALOG
。
您的 Chat 应用必须通过以下方式处理互动事件: 执行以下操作之一:
可选:返回其他对话框
用户提交初始对话框后,Chat 应用可以执行以下操作 返回一个或多个其他对话框,帮助用户 提交表单、填写多步骤表单或动态填充表单内容。
要加载用户在初始对话框中输入的任何数据,您必须添加
将参数传递给用于打开下一个对话框的按钮,或者将原始
CARD_CLICKED
互动事件。有关详情,请参阅
将数据转移到其他卡。
在此示例中,Chat 应用打开一个对话框
在提交之前返回第二个对话框。要加载输入数据,
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 脚本
此示例通过返回 卡片 JSON。 您还可以使用 Apps 脚本卡片服务。
/**
* 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 应用收到与 以下信息:
eventType
为CARD_CLICKED
。dialogEventType
为SUBMIT_DIALOG
。common.formInputs
包含用户使用 widget 输入的任何数据。
以下部分介绍了如何验证用户输入的数据 关闭对话框。
验证用户输入数据并关闭对话框
为了处理用户输入的数据,Chat 应用
使用
event.common.formInputs
对象。如需详细了解如何从输入 widget 检索值,请参阅
收集和处理用户信息。
如果用户省略了必填字段,或输入了不正确的值,
Chat 应用可以返回
ActionResponse
包含 "actionStatus": "ERROR MESSAGE"
的项。
以下示例检查用户是否为微件输入了
接受字符串 (stringInputs
),例如 textInput
widget。如果没有,
Chat 应用返回错误。如果存在,
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 脚本
此示例通过返回 卡片 JSON。 您还可以使用 Apps 脚本卡片服务。
/**
* 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
字段的
widget(例如 contactName
),而 ERROR_MESSAGE 表示
错误消息的内容(例如 Don't forget to name your contact
)。
如需详细了解如何处理来自 widget 的输入数据,请参阅
从互动式微件接收数据。
可选:发送确认消息
关闭对话框后,您还可以发送新消息或更新 现有资源
要发送新消息,请返回
ActionResponse
并将 type
设置为 NEW_MESSAGE
。例如,关闭对话框
并发送短信,则返回以下内容:
{
"actionResponse": {
"type": "NEW_MESSAGE",
},
"text": "Your information has been submitted."
}
如需更新消息,请返回一个 actionResponse
对象,其中包含
更新了消息,并将 type
设置为以下其中一项:
问题排查
当 Google Chat 应用或 card 会返回错误, 聊天界面会显示一条内容为“出了点问题”的消息。 或“无法处理您的请求”。有时,Chat 界面 不会显示任何错误消息,但 Chat 应用或 卡片会产生意外结果;例如,卡片消息 。
虽然 Chat 界面中可能不会显示错误消息, 提供描述性错误消息和日志数据,以帮助您修正错误 启用 Chat 应用的错误日志记录时。如需观看方面的帮助, 请参阅 排查并修正 Google Chat 错误。