构建 HTTP Google Chat 应用

本页介绍了如何使用 HTTP 服务构建可在 Google Chat 中运行的 Google Workspace 插件。

本快速入门介绍了如何使用 Google Cloud 服务构建 HTTP 服务。如需构建 Chat 应用,您需要编写并部署一个 Cloud Run 函数,供 Chat 应用用来响应用户的消息。

在 HTTP 架构中,您可以使用 HTTP 将 Chat 配置为与 Google Cloud 或本地服务器集成,如下图所示:

使用本地服务器中的 Web 服务的 Chat 应用的架构。

在上图中,与 HTTP Chat 应用互动的用户的信息流如下所示:

  1. 用户通过私信或 Chat 聊天室在 Chat 中向 Chat 应用发送消息。
  2. 系统会向 Web 服务器发送 HTTP 请求,该服务器可以是包含 Chat 应用逻辑的云端系统,也可以是本地系统。
  3. 聊天应用逻辑可以选择性地与 Google Workspace 服务(例如 Google 日历和 Google 表格)、其他 Google 服务(例如 Google 地图、YouTube 和 Vertex AI)或其他 Web 服务(例如项目管理系统或工单工具)集成。
  4. 网络服务器会向 Chat 中的 Chat 应用服务发送 HTTP 响应。
  5. 响应会传递给用户。
  6. Chat 应用可以选择调用 Chat API 来异步发布消息或执行其他操作。

此架构可让您灵活使用系统中已有的现有库和组件,因为这些聊天应用可以使用不同的编程语言进行设计。

目标

  • 设置环境。
  • 创建和部署 Cloud Run 函数。
  • 为 Chat 扩展应用配置 Google Workspace 插件。
  • 测试应用。

前提条件

设置环境

在使用 Google API 之前,您需要在 Google Cloud 项目中启用它们。 您可以在单个 Google Cloud 项目中启用一个或多个 API。
  • 在 Google Cloud 控制台中,启用 Cloud Build API、Cloud Functions API、Cloud Pub/Sub API、Cloud Logging API、Artifact Registry API 和 Cloud Run API。

    启用 API

创建和部署 Cloud Run 函数

创建并部署一个 Cloud Run 函数,该函数可生成包含发件人显示名称和头像图片的聊天卡片。当 Chat 应用收到消息时,它会运行该函数并使用卡片进行响应。

如需为 Chat 应用创建和部署函数,请完成以下步骤:

Node.js

  1. 在 Google Cloud 控制台中,转到 Cloud Run 页面。

    转到 Cloud Run

    确保已选择 Chat 应用的项目。

  2. 点击编写函数

  3. 创建服务页面上,设置函数:

    1. 服务名称字段中,输入 addonchatapp
    2. 区域列表中,选择一个区域。
    3. 运行时列表中,选择最新版本的 Node.js。
    4. 身份验证部分中,选择需要进行身份验证
    5. 点击创建,然后等待 Cloud Run 创建服务。 控制台会将您重定向到来源标签页。
  4. 来源标签页中:

    1. 入口点中,删除默认文本并输入 avatarApp
    2. index.js 的内容替换为以下代码:
    /**
     * Google Cloud Run function that responds to messages sent from a
     * Google Chat space.
     *
     * @param {Object} req Request sent from Google Chat space
     * @param {Object} res Response to send back
     */
    import { http } from '@google-cloud/functions-framework';
    
    http('avatarApp', (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 as a variable.
        const chatMessage = req.body.chat.messagePayload.message;
    
        // Replies with the sender's avatar in a card.
        const displayName = chatMessage.sender.displayName;
        const avatarUrl = chatMessage.sender.avatarUrl;
        res.send({ hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
            text: 'Here\'s your avatar',
            cardsV2: [{
                cardId: 'avatarCard',
                card: {
                    name: 'Avatar Card',
                    header: {
                        title: `Hello ${displayName}!`,
                    },
                    sections: [{
                        widgets: [{
                            textParagraph: { text: 'Your avatar picture: ' }
                        }, {
                            image: { imageUrl: avatarUrl }
                        }]
                    }]
                }
            }]
        }}}}});
    });
    
    1. package.json 的内容替换为以下代码:
    {
      "name": "avatar-app",
      "version": "1.0.0",
      "description": "Google Chat Avatar App",
      "main": "index.js",
      "type": "module",
      "scripts": {
        "start": "node index.js"
      },
      "dependencies": {
        "@google-cloud/functions-framework": "^3.0.0"
      }
    }
    
    1. 点击保存并重新部署

