Membangun aplikasi Google Chat di belakang firewall dengan Pub/Sub

Halaman ini menjelaskan cara membuat aplikasi Chat menggunakan Pub/Sub. Jenis arsitektur untuk aplikasi Chat berguna jika organisasi Anda memiliki firewall, yang dapat mencegah Chat mengirim pesan ke aplikasi Chat Anda, atau jika aplikasi Chat menggunakan Google Workspace Events API. Namun, arsitektur ini memiliki batasan-batasan sebagai berikut karena fakta bahwa ini Aplikasi chat hanya dapat mengirim dan menerima pesan asinkron:

  • Tidak dapat menggunakan dialog dalam pesan. Sebagai gantinya, gunakan pesan kartu.
  • Tidak dapat memperbarui kartu individual dengan respons sinkron. Sebagai gantinya, update seluruh pesan dengan memanggil patch .

Diagram berikut menunjukkan arsitektur Aplikasi Chat yang dibangun dengan Pub/Sub:

Arsitektur aplikasi Chat yang diimplementasikan dengan Pub/Sub.

Pada diagram sebelumnya, pengguna berinteraksi dengan Pub/Sub Aplikasi Chat memiliki alur informasi berikut:

  1. Pengguna mengirim pesan di Chat kepada aplikasi Chat, baik di pesan langsung maupun dalam Ruang Chat atau acara terjadi di ruang Chat dengan aplikasi Chat yang memiliki subscription Anda.

  2. Chat mengirimkan pesan ke topik Pub/Sub.

  3. Server aplikasi, yang merupakan sistem {i>cloud<i} atau lokal yang berisi logika aplikasi Chat, berlangganan ke topik Pub/Sub untuk menerima pesan melalui firewall.

  4. Secara opsional, aplikasi Chat dapat memanggil Chat API untuk memposting pesan secara asinkron atau melakukan operasional bisnis.

Prasyarat

Java

Menyiapkan lingkungan

Sebelum menggunakan Google API, Anda harus mengaktifkannya di project Google Cloud. Anda dapat mengaktifkan satu atau beberapa API dalam satu project Google Cloud.
  • Di konsol Google Cloud, aktifkan Google Chat API dan Pub/Sub API.

    Aktifkan API

Menyiapkan Pub/Sub

  1. Membuat topik Pub/Sub yang dapat dikirimi pesan oleh Chat API. Sebaiknya gunakan satu topik per aplikasi Chat.

  2. Memberikan izin Chat untuk memublikasikan topik dengan menetapkan peran Pub/Sub Publisher ke akun layanan:

    chat-api-push@system.gserviceaccount.com
    
  3. Membuat akun layanan untuk aplikasi Chat guna mendapatkan otorisasi dengan Pub/Sub dan Lakukan chat dan simpan file kunci pribadi ke direktori kerja Anda.

  4. Membuat langganan pull ke topik.

  5. Tetapkan Pub/Sub Subscriber Role pada langganan untuk akun layanan yang telah dibuat sebelumnya.

Tulis naskah

