Mở hộp thoại tương tác

Trang này mô tả cách ứng dụng Chat của bạn có thể mở hộp thoại để phản hồi người dùng.

Hộp thoại là giao diện dạng cửa sổ, dựa trên thẻ mở ra từ một không gian hoặc tin nhắn trên Chat. Hộp thoại và nội dung của hộp thoại chỉ hiển thị với người dùng đã mở hộp thoại đó.

Ứng dụng Chat có thể sử dụng hộp thoại để yêu cầu và thu thập thông tin từ người dùng Chat, bao gồm cả biểu mẫu nhiều bước. Để biết thêm thông tin chi tiết về cách tạo dữ liệu đầu vào của biểu mẫu, hãy xem phần Thu thập và xử lý thông tin từ người dùng.

Điều kiện tiên quyết

Node.js

Ứng dụng Google Chat đã bật các tính năng tương tác. Để tạo một ứng dụng Chat tương tác bằng dịch vụ HTTP, hãy hoàn tất hướng dẫn bắt đầu nhanh này.

Python

Ứng dụng Google Chat đã bật các tính năng tương tác. Để tạo một ứng dụng Chat tương tác bằng dịch vụ HTTP, hãy hoàn tất hướng dẫn bắt đầu nhanh này.

Java

Ứng dụng Google Chat đã bật các tính năng tương tác. Để tạo một ứng dụng Chat tương tác bằng dịch vụ HTTP, hãy hoàn tất hướng dẫn bắt đầu nhanh này.

Apps Script

Ứng dụng Google Chat đã bật các tính năng tương tác. Để tạo một ứng dụng Chat có thể tương tác trong Apps Script, hãy hoàn thành hướng dẫn nhanh này.

Mở hộp thoại

Một hộp thoại có nhiều tiện ích khác nhau.
Hình 1: Một ứng dụng Chat mẫu mở một hộp thoại để thu thập thông tin liên hệ.

Phần này giải thích cách phản hồi và thiết lập hộp thoại bằng cách làm như sau:

  1. Kích hoạt yêu cầu hộp thoại từ một lượt tương tác của người dùng.
  2. Xử lý yêu cầu bằng cách trả về và mở một hộp thoại.
  3. Sau khi người dùng gửi thông tin, hãy xử lý thông tin đã gửi bằng cách đóng hộp thoại hoặc trả về một hộp thoại khác.

Kích hoạt yêu cầu hộp thoại

Ứng dụng Chat chỉ có thể mở hộp thoại để phản hồi một lượt tương tác của người dùng, chẳng hạn như lệnh dấu gạch chéo hoặc lượt nhấp vào nút từ một tin nhắn trong thẻ.

Để phản hồi người dùng bằng một hộp thoại, ứng dụng Chat phải tạo một hoạt động tương tác kích hoạt yêu cầu hộp thoại, chẳng hạn như sau:

  • Phản hồi lệnh dấu gạch chéo. Để kích hoạt yêu cầu từ một lệnh gạch chéo, bạn phải đánh dấu vào hộp đánh dấu Mở hộp thoại khi thiết lập lệnh.
  • Phản hồi một lượt nhấp vào nút trong tin nhắn, dưới dạng một phần của thẻ hoặc ở cuối tin nhắn. Để kích hoạt yêu cầu từ một nút trong thông báo, bạn hãy định cấu hình hành động onClick của nút đó bằng cách đặt interaction thành OPEN_DIALOG.
  • Phản hồi một lượt nhấp vào nút trên trang chủ của ứng dụng Chat. Để tìm hiểu về cách mở hộp thoại từ trang chủ, hãy xem bài viết Tạo trang chủ cho ứng dụng Google Chat.
Nút kích hoạt hộp thoại
Hình 2: Ứng dụng Chat gửi một thông báo nhắc người dùng sử dụng lệnh gạch chéo /addContact.
Thông báo này cũng bao gồm một nút mà người dùng có thể nhấp vào để kích hoạt lệnh.

Mẫu mã sau đây cho biết cách kích hoạt yêu cầu hộp thoại từ một nút trong thông báo thẻ. Để mở hộp thoại, hãy đặt trường button.interaction thành OPEN_DIALOG:

Node.js

node/contact-form-app/index.js
buttonList: { buttons: [{
  text: "Add Contact",
  onClick: { action: {
    function: "openInitialDialog",
    interaction: "OPEN_DIALOG"
  }}
}]}

Python

python/contact-form-app/main.py
'buttonList': { 'buttons': [{
  'text': "Add Contact",
  'onClick': { 'action': {
    'function': "openInitialDialog",
    'interaction': "OPEN_DIALOG"
  }}
}]}

Java

java/contact-form-app/src/main/java/com/google/chat/contact/App.java
.setButtonList(new GoogleAppsCardV1ButtonList().setButtons(List.of(new GoogleAppsCardV1Button()
  .setText("Add Contact")
  .setOnClick(new GoogleAppsCardV1OnClick().setAction(new GoogleAppsCardV1Action()
    .setFunction("openInitialDialog")
    .setInteraction("OPEN_DIALOG"))))))));

Apps Script

Ví dụ này gửi thông báo thẻ bằng cách trả về JSON thẻ. Bạn cũng có thể sử dụng dịch vụ thẻ Apps Script.

apps-script/contact-form-app/main.gs
buttonList: { buttons: [{
  text: "Add Contact",
  onClick: { action: {
    function: "openInitialDialog",
    interaction: "OPEN_DIALOG"
  }}
}]}

Mở hộp thoại ban đầu

Khi người dùng kích hoạt một yêu cầu hộp thoại, ứng dụng Chat của bạn sẽ nhận được một sự kiện tương tác, được biểu thị dưới dạng loại event trong Chat API. Nếu lượt tương tác kích hoạt một yêu cầu hộp thoại, thì trường dialogEventType của sự kiện sẽ được đặt thành REQUEST_DIALOG.

Để mở hộp thoại, ứng dụng Chat có thể phản hồi yêu cầu bằng cách trả về đối tượng actionResponse với type được đặt thành DIALOG và đối tượng Message. Để chỉ định nội dung của hộp thoại, bạn thêm các đối tượng sau:

  • Một đối tượng actionResponse, với type được đặt thành DIALOG.
  • Đối tượng dialogAction. Trường body chứa các thành phần giao diện người dùng (UI) để hiển thị trong thẻ, bao gồm một hoặc nhiều sections của tiện ích. Để thu thập thông tin từ người dùng, bạn có thể chỉ định các tiện ích nhập dữ liệu biểu mẫu và một tiện ích nút. Để tìm hiểu thêm về cách thiết kế phần nhập thông tin trên biểu mẫu, hãy xem phần Thu thập và xử lý thông tin từ người dùng.

Mã mẫu sau đây cho thấy cách ứng dụng Chat trả về một phản hồi mở ra hộp thoại:

Node.js

node/contact-form-app/index.js
/**
 * Opens the initial step of the dialog that lets users add contact details.
 *
 * @return {Object} a message with an action response to open a dialog.
 */
function openInitialDialog() {
  return { actionResponse: {
    type: "DIALOG",
    dialogAction: { dialog: { body: { sections: [{
      header: "Add new contact",
      widgets: CONTACT_FORM_WIDGETS.concat([{
        buttonList: { buttons: [{
          text: "Review and submit",
          onClick: { action: { function: "openConfirmation" }}
        }]}
      }])
    }]}}}
  }};
}

Python

python/contact-form-app/main.py
def open_initial_dialog() -> dict:
  """Opens the initial step of the dialog that lets users add contact details."""
  return { 'actionResponse': {
    'type': "DIALOG",
    'dialogAction': { 'dialog': { 'body': { 'sections': [{
      'header': "Add new contact",
      'widgets': CONTACT_FORM_WIDGETS + [{
        'buttonList': { 'buttons': [{
          'text': "Review and submit",
          'onClick': { 'action': { 'function': "openConfirmation" }}
        }]}
      }]
    }]}}}
  }}

Java