Python

  1. 在 Google Cloud 控制台中,转到 Cloud Run 页面。

    转到 Cloud Run

    确保已选择 Chat 应用的项目。

  2. 点击编写函数

  3. 创建服务页面上,设置函数:

    1. 服务名称字段中,输入 addonchatapp
    2. 区域列表中,选择一个区域。
    3. 运行时列表中,选择最新版本的 Python。
    4. 身份验证部分中,选择需要进行身份验证
    5. 点击创建,然后等待 Cloud Run 创建服务。 控制台会将您重定向到来源标签页。
  4. 来源标签页中:

    1. 入口点中,删除默认文本并输入 avatar_app
    2. main.py 的内容替换为以下代码:
    from typing import Any, Mapping
    
    import flask
    import functions_framework
    
    @functions_framework.http
    def avatar_app(req: flask.Request) -> Mapping[str, Any]:
        """Google Cloud Run Function that handles requests from Google Chat
    
        Args:
            flask.Request: the request
    
        Returns:
            Mapping[str, Any]: the response
        """
        if req.method == "GET":
            return "Hello! This function must be called from Google Chat."
    
        request_json = req.get_json(silent=True)
    
        # Stores the Google Chat event as a variable.
        chat_message = request_json["chat"]["messagePayload"]["message"]
    
        # Replies with the sender's avatar in a card.
        display_name = chat_message["sender"]["displayName"]
        avatar_url = chat_message["sender"]["avatarUrl"]
        return { "hostAppDataAction": { "chatDataAction": { "createMessageAction": { "message": {
            "text": "Here's your avatar",
            "cardsV2": [{
                "cardId": "avatarCard",
                "card": {
                    "name": "Avatar Card",
                    "header": { "title": f"Hello {display_name}!" },
                    "sections": [{
                        "widgets": [{
                            "textParagraph": { "text": "Your avatar picture:" }
                        }, {
                            "image": { "imageUrl": avatar_url }
                        }]
                    }]
                }
            }]
        }}}}}
    
    1. 点击保存并重新部署

