昨天我們拿到Public Key和Private Key,現在要來使用這些權限,
讓伺服器成功推播訊息到使用者裝置上。
使用者新增文章的時候,會觸發之前我們串好firebase的功能(storePostData()),
現在當觸發該方法的時候,除了回傳成功上傳訊息時,順便從firebase上,抓取subscriptions資料表中,所有訂閱使用者,並發送推播訊息。
首先開啟functions/index.js,因為要模擬從firebase準備訊息
推播給用戶端手機,勢必我們訊息必須寫在伺服器端。
接著找到storePostData()
exports.storePostData = functions.https.onRequest(function(request, response) {
cors(request, response, function(){
admin.database().ref('article').push({
//..之前的程式
})
.then(function(){
webpush.setVapidDetails('mailto:monkey030210@gmail.com',
vapidKeys.publicKey,
vapidKeys.privateKey
);
return admin.database().ref('subscriptions').once('value');
})
.then(function(subs){
subs.forEach(function(sub){
var pushConfig = {
endpoint: sub.val().endpoint,
keys: {
auth: sub.val().keys.auth,
p256dh: sub.val().keys.p256dh
}
};
webpush.sendNotification(pushConfig, JSON.stringify({title: '回來逛逛哦', content: '再撐一下就到30天啦'}))
.catch(function(err){
console.log('Server 推播失敗',err);
});
});
response.status(201).json({message: '資料送出', id: request.body.id});
})
.catch(function(err) {
response.status(500).json({error: err});
});
});
})
好長一段程式阿,來分段解釋一下
var webpush = require('web-push');
var vapidKeys = {
publicKey: 'BNaAfuqm_lOcGE8H8z-ad1BjE3gBmDQDppECZC1btjfVs4fpSAJbKUujBa31GYiUzOmwHQW4FX1qxGfXTsqBym8',
privateKey: 'GKukjt9CaJccs88FK7Wqt3MrH9E9EmqOLjYYodZukZY'
}
這邊我們需要先引用web-push才能使用該功能,
另外建立一個物件(非必要),放昨天拿到的公鑰和私鑰。
.then(function(){
webpush.setVapidDetails('mailto:monkey030210@gmail.com',
vapidKeys.publicKey,
vapidKeys.privateKey
);
return admin.database().ref('subscriptions').once('value');
})
接著webpush.setVapidDetails()用來設定推播前的資格驗證,第一個可以放URL或是Mail用途是當Push Server如果要回傳一些資訊時,他們會直接傳到上面的E-mail。
後面放Key。
並回傳subscriptions的內容,once一樣回傳型別是Promise
.then(function(subs){
subs.forEach(function(sub){
var pushConfig = {
endpoint: sub.val().endpoint,
keys: {
auth: sub.val().keys.auth,
p256dh: sub.val().keys.p256dh
}
};
webpush.sendNotification(pushConfig, JSON.stringify({title: '回來逛逛哦', content: '再撐一下就到30天啦'}))
.catch(function(err){
console.log('Server 推播失敗',err);
});
});
response.status(201).json({message: '資料送出', id: request.body.id});
})
.catch(function(err) {
response.status(500).json({error: err});
});
forEach可以尋訪所有物件內容,這裡一樣建一個物件存放每個訂閱裝置的三個資料內容,webpush.sendNotification,透過此方法,傳送推播訊息給使用者,第一個參數放發送推播所需的endpoint和key,後面則是傳送一組Json格式的資料,最後成功顯示這串字,就代表我們成功啦
後面一樣接catch方便抓取錯誤訊息。
在firebase中,嘗試傳送推播訊息,但如果沒有寫push監聽事件,是不會有任何事情發生的,因為用戶端的Service Worker並沒有接口來接訊息。
self.addEventListener('push', function(event){
console.log('收到推播訊息', event);
var contentObj = {title: '新訊息', content: '預設訊息,會被伺服器訊息覆蓋'};
if(event.data){
contentObj = JSON.parse(event.data.text());
}
var options = {
body: contentObj.content,
icon: '/src/images/icons/demo-icon96.png',
lang: 'zh-Hant', //BCP 47
vibrate: [100, 50, 200],
badge: '/src/images/icons/demo-icon96.png',
tag: 'first-notification'
};
event.waitUntil(
self.registration.showNotification(contentObj.title, options)
);
});
這裡設定一組contentObj,裡面存含預設內容的title和content
假設觸發push時,收到的推播內容,理應覆蓋掉上面的預設值
假設event.data不是空值,就將在firebase推送的Json格式的物件內容,
覆蓋contentObj的值。
後面就是開始寫推播的設定,在Service Worker,使用self.registration.showNotification(標題, 推播設定)來顯示訊息
填寫發文表單
點選「發佈」
結果
右下角成功顯示,在伺服器撰寫的訊息內容
Console視窗也看到成功訊息。
在修改程式時,前面我們習慣每次修改後,更改版號和清除瀏覽器上所有快取資源。
但因為訂閱是綁定裝置瀏覽器的,還記得綁定成功時,會存有endpoint和key到伺服器,
假如清除快取資料,也解除裝置上的Service Worker,那麼我們綁定的鑰匙與endpoint則會無法對應,造成失敗的現象。
所以在修改程式後,記得不要清除網站所有快取,只需要更新版號,重整網頁,並手動觸發activate來更新快取住的檔案。
[https://developers.google.com/web/ilt/pwa/introduction-to-push-notifications](google: 介紹推播)
https://github.com/DakHarry/30day-pwas-practice