java/contact-form-app/src/main/java/com/google/chat/contact/App.java
// Opens the initial step of the dialog that lets users add contact details.
Message openInitialDialog() {
  return new Message().setActionResponse(new ActionResponse()
    .setType("DIALOG")
    .setDialogAction(new DialogAction().setDialog(new Dialog().setBody(new GoogleAppsCardV1Card()
      .setSections(List.of(new GoogleAppsCardV1Section()
        .setHeader("Add new contact")
        .setWidgets(Stream.concat(
          CONTACT_FORM_WIDGETS.stream(),
          List.of(new GoogleAppsCardV1Widget()
            .setButtonList(new GoogleAppsCardV1ButtonList().setButtons(List.of(new GoogleAppsCardV1Button()
            .setText("Review and submit")
            .setOnClick(new GoogleAppsCardV1OnClick().setAction(new GoogleAppsCardV1Action()
              .setFunction("openConfirmation"))))))).stream()).collect(Collectors.toList()))))))));
}

Apps Script

Ví dụ này gửi thông báo thẻ bằng cách trả về JSON thẻ. Bạn cũng có thể sử dụng dịch vụ thẻ Apps Script.

apps-script/contact-form-app/main.gs
/**
 * Opens the initial step of the dialog that lets users add contact details.
 *
 * @return {Object} a message with an action response to open a dialog.
 */
function openInitialDialog() {
  return { actionResponse: {
    type: "DIALOG",
    dialogAction: { dialog: { body: { sections: [{
      header: "Add new contact",
      widgets: CONTACT_FORM_WIDGETS.concat([{
        buttonList: { buttons: [{
          text: "Review and submit",
          onClick: { action: { function: "openConfirmation" }}
        }]}
      }])
    }]}}}
  }};
}

Xử lý việc gửi hộp thoại

Khi người dùng nhấp vào nút gửi hộp thoại, ứng dụng Chat sẽ nhận được một sự kiện tương tác CARD_CLICKED, trong đó dialogEventTypeSUBMIT_DIALOG.

Ứng dụng Chat của bạn phải xử lý sự kiện tương tác bằng cách làm theo một trong những cách sau:

Không bắt buộc: Trả về một hộp thoại khác

Sau khi người dùng gửi hộp thoại ban đầu, ứng dụng Chat có thể trả về một hoặc nhiều hộp thoại bổ sung để giúp người dùng xem lại thông tin trước khi gửi, hoàn tất biểu mẫu nhiều bước hoặc tự động điền nội dung biểu mẫu.

Để xử lý dữ liệu mà người dùng nhập, ứng dụng Chat sử dụng đối tượng event.common.formInputs. Để tìm hiểu thêm về cách truy xuất giá trị từ các tiện ích đầu vào, hãy xem phần Thu thập và xử lý thông tin từ người dùng.

Để theo dõi mọi dữ liệu mà người dùng nhập từ hộp thoại ban đầu, bạn phải thêm các tham số vào nút mở hộp thoại tiếp theo. Để biết thông tin chi tiết, hãy xem phần Chuyển dữ liệu sang thẻ khác.

Trong ví dụ này, ứng dụng Chat sẽ mở một hộp thoại ban đầu dẫn đến hộp thoại thứ hai để xác nhận trước khi gửi:

Node.js

node/contact-form-app/index.js
/**
 * Responds to CARD_CLICKED interaction events in Google Chat.
 *
 * @param {Object} event the CARD_CLICKED interaction event from Google Chat.
 * @return {Object} message responses specific to the dialog handling.
 */
function onCardClick(event) {
  // Initial dialog form page
  if (event.common.invokedFunction === "openInitialDialog") {
    return openInitialDialog();
  // Confirmation dialog form page
  } else if (event.common.invokedFunction === "openConfirmation") {
    return openConfirmation(event);
  // Submission dialog form page
  } else if (event.common.invokedFunction === "submitForm") {
    return submitForm(event);
  }
}

/**
 * Opens the initial step of the dialog that lets users add contact details.
 *
 * @return {Object} a message with an action response to open a dialog.
 */
