เปิดกล่องโต้ตอบแบบอินเทอร์แอกทีฟ

หน้านี้อธิบายวิธีที่แอป Chat ของคุณเปิดกล่องโต้ตอบได้ ตอบกลับผู้ใช้ได้

กล่องโต้ตอบเป็นอินเทอร์เฟซที่อิงตามการ์ดในโหมดหน้าต่าง ที่เปิดจากพื้นที่ใน Chat หรือข้อความ กล่องโต้ตอบและ เนื้อหาจะปรากฏแก่ผู้ใช้ที่เปิดดูเนื้อหาเท่านั้น

แอปแชทสามารถใช้กล่องโต้ตอบเพื่อขอและรวบรวมข้อมูลจาก ผู้ใช้ Chat รวมถึงแบบฟอร์มแบบหลายขั้นตอน สำหรับรายละเอียดเพิ่มเติม เกี่ยวกับการสร้างอินพุตฟอร์ม โปรดดูหัวข้อรวบรวมและประมวลผลข้อมูลจากผู้ใช้

ข้อกำหนดเบื้องต้น

Node.js

  • แอป Google Chat ที่เปิดใช้ฟีเจอร์แบบอินเทอร์แอกทีฟ วิธีสร้าง แอป Chat แบบอินเทอร์แอกทีฟที่ใช้บริการ HTTP ให้ทำการเริ่มต้นอย่างรวดเร็วนี้ให้เสร็จสมบูรณ์

Python

  • แอป Google Chat ที่เปิดใช้ฟีเจอร์แบบอินเทอร์แอกทีฟ วิธีสร้าง แอป Chat แบบอินเทอร์แอกทีฟที่ใช้บริการ HTTP ให้ทำการเริ่มต้นอย่างรวดเร็วนี้ให้เสร็จสมบูรณ์

Apps Script

  • แอป Google Chat ที่เปิดใช้ฟีเจอร์แบบอินเทอร์แอกทีฟ วิธีสร้าง แอป Chat แบบอินเทอร์แอกทีฟใน 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 เป็น DIALOG และ Message ออบเจ็กต์ หากต้องการระบุเนื้อหาของกล่องโต้ตอบ ให้ใส่ข้อมูลต่อไปนี้ ออบเจ็กต์มีดังนี้

  • 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 คือข้อความที่แสดงในปุ่ม (เช่น Next หรือ Submit) WIDGETS แสดงถึงอย่างน้อย 1 รายการ วิดเจ็ตอินพุตฟอร์ม และ FUNCTION_NAME คือฟังก์ชันที่จะทำงานเมื่อผู้ใช้คลิกปุ่ม

จัดการการส่งกล่องโต้ตอบ

เมื่อผู้ใช้คลิกปุ่มที่ส่งกล่องโต้ตอบ แอป Chat ได้รับ การโต้ตอบ CARD_CLICKED เหตุการณ์ที่ dialogEventType คือ SUBMIT_DIALOG

แอป Chat ต้องจัดการเหตุการณ์การโต้ตอบภายในวันที่ ดำเนินการอย่างใดอย่างหนึ่งต่อไปนี้

ไม่บังคับ: แสดงกล่องโต้ตอบอีกกล่องหนึ่ง

หลังจากผู้ใช้ส่งกล่องโต้ตอบเริ่มต้น แอป Chat จะทำสิ่งต่อไปนี้ได้ แสดงกล่องโต้ตอบเพิ่มเติมหนึ่งข้อความขึ้นไป เพื่อช่วยให้ผู้ใช้ตรวจสอบข้อมูลก่อน การส่ง กรอกแบบฟอร์มหลายขั้นตอน หรือเติมข้อมูลในแบบฟอร์มแบบไดนามิก

