Thu thập và xử lý thông tin của người dùng Google Chat

Hướng dẫn này mô tả cách các ứng dụng Google Chat có thể thu thập và xử lý thông tin từ người dùng bằng cách tạo dữ liệu đầu vào biểu mẫu trong giao diện dựa trên thẻ.

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

Các ứng dụng Chat yêu cầu người dùng cung cấp thông tin để thực hiện các hành động trong hoặc ngoài Chat, bao gồm cả những cách sau:

  • Định cấu hình chế độ cài đặt. Ví dụ: cho phép người dùng tuỳ chỉnh chế độ cài đặt thông báo hoặc định cấu hình và thêm ứng dụng Chat vào một hoặc nhiều không gian.
  • Tạo hoặc cập nhật thông tin trong các ứng dụng khác của Google Workspace. Ví dụ: cho phép người dùng tạo một sự kiện trên Lịch Google.
  • Cho phép người dùng truy cập và cập nhật tài nguyên trong các ứng dụng hoặc dịch vụ web khác. Ví dụ: một ứng dụng Chat có thể giúp người dùng cập nhật trạng thái của phiếu yêu cầu hỗ trợ ngay trong không gian trên Chat.

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

HTTP

Một tiện ích bổ sung của Google Workspace giúp mở rộng Google Chat. Để tạo một ứng dụng, hãy hoàn tất hướng dẫn nhanh về HTTP.

Apps Script

Một tiện ích bổ sung của Google Workspace giúp mở rộng Google Chat. Để tạo một tiện ích bổ sung, hãy hoàn tất hướng dẫn bắt đầu nhanh với Apps Script.

Tạo biểu mẫu bằng thẻ

Để thu thập thông tin, các ứng dụng Chat thiết kế biểu mẫu và dữ liệu đầu vào, đồng thời tạo chúng thành thẻ. Để hiển thị thẻ cho người dùng, các ứng dụng Chat có thể sử dụng các giao diện Chat sau:

  • Tin nhắn trò chuyện có chứa một hoặc nhiều thẻ.
  • Hộp thoại là những thẻ mở ra trong một cửa sổ mới từ tin nhắn và trang chủ.

Các ứng dụng trò chuyện có thể tạo thẻ bằng các tiện ích sau:

  • Các tiện ích đầu vào biểu mẫu yêu cầu người dùng cung cấp thông tin. Bạn có thể thêm xác thực vào các tiện ích nhập biểu mẫu (không bắt buộc) để đảm bảo người dùng nhập và định dạng thông tin một cách chính xác. Các ứng dụng trò chuyện có thể sử dụng những tiện ích đầu vào biểu mẫu sau đây:

    • Đầu vào văn bản (textInput) cho văn bản tự do hoặc văn bản được đề xuất.
    • Đầu vào lựa chọn (selectionInput) là những phần tử có thể chọn trên giao diện người dùng, chẳng hạn như hộp đánh dấu, nút chọn và trình đơn thả xuống. Các tiện ích đầu vào lựa chọn cũng có thể điền sẵn và đề xuất các mục từ dữ liệu trên Google Workspace (chẳng hạn như một không gian trên Chat) hoặc một nguồn dữ liệu động. Để biết thông tin chi tiết, hãy xem phần Thêm một trình đơn chọn nhiều mục.

    • Bộ chọn ngày giờ (dateTimePicker) cho các mục ngày và giờ.

  • Một tiện ích nút để người dùng có thể gửi các giá trị mà họ đã nhập vào thẻ. Sau khi người dùng nhấp vào nút này, ứng dụng Chat có thể xử lý thông tin mà ứng dụng nhận được.

Trong ví dụ sau, một thẻ thu thập thông tin liên hệ bằng cách sử dụng một mục nhập văn bản, bộ chọn ngày giờ và mục nhập lựa chọn:

Để xem thêm ví dụ về các tiện ích tương tác mà bạn có thể dùng để thu thập thông tin, hãy xem phần Thiết kế thẻ hoặc hộp thoại tương tác trong tài liệu về API Google Chat.

Thêm trình đơn nhiều lựa chọn

Để tuỳ chỉnh các mục lựa chọn hoặc cho phép người dùng chọn các mục từ một nguồn dữ liệu động, các ứng dụng Chat có thể sử dụng trình đơn chọn nhiều mục. Đây là một loại tiện ích SelectionInput. Ví dụ: thẻ sau đây hiển thị một trình đơn chọn nhiều mục, trong đó người dùng có thể chọn linh hoạt trong danh sách người liên hệ:

