Chat-Apps erstellen

Auf dieser Seite wird beschrieben, wie Sie Apps erstellen, die Ereignisse aus Google Chat empfangen, verarbeiten und darauf reagieren:

  • Nachrichten und andere Ereignisse erhalten, die von Google Chat generiert wurden
  • Antworten auf Antworten und andere Nachrichten an Google Chat senden

Weitere Informationen zu Einschränkungen und Anwendungsfällen finden Sie unter Chat-Apps.

Möglichkeiten zum Erstellen von Chat-Apps

Sie können eine Chat-App mit Google Apps Script, Ihrem eigenen technischen Stack oder Google AppSheet (Beta) erstellen.

Informationen zum Erstellen einer einfachen Chat-App finden Sie in den folgenden Kurzanleitungen:

  • Chat-App mit Google Apps Script erstellen
  • Chat-App mit Google Cloud Functions erstellen
  • Chat-App mit AppSheet erstellen (Beta)

    Zum Erstellen einer Chat-App ohne Code mit AppSheet (Beta) müssen Sie ein Google Cloud-Projekt erstellen und mit Ihrer Chat-App verbinden. Dies kann automatisch oder manuell über die Google Cloud Console durchgeführt werden. Anschließend können Sie die Chat-App-Interaktionen anpassen und die App privat für bestimmte Personen oder Gruppen innerhalb Ihrer Google Workspace-Organisation veröffentlichen. Weitere Informationen finden Sie in der AppSheet-Dokumentation unter Chat-Apps.

    Informationen zum Deaktivieren von Chat-Apps mit AppSheet finden Sie in der Google Workspace-Admin-Dokumentation unter Chat für Ihre Organisation aktivieren oder deaktivieren und Chat-Apps deaktivieren in der AppSheet-Dokumentation.

Endpunkttypen

Ereignisse aus Google Chat werden über einen Endpunkt an Ihre App gesendet. Es gibt verschiedene Typen von Ereignissen:

  • HTTPS-Endpunkte präsentieren Ihre Anwendung als Webdienst. Sie müssen einen Webserver einrichten, der als Schnittstelle für die Implementierung Ihrer Anwendung dient. Ihre Anwendung kann auf diese Ereignisse synchron oder asynchron reagieren.
  • Google Cloud Pub/Sub-Endpunkte verwenden ein Thema in Google Cloud Pub/Sub, um ein Ereignis an die Implementierung Ihrer Anwendung weiterzuleiten. Dies ist hilfreich, wenn die Implementierung hinter einer Firewall liegt. Anwendungen, die Pub/Sub-Endpunkte verwenden, können nur asynchron reagieren.
  • Mit DialogFlow-Endpunkten kann Ihre Anwendung die NLP-Funktionen von DialogFlow verwenden. Weitere Informationen finden Sie in der DialogFlow-Dokumentation.

Für eine einfache, einfache Anwendungsarchitektur sollten Sie eine Anwendung mit einem HTTPS-Endpunkt (im Wesentlichen einem Webdienst) implementieren, der synchron antwortet und die Nutzlast immer in die HTTPS-POST-Antwort einschließt. Dieser Ansatz erfordert keine Autorisierung, daher ist kein Dienstkonto erforderlich. Im Abschnitt Einfache Implementierung von Anwendungen unten finden Sie ein Beispiel für diesen Anwendungsstil.

Wenn Ihre Anwendung sich hinter einer Firewall befindet oder unerwünschte Nachrichten wie Alarme oder andere Benachrichtigungen an Google Chat sendet, müssen Sie möglicherweise einen komplexeren Ansatz wählen.

Eine sehr einfache App-Implementierung

Mit dem folgenden Code wird eine einfache Anwendung in Python mit dem Web-Framework Flask implementiert.

#!/usr/bin/env python3
"""Example app that returns a synchronous response."""

from flask import Flask, request, json


app = Flask(__name__)


@app.route('/', methods=['POST'])
def on_event():
  """Handles an event from Google Chat."""
  event = request.get_json()
  if event['type'] == 'ADDED_TO_SPACE' and not event['space']['singleUserBotDm']:
    text = 'Thanks for adding me to "%s"!' % (event['space']['displayName'] if event['space']['displayName'] else 'this chat')
  elif event['type'] == 'MESSAGE':
    text = 'You said: `%s`' % event['message']['text']
  else:
    return
  return json.jsonify({'text': text})


if __name__ == '__main__':
  app.run(port=8080, debug=True)

Da es sich um einen Webdienst handelt, stellt die Anwendung einen HTTPS-Endpunkt bereit und muss Cloud Pub/Sub nicht verwenden, um Ereignisse an ihn weiterzuleiten. Da die Antwortnutzlast immer in der JSON-Antwort zurückgegeben wird, muss sie sich nicht über ein Dienstkonto authentifizieren.

