PHP Classes

File: PNServiceWorker.js

Recommend this page to a friend!
  Classes of Stefan Kientzler   PHP Web Push Notifications Server   PNServiceWorker.js   Download  
File: PNServiceWorker.js
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: PHP Web Push Notifications Server
Queue and push notifications to Web users
Author: By
Last change: fixes after set phpstan level 7
Date: 2 years ago
Size: 7,570 bytes
 

Contents

Class file image Download
/** * Serviceworker for web push notifications * @package PNServer */ // values to be modified for own project // VAPID appPublic key const strAppPublicKey = 'create your own VAPID key pair and insert public key here'; // URL to save subscription on server via Fetch API const strSubscriberURL = 'https://www.your-domain.org/PNSubscriber.php'; // default Notification Title if not pushed by server const strDefTitle = 'Your company or product'; // default Notification Icon if not pushed by server const strDefIcon = './elephpant.png'; /** * encode the public key to Array buffer * @param {string} strBase64 - key to encode * @return {Array} - UInt8Array */ function encodeToUint8Array(strBase64) { var strPadding = '='.repeat((4 - (strBase64.length % 4)) % 4); strBase64 = (strBase64 + strPadding).replace(/\-/g, '+').replace(/_/g, '/'); var rawData = atob(strBase64); var aOutput = new Uint8Array(rawData.length); for (i = 0; i < rawData.length; ++i) { aOutput[i] = rawData.charCodeAt(i); } return aOutput; } /** * event listener to subscribe notifications and save subscription at server * @param {ExtendableEvent} event */ async function pnSubscribe(event) { console.log('Serviceworker: activate event'); try { var appPublicKey = encodeToUint8Array(strAppPublicKey); var opt = { applicationServerKey: appPublicKey, userVisibleOnly: true }; self.registration.pushManager.subscribe(opt) .then((sub) => { // subscription succeeded - send to server pnSaveSubscription(sub) .then((response) => { console.log(response); }).catch((e) => { // registration failed console.log('SaveSubscription failed with: ' + e); }); }).catch((e) => { // registration failed console.log('Subscription failed with: ' + e); }); } catch (e) { console.log('Error subscribing notifications: ' + e); } } /** * event listener handling when subscription change * just re-subscribe * @param {PushSubscriptionChangeEvent} event */ async function pnSubscriptionChange(event) { console.log('Serviceworker: subscription change event: ' + event); try { // re-subscribe with old options self.registration.pushManager.subscribe(event.oldSubscription.options) .then((sub) => { // subscription succeeded - send to server pnSaveSubscription(sub) .then((response) => { console.log(response); }).catch((e) => { // registration failed console.log('SaveSubscription failed with: ' + e); }); }).catch((e) => { // registration failed console.log('Subscription failed with: ' + e); }); } catch (e) { console.log('Error subscribing notifications: ' + e); } } /** * save subscription on server * using Fetch API to send subscription infos to the server * subscription is encance with the userAgent for internal use on the server * @param {object} sub - PushSubscription * @return {string} - response of the request */ async function pnSaveSubscription(sub) { // stringify and parse again to add 'custom' property // ... otherwise added property will be ignored when stringify subscription direct to body! var body = JSON.parse(JSON.stringify(sub)); body.userAgent = navigator.userAgent; var fetchdata = { method: 'post', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), }; // we're using fetch() to post the data to the server var response = await fetch(strSubscriberURL, fetchdata); // activate following two lines, if any PHP-Error in the subscriber script occurs // -> in that case, response won't contain valid JSON data! /* var cloned = response.clone(); console.log('Response: ', await cloned.text()); */ return await response.json(); } /** * event listener to show notification * @param {PushEvent} event */ function pnPushNotification(event) { console.log('push event: ' + event); var strTitle = strDefTitle; var oPayload = null; var opt = { icon: strDefIcon }; if (event.data) { // PushMessageData Object containing the pushed payload try { // try to parse payload JSON-string oPayload = JSON.parse(event.data.text()); } catch (e) { // if no valid JSON Data take text as it is... // ... comes maybe while testing directly from DevTools opt = { icon: strDefIcon, body: event.data.text(), }; } if (oPayload) { if (oPayload.title !== undefined && oPayload.title !== '') { strTitle = oPayload.title; } opt = oPayload.opt; if (oPayload.opt.icon === undefined || oPayload.opt.icon === null || oPayload.icon === '') { // if no icon defined, use default opt.icon = strDefIcon; } } } var promise = self.registration.showNotification(strTitle, opt); event.waitUntil(promise); } /** * event listener to notification click * if URL passed, just open the window... * @param {NotificationClick} event */ function pnNotificationClick(event) { console.log('notificationclick event: ' + event); if (event.notification.data && event.notification.data.url) { const promise = clients.openWindow(event.notification.data.url); event.waitUntil(promise); } if (event.action !== "") { // add handler for user defined action here... // pnNotificationAction(event.action); console.log('notificationclick action: ' + event.action); } } /** * event listener to notification close * ... if you want to do something for e.g. analytics * @param {NotificationClose} event */ function pnNotificationClose(event) { console.log('notificationclose event: ' + event); } /**========================================================= * add all needed event-listeners * - activate: subscribe notifications and send to server * - push: show push notification * - click: handle click an notification and/or action * button * - change: subscription has changed * - close: notification was closed by the user *=========================================================*/ // add event listener to subscribe and send subscription to server self.addEventListener('activate', pnSubscribe); // and listen to incomming push notifications self.addEventListener('push', pnPushNotification); // ... and listen to the click self.addEventListener('notificationclick', pnNotificationClick); // subscription has changed self.addEventListener('pushsubscriptionchange', pnSubscriptionChange); // notification was closed without further action self.addEventListener('notificationclose', pnNotificationClose);