WebPush can be used to send notifications to endpoints which server delivers Web Push

Last update: Jun 20, 2022

WebPush

Web Push library for PHP

Build Status SensioLabsInsight

WebPush can be used to send notifications to endpoints which server delivers Web Push notifications as described in the Web Push protocol. As it is standardized, you don't have to worry about what server type it relies on.

Requirements

PHP 7.3+ and the following extensions:

  • gmp (optional but better for performance)
  • mbstring
  • curl
  • openssl

There is no support and maintenance for older PHP versions, however you are free to use the following compatible versions:

  • PHP 5.6 or HHVM: v1.x
  • PHP 7.0: v2.x
  • PHP 7.1: v3.x-v5.x
  • PHP 7.2: v6.x

Installation

Use composer to download and install the library and its dependencies.

composer require minishlink/web-push

Usage

Subscription::create([ // this is the structure for the working draft from october 2018 (https://www.w3.org/TR/2018/WD-push-api-20181026/) "endpoint" => "https://example.com/other/endpoint/of/another/vendor/abcdef...", "keys" => [ 'p256dh' => '(stringOf88Chars)', 'auth' => '(stringOf24Chars)' ], ]), 'payload' => '{"msg":"Hello World!"}', ], ]; $webPush = new WebPush(); // 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()}"; } } /** * send one notification and flush directly * @var MessageSentReport $report */ $report = $webPush->sendOneNotification( $notifications[0]['subscription'], $notifications[0]['payload'] // optional (defaults null) );">


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 !',
    ], [
        'subscription' => Subscription::create([
            'endpoint' => 'https://fcm.googleapis.com/fcm/send/abcdef...', // Chrome
        ]),
        'payload' => null,
    ], [
        'subscription' => Subscription::create([
            'endpoint' => 'https://example.com/other/endpoint/of/another/vendor/abcdef...',
            'publicKey' => '(stringOf88Chars)',
            'authToken' => '(stringOf24Chars)',
            'contentEncoding' => 'aesgcm', // one of PushManager.supportedContentEncodings
        ]),
        'payload' => '{msg:"test"}',
    ], [
          'subscription' => Subscription::create([ // this is the structure for the working draft from october 2018 (https://www.w3.org/TR/2018/WD-push-api-20181026/) 
              "endpoint" => "https://example.com/other/endpoint/of/another/vendor/abcdef...",
              "keys" => [
                  'p256dh' => '(stringOf88Chars)',
                  'auth' => '(stringOf24Chars)'
              ],
          ]),
          'payload' => '{"msg":"Hello World!"}',
      ],
];

$webPush = new WebPush();

// 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()}";
    }
}

/**
 * send one notification and flush directly
 * @var MessageSentReport $report
 */
$report = $webPush->sendOneNotification(
    $notifications[0]['subscription'],
    $notifications[0]['payload'] // optional (defaults null)
);

Full examples of Web Push implementations

Authentication (VAPID)

Browsers need to verify your identity. A standard called VAPID can authenticate you for all browsers. You'll need to create and provide a public and private key for your server. These keys must be safely stored and should not change.

You can specify your authentication details when instantiating WebPush. The keys can be passed directly (recommended), or you can load a PEM file or its content:



use Minishlink\WebPush\WebPush;

$endpoint = 'https://fcm.googleapis.com/fcm/send/abcdef...'; // Chrome

$auth = [
    'VAPID' => [
        'subject' => 'mailto:[email protected]', // can be a mailto: or your website address
        'publicKey' => '~88 chars', // (recommended) uncompressed public key P-256 encoded in Base64-URL
        'privateKey' => '~44 chars', // (recommended) in fact the secret multiplier of the private key encoded in Base64-URL
        'pemFile' => 'path/to/pem', // if you have a PEM file and can link to it on your filesystem
        'pem' => 'pemFileContent', // if you have a PEM file and want to hardcode its content
    ],
];

$webPush = new WebPush($auth);
$webPush->queueNotification(...);

In order to generate the uncompressed public and secret key, encoded in Base64, enter the following in your Linux bash:

$ openssl ecparam -genkey -name prime256v1 -out private_key.pem
$ openssl ec -in private_key.pem -pubout -outform DER|tail -c 65|base64|tr -d '=' |tr '/+' '_-' >> public_key.txt
$ openssl ec -in private_key.pem -outform DER|tail -c +8|head -c 32|base64|tr -d '=' |tr '/+' '_-' >> private_key.txt

If you can't access a Linux bash, you can print the output of the createVapidKeys function:

var_dump(VAPID::createVapidKeys()); // store the keys afterwards

On the client-side, don't forget to subscribe with the VAPID public key as the applicationServerKey: (urlBase64ToUint8Array source here)

serviceWorkerRegistration.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: urlBase64ToUint8Array(vapidPublicKey)
})

Reusing VAPID headers

VAPID headers make use of a JSON Web Token (JWT) to verify your identity. That token payload includes the protocol and hostname of the endpoint included in the subscription and an expiration timestamp (usually between 12-24h), and it's signed using your public and private key. Given that, two notifications sent to the same push service will use the same token, so you can reuse them for the same flush session to boost performance using:

$webPush->setReuseVAPIDHeaders(true);

Notifications and default options

Each notification can have a specific Time To Live, urgency, and topic. You can change the default options with setDefaultOptions() or in the constructor:

'new_event', // not defined by default, 'batchSize' => 200, // defaults to 1000 ]; // for every notifications $webPush = new WebPush([], $defaultOptions); $webPush->setDefaultOptions($defaultOptions); // or for one notification $webPush->sendOneNotification($subscription, $payload, ['TTL' => 5000]);">


use Minishlink\WebPush\WebPush;

$defaultOptions = [
    'TTL' => 300, // defaults to 4 weeks
    'urgency' => 'normal', // protocol defaults to "normal"
    'topic' => 'new_event', // not defined by default,
    'batchSize' => 200, // defaults to 1000
];

// for every notifications
$webPush = new WebPush([], $defaultOptions);
$webPush->setDefaultOptions($defaultOptions);

// or for one notification
$webPush->sendOneNotification($subscription, $payload, ['TTL' => 5000]);

TTL

Time To Live (TTL, in seconds) is how long a push message is retained by the push service (eg. Mozilla) in case the user browser is not yet accessible (eg. is not connected). You may want to use a very long time for important notifications. The default TTL is 4 weeks. However, if you send multiple nonessential notifications, set a TTL of 0: the push notification will be delivered only if the user is currently connected. For other cases, you should use a minimum of one day if your users have multiple time zones, and if they don't several hours will suffice.

urgency

Urgency can be either "very-low", "low", "normal", or "high". If the browser vendor has implemented this feature, it will save battery life on mobile devices (cf. protocol).

topic

Similar to the old collapse_key on legacy GCM servers, this string will make the vendor show to the user only the last notification of this topic (cf. protocol).

batchSize

If you send tens of thousands notifications at a time, you may get memory overflows due to how endpoints are called in Guzzle. In order to fix this, WebPush sends notifications in batches. The default size is 1000. Depending on your server configuration (memory), you may want to decrease this number. Do this while instanciating WebPush or calling setDefaultOptions. Or, if you want to customize this for a specific flush, give it as a parameter : $webPush->flush($batchSize).

Server errors

You can see what the browser vendor's server sends back in case it encountered an error (push subscription expiration, wrong parameters...).

getReason()}"; // also available (to get more info) /** @var \Psr\Http\Message\RequestInterface $requestToPushService */ $requestToPushService = $report->getRequest(); /** @var \Psr\Http\Message\ResponseInterface $responseOfPushService */ $responseOfPushService = $report->getResponse(); /** @var string $failReason */ $failReason = $report->getReason(); /** @var bool $isTheEndpointWrongOrExpired */ $isTheEndpointWrongOrExpired = $report->isSubscriptionExpired(); } }">


/** @var \Minishlink\WebPush\MessageSentReport $report */
foreach ($webPush->flush() as $report) {
    $endpoint = $report->getEndpoint();

    if ($report->isSuccess()) {
        echo "[v] Message sent successfully for subscription {$endpoint}.";
    } else {
        echo "[x] Message failed to sent for subscription {$endpoint}: {$report->getReason()}";
        
        // also available (to get more info)
        
        /** @var \Psr\Http\Message\RequestInterface $requestToPushService */
        $requestToPushService = $report->getRequest();
        
        /** @var \Psr\Http\Message\ResponseInterface $responseOfPushService */
        $responseOfPushService = $report->getResponse();
        
        /** @var string $failReason */
        $failReason = $report->getReason();
        
        /** @var bool $isTheEndpointWrongOrExpired */
        $isTheEndpointWrongOrExpired = $report->isSubscriptionExpired();
    }
}

PLEASE NOTE: You can only iterate once over the \Generator object.

Firefox errors are listed in the autopush documentation.

Payload length, security, and performance

Payloads are encrypted by the library. The maximum payload length is theoretically 4078 bytes (or ASCII characters). For compatibility reasons though, your payload should be less than 3052 bytes long.

The library pads the payload by default. This is more secure but it decreases performance for both your server and your user's device.

Why is it more secure?

When you encrypt a string of a certain length, the resulting string will always have the same length, no matter how many times you encrypt the initial string. This can make attackers guess the content of the payload. In order to circumvent this, this library adds some null padding to the initial payload, so that all the input of the encryption process will have the same length. This way, all the output of the encryption process will also have the same length and attackers won't be able to guess the content of your payload.

Why does it decrease performance?

Encrypting more bytes takes more runtime on your server, and also slows down the user's device with decryption. Moreover, sending and receiving the packet will take more time. It's also not very friendly with users who have limited data plans.

How can I disable or customize automatic padding?

You can customize automatic padding in order to better fit your needs.

Here are some ideas of settings:

  • (default) Encryption::MAX_COMPATIBILITY_PAYLOAD_LENGTH (3052 bytes) for compatibility purposes with Firefox for Android
  • Encryption::MAX_PAYLOAD_LENGTH (4078 bytes) for maximum security
  • false for maximum performance
  • If you know your payloads will not exceed X bytes, then set it to X for the best balance between security and performance.


use Minishlink\WebPush\WebPush;

$webPush = new WebPush();
$webPush->setAutomaticPadding(false); // disable automatic padding
$webPush->setAutomaticPadding(512); // enable automatic padding to 512 bytes (you should make sure that your payload is less than 512 bytes, or else an attacker could guess the content)
$webPush->setAutomaticPadding(true); // enable automatic padding to default maximum compatibility length

Customizing the HTTP client