หากต้องการโหลดข้อมูลที่ผู้ใช้ป้อนจากกล่องโต้ตอบเริ่มต้น คุณต้องเพิ่ม ไปยังปุ่มที่เปิดกล่องโต้ตอบถัดไป หรือส่ง CARD_CLICKED เหตุการณ์การโต้ตอบจากกล่องโต้ตอบเริ่มต้น โปรดดูรายละเอียดที่หัวข้อ โอนข้อมูลไปยังการ์ดอื่น

ในตัวอย่างนี้ แอป Chat จะเปิดกล่องโต้ตอบที่ จะแสดงกล่องโต้ตอบที่ 2 ก่อนส่ง ในการโหลดข้อมูลอินพุต แอป 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

/**
* 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 แสดงถึงอย่างน้อย 1 รายการ วิดเจ็ตอินพุตฟอร์ม

ปิดกล่องโต้ตอบ

เมื่อผู้ใช้คลิกปุ่มในกล่องโต้ตอบ แอป Chat ได้รับเหตุการณ์การโต้ตอบกับ ข้อมูลต่อไปนี้

  • eventType มีค่า CARD_CLICKED
  • dialogEventType มีค่า SUBMIT_DIALOG
  • common.formInputs มีข้อมูลที่ผู้ใช้ป้อนโดยใช้วิดเจ็ต

ส่วนต่อไปนี้จะอธิบายวิธีตรวจสอบข้อมูลที่ผู้ใช้ป้อน ปิดกล่องโต้ตอบ

ตรวจสอบข้อมูลอินพุตของผู้ใช้และปิดกล่องโต้ตอบ

หากต้องการประมวลผลข้อมูลที่ผู้ใช้ป้อน แอป Chat ใช้เมธอด event.common.formInputs ออบเจ็กต์ หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับการเรียกค่าจากวิดเจ็ตอินพุต โปรดดู รวบรวมและประมวลผลข้อมูลจากผู้ใช้

หากผู้ใช้ละฟิลด์ที่จำเป็น หรือป้อนค่าที่ไม่ถูกต้อง แอป Chat สามารถตอบกลับแบบมีข้อผิดพลาดด้วยการส่งคืน ActionResponse ที่มี "actionStatus": "ERROR MESSAGE"

ตัวอย่างต่อไปนี้จะตรวจสอบว่าผู้ใช้ป้อนค่าสำหรับวิดเจ็ตที่ ยอมรับสตริง (stringInputs) เช่น วิดเจ็ต textInput หากไม่ระบุ ระบบจะ แอป 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 Script

ตัวอย่างนี้ส่งข้อความการ์ดโดยการส่งคืน JSON ของการ์ด คุณยังสามารถใช้ บริการการ์ด Apps Script

/**
* 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 เป็นอย่างใดอย่างหนึ่งต่อไปนี้

แก้ปัญหา

เมื่อแอป Google Chat หรือ card จะแสดงผลข้อผิดพลาด อินเทอร์เฟซ Chat แสดงข้อความว่า "เกิดข้อผิดพลาด" หรือ "ไม่สามารถดำเนินการตามคำขอของคุณ" บางครั้ง UI ของ Chat ไม่แสดงข้อความแสดงข้อผิดพลาดใดๆ แต่แอป Chat หรือ ทำให้เกิดผลลัพธ์ที่ไม่คาดคิด เช่น ข้อความในการ์ดอาจ ปรากฏขึ้น

แม้ว่าข้อความแสดงข้อผิดพลาดอาจไม่แสดงใน UI ของแชท มีข้อความแสดงข้อผิดพลาดและข้อมูลบันทึกที่สื่อความหมายเพื่อช่วยคุณแก้ไขข้อผิดพลาด เมื่อมีการเปิดข้อผิดพลาดในการบันทึกสำหรับแอป Chat หากต้องการความช่วยเหลือในการดู การแก้ไขข้อบกพร่องและการแก้ไขข้อผิดพลาด โปรดดู แก้ปัญหาข้อผิดพลาดของ Google Chat