web-push-php
web-push-php copied to clipboard
Payload not arriving in chrome
Hi
It seems the payload arrives as null in event.data on the client side after a push message has been recieved.
Testing with the following code:
require __DIR__ . '/vendor/autoload.php';
use Minishlink\WebPush\WebPush;
use Minishlink\WebPush\Subscription;
$auth = [
'VAPID' => [
'subject' => 'htts://testpush.test/',
'publicKey' => 'BBFwt4l1ZvIoCkH2Cp9DSQKGN6MUQ5mFXrT3OLKNsoqSTweloz87hZtIA64Zgx2zROgxPWN1l61q8ezM0QkD2Dg',
'privateKey' => 'XXXX',
],
];
$notifications = [
[
'subscription' => Subscription::create([
'endpoint' => 'https://fcm.googleapis.com/fcm/send/f1azG0YpefY:APA91bEgPUCksrDdHc3vpd8JZUsiLnf6sphqgw8TdyPVyTMaviZGvBY76RPJ2zFmMFpvhxoL3hvbvMSJ_O8Ct5nqKmDYozsZh-IU-gm2DWqeTVRRgW9k6Hq58vxnYi75RehmdXbEr_yb', // Chrome
'contentEncoding' => 'aes128gcm',
'publicKey' => 'BBFwt4l1ZvIoCkH2Cp9DSQKGN6MUQ5mFXrT3OLKNsoqSTweloz87hZtIA64Zgx2zROgxPWN1l61q8ezM0QkD2Dg',
'privateKey' => 'XXXX',
'authToken' => '',
'payload' => '{"msg":"Hello World!"}' // optional (defaults null),
]),
],
];
$webPush = new WebPush($auth);
// send multiple notifications with payload
foreach ($notifications as $notification) {
$webPush->queueNotification(
$notification['subscription'],
$notification['payload'] // optional (defaults null)
);
}
/**
* Check sent results
* @var MessageSentReport $report
*/
foreach ($webPush->flush() as $report) {
$endpoint = $report->getRequest()->getUri()->__toString();
if ($report->isSuccess()) {
echo "[v] Message sent successfully for subscription {$endpoint}.";
} else {
echo "[x] Message failed to sent for subscription {$endpoint}: {$report->getReason()}";
}
}
The message is successfully sent, and notification appears on the client, however the event.data is always empty. Couldf you please help with the above?
Musaffar
Hey, above you have a bug,
your payload should be inside your notification array, not your subscription object
$notifications = [
[
'subscription' => Subscription::create([
'endpoint' => 'https://fcm.googleapis.com/fcm/send/f1azG0YpefY:APA91bEgPUCksrDdHc3vpd8JZUsiLnf6sphqgw8TdyPVyTMaviZGvBY76RPJ2zFmMFpvhxoL3hvbvMSJ_O8Ct5nqKmDYozsZh-IU-gm2DWqeTVRRgW9k6Hq58vxnYi75RehmdXbEr_yb', // Chrome
'contentEncoding' => 'aes128gcm',
'publicKey' => 'BBFwt4l1ZvIoCkH2Cp9DSQKGN6MUQ5mFXrT3OLKNsoqSTweloz87hZtIA64Zgx2zROgxPWN1l61q8ezM0QkD2Dg',
'privateKey' => 'XXXX',
'authToken' => '',
]),
'payload' => '{"msg":"Hello World!"}' // optional (defaults null),
],
];
Any solution to this problem? I spent a while trying to make it work. It's not working, "data" field is null
@sadektouati Did you find a solution or did you give up?
@sadektouati Did you find a solution or did you give up?
I sort of gave up. How about you
@sadektouati Did you find a solution or did you give up?
I sort of gave up. How about you
I am not much further, but I will update / notify you if it works for me.
@richard-llmnn Thank you very much
@sadektouati It works on my localhost :+1: after a bit of try and error. Please make sure that you have the publicKey (p265dh), the endpoint and the authToken (auth). My backend send notification code looks like this:
$subscription = [
'endpoint' => $credential->getEndpoint(),
'publicKey' => $credential->getPublicKey(),
'authToken' => $credential->getAuthtoken(),
];
$payload = [
"title" => "Hallo Push-Welt!",
"body" => "Hi! Dies ist eine Testnachricht!",
"badge" => "/assets/img/test1.svg",
"icon" => "/assets/img/test2.svg",
"image" => "https://unterricht.cloud/wp-content/themes/bueffel/assets/img/unterricht-logo.png",
"tag" => "test",
"data" => [
"show1" => "/test1",
"show2" => "/test2",
"default" => "/test3"
],
];
$message = [
'subscription' => Subscription::create($subscription),
'payload' => json_encode($payload),
];
// $this->webpushConnection is the WebPush object (Minishlink\WebPush\WebPush)
$this->webpushConnection->queueNotification(
$message['subscription'],
$message['payload']
);
foreach ($this->webpushConnection->flush() as $report) {
}
@richard-llmnn I'm happy to hear that.
Can you please tell me what goes where ?
Here's the object I get from the subscription:
{ "keys": {"auth": "string", "p256dh": "string"}, "endpoint": "string", "expirationTime": null }
`$subscription = [
'endpoint' => $credential->getEndpoint(),
'publicKey' => $credential->getPublicKey(),
'authToken' => $credential->getAuthtoken(),
];
`
@sadektouati On the client you get the subscription object. In my project I send the endpoint, keys.auth and keys.p265d to my backend api. The backend saves the data to a mysql database. The structrue looks like:
Webpush_ID | endpoint | publicKey | authToken
1 | https://fcm.googleapis.com/fcm/sen.... | BMrfFtMtL9IWl9vchDbbbYzJlbQwpl... | pbs9Y6r5TscHC64Ce9... // example data
So, my backend saves the data in the database as follows:
- endpoint (from client) -> DB endpoint
- keys.p265d (from client) -> DB publicKey
- keys.auth (from client) -> DB authToken
Now if you want to send a message to the users that has subscripted to your webpush you have to do the following:
- Fetch the data from the database (I use for this symfony/doctrine orm, so all rows are saved in a own object. My name for the row object is
$credentialand with the getter methods I get the data for the row.) - use the code from my comment: https://github.com/web-push-libs/web-push-php/issues/334#issuecomment-996893924
Some good tutorials are:
- https://www.bjoern.info/2020/05/web-push-notifications-mit-php-und-js/ (German)
- https://www.attheminute.com/article/sending-a-web-push-notification-tutorial (English)
- https://felixgerschau.com/web-push-notifications-tutorial/ (English)
@richard-llmnn Thank you very much, now it's working.
My problem was that intead of this:
Subscription::create([ 'endpoint' => $endpoint, 'publicKey' => $p256dh, 'authToken' => $keys_auth, 'contentEncoding' => 'aesgcm', ]),
I was doing this:
Subscription::create([ 'endpoint' => $endpoint, $p256dh, $keys_auth, 'contentEncoding' => 'aesgcm', ]),
I'll open a new issue for this.
Make sure you update the subscription on your server each time it's changed on the client. I did something similar to this: https://medium.com/@madridserginho/how-to-handle-webpush-api-pushsubscriptionchange-event-in-modern-browsers-6e47840d756f
me too, I cannot send push.. Even if all reports are successful, I cannot see a push notification, neither in the browser on my laptop, nor in the mobile phone (Android). I use Lumen
$payload = [
'title' => 'test',
'body' => 'Messaggio di test',
'vibrate' => [100, 50, 100],
'silent' => false,
];
$notifications = Subscription::all()->map(function($item) use ($payload) {
$subsData = json_decode($item->subscription, true);
return [
'subscription' => Subs::create($subsData),
'payload' => json_encode($payload)
];
})->toArray();
$auth = Config::get('vapid');
$webPush = new WebPush($auth);
// send multiple notifications with payload
foreach ($notifications as $n) {
$webPush->queueNotification(
$n['subscription'],
$n['payload'] // optional (defaults null)
);
}
$results = [];
foreach ($webPush->flush() as $report) {
// $endpoint = $report->getRequest()->getUri()->__toString();
if (!$report->isSuccess()) {
$results[] = $report;
}
}
where $auth = Config::get('vapid'); returns something like this
[
'VAPID' => [
'subject' => 'myemail'
'publicKey' => '<publicKey>'
'privateKey' => '<secretKey>'
],
]
and $item->subscription is already a json of the form
{
"endpoint":"endpointUrl",
"expirationTime":null,
"keys":{
"p256dh":"pdkey",
"auth":"authkey"
}
}
@falco442 in my case it was a matter of making a subscription exactly as
Subscription::create([ 'endpoint' => <endpoint>, 'publicKey' => <p256d>, 'authToken' => <keys_auth>, 'contentEncoding' => 'aesgcm', ]),
the endpoint, publicKey, authToken are the keys you received in the subscription object on the client.
me too, I cannot send push.. Even if all reports are successful, I cannot see a push notification, neither in the browser on my laptop, nor in the mobile phone (Android). I use Lumen
$payload = [ 'title' => 'test', 'body' => 'Messaggio di test', 'vibrate' => [100, 50, 100], 'silent' => false, ]; $notifications = Subscription::all()->map(function($item) use ($payload) { $subsData = json_decode($item->subscription, true); return [ 'subscription' => Subs::create($subsData), 'payload' => json_encode($payload) ]; })->toArray(); $auth = Config::get('vapid'); $webPush = new WebPush($auth); // send multiple notifications with payload foreach ($notifications as $n) { $webPush->queueNotification( $n['subscription'], $n['payload'] // optional (defaults null) ); } $results = []; foreach ($webPush->flush() as $report) { // $endpoint = $report->getRequest()->getUri()->__toString(); if (!$report->isSuccess()) { $results[] = $report; } }where
$auth = Config::get('vapid');returns something like this[ 'VAPID' => [ 'subject' => 'myemail' 'publicKey' => '<publicKey>' 'privateKey' => '<secretKey>' ], ]and
$item->subscriptionis already a json of the form{ "endpoint":"endpointUrl", "expirationTime":null, "keys":{ "p256dh":"pdkey", "auth":"authkey" } }
Do you get it working?
@richard-llmnn I think the problem is in your
$subsData = json_decode($item->subscription, true);
it should be :
$subsData = [ 'endpoint' => $endpoint, 'publicKey' => $p256dh, 'authToken' => $keys_auth, 'contentEncoding' => 'aesgcm', ];
json_decode($item->subscription, true) would give you [ 'endpoint' => $endpoint, 'keys' => ['p256dh' => $p256dh, 'auth' => $keys_auth]];
I hope this helps you
You may have to modify the service worker JS which is listening for push event.
self.addEventListener('push', function (event) {
if (!(self.Notification && self.Notification.permission === 'granted')) {
return;
}
const sendNotification = body => {
// you could refresh a notification badge here with postMessage API
const title = "Web Push example";
return self.registration.showNotification(title, {
body,
});
};
// Notice this part carefully. event.waitUntil is only getting called when event.data is non-empty.
if (event.data) {
console.log( event );
const message = event.data.text();
event.waitUntil(sendNotification(message));
}
});
Using this script started showing the push notifications.
Hello,
For me it was one of this key ('endpoint', 'keys', 'p256dh', 'auth', 'contentEncoding', 'publicKey', 'authToken') which was badly written by me, the optional keys in the table are not verified if they are well formatted (so treat as null), to get payload you need to have endpoint, publicKey and authToken OR endpoint, keys with ph256dh and auth.
Hope it save someone times XD