[Pub/Sub - Cloud Functions] Google Cloud APIからの通知を受け取る

Googleのサービス、Pub/SubとCloud Functionsを使用して
Google Cloud APIからの通知を受け取る方法をご紹介します。

|No||目次|
|---|---|---|
|1||[Pub/Sub でトピックを作成](#1-pubsub-でトピックを作成)|
||1|[Pub/Subの検索](#11-pubsubの検索)|
||2|[トピックを作成](#12-トピックを作成)|
||3|[権限の設定](#13-権限の設定)|
|2||[Cloud Functions でファンクションを作成](#2-cloud-functions-でファンクションを作成)|
||1|[Cloud Functions 検索](#21-cloud-functions-検索)|
||2|[ファンクションを作成](#22-ファンクションを作成)|
||3|[ファンクションURLの取得](#23-ファンクションurlの取得)|
|3||[Pub/Sub でサブスクリプションを作成](#3-pubsub-でサブスクリプションを作成)|
||1|[サブスクリプションを作成](#31-サブスクリプションを作成)|
||2|[トピックの名前を取得](#32-トピックの名前を取得)|
|4||[APIからの通知を受け取る](#4-apiからの通知を受け取る)|

## 1. Pub/Sub でトピックを作成
Pub/Subでトピックを作成します。

#### 1.1. Pub/Subの検索
Pubと入力して、Pub/Subを選択します。
<img width=420 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/c1a37cc2-3641-0dd8-3819-2eff1b1a414c.png">

#### 1.2. トピックを作成
Pub/Sub画面の「トピックを作成」ボタンを押下します。
<img width=420 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/f22f09c1-c33f-819f-ed82-e67046579702.png">

トピックIDにトピック名を入力し、
「デフォルトのサブスクリプションを追加する」からチェックを外して
「作成」ボタンを押下します。
<img width=420 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/42e49189-ccd6-4ea9-7561-6cffc694cd7a.png">

#### 1.3. 権限の設定
作成したトピックの右側のメニューから「権限の表示」を選択します。
<img width=420 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/6e4ecdcb-2d28-66d7-4736-ace3612b21b6.png">

「プリンシバルを追加」を押します。
<img width=320 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/c0700a91-6a15-ed3a-5923-217b91ecd692.png">

新しいプリンシバルに利用したいAPIのプリンシバルを追加し、
ロールに「Pub/Sub パブリッシャー」を選択し、「保存」ボタンを押します。
<img width=320 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/3f2cb793-e5c6-b4d1-cf9c-0b2d3a2ac6c7.png">

## 2. Cloud Functions でファンクションを作成

#### 2.1. Cloud Functions 検索
cloud functionsと入力して、Cloud Functionsを選択します。
<img width=420 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/e0ea89c2-fcb3-5a6e-1888-b9b0a0c78a4f.png">

#### 2.2. ファンクションを作成
Cloud Functions画面の「ファンクションを作成」ボタンを押します。
<img width=420 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/5a05ae46-f1e1-9c2a-18fb-ef572c9258c8.png">
下記を選択・入力して、「次へ」を押します。
|設定|設定値|
|---|---|
|環境|第２世代|
|関数名|任意の関数名|
|リージョン|asia-northeast1(東京)|
|トリガーのタイプ|Cloud Pub/Sub|
|Cloud Pub/Sub トピック|[1.Pub/Sub でトピックを作成](#1-pubsub-でトピックを作成)で作成したトピックを選択|
<img width=320 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/93a50b34-fcfb-7077-0328-d6c6dda9db91.png">

ランタイムにJava 21を選択します。
<img width=420 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/a26cfdd5-ab0f-a3ff-b895-b8e1fa71a461.png">

関数が自動で作成されますが、利用するCloud APIの通知によっては
MessageのgetData()でNULLが返ってくるので、下記のようにコードを修正します。

修正後、「デプロイ」ボタンを押下します。
```java
package gcfv2pubsub;

import com.google.cloud.functions.CloudEventsFunction;
import com.google.events.cloud.pubsub.v1.MessagePublishedData;
import com.google.events.cloud.pubsub.v1.Message;
import com.google.gson.Gson;
import io.cloudevents.CloudEvent;
import java.util.Base64;
import java.util.logging.Logger;

public class PubSubFunction implements CloudEventsFunction {
  private static final Logger logger = Logger.getLogger(PubSubFunction.class.getName());

  @Override
  public void accept(CloudEvent event) {
    logger.info("Event: " + event.getId());
    logger.info("Event Type: " + event.getType());

    String cloudEventData = new String(event.getData().toBytes());
    logger.info("Event Data: " + cloudEventData);

    Gson gson = new Gson();
    MessagePublishedData data = gson.fromJson(cloudEventData, MessagePublishedData.class);
    Message message = data.getMessage();
    if(message!=null){
      String encodedData = message.getData();
      if(encodedData!=null){
        String decodedData = new String(Base64.getDecoder().decode(encodedData));
        logger.info("Message EncodedData: " + encodedData);
      }
    }
  }
}
```
#### 2.3. ファンクションURLの取得
ファンクションが作成されるので、URLを控えます。
<img width=420 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/8590d830-72aa-5237-c969-dc801a2ae87d.png">

## 3. Pub/Sub でサブスクリプションを作成
#### 3.1. サブスクリプションを作成
Pub/Subを開いて、メニューの「サブスクリプション」を選択し、
「サブスクリプションを作成」を押下します。
<img width=420 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/46d2932d-43cf-a95b-7bb6-0ad1806b7cd3.png">

下記を選択・入力して、「作成」ボタンを押します。
|設定|設定値|
|---|---|
|サブスクリプションID|任意の名前|
|Cloud Pab/Sub トピック|[1.Pub/Sub でトピックを作成](#1-pubsub-でトピックを作成)で作成したトピックを選択|
|配信タイプ|push|
|エンドポイントURL|[2.3. ファンクションURLの取得](#23-ファンクションurlの取得)で取得したURL|

<img width=420 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/72de1c8c-f2bf-cd88-0aa3-26d48c5ae172.png">

#### 3.2. トピックの名前を取得
トピックの名前を控えます。この名前をAPIで使用します。
<img width=420 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/21b12bcf-0a05-d786-b3c8-81caae1b2172.png">

## 4. APIからの通知を受け取る
[3.2. トピックの名前を取得](#32-トピックの名前を取得)で取得した
トピックの名前を指定してGmailの監視を行います。

Gmail APIについては
[⧉[Gmail API] JavaでGmail APIを使う](https://qiita.com/doran/items/a078e966bfd93c4b19c2)
をご参照ください。

```java
public static void main(String[] args) throws Exception{
    Gmail gmail = getGmail();
    Gmail.Users.Watch watch = gmail.users().watch(
        "me",
        new WatchRequest().setTopicName("トピックの名前")
    );
    System.out.println(watch.execute());
}
 ```
先程の「me」宛にメールが届くなど変更があった場合に、下記の通知が届きます。
<img width=420 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/47d23934-e858-53f3-50bd-72aefa5a1ddb.png">
<br>
<br>
おしまい。。