Java

  1. 在 Google Cloud 控制台中,转到 Cloud Run 页面。

    转到 Cloud Run

    确保已选择 Chat 应用的项目。

  2. 点击编写函数

  3. 创建服务页面上,设置函数:

    1. 服务名称字段中,输入 addonchatapp
    2. 区域列表中,选择一个区域。
    3. 运行时列表中,选择最新版本的 Java。
    4. 身份验证部分中,选择需要进行身份验证
    5. 点击创建,然后等待 Cloud Run 创建服务。 控制台会将您重定向到来源标签页。
  4. 来源标签页中:

    1. 入口点中,删除默认文本并输入 AvatarApp
    2. 将默认 Java 文件重命名为 src/main/java/gcfv2/AvatarApp.java
    3. AvatarApp.java 的内容替换为以下代码:
    import java.util.List;
    
    import com.google.api.services.chat.v1.model.CardWithId;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1Card;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1CardHeader;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1Image;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1Section;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1TextParagraph;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1Widget;
    import com.google.api.services.chat.v1.model.Message;
    import com.google.cloud.functions.HttpFunction;
    import com.google.cloud.functions.HttpRequest;
    import com.google.cloud.functions.HttpResponse;
    import com.google.gson.Gson;
    import com.google.gson.JsonObject;
    
    public class AvatarApp implements HttpFunction {
        private static final Gson gson = new Gson();
    
        @Override
        public void service(HttpRequest request, HttpResponse response) throws Exception {
            JsonObject body = gson.fromJson(request.getReader(), JsonObject.class);
            if (request.getMethod().equals("GET") || !body.has("chat")) {
                response.getWriter().write("Hello! This function is meant to be used " +
                    "in a Google Chat Space..");
                return;
            }
    
            // Stores the Google Chat event as a variable.
            JsonObject chatMessage = body.getAsJsonObject("chat")
                .getAsJsonObject("messagePayload").getAsJsonObject("message");
    
            // Replies with the sender's avatar in a card.
            String displayName = chatMessage.getAsJsonObject("sender").get("displayName").getAsString();
            String avatarUrl = chatMessage.getAsJsonObject("sender").get("avatarUrl").getAsString();
            Message message = createMessage(displayName, avatarUrl);
    
            JsonObject createMessageAction = new JsonObject();
            createMessageAction.add("message", gson.fromJson(gson.toJson(message), JsonObject.class));
    
            JsonObject chatDataAction = new JsonObject();
            chatDataAction.add("createMessageAction", createMessageAction);
    
            JsonObject hostAppDataAction = new JsonObject();
            hostAppDataAction.add("chatDataAction", chatDataAction);
    
            JsonObject dataActions = new JsonObject();
            dataActions.add("hostAppDataAction", hostAppDataAction);
            response.getWriter().write(gson.toJson(dataActions));
        }
    
        Message createMessage(String displayName, String avatarUrl) {
            GoogleAppsCardV1CardHeader cardHeader = new GoogleAppsCardV1CardHeader();
            cardHeader.setTitle(String.format("Hello %s!", displayName));
    
            GoogleAppsCardV1TextParagraph textParagraph = new GoogleAppsCardV1TextParagraph();
            textParagraph.setText("Your avatar picture: ");
    
            GoogleAppsCardV1Widget avatarWidget = new GoogleAppsCardV1Widget();
            avatarWidget.setTextParagraph(textParagraph);
    
            GoogleAppsCardV1Image image = new GoogleAppsCardV1Image();
            image.setImageUrl(avatarUrl);
    
            GoogleAppsCardV1Widget avatarImageWidget = new GoogleAppsCardV1Widget();
            avatarImageWidget.setImage(image);
    
            GoogleAppsCardV1Section section = new GoogleAppsCardV1Section();
            section.setWidgets(List.of(avatarWidget, avatarImageWidget));
    
            GoogleAppsCardV1Card card = new GoogleAppsCardV1Card();
            card.setName("Avatar Card");
            card.setHeader(cardHeader);
            card.setSections(List.of(section));
    
            CardWithId cardWithId = new CardWithId();
            cardWithId.setCardId("avatarCard");
            cardWithId.setCard(card);
    
            Message message = new Message();
            message.setText("Here's your avatar");
            message.setCardsV2(List.of(cardWithId));
    
            return message;
        }
    }
    
  5. 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</groupId>
        <artifactId>avatar-app</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <properties>
            <maven.compiler.target>17</maven.compiler.target>
            <maven.compiler.source>17</maven.compiler.source>
        </properties>
    
        <dependencies>
            <dependency>
            <groupId>com.google.cloud.functions</groupId>
            <artifactId>functions-framework-api</artifactId>
            <version>1.0.4</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
            <dependency>
                <groupId>com.google.code.gson</groupId>
                <artifactId>gson</artifactId>
                <version>2.9.1</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/com.google.apis/google-api-services-chat -->
            <dependency>
                <groupId>com.google.apis</groupId>
                <artifactId>google-api-services-chat</artifactId>
                <version>v1-rev20230115-2.0.0</version>
            </dependency>
        </dependencies>
    
        <!-- Required for Java functions in the inline editor -->
        <build>
            <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                <excludes>
                    <exclude>.google/</exclude>
                </excludes>
                </configuration>
            </plugin>
            </plugins>
        </build>
    </project>
    
    1. 点击保存并重新部署

系统会打开 Cloud Run 服务详情页面。等待函数部署。

配置插件

