Tạo ứng dụng Google Chat làm webhook

Trang này mô tả cách thiết lập webhook để gửi thông báo không đồng bộ vào một không gian Chat bằng cách sử dụng trình kích hoạt bên ngoài. Ví dụ: bạn có thể định cấu hình một ứng dụng giám sát để thông báo cho nhân viên trực điện thoại trên Chat khi một máy chủ gặp sự cố. Để gửi thông báo đồng bộ bằng ứng dụng Chat, hãy xem bài viết Gửi thông báo.

Với loại thiết kế cấu trúc này, người dùng không thể tương tác với webhook hoặc ứng dụng bên ngoài được kết nối vì giao tiếp là một chiều. Webhook không phải là dạng trò chuyện. Chúng không thể phản hồi hoặc nhận thông báo từ người dùng hoặc các sự kiện tương tác của ứng dụng Chat. Để phản hồi thông báo, hãy tạo ứng dụng Chat thay vì webhook.

Mặc dù webhook không phải là ứng dụng Chat về mặt kỹ thuật (webhook kết nối các ứng dụng bằng yêu cầu HTTP tiêu chuẩn), nhưng trang này gọi webhook là ứng dụng Chat để đơn giản hoá. Mỗi webhook chỉ hoạt động trong phòng Chat mà webhook đó được đăng ký. Webhook đến hoạt động trong tin nhắn trực tiếp, nhưng chỉ khi tất cả người dùng đều bật ứng dụng Chat. Bạn không thể xuất bản webhook lên Google Workspace Marketplace.

Sơ đồ sau đây cho thấy cấu trúc của một webhook được kết nối với Chat:

Cấu trúc cho webhook đến để gửi tin nhắn không đồng bộ đến Chat.

Trong sơ đồ trước đó, ứng dụng Chat có luồng thông tin sau:

  1. Logic của ứng dụng Chat nhận thông tin từ các dịch vụ bên thứ ba bên ngoài, chẳng hạn như hệ thống quản lý dự án hoặc công cụ tạo phiếu yêu cầu hỗ trợ.
  2. Logic của ứng dụng Chat được lưu trữ trong một hệ thống trên đám mây hoặc tại chỗ có thể gửi thông báo bằng cách sử dụng URL webhook đến một không gian Chat cụ thể.
  3. Người dùng có thể nhận thông báo từ ứng dụng Chat trong không gian Chat cụ thể đó, nhưng không thể tương tác với ứng dụng Chat.

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

Node.js

Python

Java

Apps Script

Tạo webhook

Để tạo webhook, hãy đăng ký webhook đó trong phòng Chat mà bạn muốn nhận thông báo, sau đó viết một tập lệnh gửi thông báo.

Đăng ký webhook đến

  1. Trong trình duyệt, hãy mở Chat. Bạn không thể định cấu hình webhook từ ứng dụng di động Chat.
  2. Chuyển đến không gian mà bạn muốn thêm webhook.
  3. Bên cạnh tiêu đề không gian, hãy nhấp vào mũi tên mở rộng thêm, rồi nhấp vào Ứng dụng và tính năng tích hợp.
  4. Nhấp vào biểu tượng thêmThêm webhook.

  5. Trong trường Name (Tên), hãy nhập Quickstart Webhook.

  6. Trong trường Avatar URL (URL hình đại diện), hãy nhập https://developers.google.com/chat/images/chat-product-icon.png.

  7. Nhấp vào Lưu.

  8. Để sao chép URL webhook, hãy nhấp vào Tuỳ chọn khác, rồi nhấp vào Sao chép đường liên kết.

    URL webhook chứa 2 tham số: key (một giá trị chung được chia sẻ giữa các webhook) và token (một giá trị duy nhất phải được giữ bí mật để duy trì tính bảo mật của webhook).

Viết tập lệnh webhook

Tập lệnh webhook mẫu sẽ gửi một thông báo đến không gian mà webhook được đăng ký bằng cách gửi yêu cầu POST đến URL webhook. API Chat phản hồi bằng một thực thể của Message.

Chọn một ngôn ngữ để tìm hiểu cách tạo tập lệnh webhook:

Node.js

  1. Trong thư mục làm việc, hãy tạo một tệp có tên là index.js.

  2. Trong index.js, hãy dán mã sau:

    solutions/webhook-chat-app/index.js
    /**
     * Sends asynchronous message to Google Chat
     * @return {Object} response
     */
    async function webhook() {
      const url = "https://chat.googleapis.com/v1/spaces/SPACE_ID/messages?key=KEY&token=TOKEN"
      const res = await fetch(url, {
        method: "POST",
        headers: {"Content-Type": "application/json; charset=UTF-8"},
        body: JSON.stringify({
          text: "Hello from a Node script!"
        })
      });
      return await res.json();
    }
    
    webhook().then(res => console.log(res));
  3. Thay thế giá trị cho biến url bằng URL webhook mà bạn đã sao chép khi đăng ký webhook.

Python

  1. Trong thư mục làm việc, hãy tạo một tệp có tên là quickstart.py.

  2. Trong quickstart.py, hãy dán mã sau:

    solutions/webhook-chat-app/quickstart.py
    from json import dumps
    from httplib2 import Http
    
    # Copy the webhook URL from the Chat space where the webhook is registered.
    # The values for SPACE_ID, KEY, and TOKEN are set by Chat, and are included
    # when you copy the webhook URL.
    
    def main():
        """Google Chat incoming webhook quickstart."""
        url = "https://chat.googleapis.com/v1/spaces/SPACE_ID/messages?key=KEY&token=TOKEN"
        app_message = {
            "text": "Hello from a Python script!"
        }
        message_headers = {"Content-Type": "application/json; charset=UTF-8"}
        http_obj = Http()
        response = http_obj.request(
            uri=url,
            method="POST",
            headers=message_headers,
            body=dumps(app_message),
        )
        print(response)
    
    
    if __name__ == "__main__":
        main()
  3. Thay thế giá trị cho biến url bằng URL webhook mà bạn đã sao chép khi đăng ký webhook.

Java

  1. Trong thư mục làm việc, hãy tạo một tệp có tên là pom.xml.

  2. Trong pom.xml, hãy sao chép và dán nội dung sau:

    solutions/webhook-chat-app/pom.xml
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.google.chat.webhook</groupId>
      <artifactId>webhook-app</artifactId>
      <version>0.1.0</version>
      <name>webhook-app</name>
    
      <properties>
        <maven.compiler.target>11</maven.compiler.target>
        <maven.compiler.source>11</maven.compiler.source>
      </properties>
    
      <dependencies>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.9.1</version>
        </dependency>
      </dependencies>
    
      <build>
        <pluginManagement>
          <plugins>
            <plugin>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>3.8.0</version>
            </plugin>
          </plugins>
        </pluginManagement>
      </build>
    </project>
  3. Trong thư mục làm việc, hãy tạo cấu trúc thư mục sau: src/main/java.

  4. Trong thư mục src/main/java, hãy tạo một tệp có tên là App.java.

  5. Trong App.java, hãy dán mã sau:

    solutions/webhook-chat-app/src/main/java/com/google/chat/webhook/App.java
    import com.google.gson.Gson;
    import java.net.http.HttpClient;
    import java.net.http.HttpRequest;
    import java.net.http.HttpResponse;
    import java.util.Map;
    import java.net.URI;
    
    public class App {
      private static final String URL = "https://chat.googleapis.com/v1/spaces/SPACE_ID/messages?key=KEY&token=TOKEN";
      private static final Gson gson = new Gson();
      private static final HttpClient client = HttpClient.newHttpClient();
    
      public static void main(String[] args) throws Exception {
        String message = gson.toJson(Map.of(
          "text", "Hello from Java!"
        ));
    
        HttpRequest request = HttpRequest.newBuilder(URI.create(URL))
          .header("accept", "application/json; charset=UTF-8")
          .POST(HttpRequest.BodyPublishers.ofString(message)).build();
    
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    
        System.out.println(response.body());
      }
    }
  6. Thay thế giá trị cho biến URL bằng URL webhook mà bạn đã sao chép khi đăng ký webhook.

