Créer une application Google Chat derrière un pare-feu avec Pub/Sub

Cette page explique comment créer une application Chat à l'aide de Pub/Sub. Ce type d'architecture d'une application Chat est utile si votre organisation dispose d'un pare-feu qui peut empêcher Chat d'envoyer des messages à votre application Chat, ou si cette application utilise l'API Google Workspace Events. Cependant, cette architecture présente les limites suivantes, car ces applications Chat ne peuvent envoyer et recevoir que des messages asynchrones:

  • Impossible d'utiliser des boîtes de dialogue dans les messages. Utilisez plutôt un message sous forme de fiche.
  • Impossible de mettre à jour des fiches individuelles avec une réponse synchrone. Mettez plutôt à jour l'intégralité du message en appelant la méthode patch.

Le schéma suivant illustre l'architecture d'une application Chat créée avec Pub/Sub:

Architecture d'une application Chat implémentée avec Pub/Sub.

Dans le schéma précédent, un utilisateur qui interagit avec une application de chat Pub/Sub présente le flux d'informations suivant:

  1. Un utilisateur envoie un message dans Chat à une application Chat, dans un message privé ou dans un espace Chat, ou un événement se produit dans un espace Chat pour lequel l'application Chat dispose d'un abonnement actif.

  2. Chat envoie le message à un sujet Pub/Sub.

  3. Un serveur d'application, qui est un système cloud ou sur site contenant la logique d'application Chat, s'abonne au sujet Pub/Sub afin de recevoir le message via le pare-feu.

  4. L'application Chat peut éventuellement appeler l'API Chat pour publier des messages de manière asynchrone ou effectuer d'autres opérations.

Prérequis

Java

Configurer l'environnement

Avant d'utiliser les API Google, vous devez les activer dans un projet Google Cloud. Vous pouvez activer une ou plusieurs API dans un même projet Google Cloud.
  • Dans la console Google Cloud, activez les API Google Chat et Pub/Sub.

    Activer les API

Configurer Pub/Sub

  1. Créez un sujet Pub/Sub auquel l'API Chat peut envoyer des messages. Nous vous recommandons d'utiliser un seul sujet par application Chat.

  2. Accordez l'autorisation Chat de publier sur le sujet en attribuant le rôle Éditeur Pub/Sub au compte de service suivant:

    chat-api-push@system.gserviceaccount.com
    
  3. Créez un compte de service permettant à l'application Chat de l'autoriser avec Pub/Sub et Chat, puis enregistrez le fichier de clé privée dans votre répertoire de travail.

  4. Créez un abonnement pull associé au sujet.

  5. Attribuez le rôle d'abonné Pub/Sub sur l'abonnement pour le compte de service que vous avez créé précédemment.

Écrire le script

Java

  1. Dans une CLI, fournissez les identifiants du compte de service:

    export GOOGLE_APPLICATION_CREDENTIALS=SERVICE_ACCOUNT_FILE_PATH
    
  2. Dans votre répertoire de travail, créez un fichier nommé pom.xml.

  3. Dans le fichier pom.xml, collez le code suivant:

    <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.pubsub</groupId>
    <artifactId>java-pubsub-app</artifactId>
    <version>0.1.0</version>
    
    <name>java-pubsub-app</name>
    
    <properties>
      <maven.compiler.target>11</maven.compiler.target>
      <maven.compiler.source>11</maven.compiler.source>
    </properties>
    
    <dependencyManagement>
      <dependencies>
        <dependency>
          <groupId>com.google.cloud</groupId>
          <artifactId>libraries-bom</artifactId>
          <version>26.26.0</version>
          <type>pom</type>
          <scope>import</scope>
        </dependency>
      </dependencies>
    </dependencyManagement>
    
    <dependencies>
      <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.9.1</version>
      </dependency>
      <dependency>
        <groupId>com.google.api-client</groupId>
        <artifactId>google-api-client</artifactId>
        <version>1.32.1</version>
      </dependency>
      <dependency>
        <groupId>com.google.cloud</groupId>
        <artifactId>google-cloud-pubsub</artifactId>
      </dependency>
      <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.14.2</version>
      </dependency>
    </dependencies>
    
    <build>
      <pluginManagement>
        <plugins>
          <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.0</version>
          </plugin>
        </plugins>
      </pluginManagement>
    </build>
    </project>
    
  4. Dans votre répertoire de travail, créez la structure de répertoires src/main/java.

  5. Dans le répertoire src/main/java, créez un fichier nommé Main.java.

  6. Dans Main.java, collez le code suivant:

    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.node.JsonNodeFactory;
    import com.fasterxml.jackson.databind.node.ObjectNode;
    import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
    import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
    import com.google.api.client.http.ByteArrayContent;
    import com.google.api.client.http.GenericUrl;
    import com.google.api.client.http.HttpContent;
    import com.google.api.client.http.HttpRequest;
    import com.google.api.client.http.HttpRequestFactory;
    import com.google.api.client.http.HttpTransport;
    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.PubsubMessage;
    import com.google.pubsub.v1.ProjectSubscriptionName;
    import java.io.FileInputStream;
    import java.util.Collections;
    
    public class Main {
    
      public static final String CREDENTIALS_PATH_ENV_PROPERTY = "GOOGLE_APPLICATION_CREDENTIALS";
    
      // Google Cloud Project ID
      public static final String PROJECT_ID = PROJECT_ID;
    
      // Cloud Pub/Sub Subscription ID
      public static final String SUBSCRIPTION_ID = SUBSCRIPTION_ID
    
      public static void main(String[] args) throws Exception {
        ProjectSubscriptionName subscriptionName =
            ProjectSubscriptionName.of(PROJECT_ID, SUBSCRIPTION_ID);
    
        // 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("Starting subscriber...");
        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";
    
      // Response URL Template with placeholders for space id.
      private static final String RESPONSE_URL_TEMPLATE =
          "https://chat.googleapis.com/v1/__SPACE_ID__/messages";
    
      // Response echo message template.
      private static final String RESPONSE_TEMPLATE = "You said: `__MESSAGE__`";
    
      private static final String ADDED_RESPONSE = "Thank you for adding me!";
    
      GoogleCredential credential;
      HttpTransport httpTransport;
      HttpRequestFactory requestFactory;
    
      EchoApp() throws Exception {
        credential =
            GoogleCredential.fromStream(new FileInputStream(SERVICE_ACCOUNT_KEY_PATH))
                .createScoped(Collections.singleton(GOOGLE_CHAT_API_SCOPE));
        httpTransport = GoogleNetHttpTransport.newTrustedTransport();
        requestFactory = httpTransport.createRequestFactory(credential);
      }
    
      // 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();
        }
      }
    
      public void handle(JsonNode eventJson) throws Exception {
        JsonNodeFactory jsonNodeFactory = new JsonNodeFactory(false);
        ObjectNode responseNode = jsonNodeFactory.objectNode();
    
        // Construct the response depending on the event received.
    
        String eventType = eventJson.get("type").asText();
        switch (eventType) {
          case "ADDED_TO_SPACE":
            responseNode.put("text", ADDED_RESPONSE);
            // 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")) {
              break;
            }
          case "MESSAGE":
            responseNode.put("text",
                RESPONSE_TEMPLATE.replaceFirst(
                    "__MESSAGE__", eventJson.get("message").get("text").asText()));
            // In case of message, post the response in the same thread.
            ObjectNode threadNode = jsonNodeFactory.objectNode();
            threadNode.put("name", eventJson.get("message").get("thread").get("name").asText());
            responseNode.put("thread", threadNode);
            break;
          case "REMOVED_FROM_SPACE":
          default:
            // Do nothing
            return;
        }
    
        // Post the response to Google Chat.
    
        String URI =
            RESPONSE_URL_TEMPLATE.replaceFirst(
                "__SPACE_ID__", eventJson.get("space").get("name").asText());
        GenericUrl url = new GenericUrl(URI);
    
        HttpContent content =
            new ByteArrayContent("application/json", responseNode.toString().getBytes("UTF-8"));
        HttpRequest request = requestFactory.buildPostRequest(url, content);
        com.google.api.client.http.HttpResponse response = request.execute();
      }
    }
    

    Remplacez les éléments suivants :

    • PROJECT_ID : ID de projet Google Cloud.
    • SUBSCRIPTION_ID: ID de l'abonnement Pub/Sub que vous avez créé précédemment.