Bạn có thể điền các mục cho trình đơn chọn nhiều từ các nguồn dữ liệu sau:

  • Dữ liệu Google Workspace, bao gồm cả người dùng hoặc phòng Chat mà người dùng là thành viên. Trình đơn này chỉ điền sẵn các mục trong cùng một tổ chức Google Workspace.
  • Nguồn dữ liệu bên ngoài, chẳng hạn như cơ sở dữ liệu quan hệ. Ví dụ: bạn có thể sử dụng trình đơn chọn nhiều mục để giúp người dùng chọn trong danh sách khách hàng tiềm năng từ hệ thống quản lý quan hệ khách hàng (CRM).

Điền sẵn các mục từ một nguồn dữ liệu Google Workspace

Để sử dụng nguồn dữ liệu Google Workspace, hãy chỉ định trường platformDataSource trong tiện ích SelectionInput. Không giống như các loại dữ liệu đầu vào lựa chọn khác, bạn bỏ qua các đối tượng SelectionItem vì các mục lựa chọn này được lấy động từ Google Workspace.

Đoạn mã sau đây cho thấy một trình đơn chọn nhiều người dùng Google Workspace. Để điền sẵn người dùng, chế độ cài đặt đầu vào lựa chọn sẽ đặt commonDataSource thành USER:

JSON

{
  "selectionInput": {
    "name": "contacts",
    "type": "MULTI_SELECT",
    "label": "Selected contacts",
    "multiSelectMaxSelectedItems": 5,
    "multiSelectMinQueryLength": 1,
    "platformDataSource": {
      "commonDataSource": "USER"
    }
  }
}

Đoạn mã sau đây cho thấy một trình đơn chọn nhiều mục của các không gian trò chuyện. Để điền vào các khoảng trống, đầu vào lựa chọn chỉ định trường hostAppDataSource. Trình đơn chọn nhiều mục cũng đặt defaultToCurrentSpace thành true, nhờ đó, không gian hiện tại sẽ là lựa chọn mặc định trong trình đơn:

JSON

{
  "selectionInput": {
    "name": "spaces",
    "type": "MULTI_SELECT",
    "label": "Selected contacts",
    "multiSelectMaxSelectedItems": 3,
    "multiSelectMinQueryLength": 1,
    "platformDataSource": {
      "hostAppDataSource": {
        "chatDataSource": {
          "spaceDataSource": {
            "defaultToCurrentSpace": true
          }
        }
      }
    }
  }
}

Điền sẵn các mục từ một nguồn dữ liệu bên ngoài

Trình đơn chọn nhiều mục cũng có thể điền sẵn các mục từ nguồn dữ liệu bên ngoài hoặc bên thứ ba. Để sử dụng một nguồn dữ liệu bên ngoài, bạn chỉ định trường externalDataSource trong tiện ích SelectionInput chứa hàm truy vấn và trả về các mục từ nguồn dữ liệu.

Để giảm số lượng yêu cầu gửi đến một nguồn dữ liệu bên ngoài, bạn có thể thêm các mục được đề xuất xuất hiện trong trình đơn chọn nhiều mục trước khi người dùng nhập vào trình đơn. Ví dụ: bạn có thể điền sẵn những người liên hệ mà người dùng đã tìm kiếm gần đây. Để điền sẵn các mục đề xuất từ một nguồn dữ liệu bên ngoài, hãy chỉ định các đối tượng SelectionItem tĩnh.

Đoạn mã sau đây cho thấy một trình đơn chọn nhiều mục truy vấn và điền các mục từ một nguồn dữ liệu bên ngoài:

JSON

{
  "selectionInput": {
    "name": "contacts",
    "type": "MULTI_SELECT",
    "label": "Selected contacts",
    "multiSelectMaxSelectedItems": 3,
    "multiSelectMinQueryLength": 1,
    "externalDataSource": { "function": "FUNCTION" },
    // Suggested items loaded by default.
    // The list is static here but it could be dynamic.
    "items": [FUNCTION]
  }
}

Thay thế FUNCTION bằng URL HTTP hoặc tên hàm Apps Script truy vấn cơ sở dữ liệu bên ngoài. Để xem ví dụ hoàn chỉnh minh hoạ cách trả về các mục được đề xuất, hãy xem phần Đề xuất các mục chọn nhiều.

Nhận dữ liệu từ các tiện ích tương tác

Bất cứ khi nào người dùng nhấp vào một nút, hành động của ứng dụng Chat sẽ được kích hoạt cùng với thông tin về hoạt động tương tác. Trong commonEventObject của tải trọng sự kiện, đối tượng formInputs chứa mọi giá trị mà người dùng nhập.

