web-push-libs / web-push-php

Web Push library for PHP
MIT License
1.69k stars 295 forks source link

event.data is always null #355

Closed kkCode closed 6 months ago

kkCode commented 2 years ago

PHP Version: 7.4.26 web-push-php Version: 7.0.0 Browser: Microsoft Edge v104.0.1271.2

php code like this : $notification = [ 'subscription' => Subscription::create([ 'endpoint' => 'https://sg2p.notify.windows.com/...', // Edge, 'publicKey' => '...', // base 64 encoded, should be 88 chars 'authToken' => '...', // base 64 encoded, should be 24 chars ]), 'payload' => json_encode([ "title"=>"have news" ]), ]

Problem

The browser can receive notification, but the event.data is always null.

kkCode commented 2 years ago

After repeated attempts, I found a solution, using this notification format.

$notifications = [ 'subscription' => Subscription::create([ 'endpoint' => 'https://sg2p.notify.windows.com/...', // Edge, 'keys' => [ 'p256dh' => '...', 'auth' => '...', ] ]), 'payload' => json_encode([ "title"=>"have news" ]), ]

P256dh and auth are obtained from the result of javascript's pushManager.subscribe.

Filikec commented 2 years ago

I love u, this worked for me as well.

After repeated attempts, I found a solution, using this notification format.

$notifications = [ 'subscription' => Subscription::create([ 'endpoint' => 'https://sg2p.notify.windows.com/...', // Edge, 'keys' => [ 'p256dh' => '...', 'auth' => '...', ] ]), 'payload' => json_encode([ "title"=>"have news" ]), ]

P256dh and auth are obtained from the result of javascript's pushManager.subscribe.

levelsio commented 10 months ago

Documentation of Web Push PHP seems completely wrong as in the docs at https://github.com/web-push-libs/web-push-php it says:

`<?php

use Minishlink\WebPush\WebPush; use Minishlink\WebPush\Subscription;

// array of notifications $notifications = [ [ 'subscription' => Subscription::create([ 'endpoint' => 'https://updates.push.services.mozilla.com/push/abc...', // Firefox 43+, 'publicKey' => 'BPcMbnWQL5GOYX/5LKZXT6sLmHiMsJSiEvIFvfcDvX7IZ9qqtq68onpTPEYmyxSQNiH7UD/98AUcQ12kBoxz/0s=', // base 64 encoded, should be 88 chars 'authToken' => 'CxVX6QsVToEGEcjfYPqXQw==', // base 64 encoded, should be 24 chars ]), 'payload' => 'hello !', ], ];

$webPush = new WebPush();

// send multiple notifications with payload foreach ($notifications as $notification) { $webPush->queueNotification( $notification['subscription'], $notification['payload'] // optional (defaults null) ); }

/**

/**

This will ALWAYS produce empty data though (tested in Chrome MacOS).

Only by following the posters above I made it work. It manually takes the p256dh and auth key and inserts it into a nested array under keys. I believe the docs need to be changed because it took me hours to figure this out too!

$webPushSubscriptionObject=Subscription::create([ 'endpoint' => $webPushSubscriptionFromDb['endpoint'], 'publicKey' => $config['webPush']['key']['public'], 'authToken' => $webPushSubscriptionFromDb['auth'], 'keys'=>array( 'p256dh'=>$webPushSubscriptionFromDb['keys']['p256dh'], 'auth'=>$webPushSubscriptionFromDb['keys']['auth'] ) ]);

Minishlink commented 10 months ago

Yes the readme is not very clear right now, because of all the old standards and/or browser implementations. Note that even when sending a payload, some browser implementations might not respect/handle it and you should handle the case where payload is undefined on the client-side.

The PushSubscription object on the client side can currently be one of the following objects that are here. I believe most of the current browsers send the first type (with p256dh and auth) but it might also not be the case, and some users will certainly be on older/exotic browsers.

Storing the whole client-side PushSubscription object with toJSON() (see example) is the way to go. You might also store the endpoint alongside for a unique identifier. And then you simply decode that JSON and create a subscription from it (example). It should be transparent, as browsers might change the PushSubscription object in the future (and updating this lib should be the only change necessary to handle these new cases).

Minishlink commented 10 months ago

README updated, is it more clear? https://github.com/web-push-libs/web-push-php/commit/156a3b65ad5d2193708833313ab2b78d0b548248

levelsio commented 10 months ago

Storing the whole client-side PushSubscription object with toJSON() (see example) is the way to go. You might also store the endpoint alongside for a unique identifier. And then you simply decode that JSON and create a subscription from it (example). It should be transparent, as browsers might change the PushSubscription object in the future (and updating this lib should be the only change necessary to handle these new cases).

I do that, but that does not work. Here's the saved JS subscription array from a Chrome client (with redacted keys):

{"endpoint":"https://fcm.googleapis.com/fcm/send/REDACTED","expirationTime":null,"keys":{"p256dh":"REDACTED","auth":"REDACTED"}}

Just submitting that as a subscription object into Web Push PHP fails to send data to a Chrome client. Data will always be null.

Instead we have to do modify the subscription JS array from client and add publicKey and authToken in there again, like this:

$webPushSubscriptionObject=Subscription::create([ 'endpoint' => $webPushSubscriptionFromDb['endpoint'], 'publicKey' => $config['webPush']['key']['public'], 'authToken' => $webPushSubscriptionFromDb['auth'], 'keys'=>array( 'p256dh'=>$webPushSubscriptionFromDb['keys']['p256dh'], 'auth'=>$webPushSubscriptionFromDb['keys']['auth'] ) ]);

Thanks!

Minishlink commented 10 months ago

That's weird, this is exactly what's being done in the example and it works flawlessly with a payload. Do you decode with json_decode($subscription, true)? (in order to have an associative array)

levelsio commented 10 months ago

Yep I did, and it works because push events show up in client but event data is null in Chrome. See the other people with same problem.

On Wed, Oct 18, 2023, at 22:41, Louis Lagrange wrote:

That's weird, this is exactly what's being done in the example https://github.com/Minishlink/web-push-php-example/blob/master/src/send_push_notification.php#L9 and it works flawlessly with a payload. Do you decode with json_decode($subscription, true)? (in order to have an associative array)

— Reply to this email directly, view it on GitHub https://github.com/web-push-libs/web-push-php/issues/355#issuecomment-1769364452, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABWR2AD5U3K7Q3CLDN3PGYLYABEHLAVCNFSM5X4W73YKU5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TCNZWHEZTMNBUGUZA. You are receiving this because you commented.Message ID: @.***>