--
前言
PWA 作為網站過度到 App 的應用,熄屏、紅點通知、推播點選進入相對應功能也都可以正常使用,如果不是自己安裝和 App 使用體驗沒有不同。
--
參考資源
- 你知道這是什麼嗎? Chrome extension MV3 With Vite - Day8 Service Worker 訂閱推播 - iT 邦幫忙
- Day27-Push Notification之成為訂閱用戶(Firebase實作) - iT 邦幫忙
- Day28-Push Notification伺服器推播訊息實作 - iT 邦幫忙
--
網頁註冊 FCM 取得身份
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
// 系統是否支援 if (!("Notification" in window)) { console.log("不支援推送通知"); } // service Worker function urlB64ToUint8Array(base64String) { const padding = '='.repeat((4 - base64String.length % 4) % 4); const base64 = (base64String + padding) .replace(/\-/g, '+') .replace(/_/g, '/'); const rawData = window.atob(base64); const outputArray = new Uint8Array(rawData.length); for (let i = 0; i < rawData.length; ++i) { outputArray[i] = rawData.charCodeAt(i); } return outputArray; } // 接收發送的身份 const applicationServerPublicKey = 'BGQsM1ZSgzMCvBeHEhhcwrBALSsRvFOyK6ErMYZmJoXHiIdJVwuffhTa5HUnmaTiVs6jWLUnUA-x05JVn2uKi38'; const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey); // 註冊 sw.js function serviceWorker_register(){ if ('serviceWorker' in navigator) { navigator.serviceWorker .register('./sw.js') .then(reg => { return reg.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: applicationServerKey }); }) .then(subscription => { // 上傳使用者註冊身份 // ... }) .catch(err => { console.log('Failed to subscribe the user: ', err); }); } } function requestPermission(){ Notification.requestPermission().then((permission) => { // 取得授權後執行動作 serviceWorker_register(); }); } |
--
sw.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
const cacheVersion = 'v2'; const cacheName = "upad12"; const filesToCache = [ '/application/views/app/style.css', '/application/views/app/user_bootstrap5.css', '/public/3rd/php.js', ]; self.addEventListener('install', event => { // console.log("[Service Worker] Install"); event.waitUntil( (async () => { const cache = await caches.open(cacheName); await cache.addAll(filesToCache); })(), ); }); self.addEventListener('fetch', event => { // console.log('[ServiceWorker] fetch', event.request); event.respondWith( caches.match(event.request).then((response) => { return response || fetch(event.request); }) ); }); self.addEventListener('push', function(event) { // console.log(event.data.json()); const payload = event.data.json(); let options = { body: payload.message, icon: payload.icon, badge: payload.icon, // tag: "", // renotify: true, data: { role : payload.role, source : payload.source, child_id : payload.child_id, }, }; event.waitUntil( self.registration.showNotification(payload.title, options) ); }); // self.addEventListener("notificationclick", (event) => { const push_data = event.notification.data; console.log("On notification click: ", push_data); event.waitUntil( clients .matchAll({ type: "window", }) .then((clientList) => { let url = '/app'; if ( push_data.source === '刷卡' ){ if ( push_data.role === '11' ) url = '/app/Boss/EmployeeAttendance'; if ( push_data.role === '21' ) url = '/app/Student/Attendance'; if ( push_data.role === '30' ) url = '/app/Parents/ChildCalendar/?child_id=' + push_data.child_id; } return clients.openWindow(url); }), ); event.notification.close(); }); |
--
發送端:安裝 web-push
安裝時加上 -g 為使用命令列
1 |
npm install web-push -g |
取得發送者身份,只要有身份就可以發送,不同電腦也可以共用
1 |
web-push generate-vapid-keys |
1 2 3 4 5 6 7 8 9 |
======================================= Public Key: BPrtEl0VOWdEdP_hwl-P1xnLkuzD9qiNfUBaOzO5KUxBXeE2VnkWwzKP0PSm4cjprR6nK9Jg3ziBnINqAFKHf9k Private Key: G8y_V-PUwP188uPCpKn0Io8XPdzEEbfhKJ2AGw24dhk ======================================= |
推送訊息
1 2 3 4 5 6 7 8 |
web-push send-notification --endpoint=https://fcm.googleapis.com/fcm/send/eIz-0oEdA88:APA91bF_A-eANS-pfHzvQ6ixWeJQdrEODeiwV9seclwqSiLd7nYT7-CKnqSJpE66cLyV3yYlJxNzClCeLbnpGq00JixEcd6lDUkcalFJVFLQjPq7R2ufdAVkfGBINHT1rXaQc8KZvoEQ --key=BFhr8ZmNlw_rBUxc4d8oLEwYjkabBb6sXQ1SW-tEogsPrV3mmvGhVhABMOuzi7vrhkAn8saLcQ81WsWpuyjQ9TE --auth=e-CL1SS37TSvRe7Swx4idA --vapid-pubkey=BGQsM1ZSgzMCvBeHEhhcwrBALSsRvFOyK6ErMYZmJoXHiIdJVwuffhTa5HUnmaTiVs6jWLUnUA-x05JVn2uKi38 --vapid-pvtkey=CWROTKckpwAgt02x2l8WWK1Vq2kTMduODZz5oJ1ICYo --vapid-subject=https://hoyo.idv.tw --payload="{\"message\":\"This is a message\",\"title\":\"this is a title\",\"icon\":\"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQFQpoz6_MxzG3k_NCSWrhcW-H3nU5GoDhCysqPfXUEzmCQGpsuIQ\"}" |
- --endpoint 使用者註冊取得的 endpoint,接收推播的訊息發送的平台,不同的裝置、瀏覽器 endpoint 都不同,例如 Google Chrome 使用 Google 的 FCM (Firebase Cloud Messaging),Microsoft Edge 使用 WNS (Windows Push Notification Service)
- --key 使用者註冊取得 keys 的 p256dh
- --auth 使用者註冊取得 keys 的 auth
- --vapid-pubkey 使用 generate-vapid-keys 取得的 Public Key
- --vapid-pvtkey使用 generate-vapid-keys 取得的 Private Key
- --vapid-subject 使用 email (mailto:your@email.com) 或是網址 (https://your-website.com) 申明身份
- --payload 發送內容,純文字格式隨意,只要接收後可處理,一般都是使用 JSON
--
支援性
推播各家必須使用自己的主機進行,因此 endpoint 就不相同
- Chrome:https://fcm.googleapis.com/fcm/send/
- Edge:https://wns2-ln2p.notify.windows.com/w/?token=
- Firefox:https://updates.push.services.mozilla.com/wpush/v2/
- Safari:https://web.push.apple.com/
因為 endpoint 主機都是從各自瀏覽器提供,所以反應速度可能會有不同
--
注意事項
- 修改 sw.js 必須重新啟動瀏覽器
--
範例
- pushpad.xyz/service-worker.js
- ecpay.com.tw/Scripts/BrowserMessage/BrowserMessage.js
- ecpay.com.tw//Scripts/BrowserMessage/service-worker.js
--
668 total views, 6 views today