Как отправлять веб-push-уведомления с помощью PHP
Web Push API позволяет отправлять push-уведомления в веб-браузеры и API. Хотя большая часть логики происходит в браузере, вам все равно нужен компонент на стороне сервера для генерации ваших уведомлений. Вот как реализовать серверную часть Web Push с помощью PHP.
Предпосылки
Для целей этого руководства мы предполагаем, что вы знакомы с основами создания HTTP API в PHP. Вам нужно будет открыть несколько общедоступных конечных точек, используя вашу веб-инфраструктуру. Они будут вызываться вашим JavaScript в браузере для регистрации и отмены регистрации устройств.
В этой статье не будет затрагиваться код на стороне браузера или то, как он работает. Вам потребуется собрать сервис-воркер, который будет реагировать на входящие push-события и отображать пользователю уведомление.
На высоком уровне поток Web Push выглядит так:
- Принудительная подписка регистрируется в браузере. Браузер выдает уникальный URL-адрес конечной точки для вашего JavaScript.
- Ваш JavaScript отправляет данные о подписке на ваш сервер и идентифицирует пользователя, к которому они относятся.
- Когда серверной части необходимо отправить push-уведомление, создайте полезные данные и отправьте их на URL-адрес конечной точки, указанный в данных подписки.
- Браузер пользователя получит полезную нагрузку через платформу доставки уведомлений поставщика. Ваш сервис-воркер JavaScript обрабатывает последующее событие и использует API уведомлений браузера, чтобы предупредить пользователя.
Вот как реализовать серверные аспекты шагов с 1 по 3.
Получение настройки
Мы будем использовать пакет Packagist web-push
от minishlink. Это абстрагирует взаимодействие с каждой платформой уведомлений браузера, поэтому вам не нужно вручную различать типы конечных точек.
Добавьте пакет в свой проект с помощью Composer:
composer require minishlink/web-push
Чтобы использовать последнюю версию, вам нужен PHP 7.2 или выше с gmp
, mbstring
, curl
и openssl
. расширения. Если вы должны использовать более раннюю версию PHP, привяжите пакет к более ранней версии для обеспечения совместимости.
Библиотека предоставляет базовый класс WebPush
с методами, позволяющими отправлять уведомления по отдельности или в виде пакетов. Подписки представлены экземплярами класса Subscription
.
Предоставление ключей VAPID
Доверие к соответствующей стандартам экосистеме Web Push обеспечивается за счет использования ключей VAPID. Вашему серверу нужна пара ключей VAPID, чтобы он мог аутентифицировать себя в браузерах. Открытый ключ должен быть открыт через конечную точку API.
Вы можете сгенерировать набор ключей VAPID с помощью пакета web-push
:
use MinishlinkWebPushVAPID; $keyset = VAPID::createVapidKeys(); // public key - this needs to be accessible via an API endpoint echo $keyset["publicKey"]; // private key - never expose this! echo $keyset["privateKey"]; file_put_contents("vapid.json", json_encode($keyset));
Создайте ключи для своей системы и сохраните их в постоянном месте. Добавьте конечную точку API, чтобы ваш клиентский JavaScript мог получить открытый ключ. Это будет использоваться для настройки push-подписки браузера. Устройство пользователя будет принимать входящие push-события, если они были подписаны с использованием соответствующего закрытого ключа VAPID.
Регистрация push-подписок
Следующим шагом в последовательности является получение запросов на push-подписку от ваших клиентов. Как только браузер подтвердит новую push-подписку, ваш JavaScript должен отправить URL-адрес конечной точки подписки и связанные ключи аутентификации на ваш сервер. Сохраните эти данные вместе с идентификатором пользователя, чтобы впоследствии можно было получить все устройства, зарегистрированные с помощью push-уведомлений, связанные с пользователем.
Мы опускаем примеры кода для этого шага, так как реализация зависит от вашего уровня хранения данных и значений, которые отправляет ваш JavaScript. Обычно это JSON-представление объекта PushSubscription
. Вам нужен простой набор конечных точек CRUD API с поддержкой базы данных, чтобы создать подписку, заменить существующую и запросить удаление, когда пользователь отменяет подписку.
Подготовка подписок
После успешной регистрации клиента вы можете начать отправлять уведомления с помощью библиотеки web-push
. Начните с создания экземпляра класса WebPush
:
use MinishlinkWebPushWebPush; $webPush = new WebPush([ "VAPID" => [ "subject" => "https://example.com", "publicKey" => "VAPID_Public_Key_Here", "privateKey" => "VAPID_Private_Key_Here" ] ]);
Вы можете повторно использовать один экземпляр WebPush
при каждой отправке уведомления. Библиотека должна быть настроена с помощью набора ключей VAPID, который вы создали ранее. Ключи должны быть закодированы как Base64, но это будет сделано за вас, если вы создадите их с помощью библиотеки.
VAPID subject
используется для идентификации вашего сервера и его контактных данных. Вы можете указать URL-адрес веб-сайта или ссылку на адрес электронной почты mailto:
.
Затем вам нужно получить push-подписку, на которую вы будете отправлять. Используйте свою систему доступа к данным для поиска URL-адресов конечной точки push-уведомлений, связанных с пользователем, которому вы хотите отправить сообщение. Преобразуйте каждую подписку в экземпляр Subscription
:
use MinishlinkWebPushSubscription; // Get user's push data... // SELECT * FROM push_subscriptions WHERE user_id = 123456 $subscription = Subscription::create([ "endpoint" => "https://fcm.google.com/...", "contentEncoding" => "aesgcm", "authToken" => "<auth token from JavaScript PushSubscription object>" "keys" => [ "auth" => "<auth token from JavaScript PushSubscription object>", "p256dh" => "<p256dh token from JavaScript PushSubscription object>" ] ]);
Свойство auth
объекта PushSubscription
повторяется дважды, чтобы соответствовать двум различным версиям спецификации, используемой службами браузера. Свойство P256DH — это еще один открытый ключ, который следует указывать при установке в подписке.
Библиотека web-push
совместима с конечными точками push-уведомлений Chrome и Firefox. Он также будет работать с любой другой реализацией Web Push, соответствующей текущему стандарту.
Отправка уведомления
Теперь объедините экземпляры WebPush
и Subscription
, чтобы отправить уведомление:
$result = $webPush -> sendOneNotification( $subscription, json_encode([ "message" => "Demo notification", "foo" => "bar" ]) );
Вызов sendOneNotification()
обеспечивает немедленную доставку одного уведомления. Полезная нагрузка в этом случае представляет собой массив в формате JSON с двумя свойствами. Вам решать, какие данные вы отправляете и в каком формате — ваш JavaScript-клиент получает их как есть и может интерпретировать по мере необходимости.
Отправка уведомления возвращает класс результата, который позволяет проверить успешность операции:
if ($result -> isSuccess()) { // all good } else { // something went wrong error_log($result -> getReason()); // provides raw HTTP response data error_log($result -> getResponse()); }
Вы можете предпринять действия, чтобы повторить попытку или отменить доставку в случае возникновения ошибки.
Срок действия подписки на уведомления также может истечь. Вызовите метод isSubscriptionExpired()
для результирующего класса, чтобы определить, является ли это причиной сбоя. В этом сценарии вы можете удалить подписку из своей базы данных, гарантируя, что вы больше ничего не отправите в мертвую конечную точку.
Пакетные уведомления
Уведомления можно объединять для доставки одним вызовом метода:
$webPush -> queueNotification($subscription, ["msg" => "first"]); $webPush -> queueNotification($subscription, ["msg" => "second"]); foreach ($webPush -> flush() as $i => $result) { echo ("Notification $i was " . ($result -> isSuccess() ? "sent" : "not sent")); }
Это полезно, когда вы знаете, что будете отправлять большое количество уведомлений за короткий промежуток времени. Поставьте все свои полезные нагрузки в очередь и позвольте web-push
доставить их оптимальным образом.
Вы можете ограничить количество уведомлений, отправляемых в одном flush()
, передав методу целое число:
$webPush -> flush(100); // send 100 messages
Значение по умолчанию: 1000
.
Параметры уведомлений
sendOneNotification()
и queueNotification()
принимают следующие параметры в качестве третьего аргумента массива:
TTL
— определяет, как долго платформа уведомлений браузера будет удерживать уведомление, если оно не может быть немедленно передано на устройство пользователя. Если устройство пользователя находится в автономном режиме, платформы по умолчанию пытаются доставить его в течение следующих четырех недель. Если вы отправляете уведомление, которое не будет актуально на следующей неделе, измените TTL соответствующим образом, чтобы пользователь не видел устаревший контент.срочность
— принимает в качестве значенийнормальный
,низкий
илиочень низкий
. Некоторые платформы могут использовать это для настройки частоты доставки уведомлений. Устройства, которые переходят в режим экономии заряда батареи, могут приостанавливать доставку несрочных уведомлений.batchSize
— имеет тот же эффект, что и аргумент дляflush()
, описанный выше.
Вы можете настроить значения параметров по умолчанию, используя второй аргумент конструктора WebPush
:
$webPush = new WebPush(["VAPID" => [...]], ["TTL" => 3600]);
Краткое содержание
Библиотека web-push
упрощает отправку уведомлений Web Push с помощью PHP. Вы получаете уровень абстракции поверх различных браузерных платформ, который поддерживает пакетную обработку, обработку ошибок и все функции Web Push.
Механизм Web Push — это необычная система браузера, поскольку она зависит от удаленных серверных компонентов, которые вы предоставляете сами. Это может сделать его непрозрачным и техническим. На практике создать простой PHP-бэкенд можно быстро и легко; реализация внешнего интерфейса обычно требует больше времени, особенно если вы еще не используете функции сервис-воркера.