function openInitialDialog() {
  return { actionResponse: {
    type: "DIALOG",
    dialogAction: { dialog: { body: { sections: [{
      header: "Add new contact",
      widgets: CONTACT_FORM_WIDGETS.concat([{
        buttonList: { buttons: [{
          text: "Review and submit",
          onClick: { action: { function: "openConfirmation" }}
        }]}
      }])
    }]}}}
  }};
}

/**
 * Returns the second step as a dialog or card message that lets users confirm details.
 *
 * @param {Object} event the interactive event with form inputs.
 * @return {Object} returns a dialog or private card message.
 */
function openConfirmation(event) {
  const name = fetchFormValue(event, "contactName") ?? "";
  const birthdate = fetchFormValue(event, "contactBirthdate") ?? "";
  const type = fetchFormValue(event, "contactType") ?? "";
  const cardConfirmation = {
    header: "Your contact",
    widgets: [{
      textParagraph: { text: "Confirm contact information and submit:" }}, {
      textParagraph: { text: "<b>Name:</b> " + name }}, {
      textParagraph: {
        text: "<b>Birthday:</b> " + convertMillisToDateString(birthdate)
      }}, {
      textParagraph: { text: "<b>Type:</b> " + type }}, {
      buttonList: { buttons: [{
        text: "Submit",
        onClick: { action: {
          function: "submitForm",
          parameters: [{
            key: "contactName", value: name }, {
            key: "contactBirthdate", value: birthdate }, {
            key: "contactType", value: type
          }]
        }}
      }]}
    }]
  };

  // Returns a dialog with contact information that the user input.
  if (event.isDialogEvent) {
    return { action_response: {
      type: "DIALOG",
      dialogAction: { dialog: { body: { sections: [ cardConfirmation ]}}}
    }};
  }

  // Updates existing card message with contact information that the user input.
  return {
    actionResponse: { type: "UPDATE_MESSAGE" },
    privateMessageViewer: event.user,
    cardsV2: [{
      card: { sections: [cardConfirmation]}
    }]
  }
}

Python

python/contact-form-app/main.py
def on_card_click(event: dict) -> dict:
  """Responds to CARD_CLICKED interaction events in Google Chat."""
  # Initial dialog form page
  if "openInitialDialog" == event.get('common').get('invokedFunction'):
    return open_initial_dialog()
  # Confirmation dialog form page
  elif "openConfirmation" == event.get('common').get('invokedFunction'):
    return open_confirmation(event)
  # Submission dialog form page
  elif "submitForm" == event.get('common').get('invokedFunction'):
    return submit_form(event)


def open_initial_dialog() -> dict:
  """Opens the initial step of the dialog that lets users add contact details."""
  return { 'actionResponse': {
    'type': "DIALOG",
    'dialogAction': { 'dialog': { 'body': { 'sections': [{
      'header': "Add new contact",
      'widgets': CONTACT_FORM_WIDGETS + [{
        'buttonList': { 'buttons': [{
          'text': "Review and submit",
          'onClick': { 'action': { 'function': "openConfirmation" }}
        }]}
      }]
    }]}}}
  }}


def open_confirmation(event: dict) -> dict:
  """Returns the second step as a dialog or card message that lets users confirm details."""
  name = fetch_form_value(event, "contactName") or ""
  birthdate = fetch_form_value(event, "contactBirthdate") or ""
  type = fetch_form_value(event, "contactType") or ""
  card_confirmation = {
    'header': "Your contact",
    'widgets': [{
      'textParagraph': { 'text': "Confirm contact information and submit:" }}, {
      'textParagraph': { 'text': "<b>Name:</b> " + name }}, {
      'textParagraph': {
        'text': "<b>Birthday:</b> " + convert_millis_to_date_string(birthdate)
      }}, {
      'textParagraph': { 'text': "<b>Type:</b> " + type }}, {
      'buttonList': { 'buttons': [{
        'text': "Submit",
        'onClick': { 'action': {
          'function': "submitForm",
          'parameters': [{
            'key': "contactName", 'value': name }, {
            'key': "contactBirthdate", 'value': birthdate }, {
            'key': "contactType", 'value': type
          }]
        }}
      }]}
    }]
  }

  # Returns a dialog with contact information that the user input.
  if event.get('isDialogEvent'): 
    return { 'action_response': {
      'type': "DIALOG",
      'dialogAction': { 'dialog': { 'body': { 'sections': [card_confirmation] }}}
    }}

  # Updates existing card message with contact information that the user input.
  return {
    'actionResponse': { 'type': "UPDATE_MESSAGE" },
    'privateMessageViewer': event.get('user'),
    'cardsV2': [{
      'card': { 'sections': [card_confirmation] }
    }]
  }

