Posted at

Firebase Cloud Messagingで始めるWebプッシュ通知


1)はじめに

スマホアプリと同じようなプッシュ通知の機能を、Webサイトに持たせる仕組みを使ってみましょう!みんな大好きmBaas、FirebaseのCloud Messaging(以下FCM)では、お手軽にWebプッシュ通知を実装することが可能です!なんと無料!太っ腹ですね!!:relaxed:

対応しているブラウザは【Desktop】Chrome / Firefox / Edge、【Mobile】Chrome / Firefoxとなっています。また、常時SSL必須となります。

今回のDEMOはこちら


2)FirebaseのJavaScriptタグを設置する



この画面の</>アイコンをクリックすると、下記のタグがポップアップするのでコピーしてHTML の一番下、他のスクリプトタグの前に貼り付けます。


index.html

<script src="https://www.gstatic.com/firebasejs/5.5.4/firebase.js"></script>

<script>
// Initialize Firebase
var config = {
apiKey: "<API_KEY>",
authDomain: "<PROJECT_ID>.firebaseapp.com",
databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
projectId: "<PROJECT_ID>",
storageBucket: "<BUCKET>.appspot.com",
messagingSenderId: "<SENDER_ID>"
};
firebase.initializeApp(config);
</script>


3)manifest.jsonの作成

また、<head>内に下記タグを設置します。


index.html

<link rel="manifest" href="/manifest.json">


ウェブアプリ マニフェストファイル(manifest.json)を作成、ドキュメントルートに設置します。既にある場合は下記タグを追加します。

これは、FCMがこのアプリへのメッセージ送信を許可されていることを示しています(この値は固定値で変更不可)。


manifest.json

{

"gcm_sender_id": "103953800507"
}


4)見た目を作る

今回はわかりやすいよう、下記のみを作成します。

通知の権限許可



トークン(インスタンスID)取得と画面への表示



cURLでプッシュ通知を送信



トークン削除

表画面側は下記のように、ボタンと入力フィールドを置いておきます。


index.html

<p>

<input type="button" id="btnSubscribe" value="通知を許可する">
<input type="button" id="btnUnSubscribe" value="トークン削除" style="display:none;">
</p>
<p><input type="text" value="YOUR-INCETANCE-ID-TOKEN" id="textInstanceIdToken" style="width:100%;box-sizing:border-box;"></p>
<div id="sendWebPushArea" style="display:none;">
<p>下記をコピーしてこのタブを閉じ、別ブラウザで見てください</p>
<input type="text" value="" id="sendWebPush" style="width:100%;box-sizing:border-box;">
</div>


5)処理の流れを理解する

main.jsを作成しこのページから参照します。


main.js

const btnSubscribe = document.getElementById('btnSubscribe');

const btnUnSubscribe = document.getElementById('btnUnSubscribe');
const textInstanceIdToken = document.getElementById('textInstanceIdToken');
const sendWebPushArea = document.getElementById('sendWebPushArea');
const sendWebPush = document.getElementById('sendWebPush');

// メッセージング オブジェクトの取得
const messaging = firebase.messaging();

// アプリにウェブ認証情報を設定する
messaging.usePublicVapidKey("<YOUR-PUBLIC-VAPID-KEY");

// 権限要求
function requestPermission() {
// 通知を受信する権限を要求する
messaging.requestPermission().then(function() {
// 現在の登録トークンの取得
messaging.getToken().then(function(token) {
textInstanceIdToken.value = token;
btnSubscribe.style.display = 'none';
btnUnSubscribe.style.display = 'block';
sendWebPushArea.style.display = 'block';
sendWebPush.value = 'https://andus.heteml.jp/firebase_cloud_messaging/send.php?id=' + token;
}).catch(function(err) {
textInstanceIdToken.value = 'トークンの取得に失敗しました(' + err + ')。';
});
}).catch(function(err) {
textInstanceIdToken.value = '通知の許可が得られませんでした(' + err + ')。';
});
}

// トークン削除
function deleteToken() {
// トークン取得
messaging.getToken().then(function(currentToken) {
// トークン削除
messaging.deleteToken(currentToken).then(function() {
textInstanceIdToken.value = 'トークンが削除されました';
btnSubscribe.style.display = 'block';
btnUnSubscribe.style.display = 'none';
sendWebPushArea.style.display = 'none';
sendWebPush.value = '';
}).catch(function(err) {
textInstanceIdToken.value = 'トークンの削除に失敗しました(' + err + ')。';
});
}).catch(function(err) {
textInstanceIdToken.value = 'トークンの取得に失敗しました(' + err + ')。';
});
}

