Creare un'app Google Chat protetta da un firewall con Pub/Sub

In questa pagina viene spiegato come creare un'app di chat utilizzando Pub/Sub. Questo tipo di architettura per un'app di Chat è utile se la tua organizzazione dispone di un firewall, che può impedire a Chat di inviare messaggi all'app Chat, o se quest'ultima utilizza l'API Google Workspace Eventi. Tuttavia, questa architettura presenta le seguenti limitazioni dovute al fatto che queste app di Chat possono solo inviare e ricevere messaggi asincroni:

  • Non è possibile utilizzare le finestre di dialogo nei messaggi. Utilizza invece un messaggio con scheda.
  • Impossibile aggiornare singole schede con una risposta sincrona. Puoi invece aggiornare l'intero messaggio chiamando il metodo patch.

Il seguente diagramma mostra l'architettura di un'app di Chat creata con Pub/Sub:

Architettura di un'app di chat implementata con Pub/Sub.

Nel diagramma precedente, un utente che interagisce con un'app di chat di Pub/Sub ha il seguente flusso di informazioni:

  1. Un utente invia un messaggio in Chat a un'app Chat, in un messaggio diretto o in uno spazio di Chat, oppure si verifica un evento in uno spazio di Chat per il quale l'app Chat ha un abbonamento attivo.

  2. Chat invia il messaggio a un argomento Pub/Sub.

  3. Un server delle applicazioni, ovvero un sistema cloud o on-premise che contiene la logica dell'app Chat, sottoscrive l'argomento Pub/Sub per ricevere il messaggio attraverso il firewall.

  4. Facoltativamente, l'app Chat può chiamare l'API Chat per pubblicare i messaggi in modo asincrono o eseguire altre operazioni.

Prerequisiti

Java

Configurare l'ambiente

Prima di utilizzare le API di Google, devi attivarle in un progetto Google Cloud. Puoi attivare una o più API in un singolo progetto Google Cloud.
  • Nella console Google Cloud, abilita l'API Google Chat e l'API Pub/Sub.

    Abilita le API

Configurare Pub/Sub

  1. Crea un argomento Pub/Sub a cui l'API Chat può inviare messaggi. Ti consigliamo di utilizzare un solo argomento per ogni app Chat.

  2. Concedi a Chat l'autorizzazione di pubblicazione nell'argomento assegnando il ruolo Publisher Pub/Sub al seguente account di servizio:

    chat-api-push@system.gserviceaccount.com
    
  3. Crea un account di servizio per l'app Chat da autorizzare con Pub/Sub e Chat e salva il file della chiave privata nella tua directory di lavoro.

  4. Crea una sottoscrizione pull per l'argomento.

  5. Assegna il ruolo Sottoscrittore Pub/Sub nell'abbonamento per l'account di servizio creato in precedenza.

Scrivi lo script

Java

  1. In un'interfaccia a riga di comando, fornisci le credenziali dell'account di servizio:

    export GOOGLE_APPLICATION_CREDENTIALS=SERVICE_ACCOUNT_FILE_PATH
    
  2. Nella directory di lavoro, crea un file denominato pom.xml.

  3. Nel file pom.xml, incolla il seguente codice:

    <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. Nella tua directory di lavoro, crea la struttura di directory src/main/java.

  5. Nella directory src/main/java, crea un file denominato Main.java.

  6. In Main.java, incolla il seguente codice:

    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();
      }
    }
    

    Sostituisci quanto segue:

    • PROJECT_ID: l'ID del progetto Google Cloud.
    • SUBSCRIPTION_ID: l'ID della sottoscrizione Pub/Sub creata in precedenza.

Pubblicare l'app in Chat

  1. Nella console Google Cloud, vai a Menu > API e servizi > API e servizi abilitati > API Google Chat > Configurazione.

    Vai a Configurazione

  2. Configura l'app Chat per Pub/Sub:

    1. In Nome app, inserisci Quickstart App.
    2. In URL avatar, inserisci https://developers.google.com/chat/images/quickstart-app-avatar.png.
    3. In Descrizione, inserisci Quickstart app.
    4. In Funzionalità, seleziona Ricevi messaggi 1:1 e Partecipa a spazi e conversazioni di gruppo.
    5. In Impostazioni di connessione, seleziona Cloud Pub/Sub e incolla il nome dell'argomento Pub/Sub che hai creato in precedenza.
    6. In Visibilità, seleziona Rendi disponibile l'app Google Chat a persone e gruppi specifici nel tuo dominio e inserisci il tuo indirizzo email.
    7. In Log, seleziona Registra errori in Logging.
  3. Fai clic su Salva.

L'app è pronta per ricevere e rispondere ai messaggi su Chat.

Esegui lo script

In un'interfaccia a riga di comando, passa alla directory di lavoro ed esegui lo script:

Java

mvn compile exec:java -Dexec.mainClass=Main

Quando esegui il codice, l'applicazione inizia ad ascoltare i messaggi pubblicati nell'argomento Pub/Sub.

Testare l'app Chat

Per testare la tua app Chat, invia all'app un messaggio diretto:

  1. Apri Google Chat.
  2. Per inviare un messaggio diretto all'app, fai clic su Avvia una chat e, nella finestra visualizzata, fai clic su Trova app.
  3. Nella finestra di dialogo Trova app, cerca "App Guida rapida".
  4. Per aprire un messaggio diretto con l'app, trova l'app Guida rapida e fai clic su Aggiungi > Chat.
  5. Nel messaggio diretto, digita Hello e premi enter. L'app Chat ti ripropone il messaggio.

Per aggiungere trusted tester e scoprire di più sui test delle funzionalità interattive, consulta Testare le funzionalità interattive per le app Google Chat.

Risolvi il problema

Quando un'app o una scheda Google Chat restituisce un errore, nell'interfaccia di Chat viene visualizzato il messaggio "Si è verificato un problema" o "Impossibile elaborare la richiesta". A volte nell'interfaccia utente di Chat non vengono visualizzati messaggi di errore, ma l'app o la scheda Chat produce un risultato imprevisto; ad esempio, è possibile che non venga visualizzato un messaggio di scheda.

Anche se un messaggio di errore potrebbe non essere visualizzato nell'interfaccia utente di Chat, sono disponibili messaggi di errore descrittivi e dati di log per aiutarti a correggere gli errori quando la registrazione degli errori per le app di Chat è attivata. Per informazioni su visualizzazione, debug e correzione degli errori, consulta l'articolo Risolvere gli errori di Google Chat.

Esegui la pulizia

Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, ti consigliamo di eliminare il progetto Cloud.

  1. Nella console Google Cloud, vai alla pagina Gestisci risorse. Fai clic su Menu > IAM e amministrazione > Gestisci risorse.

    Vai a Resource Manager

  2. Nell'elenco dei progetti, seleziona quello da eliminare e fai clic su Elimina .
  3. Nella finestra di dialogo, digita l'ID progetto e fai clic su Arresta per eliminare il progetto.