整合 web push notification 與使用者互動

Kevin Chung
Dec 4, 2020

--

最近開發了一個應用服務叫 idar,目的是利用 Google Calendar 來當作記帳工具,使用者可以在日曆上紀錄消費,我在後端監看日曆事件,然後在日曆上幫使用者建立統計的事件,讓使用者可以知道今天或是這個月總共花了多少錢。

為了增加便利性,我設計了讓使用者可以輸入電子發票資訊,由後端查詢明細後,自動建立消費紀錄並通知使用者,以及預算超支通知,原本是使用透過 Calendar API ,在日曆上建立一個帶彈出提醒視窗的事件來做通知,不過這樣會讓日曆看起來很亂,而且使用者之後還需要手動刪除。後來想到可以使用 web push message 來對使用者進行通知,經過一番測試後順利整合上去了,現在把實做的過程簡單做個紀錄。

下面是web push 運作大致的流程圖:

對我們而言,需要完成的有三個部份:

  • service_worker.js
  • register.js
  • push service

分別介紹功能與程式碼如下

Service Worker

Service worker 是一種特殊的 javascript,背景執行在瀏覽器中,即使原本的網頁已經關閉也沒關係。而它的任務非常簡單,程式碼也很單純,就是執行的時候呼叫 addEventListener 註冊接收 “push”,在收到訊息時呼叫 showNotification() 顯示通知,詳細的選項可以參考Notification API 的說明。

另外註冊 “notificationclick” 來處理後續使用者的點擊行為,如果沒有特別要處理的就呼叫 self.notification.close() 直接關閉通知即可。

要留意 service_worker.js 這個檔案的位置,建議是放在網站的公開目錄的根目錄下,我有遇到即使是路徑正確,但放在別的目錄下卻無法找到的問題。

service worker 如果有改版,瀏覽器中的版本並不會馬上更新成新版,而是讓新版本進入 pending 狀態,要關閉該網頁後才會更新,或是從開發者模式中強制關閉舊版,測試的時候要注意版本的問題。

register.js

這是網頁上負責管理 web push 的 javascript,是從 Google 的 sample code 修改簡化並移除 UI 部份的程式碼,這樣會比較容易理解它的運作邏輯。

首先在將 service worker 常駐到瀏覽器。

如果註冊 service worker 沒有問題,接著呼叫 initialiseState()檢查目前的訂閱狀態,當然在檢查之前還要先確認一下瀏覽器的支援情形。

訂閱部份也很直覺,呼叫 subscribe() 函數,applicationServerKey 需要指定 VAPID 格式的 public key,這個金鑰組可以從 Firebase 的主控台上產生,因為是標準,所以同樣的金鑰組也可用於 Firefox 瀏覽器上。

設定->雲端通訊->網路設定->網路推播憑證

取得的訂閱資料的格式如下,endpoint 包含了推播服務的 url 以及 id,而 auth 與 p256dh 則是認證用的資料,將這些資訊上傳到後端 server 儲存到資料庫中,後續推播的時候將會用到。

Push Service

這裡的 push service 是執行在自己的後端 server,主要是提供其他模組進行推播,這裡使用 web-push 這個 module 來幫忙處理與推播服務間的溝通,安裝指令如下:

npm install web-push --save

程式的部份也很簡單,需要推播到特定使用者的瀏覽器上,只要先查詢之前儲存的訂閱資訊,代入到相關資料結構中,最後呼叫 sendNotification() 即可。

web push 的訂閱是根據每個瀏覽器各自獨立的,因此如果想要同時推播給某個使用者的所有裝置時,要把這些不同的訂閱資料透過其他的唯一識別資料連結在一起,例如像 email 或是自訂的 UUID。

web push 整合過程不算困難,只是它的功能有點分散,需要註冊時使用的 javascript,執行在瀏覽器裡的 service worker,自己 server 的後端程式以及各個瀏覽器提供的推播服務,一開始會有點不確定它是怎麼運作的,不過實際上操作過一次就覺得蠻容易了。

--

--

No responses yet