Bạn có thể truy xuất các giá trị từ đối tượng commonEventObject.formInputs.WIDGET_NAME, trong đó WIDGET_NAME là trường name mà bạn đã chỉ định cho tiện ích. Các giá trị được trả về dưới dạng một loại dữ liệu cụ thể cho tiện ích.

Sau đây là một phần của đối tượng sự kiện, trong đó người dùng đã nhập các giá trị cho từng tiện ích:

{
  "commonEventObject": { "formInputs": {
    "contactName": { "stringInputs": {
      "value": ["Kai 0"]
    }},
    "contactBirthdate": { "dateInput": {
      "msSinceEpoch": 1000425600000
    }},
    "contactType": { "stringInputs": {
      "value": ["Personal"]
    }}
  }}
}

Để nhận dữ liệu, ứng dụng Chat của bạn sẽ xử lý đối tượng sự kiện để lấy các giá trị mà người dùng nhập vào các tiện ích. Bảng sau đây cho biết cách lấy giá trị cho một tiện ích đầu vào biểu mẫu nhất định. Đối với mỗi tiện ích, bảng này cho biết kiểu dữ liệu mà tiện ích chấp nhận, nơi giá trị được lưu trữ trong đối tượng sự kiện và giá trị mẫu.

Tiện ích đầu vào của biểu mẫu Loại dữ liệu đầu vào Giá trị đầu vào từ đối tượng sự kiện Giá trị mẫu
textInput stringInputs event.commonEventObject.formInputs.contactName.stringInputs.value[0] Kai O
selectionInput stringInputs Để lấy giá trị đầu tiên hoặc duy nhất, hãy dùng event.commonEventObject.formInputs.contactType.stringInputs.value[0] Personal
dateTimePicker chỉ chấp nhận ngày. dateInput event.commonEventObject.formInputs.contactBirthdate.dateInput.msSinceEpoch. 1000425600000

Sau khi nhận được dữ liệu, ứng dụng Chat có thể làm những việc sau đây:

  • Đối với những thẻ có chứa một trình đơn chọn nhiều mục, hãy điền sẵn hoặc đề xuất các mục dựa trên nội dung mà người dùng nhập vào trình đơn.
  • Chuyển dữ liệu sang một thẻ khác để người dùng có thể xem lại thông tin của họ hoặc tiếp tục đến phần tiếp theo của biểu mẫu.
  • Trả lời người dùng để xác nhận rằng người dùng đã hoàn tất biểu mẫu.

Đề xuất các mục có thể chọn nhiều

Nếu một thẻ chứa một trình đơn chọn nhiều mục điền sẵn các mục từ một nguồn dữ liệu bên ngoài, thì ứng dụng Chat có thể trả về các mục được đề xuất dựa trên nội dung mà người dùng nhập vào trình đơn. Ví dụ: nếu người dùng bắt đầu nhập Atl cho một trình đơn điền sẵn các thành phố ở Hoa Kỳ, thì ứng dụng Chat của bạn có thể tự động đề xuất Atlanta trước khi người dùng nhập xong. Ứng dụng Chat có thể đề xuất tối đa 100 mặt hàng.

Để đề xuất và tự động điền các mục trong một trình đơn chọn nhiều mục, tiện ích SelectionInput trên thẻ phải chỉ định một hàm truy vấn nguồn dữ liệu bên ngoài. Để trả về các mục được đề xuất, hàm phải thực hiện những việc sau:

  1. Xử lý một đối tượng sự kiện mà ứng dụng Chat nhận được khi người dùng nhập vào trình đơn.
  2. Từ đối tượng sự kiện, hãy lấy giá trị mà người dùng nhập, được biểu thị trong trường event.commonEventObject.parameters["autocomplete_widget_query"].
  3. Truy vấn nguồn dữ liệu bằng giá trị đầu vào của người dùng để nhận một hoặc nhiều SelectionItems để đề xuất cho người dùng.
  4. Trả về các mục được đề xuất bằng cách trả về thao tác RenderActions bằng một đối tượng modifyCard.

Đoạn mã mẫu sau đây cho thấy cách một ứng dụng Chat đề xuất các mục trong trình đơn chọn nhiều trên thẻ một cách linh động. Khi người dùng nhập vào trình đơn, hàm hoặc điểm cuối được cung cấp trong trường externalDataSource của tiện ích sẽ truy vấn một nguồn dữ liệu bên ngoài và đề xuất các mục mà người dùng có thể chọn.

Node.js