Java

java/contact-form-app/src/main/java/com/google/chat/contact/App.java
// Responds to CARD_CLICKED interaction events in Google Chat.
Message onCardClick(JsonNode event) {
  String invokedFunction = event.at("/common/invokedFunction").asText();
  // Initial dialog form page
  if ("openInitialDialog".equals(invokedFunction)) {
    return openInitialDialog();
  // Confirmation dialog form page
  } else if ("openConfirmation".equals(invokedFunction)) {
    return openConfirmation(event);
  // Submission dialog form page
  } else if ("submitForm".equals(invokedFunction)) {
    return submitForm(event);
  }
  return null; 
}

// Opens the initial step of the dialog that lets users add contact details.
Message openInitialDialog() {
  return new Message().setActionResponse(new ActionResponse()
    .setType("DIALOG")
    .setDialogAction(new DialogAction().setDialog(new Dialog().setBody(new GoogleAppsCardV1Card()
      .setSections(List.of(new GoogleAppsCardV1Section()
        .setHeader("Add new contact")
        .setWidgets(Stream.concat(
          CONTACT_FORM_WIDGETS.stream(),
          List.of(new GoogleAppsCardV1Widget()
            .setButtonList(new GoogleAppsCardV1ButtonList().setButtons(List.of(new GoogleAppsCardV1Button()
            .setText("Review and submit")
            .setOnClick(new GoogleAppsCardV1OnClick().setAction(new GoogleAppsCardV1Action()
              .setFunction("openConfirmation"))))))).stream()).collect(Collectors.toList()))))))));
}

// Returns the second step as a dialog or card message that lets users confirm details.
Message openConfirmation(JsonNode event) {
  String name = fetchFormValue(event, "contactName") != null ?
    fetchFormValue(event, "contactName") : "";
  String birthdate = fetchFormValue(event, "contactBirthdate") != null ?
    fetchFormValue(event, "contactBirthdate") : "";
  String type = fetchFormValue(event, "contactType") != null ?
    fetchFormValue(event, "contactType") : "";
  GoogleAppsCardV1Section cardConfirmationSection = new GoogleAppsCardV1Section()
    .setHeader("Your contact")
    .setWidgets(List.of(
      new GoogleAppsCardV1Widget().setTextParagraph(new GoogleAppsCardV1TextParagraph()
        .setText("Confirm contact information and submit:")),
      new GoogleAppsCardV1Widget().setTextParagraph(new GoogleAppsCardV1TextParagraph()
        .setText("<b>Name:</b> " + name)),
      new GoogleAppsCardV1Widget().setTextParagraph(new GoogleAppsCardV1TextParagraph()
        .setText("<b>Birthday:</b> " + convertMillisToDateString(birthdate))),
      new GoogleAppsCardV1Widget().setTextParagraph(new GoogleAppsCardV1TextParagraph()
        .setText("<b>Type:</b> " + type)),
      new GoogleAppsCardV1Widget().setButtonList(new GoogleAppsCardV1ButtonList().setButtons(List.of(new GoogleAppsCardV1Button()
        .setText("Submit")
        .setOnClick(new GoogleAppsCardV1OnClick().setAction(new GoogleAppsCardV1Action()
          .setFunction("submitForm")
          .setParameters(List.of(
            new GoogleAppsCardV1ActionParameter().setKey("contactName").setValue(name),
            new GoogleAppsCardV1ActionParameter().setKey("contactBirthdate").setValue(birthdate),
            new GoogleAppsCardV1ActionParameter().setKey("contactType").setValue(type))))))))));

  // Returns a dialog with contact information that the user input.
  if (event.at("/isDialogEvent") != null && event.at("/isDialogEvent").asBoolean()) {
    return new Message().setActionResponse(new ActionResponse()
      .setType("DIALOG")
      .setDialogAction(new DialogAction().setDialog(new Dialog().setBody(new GoogleAppsCardV1Card()
        .setSections(List.of(cardConfirmationSection))))));
  }

  // Updates existing card message with contact information that the user input.
  return new Message()
    .setActionResponse(new ActionResponse()
      .setType("UPDATE_MESSAGE"))
    .setPrivateMessageViewer(new User().setName(event.at("/user/name").asText()))
    .setCardsV2(List.of(new CardWithId().setCard(new GoogleAppsCardV1Card()
      .setSections(List.of(cardConfirmationSection)))));
}