Termine aus Google Chat verarbeiten

In diesem Abschnitt wird beschrieben, wie Sie Ereignisse empfangen und verarbeiten, die Ihre Anwendung von Google Chat empfängt.

App registrieren

Bevor Ihre Anwendung Ereignisse von Google Chat empfangen kann, müssen Sie ihren Endpunkt beim Veröffentlichen Ihrer Anwendung auf dem Tab mit der Chat API-Konfiguration angeben.

Sobald Sie den Endpunkt registriert und Ihre Anwendung veröffentlicht haben, erkennt Google Chat Ereignisse, die an Ihre Anwendung gerichtet sind, und sendet sie an den angegebenen Endpunkt.

App-Authentizität prüfen

Nachdem Sie Ihre HTTPS-Anwendung registriert haben, müssen Sie prüfen, ob die Anfrage tatsächlich von Google stammt.

Google Chat enthält im Header Authorization jeder HTTPS-Anfrage an eine App ein Inhabertoken. Beispiel:

POST
Host: yourappurl.com
Authorization: Bearer AbCdEf123456
Content-Type: application/json
User-Agent: Google-Dynamite

Der String AbCdEf123456 im Beispiel oben ist das Inhaberautorisierungstoken. Dieses kryptografische Token wird von Google erstellt. Sie können Ihr Inhabertoken mit einer Open-Source-Clientbibliothek der Google API prüfen:

Alle Inhabertokens, die mit Anfragen aus dem Google-Chat gesendet werden, haben chat@system.gserviceaccount.com als Aussteller, wobei das Feld audience die Projektnummer der Zielanwendung aus Google API Console angibt. Wenn die Anfrage beispielsweise an eine Anwendung mit der Projektnummer 1234567890 gerichtet ist, lautet die Zielgruppe 1234567890.

Sie sollten prüfen, ob die Anfrage von Google stammt und für die Zielanwendung bestimmt ist. Wenn das Token nicht verifiziert wird, sollte die Anwendung mit einem HTTPS-Antwortcode 401 (Unauthorized) auf die Anfrage antworten.

Java

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;

import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
import com.google.api.client.googleapis.auth.oauth2.GooglePublicKeysManager;
import com.google.api.client.http.apache.ApacheHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;

/** Tool for verifying JWT Tokens for Apps in Google Chat. */
public class JWTVerify {
  // Bearer Tokens received by apps will always specify this issuer.
  static String CHAT_ISSUER = "chat@system.gserviceaccount.com";

  // Url to obtain the public certificate for the issuer.
  static String PUBLIC_CERT_URL_PREFIX =
      "https://www.googleapis.com/service_accounts/v1/metadata/x509/";

  // Intended audience of the token, which will be the project number of the app.
  static String AUDIENCE = "1234567890";

  // Get this value from the request's Authorization HTTPS header.
  // For example, for "Authorization: Bearer AbCdEf123456" use "AbCdEf123456"
  static String BEARER_TOKEN = "AbCdEf123456";

  public static void main(String[] args) throws GeneralSecurityException, IOException {
    JsonFactory factory = new JacksonFactory();

    GooglePublicKeysManager.Builder keyManagerBuilder =
        new GooglePublicKeysManager.Builder(new ApacheHttpTransport(), factory);

    String certUrl = PUBLIC_CERT_URL_PREFIX + CHAT_ISSUER;
    keyManagerBuilder.setPublicCertsEncodedUrl(certUrl);

    GoogleIdTokenVerifier.Builder verifierBuilder =
        new GoogleIdTokenVerifier.Builder(keyManagerBuilder.build());
    verifierBuilder.setIssuer(CHAT_ISSUER);
    GoogleIdTokenVerifier verifier = verifierBuilder.build();

    GoogleIdToken idToken = GoogleIdToken.parse(factory, BEARER_TOKEN);
    if (idToken == null) {
      System.out.println("Token cannot be parsed");
      System.exit(-1);
    }

    // Verify valid token, signed by CHAT_ISSUER.
    if (!verifier.verify(idToken)
        || !idToken.verifyAudience(Collections.singletonList(AUDIENCE))
        || !idToken.verifyIssuer(CHAT_ISSUER)) {
      System.out.println("Invalid token");
      System.exit(-1);
    }

    // Token originates from Google and is targeted to a specific client.
    System.out.println("The token is valid");
  }
}

Python

import sys

from oauth2client import client

# Bearer Tokens received by apps will always specify this issuer.
CHAT_ISSUER = 'chat@system.gserviceaccount.com'

# Url to obtain the public certificate for the issuer.
PUBLIC_CERT_URL_PREFIX = 'https://www.googleapis.com/service_accounts/v1/metadata/x509/'

# Intended audience of the token, which will be the project number of the app.
AUDIENCE = '1234567890'