WebPush uses Guzzle. It will use the most appropriate client it finds, and most of the time it will be MultiCurl, which allows to send multiple notifications in parallel.

You can customize the default request options and timeout when instantiating WebPush:



use Minishlink\WebPush\WebPush;

$timeout = 20; // seconds
$clientOptions = [
    \GuzzleHttp\RequestOptions::ALLOW_REDIRECTS => false,
]; // see \GuzzleHttp\RequestOptions
$webPush = new WebPush([], [], $timeout, $clientOptions);

Common questions

Is there any plugin/bundle/extension for my favorite PHP framework?

The following are available:

Feel free to add your own!

Is the API stable?

Not until the Push API spec is finished.

What about security?

Payload is encrypted according to the Message Encryption for Web Push standard, using the user public key and authentication secret that you can get by following the Web Push API specification.

Internally, WebPush uses the WebToken framework or OpenSSL to handle encryption keys generation and encryption.

How do I scale?

Here are some ideas:

  1. Upgrade to PHP 7.3
  2. Make sure MultiCurl is available on your server
  3. Find the right balance for your needs between security and performance (see above)
  4. Find the right batch size (set it in defaultOptions or as parameter to flush())

How to solve "SSL certificate problem: unable to get local issuer certificate"?

Your installation lacks some certificates.

  1. Download cacert.pem.
  2. Edit your php.ini: after [curl], type curl.cainfo = /path/to/cacert.pem.

You can also force using a client without peer verification.

How to solve "Bad key encryption key length" or "Unsupported key type"?

Disable mbstring.func_overload in your php.ini.

How to solve "Class 'Minishlink\WebPush\WebPush' not found"

Make sure to require Composer's autoloader.

require __DIR__ . '/path/to/vendor/autoload.php';

I lost my VAPID keys!

See issue #58.

I'm using Firebase push notifications, how do I use this library?

This library is not designed for Firebase push notifications. You can still use it for your web projects (for standard WebPush notifications), but you should forget any link to Firebase while using the library.

I need to send notifications to native apps. (eg. APNS for iOS)

WebPush is for web apps. You need something like RMSPushNotificationsBundle (Symfony).

This is PHP... I need Javascript!

This library was inspired by the Node.js marco-c/web-push library.

Contributing

See CONTRIBUTING.md.

License

MIT

Sponsors

Thanks to JetBrains for supporting the project through sponsoring some All Products Packs within their Free Open Source License program.

GitHub

