2023/04/05
FCMを利用してPHPからwebプッシュを送る
とうとうiOS(16.4以降)にもWEBプッシュが実装されました。
そこで、一番簡単にプッシュ通知が送れると思われる方法を試してみました。
今回はFirebase Cloud Messagingを使用してウェブプッシュ通知を送ります。
Firebaseからプロジェクトの作成〜設定まで
https://console.firebase.google.com/
こちらから、プロジェクトの作成を行います。
プロジェクト名は何でもOKです。
Googleアナリティクスが必要であれば、有効にして下さい。私の場合は、お試しなので無効にしています。
以上でプロジェクトの作成が完了です。
次はアプリの登録を行います。
</>をクリック
アプリ名は何でもOKです。
npmでも<script>でも、どちらでも良いのですが、「firebaseConfig」は必ずどこかにメモし保持して下さい。
以上でアプリの登録は完了です。
次は作成したプロジェクトの設定をしていきます。
添付画像の赤枠部分を左から順番にクリックしていきます。
最後は「Google Cloud コンソールでAPIを管理」をクリックします。
「有効にする」ボタンをクリックします。
添付画像の様に、「サーバーキー」が表示されるかと思いますので、これをメモし保持しておきます。
「サーバーキー」がない場合は、サーバーキーを追加して下さい。
最後にウェブプッシュ証明書を追加して終了です。
「Generate key pair」をクリックして鍵を作成し、鍵ペアをメモし保持しとえきます。
以上でFirebase上の設定は全て完了です。
ファイルの用意(作成)
3つのファイルを作成します。
- index.html
- firebase-messaging-sw.js
- send.php
それぞれのファイルの役割は次の様になります。
index.html = サイトと同じ。ブラウザで開いてウェブプッシュ通知を許可する為に必要。
firebase-messaging-sw.js = ブラウザを開いていなくても裏で動かすJavaScript。ServiceWorker。
send.php = 実際にウェブプッシュ通知を送るプログラム。
【index.html】
次の2箇所を変更して下さい。
- アプリ登録時に保持しておいた「firebaseConfig」をコピーして書き換え
- <ウェブプッシュ証明書鍵ペア>をウェブプッシュ証明書の作成した際に表示される鍵ペアに書き換え
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ウェブプッシュテスト</title>
<script src="https://www.gstatic.com/firebasejs/8.2.1/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.2.1/firebase-messaging.js"></script>
<script>
// ----- ↓ ここを書き換え -----
const firebaseConfig = {
apiKey: "○○○○○○○○○○○○○○○○○○○○○○○",
authDomain: "○○○○○○○○○○○.firebaseapp.com",
projectId: "○○○○○○○○○○○",
storageBucket: "○○○○○○○○○○○.appspot.com",
messagingSenderId: "○○○○○○○○○○○",
appId: "○:○○○○○○○○○○○:web:○○○○○○○○○○○○○○○○○"
};
// ----- ↑ ここまで書き換え -----
const publicVapidKey = "<ウェブプッシュ証明書鍵ペア>";
const app = firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging(app);
/**
* 権限要求
*/
function requestPermission() {
Notification.requestPermission().then((permission) => {
switch (permission) {
case 'granted': // 許可
messaging.getToken({ vapidKey: publicVapidKey }).then((token) => {
if (token) {
console.log( "token", token );
} else {
console.log('登録トークンがありません。生成する許可をリクエストします。');
}
}).catch((err) => {
console.error('トークンの取得に失敗しました。', err);
});
break;
case 'denied': // ブロック
case 'default': // ブロックも許可もなし(xで閉じた)
default:
break;
}
});
}
/**
* トークン削除
*/
function deleteToken() {
messaging.getToken().then((token) => {
messaging.deleteToken(token).then(function() {
console.log('トークンを削除しました');
}).catch(function(err) {
console.error('トークンの削除に失敗しました', err);
});
}).catch(function(err) {
console.error('トークンの取得に失敗しました。', err);
});
}
</script>
<style>
button {
display: block;
width: 80vw;
height: 90vh;
margin: 0 auto;
}
</style>
</head>
<body>
<button type="button" onclick="requestPermission();">プッシュ通知許可</button>
</body>
</html>
【firebase-messagins-sw.js】
次の1箇所を変更して下さい。
- アプリ登録時に保持しておいた「firebaseConfig」をコピーして書き換え
importScripts('https://www.gstatic.com/firebasejs/8.2.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.2.1/firebase-messaging.js');
// ----- ↓ ここを書き換え -----
const firebaseConfig = {
apiKey: "○○○○○○○○○○○○○○○○○○○○○○○",
authDomain: "○○○○○○○○○○○.firebaseapp.com",
projectId: "○○○○○○○○○○○",
storageBucket: "○○○○○○○○○○○.appspot.com",
messagingSenderId: "○○○○○○○○○○○",
appId: "○:○○○○○○○○○○○:web:○○○○○○○○○○○○○○○○○"
};
// ----- ↑ ここまで書き換え -----
const app = firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
/**
* バックググラウド
*/
messaging.onBackgroundMessage((payload) => {
const notificationTitle = payload.notification.title;
const notificationOptions = {
body: payload.notification.body,
icon: payload.notification.icon
};
return self.registration.showNotification(notificationTitle, notificationOptions);
});
【send.php】
次の2箇所を変更して下さい。
- <サーバーキー>をAPIを有効時に表示される「サーバーキー」に書き換え
- <送りたい人のトークン>をデベロッパーツールのコンソールで表示されるtokenに書き換え
<送りたい人のトークン>については次の工程で値を取得出来るので、これだけは一旦後回しにして下さい。
define( 'FCM_API_SEVER_KEY', '<サーバーキー>');
define( 'FCM_API_URL', 'https://fcm.googleapis.com/fcm/send' );
$data = [
"notification" => [
"title" => "テストタイトル",
"body" => "PHPで送れたかな",
"icon" => "firebase-logo.png",
"click_action" => "http://~~~~~~",
],
"to" => "<送りたい人のトークン>",
];
$header = [
'Authorization: key=' . FCM_API_SEVER_KEY,
'Content-Type: application/json',
];
$context = stream_context_create(array(
'http' => array(
'method' => 'POST',
'header' => implode(PHP_EOL,$header),
'content'=> json_encode($data),
'ignore_errors' => true
)
));
$response = file_get_contents(
FCM_API_URL,
false,
$context
);
$result = json_decode($response,true);
// 返却値を確認
var_dump($result);
サイトを確認
ファイルの作成が済んだら、MAMPなどを利用してサイトを確認します。
この際に、ファイルを直接ブラウザで見ると正常に動かないので、必ずMAMPといったWEBサーバを起動して行なって下さい。
ちなみに、私の場合は次のコマンドを実行して、「http://localhost:8888」で確認しています。
php -S localhost:8888
サイトを開く際に、必ずデベロッパーツールのコンソールを開いて下さい!
サイトを開くとプッシュ通知の許可をポップアップが表示され、許可をするとコンソールに次の様なものが表示されます。
token ○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○
この「token」の後の値が<送りたい人のトークン>となります。
なので、この値をコピーしてsend.phpの<送りたい人のトークン>を書き換えます。
プッシュ通知を送る
最後にプッシュ通知を実際に送ってみます。
プッシュ通知の送信はコマンドにて行います。
php send.php
実行すると次の様なものが表示されます。
array(5) {
["multicast_id"]=>
int(6087712654587838830)
["success"]=>
int(1)
["failure"]=>
int(0)
["canonical_ids"]=>
int(0)
["results"]=>
array(1) {
[0]=>
array(1) {
["message_id"]=>
string(36) "f544c63a-37e8-40b4-9576-52cffabd8ac9"
}
}
}
成功していれば、var_dumpで出力された値のsuccess
が「1」になっていて、ウェブプッシュが送られてくるはずです!
※注意点。success
が「1」になっているが、通知が来ない場合は少し待った方が良いかもです。success
が「1」と確認して10分程経ってから、もう一度送ると通知が来たりします。
これで以上になります。
補足
実際にWebプッシュ通知サービスを独自に組み込もうと思うと、ユーザーのログイン情報との紐付けや、個別のトークンの保存と管理が必須になります。
<送りたい人のトークン>をDBに保存し、送る時はその値を使用して送るといった事が必要になるといった感じです。
さらにiOSへのWEBプッシュ通知はPWA(Progressive Web Apps)に対応していないと送る事が出来ません。
今回の例はPWAには対応していないので、実際にSafariで見ても通知を受け取る事が出来ないので、ご注意ください。
iOS対応したサンプルソースをGitHubにて公開しておりますので、よろしければこちらも併せてご確認ください。
https://github.com/nextcode-sys/pwa-webpush-test
さらにさらに、現時点でSafariでウェブプッシュを受け取るには、iPhone側のSafariの設定が必要になります。
設定方法については、こちらのサイトが分かりやすいので、ご覧ください。
https://marble-heroes.com/blog/ubbadumj0w
おまけ PWA化してWEBプッシュを試す際の注意点
- iOSにWEBプッシュ通知を送るには、PWAが必須となります。
Safariで閲覧するだけでは、WEBプッシュ通知を送ることは出来ません。 - iOS16.4の時点では、端末(iPhone)のSafariの設定から
Push API
をオンにしないとWEBプッシュ通知を受け取る事が出来ません。 - 通知の許可リクエストは読み込み時(onload)に実行してもiOSでは動きません。
ボタンを押下した(onclick)等の何かのアクションを挟まないと動きません。
ただ、細かい検証はしていないので、間違いの可能性もあります。 - PWAではconsole.logで値を確認といった事が出来ません。alertを使用しましょう。
やり方を知らないだけで何か方法があるかもしれません。 - Firebaseの次の関数を使用すると、端末(iPhone)では正常に動きません。
本リポジトリでは使用していませんが、他の記事を見た際に使用されていたらご注意下さい。messaging.usePublicVapidKey("~~~");