/**
 * Google Cloud Function that responds to events sent from a
 * Google Chat space.
 *
 * @param {Object} req Request sent from Google Chat space
 * @param {Object} res Response to send back
 */
exports.selectionInput = function selectionInput(req, res) {
  if (req.method === 'GET' || !req.body.chat) {
    return res.send('Hello! This function is meant to be used ' +
        'in a Google Chat Space.');
  }
  // Stores the Google Chat event
  const chatEvent = req.body.chat;

  // Handle user interaction with multiselect.
  if(chatEvent.widgetUpdatedPayload) {
    return res.send(queryContacts(req.body));
  }
  // Replies with a card that contains the multiselect menu.
  return res.send({ hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
    cardsV2: [{
      cardId: "contactSelector",
      card: { sections:[{ widgets: [{
        selectionInput: {
          name: "contacts",
          type: "MULTI_SELECT",
          label: "Selected contacts",
          multiSelectMaxSelectedItems: 3,
          multiSelectMinQueryLength: 1,
          externalDataSource: { function: "FUNCTION_URL" },
          // Suggested items loaded by default.
          // The list is static here but it could be dynamic.
          items: [getSuggestedContact("3")]
        }
      }]}]}
    }]
  }}}}});
};

/**
* Get contact suggestions based on text typed by users.
*
* @param {Object} event the event object that contains the user's query
* @return {Object} suggestions
*/
function queryContacts(event) {
  const query = event.commonEventObject.parameters["autocomplete_widget_query"];
  return { action: { modifyOperations: [{ updateWidget: { selectionInputWidgetSuggestions: { suggestions: [
    // The list is static here but it could be dynamic.
    getSuggestedContact("1"), getSuggestedContact("2"), getSuggestedContact("3"), getSuggestedContact("4"), getSuggestedContact("5")
  // Only return items based on the query from the user.
  ].filter(e => !query || e.text.includes(query)) }}}]}};
}

/**
 * Generate a suggested contact given an ID.
 *
 * @param {String} id The ID of the contact to return.
 * @return {Object} The contact formatted as a selection item in the menu.
 */
function getSuggestedContact(id) {
  return {
    value: id,
    startIconUri: "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
    text: "Contact " + id
  };
}

Thay thế FUNCTION_URL bằng điểm cuối HTTP truy vấn nguồn dữ liệu bên ngoài.

Apps Script

/**
* Responds to a Message trigger in Google Chat.
*
* @param {Object} event the event object from Google Chat
* @return {Object} Response from the Chat app.
*/
function onMessage(event) {
  // Replies with a card that contains the multiselect menu.
  return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
    cardsV2: [{
      cardId: "contactSelector",
      card: { sections:[{ widgets: [{
        selectionInput: {
          name: "contacts",
          type: "MULTI_SELECT",
          label: "Selected contacts",
          multiSelectMaxSelectedItems: 3,
          multiSelectMinQueryLength: 1,
          externalDataSource: { function: "queryContacts" },
          // Suggested items loaded by default.
          // The list is static here but it could be dynamic.
          items: [getSuggestedContact("3")]
        }
      }]}]}
    }]
  }}}}};
}

/**
* Get contact suggestions based on text typed by users.
*
* @param {Object} event the event object that contains the user's query
* @return {Object} suggestions
*/
function queryContacts(event) {
  const query = event.commonEventObject.parameters["autocomplete_widget_query"];
  return { action: { modifyOperations: [{ updateWidget: { selectionInputWidgetSuggestions: { suggestions: [
    // The list is static here but it could be dynamic.
    getSuggestedContact("1"), getSuggestedContact("2"), getSuggestedContact("3"), getSuggestedContact("4"), getSuggestedContact("5")
  // Only return items based on the query from the user.
  ].filter(e => !query || e.text.includes(query)) }}}]}};
}

/**
* Generate a suggested contact given an ID.
*
* @param {String} id The ID of the contact to return.
* @return {Object} The contact formatted as a selection item in the menu.
*/
function getSuggestedContact(id) {
  return {
    value: id,
    startIconUri: "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
    text: "Contact " + id
  };
}

Chuyển dữ liệu sang thẻ khác

Sau khi người dùng gửi thông tin từ một thẻ, bạn có thể cần trả về các thẻ bổ sung để thực hiện bất kỳ thao tác nào sau đây:

  • Giúp người dùng hoàn tất các biểu mẫu dài hơn bằng cách tạo các phần riêng biệt.
  • Cho phép người dùng xem trước và xác nhận thông tin từ thẻ ban đầu để họ có thể xem lại câu trả lời trước khi gửi.
  • Điền sẵn các phần còn lại của biểu mẫu một cách linh hoạt. Ví dụ: để nhắc người dùng tạo cuộc hẹn, một ứng dụng Chat có thể hiển thị thẻ ban đầu yêu cầu lý do của cuộc hẹn, sau đó điền sẵn thông tin vào một thẻ khác cung cấp thời gian có thể hẹn dựa trên loại cuộc hẹn.