Apps Script

Ví dụ này gửi thông báo thẻ bằng cách trả về JSON thẻ. Bạn cũng có thể sử dụng dịch vụ thẻ Apps Script.

apps-script/contact-form-app/main.gs
/**
 * Responds to CARD_CLICKED interaction events in Google Chat.
 *
 * @param {Object} event the CARD_CLICKED interaction event from Google Chat.
 * @return {Object} message responses specific to the dialog handling.
 */
function onCardClick(event) {
  // Initial dialog form page
  if (event.common.invokedFunction === "openInitialDialog") {
    return openInitialDialog();
  // Confirmation dialog form page
  } else if (event.common.invokedFunction === "openConfirmation") {
    return openConfirmation(event);
  // Submission dialog form page
  } else if (event.common.invokedFunction === "submitForm") {
    return submitForm(event);
  }
}

/**
 * Opens the initial step of the dialog that lets users add contact details.
 *
 * @return {Object} a message with an action response to open a dialog.
 */
function openInitialDialog() {
  return { actionResponse: {
    type: "DIALOG",
    dialogAction: { dialog: { body: { sections: [{
      header: "Add new contact",
      widgets: CONTACT_FORM_WIDGETS.concat([{
        buttonList: { buttons: [{
          text: "Review and submit",
          onClick: { action: { function: "openConfirmation" }}
        }]}
      }])
    }]}}}
  }};
}

/**
 * Returns the second step as a dialog or card message that lets users confirm details.
 *
 * @param {Object} event the interactive event with form inputs.
 * @return {Object} returns a dialog or private card message.
 */
function openConfirmation(event) {
  const name = fetchFormValue(event, "contactName") ?? "";
  const birthdate = fetchFormValue(event, "contactBirthdate") ?? "";
  const type = fetchFormValue(event, "contactType") ?? "";
  const cardConfirmation = {
    header: "Your contact",
    widgets: [{
      textParagraph: { text: "Confirm contact information and submit:" }}, {
      textParagraph: { text: "<b>Name:</b> " + name }}, {
      textParagraph: {
        text: "<b>Birthday:</b> " + convertMillisToDateString(birthdate)
      }}, {
      textParagraph: { text: "<b>Type:</b> " + type }}, {
      buttonList: { buttons: [{
        text: "Submit",
        onClick: { action: {
          function: "submitForm",
          parameters: [{
            key: "contactName", value: name }, {
            key: "contactBirthdate", value: birthdate }, {
            key: "contactType", value: type
          }]
        }}
      }]}
    }]
  };

  // Returns a dialog with contact information that the user input.
  if (event.isDialogEvent) {
    return { action_response: {
      type: "DIALOG",
      dialogAction: { dialog: { body: { sections: [ cardConfirmation ]}}}
    }};
  }

  // Updates existing card message with contact information that the user input.
  return {
    actionResponse: { type: "UPDATE_MESSAGE" },
    privateMessageViewer: event.user,
    cardsV2: [{
      card: { sections: [cardConfirmation]}
    }]
  }
}

Đóng hộp thoại

Khi người dùng nhấp vào một nút trên hộp thoại, ứng dụng Chat sẽ thực thi hành động liên quan và cung cấp cho đối tượng sự kiện thông tin sau:

Ứng dụng Chat sẽ trả về một đối tượng ActionResponse với type được đặt thành DIALOGdialogAction.