# Get this value from the request's Authorization HTTPS header.
# For example, for 'Authorization: Bearer AbCdEf123456' use 'AbCdEf123456'.
BEARER_TOKEN = 'AbCdEf123456'

try:
  # Verify valid token, signed by CHAT_ISSUER, intended for a third party.
  token = client.verify_id_token(
      BEARER_TOKEN, AUDIENCE, cert_uri=PUBLIC_CERT_URL_PREFIX + CHAT_ISSUER)

  if token['iss'] != CHAT_ISSUER:
    sys.exit('Invalid issuee')
except:
  sys.exit('Invalid token')

# Token originates from Google and is targeted to a specific client.
print 'The token is valid'

Ereignisnutzlast

Wenn Ihre App ein Ereignis von Google Chat empfängt, enthält das Ereignis einen Anfragetext: Dies ist die JSON-Nutzlast, die das Ereignis darstellt. Der Anfragetext enthält immer die folgenden Informationen:

  • type: Ein String, der den Ereignistyp angibt.
  • eventTime: String, der den Ereigniszeitstempel enthält.

Zusätzliche Informationen im Anfragetext hängen vom Ereignistyp ab. Das folgende Beispiel zeigt eine mögliche Nutzlast:

{
  "type": "MESSAGE",
  "eventTime": "2017-03-02T19:02:59.910959Z",
  "space": {
    "name": "spaces/AAAAAAAAAAA",
    "displayName": "Best Dogs Discussion Space",
    "type": "ROOM"
  },
  "message": {
    "name": "spaces/AAAAAAAAAAA/messages/CCCCCCCCCCC",
    "sender": {
      "name": "users/12345678901234567890",
      "displayName": "Chris Corgi",
      "avatarUrl": "https://lh3.googleusercontent.com/.../photo.jpg",
      "email": "chriscorgi@example.com"
    },
    "createTime": "2017-03-02T19:02:59.910959Z",
    "text": "I mean is there any good reason their legs should be longer?",
    "thread": {
      "name": "spaces/AAAAAAAAAAA/threads/BBBBBBBBBBB"
    }
  }
}

Weitere Informationen zu den verschiedenen Ereignistypen und ihren Anfrageformaten finden Sie in der Referenz zu Ereignisformaten.

Ereignis verarbeiten

Wenn Ihre Anwendung ein Ereignis von Google Chat empfängt, hängt die Verwendung dieses Ereignisses vollständig von der Implementierung ab. Die Anwendung kann einige Informationen aus einer Datenquelle abrufen, die Ereignisinformationen aufzeichnen oder nahezu alles andere. Dieses Verarbeitungsverhalten ist im Wesentlichen das, was die Anwendung definiert.

In den meisten Fällen verarbeitet eine Anwendung nicht nur die im Ereignis enthaltenen Informationen, sondern generiert auch eine Antwort an den Thread, der das Ereignis ausgegeben hat. Das folgende Diagramm beschreibt eine typische Interaktion mit einer Anwendung in einem Chatbereich:

Im obigen Diagramm werden drei Arten von Ereignissen angezeigt: ADDED_TO_SPACE, MESSAGE und REMOVED_FROM_SPACE. Eine Anwendung kann nicht mehr reagieren, nachdem sie aus einem Gruppenbereich entfernt wurde, kann aber auf die beiden anderen Typen reagieren.

Synchron antworten

Eine Anwendung kann synchron auf ein Ereignis reagieren, indem sie eine JSON-formatierte Nachrichtennutzlast in der HTTPS-Antwort zurückgibt. Die Frist für eine synchrone Antwort beträgt 30 Sekunden.

Eine synchrone Antwort von einer Anwendung wird immer in dem Thread gepostet, der das Ereignis an die Anwendung generiert hat.

Asynchron antworten

Wenn eine Anwendung nach Ablauf der Frist von 30 Sekunden auf eine Nutzernachricht reagieren muss (z. B. nach einer lange laufenden Aufgabe), kann sie asynchron antworten, indem eine Nachricht mit der Chat REST API erstellt wird.

Wiederholen

Wenn eine HTTPS-Anfrage an Ihre Anwendung fehlschlägt, z.B. eine Zeitüberschreitung, ein vorübergehender Netzwerkfehler oder ein HTTPS-Statuscode, der nicht 20 % entspricht, versucht Google Chat zusätzlich zweimal, die Zustellung jedes Mal mit einer Verzögerung von mindestens 10 Sekunden durchzuführen. Daher kann eine Anwendung in bestimmten Situationen bis zu dreimal dieselbe Nachricht erhalten. Wenn die Anfrage erfolgreich abgeschlossen wurde, aber eine ungültige Nachrichtennutzlast zurückgegeben wird, wird kein neuer Versuch unternommen.