Tworzenie aplikacji Google Chat jako webhooka

Na tej stronie opisaliśmy, jak skonfigurować webhook, aby wysyłać wiadomości asynchroniczne do pokoju Google Chat za pomocą zewnętrznych wyzwalaczy. Możesz na przykład skonfigurować aplikację monitorującą, aby powiadamiała personel dyżurny w Hangouts Chat o awarii serwera. Aby wysłać wiadomość synchroniczną za pomocą aplikacji Chat, przeczytaj artykuł Wysyłanie wiadomości.

W przypadku tego typu architektury użytkownicy nie mogą wchodzić w interakcje z webhookem ani podłączoną aplikacją zewnętrzną, ponieważ komunikacja jest jednokierunkowa. Webhooki nie są konwersacyjne. Nie mogą odpowiadać na wiadomości od użytkowników ani ich otrzymywać ani uczestniczyć w zdarzeniach interakcji z aplikacją do obsługi czatu. Aby odpowiadać na wiadomości, utwórz aplikację na czacie zamiast webhooka.

Webhook nie jest technicznie aplikacją Google Chat (łączy aplikacje za pomocą standardowych żądań HTTP), ale na potrzeby uproszczenia na tej stronie jest tak nazywany. Każdy webhook działa tylko w pokoju czatu, w którym jest zarejestrowany. Wewnętrzne wywołania webhooka działają w czatach, ale tylko wtedy, gdy wszyscy użytkownicy mają włączone aplikacje do obsługi czatu. Nie możesz publikować webhooków w Google Workspace Marketplace.

Ten diagram przedstawia architekturę webhooka połączonego z Google Chat:

Architektura webhooków przychodzących do wysyłania wiadomości asynchronicznych do Google Chat

Na poniższym diagramie przedstawiono przepływ informacji w aplikacji Google Chat:

  1. Logika aplikacji Chat otrzymuje informacje z zewnętrznych usług innych firm, takich jak system zarządzania projektami czy narzędzie do obsługi zgłoszeń.
  2. Logika aplikacji Google Chat jest hostowana w chmurze lub lokalnym systemie, który może wysyłać wiadomości za pomocą adresu URL webhooka do konkretnego pokoju Google Chat.
  3. Użytkownicy mogą otrzymywać wiadomości z aplikacji Google Chat w tym konkretnym pokoju, ale nie mogą wchodzić z nią w interakcje.

Wymagania wstępne

Python

Node.js

Java

Google Apps Script

Tworzenie webhooka

Aby utworzyć webhooka, zarejestruj go w pokoju Google Chat, w którym chcesz otrzymywać wiadomości, a następnie napisz skrypt, który będzie je wysyłać.

Rejestrowanie przychodzącego webhooka

  1. W przeglądarce otwórz Google Chat. Webhooków nie można konfigurować w aplikacji mobilnej Google Chat.
  2. Otwórz pokój, do którego chcesz dodać webhook.
  3. Obok tytułu pokoju kliknij strzałkę rozwijania w , a następnie Aplikacje i integracje.
  4. Kliknij Dodaj webhooki.

  5. W polu Nazwa wpisz Quickstart Webhook.

  6. W polu URL awatara wpisz https://developers.google.com/chat/images/chat-product-icon.png.

  7. Kliknij Zapisz.

  8. Aby skopiować adres URL webhooka, kliknij Więcej, a następnie Kopiuj link.

Tworzenie skryptu webhooka

Przykładowy skrypt webhooka wysyła wiadomość do przestrzeni, w której webhook jest zarejestrowany, wysyłając żądanie POST do adresu URL webhooka. Interfejs Chat API odpowiada instancji Message.

Wybierz język, aby dowiedzieć się, jak utworzyć skrypt webhooka:

Python

  1. W katalogu roboczym utwórz plik o nazwie quickstart.py.

  2. W aplikacji quickstart.py wklej ten kod:

    Python/webhook/quickstart.py
    from json import dumps
    from httplib2 import Http
    
    # Copy the webhook URL from the Chat space where the webhook is registered.
    # The values for SPACE_ID, KEY, and TOKEN are set by Chat, and are included
    # when you copy the webhook URL.
    
    def main():
        """Google Chat incoming webhook quickstart."""
        url = "https://chat.googleapis.com/v1/spaces/SPACE_ID/messages?key=KEY&token=TOKEN"
        app_message = {"text": "Hello from a Python script!"}
        message_headers = {"Content-Type": "application/json; charset=UTF-8"}
        http_obj = Http()
        response = http_obj.request(
            uri=url,
            method="POST",
            headers=message_headers,
            body=dumps(app_message),
        )
        print(response)
    
    
    if __name__ == "__main__":
        main()
  3. Zastąp wartość zmiennej url adresem URL webhooka, który został skopiowany podczas rejestracji webhooka.