Apps Script

  1. Trong trình duyệt, hãy truy cập vào Apps Script.

  2. Nhấp vào New Project (Dự án mới)

  3. Dán mã sau:

    solutions/webhook-chat-app/webhook.gs
    function webhook() {
      const url = "https://chat.googleapis.com/v1/spaces/SPACE_ID/messages?key=KEY&token=TOKEN"
      const options = {
        "method": "post",
        "headers": {"Content-Type": "application/json; charset=UTF-8"},
        "payload": JSON.stringify({
          "text": "Hello from Apps Script!"
        })
      };
      const response = UrlFetchApp.fetch(url, options);
      console.log(response);
    }
  4. Thay thế giá trị cho biến url bằng URL webhook mà bạn đã sao chép khi đăng ký webhook.

Chạy tập lệnh webhook

Trong CLI, hãy chạy tập lệnh:

Node.js

  node index.js

Python

  python3 quickstart.py

Java

  mvn compile exec:java -Dexec.mainClass=App

Apps Script

  • Nhấp vào Chạy.

Khi bạn chạy mã, webhook sẽ gửi một thông báo đến không gian mà bạn đã đăng ký.

Bắt đầu hoặc trả lời một chuỗi tin nhắn

  1. Chỉ định spaces.messages.thread.threadKey là một phần của nội dung yêu cầu thông báo. Tuỳ thuộc vào việc bạn đang bắt đầu hay trả lời một chuỗi, hãy sử dụng các giá trị sau cho threadKey:

    • Nếu bắt đầu một chuỗi, hãy đặt threadKey thành một chuỗi tuỳ ý, nhưng hãy ghi lại giá trị này để đăng câu trả lời cho chuỗi.

    • Nếu trả lời một chuỗi, hãy chỉ định threadKey được đặt khi chuỗi bắt đầu. Ví dụ: để đăng câu trả lời cho chuỗi mà thông báo ban đầu sử dụng MY-THREAD, hãy đặt MY-THREAD.

  2. Xác định hành vi của chuỗi nếu không tìm thấy threadKey đã chỉ định:

    • Trả lời một chuỗi hoặc bắt đầu một chuỗi mới. Thêm tham số messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD vào URL webhook. Việc truyền tham số URL này sẽ khiến Chat tìm kiếm một chuỗi hiện có bằng cách sử dụng threadKey đã chỉ định. Nếu tìm thấy một chuỗi, thì thông báo sẽ đăng dưới dạng câu trả lời cho chuỗi đó. Nếu không tìm thấy chuỗi nào, thì thông báo sẽ bắt đầu một chuỗi mới tương ứng với threadKey đó.

    • Trả lời một chuỗi hoặc không làm gì cả. Thêm tham số messageReplyOption=REPLY_MESSAGE_OR_FAIL vào URL webhook. Việc truyền tham số URL này sẽ khiến Chat tìm kiếm một chuỗi hiện có bằng cách sử dụng threadKey đã chỉ định. Nếu tìm thấy một chuỗi, thì thông báo sẽ đăng dưới dạng câu trả lời cho chuỗi đó. Nếu không tìm thấy chuỗi nào, thì thông báo sẽ không được gửi.

    Để tìm hiểu thêm, hãy xem messageReplyOption.

Mã mẫu sau đây bắt đầu hoặc trả lời một chuỗi tin nhắn:

Node.js

solutions/webhook-chat-app/thread-reply.js
/**
 * Sends asynchronous message to Google Chat
 * @return {Object} response
 */
async function webhook() {
  const url = "https://chat.googleapis.com/v1/spaces/SPACE_ID/messages?key=KEY&token=TOKEN&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD"
  const res = await fetch(url, {
    method: "POST",
    headers: {"Content-Type": "application/json; charset=UTF-8"},
    body: JSON.stringify({
      text: "Hello from a Node script!",
      thread: {
        threadKey: "THREAD_KEY_VALUE"
      }
    })
  });
  return await res.json();
}

webhook().then(res => console.log(res));

Python

solutions/webhook-chat-app/thread-reply.py
from json import dumps
from httplib2 import Http

