FCM HTTP v1 APIを使ってWeb Push送信

FCMのcurlを利用したWeb Push送信(FCM HTTP APIというらしいです)は
[前の記事](https://qiita.com/nishi-sankosc/private/8e3ede67bfb3263efa57)で記述しましたが、
インターフェイスが新しくなったHTTP v1 APIというものが公開されていたため、
そちらを試していきます。

##処理の違い
新しいFCM HTTP v1 APIでは、手順が１つ増えます。
ならべてみますと

###FCM HTTP API(前回のAPI)

- 固定のURLに`サーバーキー`を使って、登録トークンの相手にPushを送信

###FCM HTTP v1 APIの流れ
- `サービス アカウント用の秘密鍵ファイル`を使い`アクセストークン`の取得
- プロジェクト毎のURLに`アクセストークン`を使ってアクセスし、
登録トークンの相手にPushを送信

となっており、通信に使う情報が固定の`サーバーキー`だったのが、
一時的な`アクセストークン`となったことでセキュリティが上がったといったところでしょうか。

##アクセストークンの取得
アクセストークンの取得方法は
[公式の移行ガイド](https://firebase.google.com/docs/cloud-messaging/migrate-v1?hl=ja)を参考にすると
Node.js、Java、Python、Go、C#と用意があるようですが、
今回はNode.jsで取得していきたいと思います。
※Node.js自体のインストールは割愛させて頂きます。

###サービス アカウント用の秘密鍵ファイルの取得
アクセストークンを取得する為の認証ファイルを取得します。
Firebaseコンソールにてアプリの設定を確認(歯車マークを選択)すると設定画面に遷移します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645739/9e9ef184-d3e0-31a4-5a1c-b0b6d4c80597.png)

サービスアカウントのタブを選び、
画面下部の秘密鍵の生成ボタンを押すとダウンロードができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645739/beab5e82-e0e1-a880-79b4-1e78c41febeb.png)

###node.jsでアクセストークンを取得
node.jsでのアクセストークン取得のjsファイルを作成。
今回は8080ポートにアクセスするとアクセストークンが取得できるようにしています。

```javascript:getAccessToken.js
// google apiを使用
let {google} = require('googleapis');
// httpを使用
let http = require('http');

let server = http.createServer(function(req, res) {
  // アクセストークン取得
  const r = getAccessToken();
  r.then( (val) => {
    // アクセストークンが取得成功したらトークンを描画
    res.write(val);
    res.end();
 } );
}).listen(8080); // 8080ポートで待ち受け

// アクセストークン取得関数
 function getAccessToken() {
  return new Promise(function(resolve, reject) {
    var key = require('./web-push-test-202006-firebase-adminsdk-vbnax-xxxxxxxxxx.json');
    var jwtClient = new google.auth.JWT(
      key.client_email,
      null,
      key.private_key,
       [
         'https://www.googleapis.com/auth/firebase.messaging', 
       ],
      null
    );
    jwtClient.authorize(function(err, tokens) {
      if (err) {
        reject(err);
        return;
      }
      resolve(tokens.access_token);
    });
  });
}
```

`./web-push-test-202006-firebase-adminsdk-vbnax-xxxxxxxxxx.json`の部分は
サービス アカウント用の秘密鍵ファイルのパスを指定してください。
※上記の例ですとgetAccessToken.jsと同階層にファイルを置いている形になります。

`googleapis`を使用しているのでnpmでインストールして、

```
> npm install googleapis
```

node.jsを立ち上げます。

```
> node getAccessToken.js
```

8080ポートにアクセスしてみると、tokenが取得できていることが確認できるかとおもいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645739/7921fcc4-94cd-9032-25db-66fe7651014f.png)

### php側で呼び出し

サーバー側のphpでアクセストークンを受け取るプログラム`get_access_token.php`を作成してアクセストークンが取得できていることを確認します。

```php:get_access_token.php
<?php
// curlの初期化
$ch = curl_init();

curl_setopt_array($ch, array(
    CURLOPT_URL => 'http://localhost:8080/', // Node.jsのURLを指定
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_RETURNTRANSFER => true,
));

// アクセストークンの取得
$access_token = curl_exec($ch);
$access_token = trim($access_token);
var_dump($access_token);

curl_close($ch);
```

無事、取得できていることを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645739/1e5f4e3e-7740-86eb-dbec-d777c7891230.png)

##Web Push送信

アクセストークンを使い、Pushを送信するプログラム`push.php`を作ります。
FCM HTTP APIと比べるとメッセージのJSONの形式も変わっていますので注意が必要です。

```php:push.php
<?php
// get_access_token.phpと同じコードを記述

// 送るメッセージ　tokenに登録トークンを設定
$json = '{
"message":{
"notification":{"title": "タイトル","body": "ボディ"},
"token":"dPteMPRIxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}';

// curlの初期化
$ch2 = curl_init();

// アクセストークンをhttpヘッダーに設定
$headers = array(
    'Content-Type: application/json',
    'Authorization: Bearer ' . $access_token
);

// 「web-push-test-202006」は各々作成したFireBaseプロジェクト名に変更
curl_setopt_array($ch2, array(
    CURLOPT_URL => 'https://fcm.googleapis.com/v1/projects/web-push-test-202006/messages:send',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POSTFIELDS => $json
));

// push送信
$response = curl_exec($ch2);

curl_close($ch2);
```
送るjsonデータの`token`には[受信側設定時](https://qiita.com/nishi-sankosc/items/38eaa16e8732f04b17ac)に取得した登録トークンを
`CURLOPT_URL`の`web-push-test-202006`には自分のFireBaseプロジェクトのIDを指定してください。


呼び出してWeb Pushを送信してみると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645739/865fe11e-e088-9779-4d9f-1243486ee18b.png)

無事、通知を受け取ることができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645739/c2f1573d-9012-bfa5-68c3-986dce6dd76d.png)

参考：
以前の HTTP から HTTP v1 に移行する
https://firebase.google.com/docs/cloud-messaging/migrate-v1?hl=ja