Java

  1. Di CLI, berikan kredensial akun layanan:

    export GOOGLE_APPLICATION_CREDENTIALS=SERVICE_ACCOUNT_FILE_PATH
    
  2. Di CLI, berikan project ID Google Cloud:

    export PROJECT_ID=PROJECT_ID
    
  3. Di CLI, berikan ID langganan untuk langganan Pub/Sub yang yang telah Anda buat sebelumnya:

    export SUBSCRIPTION_ID=SUBSCRIPTION_ID
    
  4. Di direktori kerja, buat file bernama pom.xml.

  5. Di file pom.xml, tempel kode berikut:

    java/pub-sub-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</groupId>
      <artifactId>pub-sub-app</artifactId>
      <version>0.1.0</version>
    
      <name>pub-sub-app-java</name>
    
      <properties>
        <maven.compiler.release>21</maven.compiler.release>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
      </properties>
    
      <dependencies>
        <!-- Google Chat GAPIC library -->
        <dependency>
          <groupId>com.google.api.grpc</groupId>
          <artifactId>proto-google-cloud-chat-v1</artifactId>
          <version>0.8.0</version>
        </dependency>
        <dependency>
          <groupId>com.google.api</groupId>
          <artifactId>gax</artifactId>
          <version>2.48.1</version>
        </dependency>
        <dependency>
          <groupId>com.google.cloud</groupId>
          <artifactId>google-cloud-chat</artifactId>
          <version>0.1.0</version>
        </dependency>
        <!-- Google Cloud Pub/Sub library -->
        <dependency>
          <groupId>com.google.cloud</groupId>
          <artifactId>google-cloud-pubsub</artifactId>
        <version>1.125.8</version>
        </dependency>
        <!-- JSON utilities -->
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-databind</artifactId>
          <version>2.14.2</version>
        </dependency>
      </dependencies>
    
    </project>
  6. Dalam direktori kerja Anda, buat struktur direktori src/main/java.

  7. Di direktori src/main/java, buat file bernama Main.java.

  8. Di Main.java, tempel kode berikut:

    java/pub-sub-app/src/main/java/Main.java
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.google.api.gax.core.FixedCredentialsProvider;
    import com.google.auth.oauth2.GoogleCredentials;
    import com.google.chat.v1.ChatServiceClient;
    import com.google.chat.v1.ChatServiceSettings;
    import com.google.chat.v1.CreateMessageRequest;
    import com.google.chat.v1.CreateMessageRequest.MessageReplyOption;
    import com.google.chat.v1.Message;
    import com.google.chat.v1.Thread;
    import com.google.cloud.pubsub.v1.AckReplyConsumer;
    import com.google.cloud.pubsub.v1.MessageReceiver;
    import com.google.cloud.pubsub.v1.Subscriber;
    import com.google.pubsub.v1.ProjectSubscriptionName;
    import com.google.pubsub.v1.PubsubMessage;
    import java.io.FileInputStream;
    import java.util.Collections;
    
    public class Main {
    
      public static final String PROJECT_ID_ENV_PROPERTY = "PROJECT_ID";
      public static final String SUBSCRIPTION_ID_ENV_PROPERTY = "SUBSCRIPTION_ID";
      public static final String CREDENTIALS_PATH_ENV_PROPERTY = "GOOGLE_APPLICATION_CREDENTIALS";
    
      public static void main(String[] args) throws Exception {
        ProjectSubscriptionName subscriptionName =
            ProjectSubscriptionName.of(
                System.getenv(Main.PROJECT_ID_ENV_PROPERTY),
                System.getenv(Main.SUBSCRIPTION_ID_ENV_PROPERTY));
    
        // Instantiate app, which implements an asynchronous message receiver.
        EchoApp echoApp = new EchoApp();
    
        // Create a subscriber for <var>SUBSCRIPTION_ID</var> bound to the message receiver
        final Subscriber subscriber = Subscriber.newBuilder(subscriptionName, echoApp).build();
        System.out.println("Subscriber is listening to events...");
        subscriber.startAsync();
    
        // Wait for termination
        subscriber.awaitTerminated();
      }
    }
    
    /**
     * A demo app which implements {@link MessageReceiver} to receive messages. It simply echoes the
     * incoming messages.
     */
    class EchoApp implements MessageReceiver {
    
      // Path to the private key JSON file of the service account to be used for posting response
      // messages to Google Chat.
      // In this demo, we are using the same service account for authorizing with Cloud Pub/Sub to
      // receive messages and authorizing with Google Chat to post messages. If you are using
      // different service accounts, please set the path to the private key JSON file of the service
      // account used to post messages to Google Chat here.
      private static final String SERVICE_ACCOUNT_KEY_PATH =
          System.getenv(Main.CREDENTIALS_PATH_ENV_PROPERTY);
    
      // Developer code for Google Chat API scope.
      private static final String GOOGLE_CHAT_API_SCOPE = "https://www.googleapis.com/auth/chat.bot";
    
      private static final String ADDED_RESPONSE = "Thank you for adding me!";
    
      ChatServiceClient chatServiceClient;
    
      EchoApp() throws Exception {
        GoogleCredentials credential =
            GoogleCredentials.fromStream(new FileInputStream(SERVICE_ACCOUNT_KEY_PATH))
                .createScoped(Collections.singleton(GOOGLE_CHAT_API_SCOPE));
    
        // Create the ChatServiceSettings with the app credentials
        ChatServiceSettings chatServiceSettings =
            ChatServiceSettings.newBuilder()
                .setCredentialsProvider(FixedCredentialsProvider.create(credential))
                .build();
    
        // Set the Chat service client
        chatServiceClient = ChatServiceClient.create(chatServiceSettings);
      }
    
      // Called when a message is received by the subscriber.
      @Override
      public void receiveMessage(PubsubMessage pubsubMessage, AckReplyConsumer consumer) {
        System.out.println("Id : " + pubsubMessage.getMessageId());
        // Handle incoming message, then ack/nack the received message
        try {
          ObjectMapper mapper = new ObjectMapper();
          JsonNode dataJson = mapper.readTree(pubsubMessage.getData().toStringUtf8());
          System.out.println("Data : " + dataJson.toString());
          handle(dataJson);
          consumer.ack();
        } catch (Exception e) {
          System.out.println(e);
          consumer.nack();
        }
      }
    
      // Send message to Google Chat based on the type of event.
      public void handle(JsonNode eventJson) throws Exception {
        CreateMessageRequest createMessageRequest;
        switch (eventJson.get("type").asText()) {
          case "ADDED_TO_SPACE":
            // An app can also be added to a space by @mentioning it in a message. In that case, we fall
            // through to the MESSAGE case and let the app respond. If the app was added using the
            // invite flow, we just post a thank you message in the space.
            if (!eventJson.has("message")) {
              createMessageRequest =
                  CreateMessageRequest.newBuilder()
                      .setParent(eventJson.get("space").get("name").asText())
                      .setMessage(Message.newBuilder().setText(ADDED_RESPONSE).build())
                      .build();
              break;
            }
          case "MESSAGE":
            // In case of message, post the response in the same thread.
            createMessageRequest =
                CreateMessageRequest.newBuilder()
                    .setParent(eventJson.get("space").get("name").asText())
                    .setMessageReplyOption(MessageReplyOption.REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD)
                    .setMessage(
                        Message.newBuilder()
                            .setText(
                                "You said: `" + eventJson.get("message").get("text").asText() + "`")
                            .setThread(
                                Thread.newBuilder()
                                    .setName(
                                        eventJson.get("message").get("thread").get("name").asText())
                                    .build())
                            .build())
                    .build();
            break;
          case "REMOVED_FROM_SPACE":
          default:
            // Do nothing
            return;
        }
    
        // Post the response to Google Chat.
        chatServiceClient.createMessage(createMessageRequest);
      }
    }