# Copy the webhook URL from the Chat space where the webhook is registered.
# The values for SPACE_ID, KEY, and TOKEN are set by Chat, and are included
# when you copy the webhook URL.
#
# Then, append messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD to the
# webhook URL.


def main():
    """Google Chat incoming webhook that starts or replies to a message thread."""
    url = "https://chat.googleapis.com/v1/spaces/SPACE_ID/messages?key=KEY&token=TOKEN&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD"
    app_message = {
        "text": "Hello from a Python script!",
        # To start a thread, set threadKey to an arbitratry string.
        # To reply to a thread, specify that thread's threadKey value.
        "thread": {
            "threadKey": "THREAD_KEY_VALUE"
        },
    }
    message_headers = {"Content-Type": "application/json; charset=UTF-8"}
    http_obj = Http()
    response = http_obj.request(
        uri=url,
        method="POST",
        headers=message_headers,
        body=dumps(app_message),
    )
    print(response)


if __name__ == "__main__":
    main()

Java

solutions/webhook-chat-app/src/main/java/com/google/chat/webhook/AppThread.java
import com.google.gson.Gson;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Map;
import java.net.URI;

public class App {
  private static final String URL = "https://chat.googleapis.com/v1/spaces/SPACE_ID/messages?key=KEY&token=TOKEN&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD";
  private static final Gson gson = new Gson();
  private static final HttpClient client = HttpClient.newHttpClient();

  public static void main(String[] args) throws Exception {
    String message = gson.toJson(Map.of(
      "text", "Hello from Java!",
      "thread", Map.of(
        "threadKey", "THREAD_KEY_VALUE"
      )
    ));

    HttpRequest request = HttpRequest.newBuilder(URI.create(URL))
      .header("accept", "application/json; charset=UTF-8")
      .POST(HttpRequest.BodyPublishers.ofString(message)).build();

    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

    System.out.println(response.body());
  }
}

Apps Script

solutions/webhook-chat-app/thread-reply.gs
function webhook() {
  const url = "https://chat.googleapis.com/v1/spaces/SPACE_ID/messages?key=KEY&token=TOKEN&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD"
  const options = {
    "method": "post",
    "headers": {"Content-Type": "application/json; charset=UTF-8"},
    "payload": JSON.stringify({
      "text": "Hello from Apps Script!",
      "thread": {
        "threadKey": "THREAD_KEY_VALUE"
      }
    })
  };
  const response = UrlFetchApp.fetch(url, options);
  console.log(response);
}

Xử lý lỗi

Yêu cầu webhook có thể không thành công vì nhiều lý do, bao gồm:

  • Yêu cầu không hợp lệ.
  • Webhook hoặc không gian lưu trữ webhook bị xoá.
  • Các vấn đề không liên tục như kết nối mạng hoặc hạn mức.

Khi tạo webhook, bạn nên xử lý lỗi một cách thích hợp bằng cách:

API Google Chat trả về lỗi dưới dạng a google.rpc.Status, bao gồm lỗi HTTP code cho biết loại lỗi gặp phải: lỗi máy khách (dãy 400) hoặc lỗi máy chủ (dãy 500). Để xem xét tất cả các ánh xạ HTTP, hãy xem google.rpc.Code.

{
    "code": 503,
    "message": "The service is currently unavailable.",
    "status": "UNAVAILABLE"
}

Để tìm hiểu cách diễn giải mã trạng thái HTTP và xử lý lỗi, hãy xem bài viết Lỗi.

Các điểm hạn chế và điều cần cân nhắc

  • Khi tạo thông báo bằng webhook trong API Google Chat, phản hồi không chứa toàn bộ thông báo. Phản hồi chỉ điền các trường namethread.name.
  • Webhook phải tuân theo hạn mức cho mỗi không gian đối với spaces.messages.create: 1 yêu cầu mỗi giây, được chia sẻ giữa tất cả các webhook trong không gian. Chat cũng có thể từ chối các yêu cầu webhook vượt quá 1 truy vấn mỗi giây trong cùng một không gian. Để biết thêm thông tin về hạn mức API Chat, hãy xem bài viết Giới hạn sử dụng.