實做FCM Web推播
Firebase專案設定
首先建立firebase專案後先建立個網頁應用程式
接著前往專案設定
建立或取得網路推播憑證(vapidKey)
後續Web前端串接需要使用
後端發送
發送請求授權方式有以下兩種
- server key(伺服器金鑰)
- service account + project ID(sender ID)
server key(伺服器金鑰)
在專案設定>雲端通訊頁面可建立server key
service account key
在專案設定>服務帳戶頁面可建立service account key
發送請求(service account + proejct ID)
可透過此API來發送推播
以下透過php google/apiclient來發送推播
直接使用notification參數來設定推播通知(可參考此連結)
<?php
namespace Modules\Base\Services;
class FcmService
{
protected $client;
protected $credentialFilePath, $projectId;
public function __construct()
{
$this->credentialFilePath = env('FCM_SERVICE_ACCOUNT_KEY');
$this->projectId = env('FCM_PROJECT_ID');
}
public function send(string $token) : ?string
{
$this->client = new \Google_Client();
$this->client->setApplicationName('FirebaseCloudMessage');
$this->client->setAuthConfig($this->credentialFilePath);
$this->client->addScope(['https://www.googleapis.com/auth/firebase.messaging']);
$httpClient = $this->client->authorize();
$url = "https://fcm.googleapis.com/v1/projects/{$this->projectId}/messages:send";
$params = [
'message' => [
'token' => $token,
'notification' => [
'title' => 'title',
'body' => 'content...'
],
],
];
$httpClient->post($url, [
'json' => $params,
]);
}
}
發送請求(server key)
<?php
namespace Modules\Base\Services;
use GuzzleHttp\Client;
class FcmService
{
protected $client, $messageId, $serverKey;
protected $success, $error;
public function __construct()
{
$this->serverKey = env('FCM_SERVER_KEY');
$this->client = new Client();
}
public function send(string $deviceToken)
{
$this->client->request('post', 'https://fcm.googleapis.com/fcm/send', [
'headers' => [
'Authorization' => "key={$this->serverKey}",
],
'json' => [
'to' => $deviceToken,
'notification' => [
'title' => 'title',
'body' => 'content...'
],
'data' => ['foo' => 'bar'],
],
]);
}
}
前端接收訊息
在前端可分為兩中情況來接收訊息
一種是前景一種是背景下列將詳細敘述
參考文件:https://firebase.google.com/docs/cloud-messaging/js/receive
通知權限
在接收通知之前
我們要先確認user有允許網站通知權限
若user已經拒絕通知權限
可在Web提醒使用者前往瀏覽器通知設定開放通知權限
請求通知權限方式
await window.Notification.requestPermission()
取得通知權限方式
window.Notification.permission
// default: 使用者尚未給予任何權限 (無法顯示通知)
// granted: 允許通知權限
// denied: 拒絕通知權限
發送通知
// sw為service worker實體
sw.showNotification('title', {
body: 'content...',
icon: 'https://foobar.com/foobar.png',
})
前景通知
import { initializeApp } from 'firebase/app'
import { getMessaging, getToken, onMessage } from 'firebase/messaging'
import { Messaging } from '@firebase/messaging'
const app = initializeApp({
apiKey: 'api-key',
authDomain: 'project-id.firebaseapp.com',
databaseURL: 'https://project-id.firebaseio.com',
projectId: 'project-id',
storageBucket: 'project-id.appspot.com',
messagingSenderId: 'sender-id',
appId: 'app-id',
});
messaging = getMessaging();
deviceToken = await getToken(messaging, {
vapidKey: 'vapidKey', // 網路推播憑證
})
onMessage(messaging, (payload) => {
// TODO
})
背景通知
若後端送出的推播請求meesage欄位中有notification屬性
下方的code在執行const messaging = firebase.messaging();後
將會背景收到推播後自動產生通知
若不希望自動產生通知
或是希望調整預設的通知icon等客製化設定
可參考下方的"不使用預設icon"段落
importScripts('https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.10.0/firebase-messaging.js');
firebase.initializeApp({
apiKey: 'api-key',
authDomain: 'project-id.firebaseapp.com',
databaseURL: 'https://project-id.firebaseio.com',
projectId: 'project-id',
storageBucket: 'project-id.appspot.com',
messagingSenderId: 'sender-id',
appId: 'app-id',
});
const messaging = firebase.messaging();
messaging.onBackgroundMessage((payload) => {
// TODO
});
不使用預設的icon
上述有提到
若後端送出的推播請求meesage欄位中有notification屬性
將會自動在背景模式跳出提醒
且無法由後端設定icon(Web Push請求不可自訂icon)
因此若有額外需求
可以在後端發送推播請求的時候不要使用notification屬性
透過data屬性自訂要帶入的標題、內文、icon等資料
前端在透過onMessage或是onBackgroundMessage的callback
自行建立notification
<?php
namespace Modules\Base\Services;
use GuzzleHttp\Client;
class FcmService
{
protected $client, $messageId, $serverKey;
protected $success, $error;
public function __construct()
{
$this->serverKey = env('FCM_SERVER_KEY');
$this->client = new Client();
}
public function send(string $deviceToken)
{
$this->client->request('post', 'https://fcm.googleapis.com/fcm/send', [
'headers' => [
'Authorization' => "key={$this->serverKey}",
],
'json' => [
'to' => $deviceToken,
'data' => [
'title' => 'title',
'body' => 'content...',
'icon' => 'https://foobar/foobar.jpg',
],
],
]);
}
}