部署 Cloud Run 函数后,请按以下步骤创建插件并部署 Google Chat 应用:

  1. 在 Google Cloud 控制台中,转到 Cloud Run 页面。

    转到 Cloud Run

    请务必选择启用了 Cloud Run 的项目。

  2. 在函数列表中,点击 addonchatapp

  3. 服务详情页面上,复制函数的网址。网址以 run.app 结尾。

  4. 在 Google Cloud 搜索字段中,搜索“Google Chat API”,然后点击 Google Chat API,再点击管理

    前往 Chat API

  5. 点击配置并设置 Google Chat 应用:

    1. 应用名称中,输入 Add-on Chat app
    2. 头像网址中,输入 https://developers.google.com/workspace/add-ons/images/quickstart-app-avatar.png
    3. 说明中,输入 Add-on Chat app
    4. 功能下,选择加入聊天室和群组对话
    5. 连接设置下,选择 HTTP 端点网址
    6. 复制服务账号电子邮件地址。在授权插件调用函数时,您需要提供此电子邮件地址。
    7. 触发器下,选择为所有触发器使用通用 HTTP 端点网址,然后将 Cloud Run 函数触发器的网址粘贴到相应框中。
    8. 公开范围下方,选择面向网域中的特定人员和群组提供此 Google Chat 扩展应用,然后输入您的电子邮件地址。
    9. 日志下,选择将错误记录到 Logging
  6. 点击保存

接下来,授权 Chat 应用调用 Cloud Run 函数。

授权 Google Chat 调用您的函数

如需授权 Google Workspace 插件调用您的函数,请添加具有 Cloud Run Service Invoker 角色的 Google Workspace 插件服务账号。

  1. 在 Google Cloud 控制台中,转到 Cloud Run 页面。

    转到 Cloud Run

  2. 在 Cloud Run 服务列表中,选中接收函数旁边的复选框。(请勿点击函数本身。)

  3. 点击权限。系统会打开权限面板。

  4. 点击添加主账号

  5. 新主账号中,输入与您的 Chat 应用关联的 Google Workspace 加购项服务账号的电子邮件地址。

    服务账号电子邮件地址位于 Chat API 配置页面上的连接设置 > HTTP 端点网址 > 服务账号电子邮件地址下:

    前往 Chat API 配置

  6. 选择角色中,选择 Cloud Run > Cloud Run Service Invoker

  7. 点击保存

Chat 应用已准备就绪,可以接收和回复 Chat 中的消息。

测试聊天应用

如需测试 Chat 应用,请打开与该应用的私信对话,然后发送消息:

  1. 使用您在添加自己为可信测试人员时提供的 Google Workspace 账号打开 Google Chat。

    前往 Google Chat

  2. 点击 发起新聊天
  3. 添加 1 位或多位用户字段中,输入您的 Chat 应用的名称。
  4. 从结果中选择您的 Chat 应用。系统会打开私信对话。

  5. 在与应用来往的新私信中,输入 Hello 并按 enter

Chat 应用的消息包含一张卡片,其中显示了发送者的姓名和头像图片,如下图所示:

聊天应用返回包含发件人显示名称和头像图片的卡片

如需添加可信测试员并详细了解如何测试互动功能,请参阅测试 Google Chat 应用的互动功能

问题排查

当 Google Chat 应用或卡片返回错误时,Chat 界面会显示一条消息,提示“出了点问题”。 或“无法处理您的请求”。有时,Chat 界面不会显示任何错误消息,但 Chat 应用或卡片会产生意外结果;例如,卡片消息可能不会显示。

虽然聊天界面中可能不会显示错误消息,但当为聊天应用启用错误日志记录功能后,系统会提供描述性错误消息和日志数据,帮助您修复错误。如需有关查看、调试和修复错误的帮助,请参阅排查和修复 Google Chat 错误

清理

为避免系统因本教程中使用的资源向您的 Google Cloud 账号收取费用,我们建议您删除 Cloud 项目。

  1. 在 Google Cloud 控制台中,前往管理资源页面。依次点击 菜单 > IAM 和管理 > 管理资源

    前往资源管理器

  2. 在项目列表中,选择要删除的项目,然后点击删除
  3. 在对话框中输入项目 ID,然后点击关停以删除项目。