Node.js

  1. W katalogu roboczym utwórz plik o nazwie index.js.

  2. W pliku index.js wklej ten kod:

    node/webhook/index.js
    /**
     * Sends asynchronous message to Google Chat
     * @return {Object} response
     */
    async function webhook() {
      const url = "https://chat.googleapis.com/v1/spaces/SPACE_ID/messages"
      const res = await fetch(url, {
        method: "POST",
        headers: {"Content-Type": "application/json; charset=UTF-8"},
        body: JSON.stringify({text: "Hello from a Node script!"})
      });
      return await res.json();
    }
    
    webhook().then(res => console.log(res));
  3. Zastąp wartość zmiennej url adresem URL webhooka skopiowanym podczas rejestracji webhooka.

Java

  1. W katalogu roboczym utwórz plik o nazwie pom.xml.

  2. W polu pom.xml wklej ten tekst:

    java/webhook/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.webhook</groupId>
      <artifactId>java-webhook-app</artifactId>
      <version>0.1.0</version>
    
      <name>java-webhook-app</name>
      <url>https://github.com/googleworkspace/google-chat-samples/tree/main/java/webhook</url>
    
      <properties>
        <maven.compiler.target>11</maven.compiler.target>
        <maven.compiler.source>11</maven.compiler.source>
      </properties>
    
      <dependencies>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.9.1</version>
        </dependency>
      </dependencies>
    
      <build>
        <pluginManagement>
          <plugins>
            <plugin>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>3.8.0</version>
            </plugin>
          </plugins>
        </pluginManagement>
      </build>
    </project>
  3. W katalogu roboczym utwórz tę strukturę katalogów: src/main/java.

  4. W katalogu src/main/java utwórz plik o nazwie App.java.

  5. W aplikacji App.java wklej ten kod:

    java/webhook/src/main/java/com/google/chat/webhook/App.java
    import com.google.gson.Gson;
    import java.net.http.HttpClient;
    import java.net.http.HttpRequest;
    import java.net.http.HttpResponse;
    import java.util.Map;
    import java.net.URI;
    
    public class App {
      private static final String URL = "https://chat.googleapis.com/v1/spaces/AAAAGCYeSRY/messages";
      private static final Gson gson = new Gson();
      private static final HttpClient client = HttpClient.newHttpClient();
    
      public static void main(String[] args) throws Exception {
        String message = gson.toJson(Map.of("text", "Hello from Java!"));
    
        HttpRequest request = HttpRequest.newBuilder(URI.create(URL))
          .header("accept", "application/json; charset=UTF-8")
          .POST(HttpRequest.BodyPublishers.ofString(message)).build();
    
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    
        System.out.println(response.body());
      }
    }
  6. Zastąp wartość zmiennej URL adresem URL webhooka skopiowanym podczas rejestracji webhooka.

Google Apps Script

  1. W przeglądarce otwórz Apps Script.

  2. Kliknij Nowy projekt.

  3. Wklej ten kod:

    apps-script/webhook/webhook.gs
    function webhook() {
      const url = "https://chat.googleapis.com/v1/spaces/SPACE_ID/messages"
      const options = {
        "method": "post",
        "headers": {"Content-Type": "application/json; charset=UTF-8"},
        "payload": JSON.stringify({"text": "Hello from Apps Script!"})
      };
      const response = UrlFetchApp.fetch(url, options);
      console.log(response);
    }
  4. Zastąp wartość zmiennej url adresem URL webhooka skopiowanym podczas rejestracji webhooka.

Uruchamianie skryptu webhooka

Uruchom skrypt w interfejsie wiersza poleceń:

Python

  python3 quickstart.py

Node.js

  node index.js

Java

  mvn compile exec:java -Dexec.mainClass=App

Google Apps Script

  • Kliknij Wykonaj.

Gdy uruchomisz kod, webhook wyśle wiadomość do pokoju, w którym go zarejestrowano.