Publier l'application dans Chat

  1. Dans la console Google Cloud, accédez à Menu > API et services > API et services activés > API Google Chat > Configuration.

    Accéder à la page "Configuration"

  2. Configurez l'application Chat pour Pub/Sub:

    1. Dans le champ Nom de l'application, saisissez Quickstart App.
    2. Dans URL de l'avatar, saisissez https://developers.google.com/chat/images/quickstart-app-avatar.png.
    3. Dans Description, saisissez Quickstart app.
    4. Sous Fonctionnalité, sélectionnez Recevoir des messages privés et Rejoindre des espaces et des conversations de groupe.
    5. Sous Paramètres de connexion, sélectionnez Cloud Pub/Sub et collez le nom du sujet Pub/Sub que vous avez créé précédemment.
    6. Sous Visibilité, sélectionnez Rendre cette application Google Chat accessible à des personnes et des groupes spécifiques de votre domaine, puis saisissez votre adresse e-mail.
    7. Sous Journaux, sélectionnez Consigner les erreurs dans Logging.
  3. Cliquez sur Enregistrer.

L'application est prête à recevoir des messages et à y répondre dans Chat.

Exécuter le script

Dans une CLI, accédez à votre répertoire de travail et exécutez le script suivant:

Java

mvn compile exec:java -Dexec.mainClass=Main

Lorsque vous exécutez le code, l'application commence à écouter les messages publiés dans le sujet Pub/Sub.

Tester votre application Chat

Pour tester votre application Chat, envoyez un message privé à l'application:

  1. Ouvrez Google Chat.
  2. Pour envoyer un message privé à l'application, cliquez sur Démarrer une discussion , puis sur Rechercher des applications dans la fenêtre qui s'affiche.
  3. Dans la boîte de dialogue Find apps (Rechercher des applications), recherchez "Quickstart App" (Application de démarrage rapide).
  4. Pour ouvrir un message privé avec l'application, recherchez l'application de démarrage rapide, puis cliquez sur Ajouter > Chat.
  5. Dans le message privé, saisissez Hello, puis appuyez sur enter. L'application Chat vous renvoie le message.

Pour ajouter des testeurs de confiance et en savoir plus sur le test des fonctionnalités interactives, consultez la page Tester les fonctionnalités interactives pour les applications Google Chat.

Dépannage

Lorsqu'une application ou une fiche Google Chat renvoie une erreur, l'interface Chat affiche un message indiquant "Un problème est survenu" ou "Impossible de traiter votre demande". Il peut arriver que l'interface Chat n'affiche aucun message d'erreur, mais que l'application ou la fiche Chat génère un résultat inattendu. Par exemple, il est possible qu'un message de fiche ne s'affiche pas.

Bien qu'aucun message d'erreur ne s'affiche dans l'interface Chat, des messages d'erreur descriptifs et des données de journal sont disponibles pour vous aider à corriger les erreurs lorsque la journalisation des erreurs est activée pour les applications Chat. Si vous avez besoin d'aide pour afficher, déboguer et corriger les erreurs, consultez Résoudre les erreurs Google Chat.