跳到主要内容

Firebase feat React 简易教学 (二):在网页接收 Messaging

· 7 分钟阅读
Eric Cheng

Firebase 系列文的第二篇,之前写过【如何在 React 专案中接收 Notification】,这篇文章有点像,只是不使用 cra-template-pwa,而是完全的只用 Firebase 提供的功能

前置作业

如果还没有建置专案及安装 Firebase SDK 的话,请先参考【Firebase feat React 简易教学 (一):简介&快速 hosting 新网站

产生 云端通讯 网路推播凭证金钥

到「专案设定」=>「云端通讯」 firebase cloud messaging 1

到「网路设定」=>「网路推播凭证」,点选「Generate key pair」 firebase cloud messaging 2

装会产生一个金钥组 firebase cloud messaging 3

然后同样在 App.js 加入以下 code

import { getMessaging, getToken } from "firebase/messaging";

// messaging
const messaging = getMessaging();
const vapidKey = 'BHweFH.......................'
getToken(messaging, { vapidKey: vapidKey }).then((currentToken) => {
if (currentToken) {
// 取得 currentToken,需传回 server
console.log('get currentToken');
console.log(currentToken);
} else {
console.log('No registration token available. Request permission to generate one.');
}
}).catch((err) => {
console.log('An error occurred while retrieving token. ', err);
});
  • vapidKey 就是刚才产生的金钥组
  • 这份程式会印出 currentToken 的值,这个值每个使用者每个浏览器都不一样,一般来说要把这个值传回 server 存起来,然后再依照存下来的 token 发送讯息,这里简化起见,仅先印出来

打开专案首页,叫出 Chrome DevTools,就可以看到印出来的 token firebase cloud messaging 4

建立 Listener

Firebase 有自己的 service worker,档名叫做firebase-messaging-sw.js,位置在根目录下,这里踩了点雷,需要注意

  • 这个档案不会自动产生,需要手动建立,然后根目录以 React 来说,就是放在 public 目录下,而非 src 目录
  • 因为不是放在 src 下,所以语法不太一样,不能直接用 import ...etc

将以下程式写入 firebase-messaging-sw.js,这段程式会去监听 BackgroundMessage,也就是只要浏览器开着,即使没上连上网站,也能收到讯息

// Scripts for firebase and firebase messaging
importScripts('https://www.gstatic.com/firebasejs/8.2.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.2.0/firebase-messaging.js');

const firebaseConfig = {
....
};

firebase.initializeApp(firebaseConfig);

// Retrieve firebase messaging
const messaging = firebase.messaging();

messaging.onBackgroundMessage(function (payload) {
console.log('Received background message ', payload);
});

然后 App.js 也增加以下 code,这段程式会监听在网站开启时,传送讯息会在左下角跳出小视窗

import { onMessage } from "firebase/messaging";

onMessage(messaging, (payload) => {
console.log('Message received. ', payload);
const notificationTitle = 'Message Title';
const notificationOptions = {
body: 'Message body.',
icon: '/logo192.png'
};
new Notification(notificationTitle, notificationOptions)
});

传送讯息

整理两种方法

由 Firebase 界面传送讯息

Firebase 界面本身就提供传送讯息的功能,到左侧 menu 的「Cloud Messaging」,选功能「撰写通知」,填入标题和文字,然后点选「传送测试讯息」

firebase send message 1

这时会要你输入 FCM 注册凭证,这个凭证就是上面说的要传回给 server 的 token,一般的做法是 server 会将这些 token 存在 DB 中,发送讯息就会依据这些 token 发送, 这里只需要填入刚才的 token ,然后点选发送就可以看到收到讯息了

firebase send message 2

使用 googleapis 传送讯息

在实务上应该不可能用界面来发送,而且透过程式来传送讯息,我是另外开一个小专案来测试传送,程式不难,直接上程式码

先到「专案设定」=>「服务帐户」 firebase send message 3

然后产生私密金钥,然后就可以下载个 json 档。注意:如说明,金钥是用来存取专案的权限,请勿储放在公开的存放区 firebase send message 4

下载回来的 json 档大概长这样 firebase send message 5

然后在要放送讯息的专案,安装 googleapis 和 google-auth-library

npm install googleapis
npm install google-auth-library

传送讯息程式码如下,这是 firebase 的 sample code,但我写这篇文章的时候又找不到原文在哪里,还好之前有先复制下来

const https = require('https');
const { google } = require('googleapis');

const key = require('./下载回来的私密金钥档案.json');
const PROJECT_ID = key.project_id;
const HOST = 'fcm.googleapis.com';
const PATH = '/v1/projects/' + PROJECT_ID + '/messages:send';
const MESSAGING_SCOPE = 'https://www.googleapis.com/auth/firebase.messaging';
const SCOPES = [MESSAGING_SCOPE];

const token = "要传送的浏览器 token";

/**
* Get a valid access token.
*/
function getAccessToken() {
return new Promise(function (resolve, reject) {
const jwtClient = new google.auth.JWT(
key.client_email,
null,
key.private_key,
SCOPES,
null
);
jwtClient.authorize(function (err, tokens) {
if (err) {
reject(err);
return;
}
console.log(tokens.access_token);
resolve(tokens.access_token);
});
});
}

/**
* Send HTTP request to FCM with given message.
*
* @param {object} fcmMessage will make up the body of the request.
*/
function sendFcmMessage(fcmMessage) {
getAccessToken().then(function (accessToken) {
const options = {
hostname: HOST,
path: PATH,
method: 'POST',
// [START use_access_token]
headers: {
'Authorization': 'Bearer ' + accessToken
}
// [END use_access_token]
};

const request = https.request(options, function (resp) {
resp.setEncoding('utf8');
resp.on('data', function (data) {
console.log('Message sent to Firebase for delivery, response:');
console.log(data);
});
});

request.on('error', function (err) {
console.log('Unable to send message to Firebase');
console.log(err);
});

request.write(JSON.stringify(fcmMessage));
request.end();
});
}

function buildCommonMessage() {
return {
"message": {
"token": token,
"notification": {
"title": "FCM Notification",
"body": "Notification from FCM"
}
}
}
}

sendFcmMessage(buildCommonMessage());

测试成功,就像使用 Firebase 界面传送讯息,可成功接收到传送的讯息

版权声明


這是 google 廣告