FCM(Firebase Cloud Messaging)をFirebase Admin SDKで使用するまで

はじめに

バックエンドの藤岡です。

Firebase Cloud Messaging(以下FCM)を使用していて、Firebase Admin SDKとの連携で手まどったので、備忘録としてFCMをAdmin SDKを用いてCloud Functionで使用するまでの工程をまとめようと思います。

なお、今回はあくまでセットアップまでについてをまとめるため、Admin SDKやFCMについての詳しい説明はしません。そちらについては機会があれば別の記事で書こうかと思います。

また、今回紹介しますのは、私の環境で動作したセットアップの方法ですので、環境によっては今回のやり方が上手く行かない場合はあるかと思います。その点は予めご了承下さい。

前提知識

  • Firebaseプロジェクトの立ち上げ方
  • SDKの追加方法
  • FCMの使い方

前提条件

  • Firebaseプロジェクトが既にある
  • Cloud Function、Admin SDKが使える状態にある

1.SDKを初期化する

Admin SDKを正常に使用できていても、FCMを使用しようとした場合に以下のような認証のエラーが起きてしまいました。いろいろ調べてみたところ、Admin SDKが適切に認証できていないのが問題のようでした。

errorInfo: { code: 'messaging/authentication-error',  message: 'An error occurred when trying to authenticate to the FCM servers. Make sure the credential used to authenticate this SDK has the proper permissions. See https://firebase.google.com/docs/admin/setup for setup instructions. Raw server response:

対策として、Firebaseのサービスアカウントの秘密鍵ファイルを利用して初期化したところ、うまくいきました。

手順は以下のようになります

  1. Firebaseコンソールから「設定(歯車マーク)」→「サービスアカウント」を開く
  2. Firebase Admin SDKから「新しい秘密鍵の作成」をクリック
  3. 保存されたJSONファイルをCloud Functionのルートディレクトリに設置
  4. 「サービスアカウント」の「Admin SDK 構成スニペット」をコピーしてCloud Functionの所定の位置にペースト

コピペするコードはFirebaseのバージョンにもよるとは思いますが、現時点(2022/12/15)では以下のようになっています。

var admin = require("firebase-admin");
var serviceAccount = require("path/to/serviceAccountKey.json");

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
});

参考:https://firebase.google.com/docs/admin/setup?hl=ja#add-sdk

2.Cloud Messaging APIの追加

次に、プロジェクトで関連するAPIを有効にして、FirebaseプロジェクトでFCMを使用できるようにします。

手順は以下のようになります。

  1. プロジェクトのGoogle Cloud Platformを開く
  2. 「APIとサービス」から「APIとサービスの有効化」を開く
  3. 検索窓から「Cloud Messaging」と検索し、「Firebase Cloud Messaging API」と「Cloud Messaging」を有効化にする

Firebaseプロジェクトから「プロジェクトの設定」→「Cloud Messaging」を開いたときに両APIが有効になっていればOKです。

参考:https://stackoverflow.com/questions/57767439/an-error-occurred-when-trying-to-authenticate-to-the-fcm-servers

3.コードの記述

これで、Admin SDKを使ってFCMのコードを記述することができます。

今回は試しに、何かFirestoreのtestCollectionにドキュメントが追加されたことをトリガーとして、特定のトークンの集団に通知を送信することを想定したコードを載せます。

import * as functions from "firebase-functions";

var serviceAccount = require("path/to/serviceAccountKey.json");

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
});

export const sendNotificationOnCreateDoc = functions
  .region("asia-northeast1")
  .firestore.document("testCollection/{DocID}/")
  .onCreate(async (snapshot, context) => {
    const messages: admin.messaging.Message[] = [];
    const tokens = ["YOUR_REGISTATION_TOKEN_1", "YOUR_REGISTATION_TOKEN_2"];
    tokens.forEach((token) => {
      const notification: admin.messaging.Notification = {
        title: "送信通知",
        body: `${snapshot.data().title}が送信されました`,
      };
      const message: admin.messaging.Message = {
        token: token,
        notification: notification,
      };
      messages.push(message);
    });
    if (messages.length === 0) {
      console.log("No cliant.");
      return;
    }
    try {
      await admin
        .messaging()
        .sendAll(messages)
    } catch (error) {
      throw new functions.https.HttpsError("unknown", "通知を送信できません")
    }
  });

これで受信側で通知を受信できるようにしておけば、Firestoreへの投稿を感知して通知を受信することができます。受信する方法については今回の趣旨とは異なるため割愛させていただきます。

まとめ

今回はCloud Functionで使うことを想定して、Admin SDKでFCMを使うためのセットアップの一例について紹介しました。FCMは通知の送信方法や受信方法で様々な方法があり自分の中で混乱することばかりでした。Admin SDKでのセットアップもその一つでした。この記事をご覧になっている方の中で、少しでも参考になることがあれば幸いです。