Memublikasikan aplikasi ke Chat

  1. Di Konsol Google Cloud, buka Menu &gt; API & Layanan &gt; API & yang diaktifkan Layanan &gt; Google Chat API &gt; Konfigurasi.

    Buka Configuration

  2. Konfigurasi aplikasi Chat untuk Pub/Sub:

    1. Di App name, masukkan Quickstart App.
    2. Di Avatar URL, masukkan https://developers.google.com/chat/images/quickstart-app-avatar.png.
    3. Pada Description, masukkan Quickstart app.
    4. Di bagian Functionality, pilih Receive 1:1 messages dan Join spaces and group conversations.
    5. Di bagian Connection settings, pilih Cloud Pub/Sub, lalu tempelkan nama topik Pub/Sub yang Anda buat sebelumnya.
    6. Di bagian Visibilitas, pilih Jadikan aplikasi Google Chat ini tersedia untuk orang dan grup tertentu di domain Anda, lalu masukkan alamat email Anda.
    7. Di bagian Logs, pilih Log errors to Logging.
  3. Klik Simpan.

Aplikasi siap menerima dan menanggapi pesan di Chat.

Jalankan skrip:

Di CLI, beralihlah ke direktori kerja Anda dan jalankan skrip:

Java

mvn compile exec:java -Dexec.mainClass=Main

Saat Anda menjalankan kode, aplikasi mulai memproses pesan yang dipublikasikan ke topik Pub/Sub.

Menguji aplikasi Chat Anda

Untuk menguji aplikasi Chat Anda, buka ruang pesan langsung dengan aplikasi Chat dan mengirim pesan:

  1. Buka Google Chat menggunakan akun Google Workspace yang telah Anda yang diberikan ketika Anda menambahkan diri Anda sebagai penguji tepercaya.

    Buka Google Chat

  2. Klik Chat baru.
  3. Di kolom Tambahkan 1 orang atau lebih, ketik nama Aplikasi Chat.
  4. Pilih aplikasi Chat Anda dari hasil yang ditampilkan. Iklan langsung pesan terbuka.

  5. Di pesan langsung baru dengan aplikasi, ketik Hello, lalu tekan enter.

Untuk menambahkan penguji tepercaya dan mempelajari lebih lanjut pengujian fitur interaktif, lihat Menguji fitur interaktif untuk Aplikasi Google Chat.

Memecahkan masalah

Saat aplikasi Google Chat atau kartu menampilkan error, Antarmuka Chat menampilkan pesan yang bertuliskan "Terjadi masalah". atau "Tidak dapat memproses permintaan Anda". Terkadang UI Chat tidak menampilkan pesan error apa pun, tetapi aplikasi Chat atau memberikan hasil yang tidak diharapkan; misalnya, pesan kartu mungkin tidak akan muncul.

Meskipun pesan error mungkin tidak ditampilkan di UI Chat, pesan error deskriptif dan data log tersedia untuk membantu Anda memperbaiki error saat logging error untuk aplikasi Chat diaktifkan. Untuk bantuan melihat, men-debug, dan memperbaiki error, melihat Memecahkan masalah dan memperbaiki error Google Chat.

Pembersihan

Agar tidak menimbulkan tagihan ke akun Google Cloud Anda untuk sumber daya yang digunakan dalam tutorial ini, sebaiknya Anda menghapus project Google Cloud.

  1. Di Konsol Google Cloud, buka halaman Manage resources. Klik Menu &gt; IAM & Admin &gt; Kelola Resource.

    Buka Resource Manager

  2. Dalam daftar project, pilih project yang ingin Anda hapus, lalu klik Hapus .
  3. Pada dialog, ketik project ID, lalu klik Shut down untuk menghapus menyelesaikan proyek tersebut.