// 初期化
window.onload = function() {
// イベント登録
btnSubscribe.onclick = requestPermission;
btnUnSubscribe.onclick = deleteToken;
// トークン取得
messaging.getToken().then(function(currentToken) {
if (currentToken) {
// 本来ここでサーバにトークン送る処理
//sendTokenToServer(currentToken);
textInstanceIdToken.value = currentToken;
btnSubscribe.style.display = 'none';
btnUnSubscribe.style.display = 'block';
sendWebPushArea.style.display = 'block';
sendWebPush.value = 'https://andus.heteml.jp/firebase_cloud_messaging/send.php?id=' + currentToken;
} else {
// トークン無い場合
textInstanceIdToken.value = '通知の許可をしていません。「通知を許可する」を押してください。';
}
}).catch(function(err) {
textInstanceIdToken.value = 'トークンの取得に失敗しました(' + err + ')。';
});
};




Firebase consoleのギアマークをクリック、「プロジェクトの設定」を選択、「クラウド メッセージング」を開きます。下の辺りの「ウェブ設定」「ウェブプッシュ証明書」の「鍵ペアを作成」をクリックします。

<YOUR-PUBLIC-VAPID-KEY>には生成した鍵ペアを設定します。


6)firebase-messaging-sw.jsの設置

ドキュメントルートにService Workerを設置します。

名前は「firebase-messaging-sw.js」で固定となります。


Service Workerとは?

バックグラウンド実行を可能にするJavaScriptで書かれたネットワークプロキシで、これによってモバイルでChromeを開いてない時にもプッシュ通知が可能となります。


firebase-messaging-sw.js

importScripts('https://www.gstatic.com/firebasejs/5.5.4/firebase-app.js');

importScripts('https://www.gstatic.com/firebasejs/5.5.4/firebase-messaging.js');

firebase.initializeApp({
'messagingSenderId': '<YOUR-MESSAGING-SENDER-ID>'
});

const messaging = firebase.messaging();

messaging.setBackgroundMessageHandler(function(payload) {
const notificationTitle = payload.notification.title;
const notificationOptions = {
body: payload.notification.body,
icon: payload.notification.icon
};
return self.registration.showNotification(notificationTitle, notificationOptions);
});


先程と同様にFirebase consoleにて「クラウド メッセージング」を開きます。



そして「プロジェクト認証情報」の「送信者ID」をコピーして<YOUR-MESSAGING-SENDER-ID>に貼り付け完了です。


7)PHPでcURLする

これで、得たトークンを使ってプッシュ通知を送ることが可能になりました。



DEMOページからsendすると通知が送られないため、別ブラウザで叩くことでテスト出来るようにしました。

※ 今回のプッシュ通知送信DEMOについては下記のトークンに$_GETメソッドで得た値を入れているだけです。


send.php

// 送るメッセージ

$json = '{
"notification":
{
"title": "タイトルが入ります",
"body": "本文が入ります",
"icon": "https://●●●●●●●●●.com/message.png",
"click_action": "https://●●●●●●●●●.com/"
},
"to": "<コピーしたトークン>"
}'
;

$ch = curl_init();

$headers = array(
'Content-Type: application/json',
'Authorization: key=<FCM_SERVER_KEY>'
);

curl_setopt_array($ch, array(
CURLOPT_URL => 'https://fcm.googleapis.com/fcm/send',
CURLOPT_HTTPHEADER => $headers,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => $json
));

$response = curl_exec($ch);

curl_close($ch);


<FCM_SERVER_KEY>には、先ほどの「プロジェクト認証情報」の「サーバーキー」を設定します。

そして、実際にcURLしてプッシュ通知を送信したのが下記キャプチャ(上がDesktop Chrome、下がAndroid端末)。



(まめちしき)デバッグ中にDesktop Chromeでサイトの通知をOFFにしたい時は、サイトの設定に行くよりはこっちが速い。


8)あとがき

実際にWebプッシュ通知サービスを独自に組み込もうと思ったら、ユーザーのログイン情報との紐付けや、個別のトークンの保存と管理が必須になってきます。サイトやブログの更新情報通知など、ユーザー属性を意識しなくても構わない場合にはトークンのみの保管でやって行けそうですね。

運用にあたり難しいのは、どんなタイミングでどの属性のユーザーに最適な情報を送れるか?ということでしょうね〜。


参考リンク