Rozpoczynanie wątku wiadomości lub odpowiadanie na niego

  1. W treści żądania wiadomości podaj wartość spaces.messages.thread.threadKey. W zależności od tego, czy rozpoczynasz wątek, czy na niego odpowiadasz, użyj jednej z tych wartości w polu threadKey:

    • Jeśli rozpoczynasz wątek, ustaw wartość threadKey na dowolny ciąg znaków, ale zanotuj tę wartość, aby opublikować odpowiedź na wątek.

    • Jeśli odpowiadasz na wątek, podaj threadKey ustawiony podczas inicjowania wątku. Aby na przykład opublikować odpowiedź w wątku, w którym pierwsza wiadomość używała znaku MY-THREAD, ustaw MY-THREAD.

  2. Określ zachowanie wątku, jeśli nie zostanie znaleziony określony element threadKey:

    • Odpowiedz w wątku lub zacznij nowy wątek. Dodaj parametr messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD do adresu URL webhooka. Przekazywanie tego parametru adresu URL powoduje, że czat wyszukuje istniejący wątek za pomocą określonego threadKey. Jeśli zostanie znaleziony, wiadomość zostanie opublikowana jako odpowiedź w tym wątku. Jeśli żaden nie zostanie znaleziony, wiadomość rozpocznie nowy wątek odpowiadający temu threadKey.

    • Odpowiedz w wątku lub nic nie rób. Dodaj parametr messageReplyOption=REPLY_MESSAGE_OR_FAIL do adresu URL webhooka. Przekazywanie tego parametru adresu URL powoduje, że czat wyszukuje istniejący wątek za pomocą określonego threadKey. Jeśli zostanie znaleziona, wiadomość zostanie opublikowany jako odpowiedź w tym wątku. Jeśli nie znaleziono żadnego, wiadomość nie została wysłana.

    Więcej informacji znajdziesz w artykule messageReplyOption.

Poniższy przykładowy kod uruchamia wątek lub odpowiada na niego:

Python

python/webhook/thread-reply.py
from json import dumps
from httplib2 import Http

# Copy the webhook URL from the Chat space where the webhook is registered.
# The values for SPACE_ID, KEY, and TOKEN are set by Chat, and are included
# when you copy the webhook URL.
#
# Then, append messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD to the
# webhook URL.


def main():
    """Google Chat incoming webhook that starts or replies to a message thread."""
    url = "https://chat.googleapis.com/v1/spaces/SPACE_ID/messages?key=KEY&token=TOKEN&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD"
    app_message = {
        "text": "Hello from a Python script!",
        # To start a thread, set threadKey to an arbitratry string.
        # To reply to a thread, specify that thread's threadKey value.
        "thread": {"threadKey": "THREAD_KEY_VALUE"},
    }
    message_headers = {"Content-Type": "application/json; charset=UTF-8"}
    http_obj = Http()
    response = http_obj.request(
        uri=url,
        method="POST",
        headers=message_headers,
        body=dumps(app_message),
    )
    print(response)


if __name__ == "__main__":
    main()

Node.js

node/webhook/thread-reply.js
/**
 * Sends asynchronous message to Google Chat
 * @return {Object} response
 */
async function webhook() {
  const url = "https://chat.googleapis.com/v1/spaces/SPACE_ID/messages?key=KEY&token=TOKEN&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD"
  const res = await fetch(url, {
    method: "POST",
    headers: {"Content-Type": "application/json; charset=UTF-8"},
    body: JSON.stringify({
      text: "Hello from a Node script!",
      thread: {threadKey: "THREAD_KEY_VALUE"}
    })
  });
  return await res.json();
}

webhook().then(res => console.log(res));

Google Apps Script

apps-script/webhook/thread-reply.gs
function webhook() {
  const url = "https://chat.googleapis.com/v1/spaces/SPACE_ID/messages?key=KEY&token=TOKEN&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD"
  const options = {
    "method": "post",
    "headers": {"Content-Type": "application/json; charset=UTF-8"},
    "payload": JSON.stringify({
      "text": "Hello from Apps Script!",
      "thread": {"threadKey": "THREAD_KEY_VALUE"}
    })
  };
  const response = UrlFetchApp.fetch(url, options);
  console.log(response);
}

Obsługa błędów

Żądania webhooka mogą się nie powieść z różnych powodów, m.in.:

  • Nieprawidłowe żądanie.
  • Webhook lub pokój, w którym się znajduje, został usunięty.
  • Przejściowe problemy, takie jak brak połączenia sieciowego czy limity.

Podczas tworzenia webhooka należy odpowiednio obsługiwać błędy:

Interfejs API Google Chat zwraca błędy jako google.rpc.Status, co obejmuje błąd HTTP code, który wskazuje typ błędu: błąd klienta (seria 400) lub błąd serwera (seria 500). Aby przejrzeć wszystkie mapowania HTTP, otwórz google.rpc.Code.

{
    "code": 503,
    "message": "The service is currently unavailable.",
    "status": "UNAVAILABLE"
}

Aby dowiedzieć się, jak interpretować kody stanu HTTP i jak obsługiwać błędy, zapoznaj się z artykułem Błędy.

Ograniczenia i uwagi

  • Gdy tworzysz wiadomość za pomocą webhooka w Google Chat API, odpowiedź nie zawiera pełnej wiadomości. Odpowiedź zawiera tylko pola name i thread.name.