Reputation: 481
I Want to add Web Notification to my website. I searched on Google and found some tutorials about it. As described in these tutorials I manage to show subscription box to the visitors and I can store their data also.
Main.js
'use strict';
const applicationServerPublicKey = 'BBw_opB12mBhg66Dc94m7pOlTTHb5oqFAafbhN-BNeazWk8woAcSeHdgbmQaroCYssUkqFfoHqEJyCKw';
const pushButton = document.querySelector('.js-push-btn');
let isSubscribed = false;
let swRegistration = null;
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;
}
if ('serviceWorker' in navigator && 'PushManager' in window) {
console.log('Service Worker and Push is supported');
navigator.serviceWorker.register('sw.js')
.then(function(swReg) {
console.log('Service Worker is registered', swReg);
swRegistration = swReg;
})
.catch(function(error) {
console.error('Service Worker Error', error);
});
} else {
console.warn('Push messaging is not supported');
pushButton.textContent = 'Push Not Supported';
}
function initialiseUI() {
// Set the initial subscription value
swRegistration.pushManager.getSubscription()
.then(function(subscription) {
isSubscribed = !(subscription === null);
if (isSubscribed) {
console.log('User IS subscribed.');
} else {
console.log('User is NOT subscribed.');
}
updateBtn();
});
}
function updateBtn() {
if (isSubscribed) {
pushButton.textContent = 'Disable Push Messaging';
} else {
pushButton.textContent = 'Enable Push Messaging';
}
pushButton.disabled = false;
}
sw.js
'use strict';
self.addEventListener('push', function(event) {
console.log('[Service Worker] Push Received.');
console.log(`[Service Worker] Push had this data: "${event.data.text()}"`);
const title = 'Motoroids Lab';
const options = {
body: 'Motoroids',
icon: 'images/icon.png',
badge: 'images/badge.png'
};
event.waitUntil(self.registration.showNotification(title, options));
});
self.addEventListener('notificationclick', function(event) {
console.log('[Service Worker] Notification click Received.');
event.notification.close();
event.waitUntil(
clients.openWindow('https://developers.google.com/web/')
);
});
But now I'm stuck. No matter how much I am trying, It's hard to understand how to send push messages from my server :(
I enabled SSL on my server. I installed PHP Web Push library and its dependencies on the server using composer require minishlink/web-push
command.
But what's next? I can't understand their documentation also. https://github.com/web-push-libs/web-push-php
I need some help here. Please help me to understand how it works and how to it.
Thank You
Upvotes: 13
Views: 42118
Reputation: 41
This code is working in Chrome and Mozilla.
generate.php - to generate VAPID keys:
<?php
error_reporting(E_ALL);
ini_set("display_errors", 1);
header('Content-Type: text/html; charset=utf-8');
require __DIR__ . '/vendor/autoload.php';
use Minishlink\WebPush\VAPID;
print_r(VAPID::createVapidKeys());
service-worker.js
'use strict';
/**
* Received push
*/
self.addEventListener('push', function (event) {
let pushMessageJSON = event.data.json();
self.registration.showNotification(pushMessageJSON.title, {
body: pushMessageJSON.body,
icon: pushMessageJSON.icon,
vibrate: pushMessageJSON.data.vibrate,
data: {
additionalData: pushMessageJSON.data.additionalData,
url: pushMessageJSON.data.url,
},
});
console.info("**** Recv'd a push message::", event);
});
/**
* Click by push
*/
self.addEventListener('notificationclick', function(event) {
let url = event.notification.data.url;
event.notification.close(); // Android needs explicit close.
if (!url) return;
event.waitUntil(
clients.matchAll({type: 'window'}).then( windowClients => {
// Check if there is already a window/tab open with the target URL
for (var i = 0; i < windowClients.length; i++) {
var client = windowClients[i];
// If so, just focus it.
if (client.url === url && 'focus' in client) {
return client.focus();
}
}
// If not, then open the target URL in a new window/tab.
if (clients.openWindow) {
return clients.openWindow(url);
}
})
);
});
self.addEventListener('message', function (event) {
// A message has been sent to this service worker.
console.log("sw Handling message event:", event);
});
self.addEventListener('pushsubscriptionchange', function (event) {
// The Push subscription ID has changed. The App should send this
// information back to the App Server.
console.log("sw Push Subscription Change", event);
event.waitUntil(
self.clients.matchAll()
.then(clientList => {
let sent = false;
console.debug("Service worker found clients",
JSON.stringify(clients));
clientList.forEach(client => {
console.debug("Service worker sending to client...", client);
sent = true;
client.postMessage({'type': 'update'});
});
if (sent == false) {
throw new Error("No valid client to send to.");
}
})
.catch(err => {
console.error("Service worker couldn't send message: ", err);
})
);
});
self.addEventListener('registration', function (event) {
// The service worker has been registered.
console.log("sw Registration: ", event);
});
self.addEventListener('install', function (event) {
// The serivce worker has been loaded and installed.
// The browser aggressively caches the service worker code.
console.log("sw Install: ", JSON.stringify(event));
// This replaces currently active service workers with this one
// making this service worker a singleton.
event.waitUntil(self.skipWaiting());
console.log("sw Installed: ", JSON.stringify(event));
});
self.addEventListener('activate', function (event) {
// The service worker is now Active and functioning.
console.log("sw Activate : ", JSON.stringify(event));
// Again, ensure that this is the only active service worker for this
// page.
event.waitUntil(self.clients.claim());
console.log("sw Activated: ", JSON.stringify(event));
navigator.serviceWorker
});
index.html to request push notification
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1"/>
</head>
<body>
<script>
if (!Notification) {
console.log('*Browser does not support Web Notification');
}
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('service-worker.js?v=1', {scope: './'})
.then(function (registration) {
console.log("Service Worker Registered");
})
.catch(function (err) {
console.log("Service Worker Failed to Register", err);
})
}
navigator.serviceWorker.ready.then((reg) => {
const subscribeOptions = {
userVisibleOnly: true,
applicationServerKey: 'BFrp-TvkuqCeNsytRt...'
};
reg.pushManager.subscribe(subscribeOptions).then((subscription) => {
//send endpoint, p256dh and auth to backend
console.log('endpoint is: ' + subscription.endpoint);
console.log('p256dh is: ' + subscription.toJSON().keys.p256dh);
console.log('auth is: ' + subscription.toJSON().keys.auth);
document.write('<p>endpoint is: ' + subscription.endpoint + '</p>');
document.write('<p>p256dh is: ' + subscription.toJSON().keys.p256dh + '</p>');
document.write('<p>auth is: ' + subscription.toJSON().keys.auth + '</p>');
});
});
</script>
</body>
</html>
send.php to send push notification
<?php
error_reporting(E_ALL);
ini_set("display_errors", 1);
header('Content-Type: text/html; charset=utf-8');
require __DIR__ . '/vendor/autoload.php';
use Minishlink\WebPush\WebPush;
use Minishlink\WebPush\Subscription;
$push = [
'subscription' => Subscription::create([
'endpoint' => 'https://fcm.googleapis.com/fcm/send/djRg_IDPtSs:APA91bFwYCC73F4X3cXELK...',
'keys' => [
'auth' => 'SPB_NNfRw...',
'p256dh' => 'BP-WMuJdP7buopSb_HrNX...'
]
]),
'payload' => json_encode([
'title' => "Hello",
'body' => "How are you?",
'icon' => "https://cdn-icons-png.flaticon.com/512/3884/3884851.png",
'data' => [
'vibrate' => [100, 200],
'additionalData' => [],
'url' => "https://google.com",
],
]),
];
$auth = [
'VAPID' => [
'subject' => '[email protected]', // can be a mailto: or your website address
'publicKey' => 'BFrp-TvkuqCeNsytRt...', // (recommended) uncompressed public key P-256 encoded in Base64-URL
'privateKey' => '9BvI1aN1CR4w4iceMS...', // (recommended) in fact the secret multiplier of the private key encoded in Base64-URL
],
];
$webPush = new WebPush($auth);
try {
$webPush->queueNotification(
$push['subscription'],
$push['payload']
);
$report = $webPush->flush()->current();
$is_success = $report->isSuccess();
$response = $report->getResponseContent();
} catch (\Throwable $th) {
$is_success = false;
$response = $th->getMessage();
}
if ($is_success) {
echo "Push was sent";
} else {
echo "Push was not sent. Error message: " . $response;
}
Upvotes: 1
Reputation: 1
you have to add this code to your project https://developers.google.com/web/fundamentals/getting-started/codelabs/push-notifications/ sometimes you will have to add code to parts that you have already created
Upvotes: -1
Reputation: 5621
Take a look at https://web-push-book.gauntface.com/ for a general introduction to Web Push. The Chapter How Push Works and Subscribing a User should be particularly interesting to you. In summary:
pushManager.subscribe
. More info here.Upvotes: 14