Để chuyển dữ liệu đầu vào từ thẻ ban đầu, bạn có thể tạo tiện ích button bằng actionParameters chứa name của tiện ích và giá trị mà người dùng nhập, như minh hoạ trong ví dụ sau:

Node.js

{
  "buttonList": { "buttons": [{
    "text": "Submit",
    "onClick": { "action": {
      "function": "FUNCTION_URL", // Must be an `https` endpoint.
      "parameters": [
        {
          "key": "WIDGET_NAME",
          "value": "USER_INPUT_VALUE"
        },
        // Can specify multiple parameters
      ]
    }}
  }]}
}

Apps Script

{
  "buttonList": { "buttons": [{
    "text": "Submit",
    "onClick": { "action": {
      "function": "submitForm",
      "parameters": [
        {
          "key": "WIDGET_NAME",
          "value": "USER_INPUT_VALUE"
        },
        // Can specify multiple parameters
      ]
    }}
  }]}
}

Trong đó, WIDGET_NAMEname của tiện ích và USER_INPUT_VALUE là nội dung mà người dùng nhập. Ví dụ: đối với một phương thức nhập văn bản thu thập tên của một người, tên tiện ích là contactName và giá trị ví dụ là Kai O.

Khi người dùng nhấp vào nút này, ứng dụng Chat của bạn sẽ nhận được một đối tượng sự kiện mà bạn có thể nhận dữ liệu.

Trả lời nội dung đã gửi trong biểu mẫu

Sau khi nhận được dữ liệu từ một thông báo hoặc hộp thoại trên thẻ, ứng dụng Chat sẽ phản hồi bằng cách xác nhận đã nhận được hoặc trả về lỗi.

Trong ví dụ sau, một ứng dụng trò chuyện gửi tin nhắn văn bản để xác nhận rằng ứng dụng đã nhận được biểu mẫu do một tin nhắn dạng thẻ gửi.

Node.js

/**
 * Google Cloud Function that handles all Google Workspace Add On events for
 * the contact manager app.
 *
 * @param {Object} req Request sent from Google Chat space
 * @param {Object} res Response to send back
 */
exports.contactManager = function contactManager(req, res) {
  const chatEvent = req.body.chat;
  const chatMessage = chatEvent.messagePayload.message;

  // Handle message payloads in the event object
  if(chatEvent.messagePayload) {
    return res.send(handleMessage(chatMessage, chatEvent.user));
  // Handle button clicks on the card
  } else if(chatEvent.buttonClickedPayload) {
    switch(req.body.commonEventObject.parameters.actionName) {
        case "openDialog":
            return res.send(openDialog());
        case "openNextCard":
            return res.send(openNextCard(req.body));
        case "submitForm":
            return res.send(submitForm(req.body));
    }
  }
};

/**
 * Submits information from a dialog or card message.
 *
 * @param {Object} event the interactive event with form inputs.
 * @return {Object} a message response that posts a private message.
 */
function submitForm(event) {
  const chatUser = event.chat.user;
  const contactName = event.commonEventObject.parameters["contactName"];

  return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
    privateMessageViewer: chatUser,
    text: "✅ " + contactName + " has been added to your contacts."
  }}}}};
}

Apps Script

/**
 * Sends private text message that confirms submission.
 *
 * @param {Object} event the interactive event with form inputs.
 * @return {Object} a message response that posts a private message.
 */
function submitForm(event) {
  const chatUser = event.chat.user;
  const contactName = event.commonEventObject.parameters["contactName"];

  return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
    privateMessageViewer: chatUser,
    text: "✅ " + contactName + " has been added to your contacts."
  }}}}};
}

Để xử lý và đóng một hộp thoại, bạn sẽ trả về một đối tượng RenderActions chỉ định xem bạn có muốn gửi một thông báo xác nhận, cập nhật thông báo hoặc thẻ ban đầu hay chỉ đóng hộp thoại. Để biết các bước, hãy xem phần Đóng hộp thoại.

Khắc phục sự cố

Khi một ứ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ị bất kỳ thông báo lỗi nào, nhưng ứng dụng hoặc thẻ Chat 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 xuất hiện trong giao diện người dùng Chat, nhưng bạn có thể sử dụng 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 lỗi trong Google Chat.