Không bắt buộc: Hiển thị thông báo

Khi đóng hộp thoại, bạn cũng có thể hiển thị thông báo văn bản.

Ứng dụng Chat có thể phản hồi bằng thông báo thành công hoặc lỗi bằng cách trả về một ActionResponse đã đặt actionStatus.

Ví dụ sau đây kiểm tra để đảm bảo các tham số hợp lệ và đóng hộp thoại bằng thông báo văn bản tuỳ thuộc vào kết quả:

Node.js

node/contact-form-app/index.js
const contactName = event.common.parameters["contactName"];
// Checks to make sure the user entered a contact name.
// If no name value detected, returns an error message.
if (!contactName) {
  const errorMessage = "Don't forget to name your new contact!";
  if (event.dialogEventType === "SUBMIT_DIALOG") {
    return { actionResponse: {
      type: "DIALOG",
      dialogAction: { actionStatus: {
        statusCode: "INVALID_ARGUMENT",
        userFacingMessage: errorMessage
      }}
    }};
  } else {
    return {
      privateMessageViewer: event.user,
      text: errorMessage
    };
  }
}

Python

python/contact-form-app/main.py
contact_name = event.get('common').get('parameters')["contactName"]
# Checks to make sure the user entered a contact name.
# If no name value detected, returns an error message.
if contact_name == "":
  error_message = "Don't forget to name your new contact!"
  if "SUBMIT_DIALOG" == event.get('dialogEventType'):
    return { 'actionResponse': {
      'type': "DIALOG",
      'dialogAction': { 'actionStatus': {
        'statusCode': "INVALID_ARGUMENT",
        'userFacingMessage': error_message
      }}
    }}
  else:
    return {
      'privateMessageViewer': event.get('user'),
      'text': error_message
    }

Java

java/contact-form-app/src/main/java/com/google/chat/contact/App.java
String contactName = event.at("/common/parameters/contactName").asText();
// Checks to make sure the user entered a contact name.
// If no name value detected, returns an error message.
if (contactName.isEmpty()) {
  String errorMessage = "Don't forget to name your new contact!";
  if (event.at("/dialogEventType") != null && "SUBMIT_DIALOG".equals(event.at("/dialogEventType").asText())) {
    return new Message().setActionResponse(new ActionResponse()
      .setType("DIALOG")
      .setDialogAction(new DialogAction().setActionStatus(new ActionStatus()
        .setStatusCode("INVALID_ARGUMENT")
        .setUserFacingMessage(errorMessage))));
  } else {
    return new Message()
      .setPrivateMessageViewer(new User().setName(event.at("/user/name").asText()))
      .setText(errorMessage);
  }
}

Apps Script

Ví dụ này gửi thông báo thẻ bằng cách trả về JSON thẻ. Bạn cũng có thể sử dụng dịch vụ thẻ Apps Script.

apps-script/contact-form-app/main.gs
const contactName = event.common.parameters["contactName"];
// Checks to make sure the user entered a contact name.
// If no name value detected, returns an error message.
if (!contactName) {
  const errorMessage = "Don't forget to name your new contact!";
  if (event.dialogEventType === "SUBMIT_DIALOG") {
    return { actionResponse: {
      type: "DIALOG",
      dialogAction: { actionStatus: {
        statusCode: "INVALID_ARGUMENT",
        userFacingMessage: errorMessage
      }}
    }};
  } else {
    return {
      privateMessageViewer: event.user,
      text: errorMessage
    };
  }
}

Để biết thông tin chi tiết về cách truyền tham số giữa các hộp thoại, hãy xem phần Chuyển dữ liệu sang thẻ khác.

Không bắt buộc: Gửi thông báo xác nhận

Khi đóng hộp thoại, bạn cũng có thể gửi một thông báo mới hoặc cập nhật thông báo hiện có.

Để gửi một thông báo mới, hãy trả về một đối tượng ActionResponse với type được đặt thành NEW_MESSAGE. Ví dụ sau đây đóng hộp thoại bằng thông báo văn bản và tin nhắn văn bản xác nhận:

Node.js