https://github.com/web-push-libs/web-push-php
Comments
  • 1. Payload support

    • (done) use phpecc/phpecc in order to generate the encryption key in prime256v1
    • when this PHP bug is fixed, replace phpecc by the PHP binding of OpenSSL (thanks @marco-c)
    • use OpenSSL with AES 128 GCM mode to encrypt the payload (need to wait for the resolution of this other PHP bug.)

    If you want to help: (thanks!)

    • vote for the PHP bugs in the above linked pages
    • or contribute to php/php-src in order to fix the bugs
    Reviewed by Minishlink at 2015-12-03 18:23
  • 2. [WIP] [BC] General project maintenance

    I've reached out to @Minishlink hoping to be able to collaborate on a roadmap for the project and shoot some ideas that he may be willing to accept into the project but haven't heard back yet. Hopefully, this will come as a sign of good faith and jump-start that process.

    Sourcing projects similar in function to fit a need in another project, I stumbled across this library as it seems to be the defacto standard for web push with PHP. I also noticed it has some great proposed contributions from some awesome contributors and decided that rather than building my own library, why not contribute back to the community.

    For anyone interested, this pull request will be a WIP and any feedback on particular changes being added in or removed are entirely welcome.

    Changes in this pull request

    • 7173909 - Removing dependency management from code
    • dae1c89 - Implementing PSR-2 and opinionated code cleanup
    • e7de87c - Implementing PSR-4 autoloading for development
    • e88ba23 - Adding tests around & cleaning up notices in \Minishlink\WebPush\Notification
    • ed52704 - Reducing public IP and cleaning up test suite of \Minishlink\WebPush\MessageSentReport [BC]
    • 0ee2485 - Separating unit and integration test suites (also snuck a fix in that encompasses the changes in #234)
    • 8bf6f80 - Implementing abstraction of HTTP communications [BC]
    • 4bf92e9 - Implementing Options
    • 78bff65 - Continuation of abstraction of HTTP communications; decoupling from third party HTTP libraries [BC]
    • e7cc878 - Implement Auth, drop support for GCM in exchange for VAPID (SEE: validation) [BC]
    • afc2cc5 - Implement Headers object to make building, manipulating and iterating over header keys and values easier and cleaner [BC]
    • ea9646e -
      • Implement Payload to keep the string payload it's encryption components together [BC]
      • Implement Queue to handle queueing of notifications and promises
      • Implement Cache to handle caching vapid headers
      • Implement SubscriptionInterface and AuthorizationInterface to allow for easier integration of the library into consumer code
      • Removed factory methods on model objects for explicit factory classes [BC]

    Additional pull requests to be considered for version 6

    • #218 - [BC]
    • #227
    • #228

    Questions

    • We're not currently running the integration tests in CI but our travis.yml is partially configured to run the entirety of our test suite, integration tests included - do we want to look into running our integration tests in CI, or clean up the otherwise unneeded configuration?
    Reviewed by ryancco at 2019-06-06 18:29
  • 3. Payload data empty when getting push notification

    Hello there!,

    I am sending push notification payload data to GCM endpoint and I am getting notification to corresponding browser but my payload data is empty in service workers JS.

    Any ideas are appreciated, Thank you!

    Reviewed by anandselva at 2016-06-24 12:02
  • 4. Add support for VAPID

    See also: https://github.com/marco-c/web-push/blob/b9156f658fc028c3388dbed005ffa5e2012b55ac/index.js#L206 https://github.com/mozilla/wp-web-push/pull/283/files#diff-05b502d88da481dfcef81a7fdb4a6da4R60

    wp-web-push is using the same libraries you're using for the payload.

    Reviewed by marco-c at 2016-04-12 16:30
  • 5. event.data in service-worker is always null

    NOTE: Please test in a least two browsers (i.e. Chrome and Firefox). This helps with diagnosing problems quicker.

    Please confirm the following:

    • [x] I have read the README entirely
    • [ ] I have verified in the issues that my problem hasn't already been resolved

    Setup

    Please provide the following details, the more info you can provide the better.

    • Operating System: Linux
    • PHP Version: 7.2
    • web-push-php Version: 4.0.2

    Please check that you have installed and enabled these PHP extensions :

    • [x] gmp
    • [x] mbstring
    • [x] curl
    • [x] openssl

    Please select any browsers that you are experiencing problems with:

    • [x] Chrome
    • [ ] Firefox
    • [ ] Firefox for Mobile
    • [ ] Opera for Android
    • [ ] Samsung Internet Browser
    • [ ] Other

    Chrome 70

    Problem

    event.data in service-worker is always null

    Expected

    event.data may not be null if a payload is defined in notification

    Features Used

    • [x] VAPID Support
    • [x] GCM API Key
    • [x] Sending with Payload

    Example / Reproduce Case

    <?php
    
    namespace App\Service;
    
    use Minishlink\WebPush\WebPush;
    use Minishlink\WebPush\Subscription;
    
    class NotificationService
    {
        /** @var Subscription */
        private $subscription;
    
        /** @var WebPush */
        private $webPush;
    
        public function __construct()
        {
            $destination = json_decode('{"endpoint":"https://fcm.googleapis.com/fcm/send/eqQOWl44JuU:APA91bG9TpM9-WbVp65uO4VZtZD06AJYBOpfigYeXq_lW3Gq7bs8Nqp4zT5DeFKjPqgd4NycaHt0VBPg-oNoi1WJnVv4vylmNjIJ_lyYovC11ztk60AtkIUFPTG-n4i_iYAoFJzwyajN","expirationTime":null,"keys":{"p256dh":"BLzGWK-7eDl0LYyFVPADfBMFa0YDLG9xsUikGhH-MMSXtgALIkoOwK6rrIowHX3tOhMw1IqNKzc3EqLhdzHst9A","auth":"Het3CBpFFMC_kuQp5DPPIw"}}', true);
            $destination['contentEncoding'] = 'aesgcm';
    
            $auth = array(
                'VAPID' => array(
                    'subject' => 'My awesome app name',
                    'publicKey' => 'My public key',
                    'privateKey' => 'My private key'
                )
            );
    
            $this->subscription = Subscription::create($destination);
            $this->webPush = new WebPush($auth);
        }
    
        public function sendNotification(string $message)
        {
            $this->webPush->sendNotification(
                $this->subscription,
                $message
            );
            return $this->webPush->flush();
        }
    }
    

    Other

    When I use $notificationService->sendNotification('Hello world'), a notification is well received in the web app but event.data is always null

    Reviewed by vcastro45 at 2018-11-16 15:55
  • 6. Sending with payload not working

    NOTE: Please test in a least two browsers (i.e. Chrome and Firefox). This helps with diagnosing problems quicker.

    Please confirm the following:

    • [X] I have read the README entirely
    • [X] I have verified in the issues that my problem hasn't already been resolved

    Setup

    Please provide the following details, the more info you can provide the better.

    • Operating System: Windows
    • PHP Version: 7.1.5
    • web-push-php Version: v3.0.0

    Please check that you have installed and enabled these PHP extensions :

    • [X] gmp
    • [X] mbstring
    • [X] curl
    • [X] openssl

    Please select any browsers that you are experiencing problems with:

    • [X] Chrome
    • [X] Firefox
    • [X] Firefox for Mobile
    • [X] Opera for Android
    • [X] Samsung Internet Browser
    • [X] Other

    Please specify the versions (i.e. Chrome Beta, Firefox Beta etc). Chrome 64

    Problem

    I am unable to send notifications with payloads. Each time the payload is not empty, the request is sent and sendNotification method returns true (when I dumped response, status code was 201), but no notification is delivered.

    Disabling the padding did not help.

    I am suspecting the encryption/signing not working correctly and I will be trying to debug it step by step against web-push for node.js, which works OK.

    Please explain what behaviour you are seeing.

    Expected

    Send notification with payload, that is delivered to the browser.

    Please explain what you expected to happen

    Features Used

    • [X] VAPID Support
    • [ ] GCM API Key
    • [X] Sending with Payload

    Example / Reproduce Case

    $subscription = '{"endpoint":"https://fcm.googleapis.com/fcm/send/fxfsxX_N7Is:APA91bFeXNv4zQ9xKl2k-rfmf5zweDJP3walARMXnQFa6pdx4_1OCldKjl1ruuKPavs67tK5_xfP3XMx2XRVRWTIrhIaS6_GIQvT4U9hmH3xDJBABVfNlBewnx0Zml6oFZKiEW9xmZ5-","expirationTime":null,"keys":{"p256dh":"BHs7fMO97vNgGePrFBCdtK4cwCirLiL56e34QqpoirN5_MC2-LgoTsJ5hV0vu6wn7oRpebgYelICX7bEvXbB7mI=","auth":"aZ5dQkxnt7yFsdV4dpZS3w=="}}';
    
    $subscription = json_decode($subscription, true);
    
    use Minishlink\WebPush\WebPush;
    
    $auth = [
        'VAPID' => [
            'subject' => 'mailto:[email protected]',
            'publicKey' => 'BDaIDoGypt1kzw1XkCItDuvH0iKb9NcsiXjltGt1rCOXy7vF2ER94UqNM-Ers0ey8FzK6bskzPpXKwwYo0LgCBA',
            'privateKey' => '-n1Xh2Zrpl3GeV50X5vBtSHFzwbDs5Ie0LMzkfsyjLs',
        ],
    ];
    
    $webPush = new WebPush($auth);
    
    $webPush->sendNotification(
        $subscription['endpoint'],
        'Hello data',
        $subscription['keys']['p256dh'],
        $subscription['keys']['auth'],
        true
    );
    

    Please provide a code sample that reproduces the issue. If there is a repository that reproduces the issue please put the link here.

    Other

    Please put any remaining notes here.

    Reviewed by lukasradek at 2018-03-12 01:12
  • 7. Call to undefined method GuzzleHttp\Exception\ConnectException::getResponse() in WebPush.php line 185

    NOTE: Please test in a least two browsers (i.e. Chrome and Firefox). This helps with diagnosing problems quicker.

    Please confirm the following:

    • [x] I have read the README entirely
    • [x] I have verified in the issues that my problem hasn't already been resolved

    Setup

    Please provide the following details, the more info you can provide the better.

    • Operating System: Linux
    • PHP Version: 7.4
    • web-push-php Version: 6.0.2

    Please check that you have installed and enabled these PHP extensions :

    • [x] gmp
    • [x] mbstring
    • [x] curl
    • [x] openssl

    Please select any browsers that you are experiencing problems with:

    • [ ] Chrome
    • [ ] Firefox
    • [ ] Firefox for Mobile
    • [ ] Opera for Android
    • [ ] Samsung Internet Browser
    • [x] Other

    Please specify the versions (i.e. Chrome Beta, Firefox Beta etc).

    Problem

    Please explain what behaviour you are seeing.

    Exception

    Expected

    Please explain what you expected to happen

    No exception

    Features Used

    • [x] VAPID Support
    • [x] Sending with Payload

    Example / Reproduce Case

    Please provide a code sample that reproduces the issue. If there is a repository that reproduces the issue please put the link here.

    Other

    Please put any remaining notes here.

    It never happened before v6.0.2 but it could be because HTTP request never failed. Also as I can see - RequestException was expected but ConnectException received.

    Reviewed by swayok at 2020-09-30 09:06
  • 8. 401 Unauthorized: authorization header must be specified

    • [x] I have read the README entirely
    • [x] I have verified in the issues that my problem hasn't already been resolved

    Setup

    • Operating System: Linux
    • PHP Version: 7.4
    • web-push-php Version: <6.0.0>

    Please check that you have installed and enabled these PHP extensions :

    • [x] gmp
    • [x] mbstring
    • [x] curl
    • [x] openssl

    Please select any browsers that you are experiencing problems with:

    • [x] CLI

    Features Used

    • [x] VAPID Support
    • [x] Sending with Payload

    Problem

    As of v6.0.0, I get a 401 Unauthorized when sending a push notification:

    Client error: POST https://fcm.googleapis.com/fcm/send/.... resulted in a 401 Unauthorized response: authorization header must be specified.

    I'm using minishlink/web-push-bundle and everything worked perfectly, but upgrading to v6 gives this problem. For Windows clients I get a curl timeout, for FCM I get this 401.

    Any idea what causes this problem?

    Reviewed by stephanvierkant at 2020-09-07 20:26
  • 9. Firefox Push Issue

    Hey, I'm not sure if you've encountered this or aware of this issue.

    But it seems like I need to send 2 Notifications in order for Firefox to work properly, I am not sure why this happening or how to solve it.

    Chrome seems to work out of the box.

    Now, an really funny think I've noticed.

    If both Chrome and Firefox are open, the notification in Firefox comes just normal.

    What could be the cause of this ? Is it something you've noticed or maybe something goes wrong.

    I've tested this theory like 7 times

    Reviewed by robertuniqid at 2016-02-12 03:05
  • 10. Rebuild/ng

    This PR is a new implementation of the Web Push Notifications. It completely breaks the previous implementation. It aims to address most of concerns and bugs that have been reported here and that are namely:

    The library is slow

    This new version uses PSR-6 based caching system and allow VAPID header and payload encryption keys to be reused. The result is that it takes less than 1ms (~) to compute the Authorization header (JWT) and encrypt the payload (AES GCM).

    | benchmark | subject | set | revs | its | mem_peak | best | mean | mode | worst | stdev | rstdev | diff | |---------------|-----------------------------------------|-----|------|-----|-------------|-------------|-------------|-------------|-------------|---------|--------|-------| | AES128GCMPaddingBench | encodeWithoutPadding | 0 | 4096 | 1 | 6,567,624b | 844.651μs | 844.651μs | 844.651μs | 844.651μs | 0.000μs | 0.00% | 5.60x | | AES128GCMPaddingBench | encodeWithRecommendedPadding | 0 | 4096 | 1 | 7,555,112b | 894.495μs | 894.495μs | 894.495μs | 894.495μs | 0.000μs | 0.00% | 5.93x | | AES128GCMPaddingBench | encodeWithMaximumPadding | 0 | 4096 | 1 | 7,555,488b | 905.728μs | 905.728μs | 905.728μs | 905.728μs | 0.000μs | 0.00% | 6.00x | | WebTokenBench | sendNotificationWithoutPayload | 0 | 4096 | 1 | 22,605,992b | 351.297μs | 351.297μs | 351.297μs | 351.297μs | 0.000μs | 0.00% | 2.33x | | WebTokenBench | sendNotificationWithoutPayloadWithCache | 0 | 4096 | 1 | 22,625,784b | 159.154μs | 159.154μs | 159.154μs | 159.154μs | 0.000μs | 0.00% | 1.06x | | WebTokenBench | sendNotificationWithPayload | 0 | 4096 | 1 | 50,266,256b | 1,313.706μs | 1,313.706μs | 1,313.706μs | 1,313.706μs | 0.000μs | 0.00% | 8.71x | | WebTokenBench | sendNotificationWithPayloadWithCache | 0 | 4096 | 1 | 50,156,568b | 669.178μs | 669.178μs | 669.178μs | 669.178μs | 0.000μs | 0.00% | 4.44x | | LcobucciBench | sendNotificationWithoutPayload | 0 | 4096 | 1 | 35,674,072b | 335.454μs | 335.454μs | 335.454μs | 335.454μs | 0.000μs | 0.00% | 2.22x | | LcobucciBench | sendNotificationWithoutPayloadWithCache | 0 | 4096 | 1 | 22,374,880b | 150.849μs | 150.849μs | 150.849μs | 150.849μs | 0.000μs | 0.00% | 1.00x | | LcobucciBench | sendNotificationWithPayload | 0 | 4096 | 1 | 62,682,896b | 1,270.005μs | 1,270.005μs | 1,270.005μs | 1,270.005μs | 0.000μs | 0.00% | 8.42x | | LcobucciBench | sendNotificationWithPayloadWithCache | 0 | 4096 | 1 | 50,069,072b | 631.355μs | 631.355μs | 631.355μs | 631.355μs | 0.000μs | 0.00% | 4.19x | | AESGCMPaddingBench | encodeWithoutPadding | 0 | 4096 | 1 | 6,221,536b | 802.347μs | 802.347μs | 802.347μs | 802.347μs | 0.000μs | 0.00% | 5.32x | | AESGCMPaddingBench | encodeWithRecommendedPadding | 0 | 4096 | 1 | 7,556,272b | 855.086μs | 855.086μs | 855.086μs | 855.086μs | 0.000μs | 0.00% | 5.67x | | AESGCMPaddingBench | encodeWithMaximumPadding | 0 | 4096 | 1 | 7,560,344b | 877.718μs | 877.718μs | 877.718μs | 877.718μs | 0.000μs | 0.00% | 5.82x |

    Cannot Upgrade XXXXX To …

    This new version mostly relies on PSR interfaces:

    • PSR-3: logging
    • PSR-6: caching
    • PSR-7: HTTP Messages
    • PSR-17: HTTP Factories
    • PSR-18: HTTP Client

    You are now free to use Guzzle, HTTPlug, Symfony Client… Regarding the JWT computation, this library provides a web-token wrapper and now a lcobucci/jwt one. You are free to use one or the other. If it does not fit on your needs, you can easily use the JWT provider you want by installing it and implementing the correct interface.

    Mutation Testing

    It is important to test the library, but also important to test the tests. This new version now uses Github Actions to perform the following tests:

    • Coding Standards (as done in early versions)
    • Tests with Code Coverage (as done in early versions)
    • Quality (as done in early versions)
    • Benchmark (new, see above)
    • Security (new)
    • Mutation Testing (new)

    Remaining Tasks

    • [x] Documentation typos
    • [x] Add a section regarding the keys (how to create)
    Reviewed by Spomky at 2020-10-03 20:41
  • 11. Return results as a \Generator

    As discussed in #183:

    • [x] provide a mapped request/response report when sending a bunch of messages
    • [x] utilize the \Generator object for better performance
    • [x] add some documentation on running the tests for making contributions easier
    • [x] update documentation on sending requests in bulk
    Reviewed by t1gor at 2018-09-21 08:22
  • 12. event.data is always null

    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.

    Reviewed by kkCode at 2022-06-05 08:35
  • 13. cURL error 28: NSS: client certificate not found (nickname not specified)

    • [x] I have read the README entirely
    • [x] I have verified in the issues that my problem hasn't already been resolved

    Setup

    • Operating System: CentOS 7
    • PHP Version: 8.1
    • web-push-php Version: 7.0.0

    Please check that you have installed and enabled these PHP extensions :

    • [x] gmp
    • [x] mbstring
    • [x] curl
    • [x] openssl

    Problem

    Occasionally, I'm seeing this error being reported when trying to send Push Notifications:

    cURL error 28: NSS: client certificate not found (nickname not specified) (see https://curl.haxx.se/libcurl/c/libcurl-errors.html)

    only for endpoints starting with:

    https://****.notify.windows.com/w/?token=

    Expected

    Hopefully we wouldn't see an error. I'm not sure what is causing this.

    Features Used

    • [x] VAPID Support
    • [x] Sending with Payload
    Reviewed by ghnp5 at 2022-06-04 03:33
  • 14. Parse error: syntax error, unexpected '|', expecting ';' or '{' in vendor/web-token/jwt-key-mgmt/JWKFactory.php on line 156

    Setup

    Please provide the following details, the more info you can provide the better.

    • Operating System:
    • PHP Version: < 7.4.29 >
    • web-push-php Version: <7.0.0>

    Please check that you have installed and enabled these PHP extensions :

    following enables: gmp, mbstring, curl, openssl

    Please select any browsers that you are experiencing problems with: All browsers tested in Chrome and firefox (latest versions)

    Problem

    I want to generate a VAPID key set using the web-push-php package.

    I get the error: Parse error: syntax error, unexpected '|', expecting ';' or '{' in .../push/vendor/web-token/jwt-key-mgmt/JWKFactory.php on line 156

    Expected

    Expected to return VAPID key

    Features Used

    VAPID Support

    Example / Reproduce Case

    Here is my code:

    require_once '../push/vendor/autoload.php'; use Minishlink\WebPush\VAPID; $keyset = VAPID::createVapidKeys(); echo $keyset["publicKey"]; file_put_contents("vapid.json", json_encode($keyset));

    Other

    It is not liking the |. Line 156 is: public static function createFromJsonObject(string $value): JWK|JWKSet

    Any ideas? Thanks

    Reviewed by JeyjooMilano at 2022-05-10 21:13
  • 15. PHP Fatal error: Uncaught TypeError: Jose\Component\Core\Util\Ecc\PrivateKey::create(): #338

    same error with #338

    Setup

    UBUNTU 20.04 LTS PHP-FPM 7.4.3 web-push-php Version: 7.0.0 Chrome-100

    • [x] gmp
    • [x] mbstring
    • [x] curl
    • [x] openssl

    Features Used

    • [x] VAPID Support
    • [x] Sending with Payload

    code

    use Minishlink\WebPush\WebPush; use Minishlink\WebPush\Subscription; require_once "vendor/autoload.php";

    $sub = Subscription::create( [ "endpoint" => 'https://fcm.googleapis.com/fcm/send/fAPQ61 ------- uf', "keys" => [ 'p256dh'=>'BD --------------------- Tw' , 'auth' => 'f --------- w' ] , ]) ;

    $payload = '{"msg":"Hello World!"}' ;

    $webPush = new WebPush(); $report = $webPush->sendOneNotification($sub , $payload);

    result -error

    2022/04/13 22:39:46 [error] 368579#368579: *717 FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught TypeError: Argument 1 passed to Jose\Component\Core\Util\Ecc\PrivateKey::create() must be an instance of Brick\Math\BigInteger, instance of GMP given, called in /var/www/public/push/vendor/minishlink/web-push/src/Encryption.php on line 355 and defined in /var/www/public/push/vendor/web-token/jwt-util-ecc/PrivateKey.php:57

    Stack trace: #0 /var/www/public/push/vendor/minishlink/web-push/src/Encryption.php(355): Jose\Component\Core\Util\Ecc\PrivateKey::create() #1 /var/www/public/push/vendor/minishlink/web-push/src/Encryption.php(105): Minishlink\WebPush\Encryption::calculateAgreementKey() #2 /var/www/public/push/vendor/minishlink/web-push/src/Encryption.php(61): Minishlink\WebPush\Encryption::deterministicEncrypt() #3 /var/www/public/push/vendor/minishlink/web-push/src/WebPush.php(224): Minishlink\WebPush\Encryption::encrypt() #4 /var/www/public/push/vendor/minishlink/web-push/src/WebPush.php(171): Minishlink\WebPush\WebPush->prepare()

    Reviewed by alpastar at 2022-04-14 07:05
  • 16. Is there a way to "get the UserAgent" for a specific subscription?

    When the user subscribes, I log the current UserAgent for that subscription.

    However, as browsers update, the UserAgent eventually becomes outdated.

    Is there a way to request the latest UserAgent for a specific subscription, to keep this info updated? (server-side)

    Reviewed by ghnp5 at 2022-04-10 20:46
  • 17. Hi, I have the same problem, the web push notifications for edge

    Hi, I have the same problem, the web push notifications for chrome and for firefox are sent without problem, however for Edge they do not arrive and I get the following error back:

    Client error: POST https://wns2-db5p.notify.windows.com/w/?token=BQYAAADuof2gokJoLSVIKIfsv0zYCQE2FwGAEXcrhE5k9Z%2f5NvhkH%2ffAVvW41p31sJ1hRqHhvN3Eya4Ax6g9vECDaJWeJzmvKB8h8Qb68yB%2blp4L6W%2bMtybken0cdIAcPfTwJt%2b5G%2foh4VDc%2fA%2biTxl%2frnDESRIsSnlFIiKnp38PZiuwsjsdr0D%2f2e7UbTXQyFQhFiGvy1YM2tPjZ5UfyYmeuc0bxfpB9MFvztXt%2fskVVWAXNyIbH9CR2L%2ble5hTwAC93XGZBBgf8Vi%2bVHkv%2fbkKoHhkTfbyHpS0n5VvYafr5L2p87Ruf24EqMOrXz94trgsxY805F0KKHG9mIsrEBIb%2fKol resulted in a 406 Not Acceptable response

    Any solution?

    I use Microsoft Edge - Versión 98.0.1108.50 (Compilación oficial) (64 bits)

    Originally posted by @raulfdeztdo in https://github.com/web-push-libs/web-push-php/issues/335#issuecomment-1040572594

    Reviewed by raulfdeztdo at 2022-02-15 18:21
This package makes it easy to send web push notifications with Laravel.

Web push notifications channel for Laravel This package makes it easy to send web push notifications with Laravel. Installation You can install the pa

Jun 30, 2022
Send push notifications to apple devices (iPhone, iPad, iPod).

Apple Apn Push Send push notifications to apple devices (iPhone, iPad, iPod). Support authenticators: Certificate Json Web Token Supported protocols:

Apr 26, 2022
Larafirebase is a package thats offers you to send push notifications or custom messages via Firebase in Laravel.
Larafirebase is a package thats offers you to send push notifications or custom messages via Firebase in Laravel.

Introduction Larafirebase is a package thats offers you to send push notifications or custom messages via Firebase in Laravel. Firebase Cloud Messagin

Jun 28, 2022
Send Firebase push notifications with Laravel php framework.

FCM Notification Channel for Laravel Send Firebase push notifications with Laravel php framework. Installation You can install this package via compos

Jun 29, 2022
Standalone PHP library for easy devices notifications push.

NotificationPusher Standalone PHP library for easy devices message notifications push. Feel free to contribute! Thanks. Contributors Cédric Dugat (Aut

Jun 15, 2022
Takes care of Apple push notifications (APNS) in your PHP projects.

Notificato Notificato takes care of push notifications in your PHP projects. Italian: notificato è: participio passato English: notified Why use Notif

Jun 27, 2022
Push notifications Library for PHP

Push notifications Library for PHP Supported Protocols Protocol Supported Driver Options APNs (Token Based) ✓ APNs\Token APNs\Token\Option APNs (Certi

Mar 25, 2022
Push Notifications using Laravel
Push Notifications using Laravel

laravel-push-notification Push Notifications using Laravel PushNotification::send(['deviceToken1', 'deviceToken2',..], 'Notification Message', 'Action

Apr 6, 2022
Laravel package to enable sending push notifications to devices

Laravel Push Notification Package to enable sending push notifications to devices Installation Update your composer.json file to include this package

Jun 16, 2022
Takes care of Apple push notifications (APNS) in your PHP projects.

Notificato Notificato takes care of push notifications in your PHP projects. Italian: notificato è: participio passato English: notified Why use Notif

Apr 17, 2022
Standalone PHP library for easy devices notifications push.

NotificationPusher Standalone PHP library for easy devices message notifications push. Feel free to contribute! Thanks. Contributors Cédric Dugat (Aut

Jun 15, 2022
:computer: Send notifications to your desktop directly from your PHP script
:computer: Send notifications to your desktop directly from your PHP script

About JoliNotif JoliNotif is a cross-platform PHP library to display desktop notifications. It works on Linux, Windows or MacOS. Requires PHP >= 7.2 (

Jun 26, 2022
Notifications in PHP (notify-send, growl, etc) like that.

#Nod Notifications in PHP (notify-send, growl, etc) like that. ##Examples Letting Nod figure out the best Adapter to use (not recommend ATM, only work

Mar 26, 2019
This package allows you to send notifications to Microsoft Teams.
This package allows you to send notifications to Microsoft Teams.

Teams connector This package allows you to send notifications to Microsoft Teams. Installation You can install the package using the Composer package

May 6, 2022
This package makes it easy to send notifications using RocketChat with Laravel 9.0+.

laravel-rocket-chat-notifications Introduction This package makes it easy to send notifications using RocketChat with Laravel 9.0+. Contents Installat

May 27, 2022
ApnsPHP: Apple Push Notification & Feedback Provider
ApnsPHP: Apple Push Notification & Feedback Provider

ApnsPHP: Apple Push Notification & Feedback Provider A full set of open source PHP classes to interact with the Apple Push Notification service for th

Jun 27, 2022
Implementations for different SMS providers for EspoCRM. Can be used for 2-factor authentication or automatic SMS sending via Workflow and BPM tools.

SMS Providers for EspoCRM An installable extension. Supported SMS Providers Twilio Spryng sms77 Setting up Install the extension. At Administration >

Jun 15, 2022
A very lightweight library to handle notifications the smart way.
A very lightweight library to handle notifications the smart way.

NAMSHI | Notificator Notificator is a very simple and lightweight library to handle notifications the smart way. It took inspiration from other librar

May 9, 2022
Sends notifications via one or more channels (email, SMS, ...).

Notifier Component The Notifier component sends notifications via one or more channels (email, SMS, ...). Resources Documentation Contributing Report

Jun 27, 2022