node/contact-form-app/index.js
// The Chat app indicates that it received form data from the dialog or card.
// Sends private text message that confirms submission.
const confirmationMessage = "✅ " + contactName + " has been added to your contacts.";
if (event.dialogEventType === "SUBMIT_DIALOG") {
  return {
    actionResponse: {
      type: "DIALOG",
      dialogAction: { actionStatus: {
        statusCode: "OK",
        userFacingMessage: "Success " + contactName
      }}
    }
  }
} else {
  return {
    actionResponse: { type: "NEW_MESSAGE" },
    privateMessageViewer: event.user,
    text: confirmationMessage
  };
}

Python

python/contact-form-app/main.py
# The Chat app indicates that it received form data from the dialog or card.
# Sends private text message that confirms submission.
confirmation_message = "✅ " + contact_name + " has been added to your contacts.";
if "SUBMIT_DIALOG" == event.get('dialogEventType'):
  return {
    'actionResponse': {
      'type': "DIALOG",
      'dialogAction': { 'actionStatus': {
        'statusCode': "OK",
        'userFacingMessage': "Success " + contact_name
      }}
    }
  }
else:
  return {
    'actionResponse': { 'type': "NEW_MESSAGE" },
    'privateMessageViewer': event.get('user'),
    'text': confirmation_message
  }

Java

java/contact-form-app/src/main/java/com/google/chat/contact/App.java
// The Chat app indicates that it received form data from the dialog or card.
// Sends private text message that confirms submission.
String confirmationMessage = "✅ " + contactName + " has been added to your contacts.";
if (event.at("/dialogEventType") != null && "SUBMIT_DIALOG".equals(event.at("/dialogEventType").asText())) {
  return new Message().setActionResponse(new ActionResponse()
    .setType("DIALOG")
    .setDialogAction(new DialogAction().setActionStatus(new ActionStatus()
      .setStatusCode("OK")
      .setUserFacingMessage("Success " + contactName))));
} else {
  return new Message()
    .setActionResponse(new ActionResponse().setType("NEW_MESSAGE"))
    .setPrivateMessageViewer(new User().setName(event.at("/user/name").asText()))
    .setText(confirmationMessage);
}

Apps Script

Ví dụ này gửi thông báo thẻ bằng cách trả về JSON thẻ. Bạn cũng có thể sử dụng dịch vụ thẻ Apps Script.

apps-script/contact-form-app/main.gs
// The Chat app indicates that it received form data from the dialog or card.
// Sends private text message that confirms submission.
const confirmationMessage = "✅ " + contactName + " has been added to your contacts.";
if (event.dialogEventType === "SUBMIT_DIALOG") {
  return {
    actionResponse: {
      type: "DIALOG",
      dialogAction: { actionStatus: {
        statusCode: "OK",
        userFacingMessage: "Success " + contactName
      }}
    }
  }
} else {
  return {
    actionResponse: { type: "NEW_MESSAGE" },
    privateMessageViewer: event.user,
    text: confirmationMessage
  };
}

Để cập nhật một thông báo, hãy trả về một đối tượng actionResponse chứa thông báo đã cập nhật và đặt type thành một trong những giá trị sau:

Khắc phục sự cố

Khi ứng dụng Google Chat hoặc thẻ trả về lỗi, giao diện Chat sẽ hiển thị thông báo "Đã xảy ra lỗi". hoặc "Không thể xử lý yêu cầu của bạn". Đôi khi, giao diện người dùng Chat không hiển thị thông báo lỗi nào, nhưng ứng dụng Chat hoặc thẻ lại tạo ra kết quả không mong muốn; ví dụ: thông báo thẻ có thể không xuất hiện.

Mặc dù thông báo lỗi có thể không hiển thị trong giao diện người dùng Chat, nhưng bạn có thể xem thông báo lỗi mô tả và dữ liệu nhật ký để khắc phục lỗi khi bật tính năng ghi nhật ký lỗi cho ứng dụng Chat. Để được trợ giúp xem, gỡ lỗi và khắc phục lỗi, hãy xem bài viết Khắc phục và khắc phục lỗi Google Chat.