Дебри firebase cloud messaging или тонкости работы service worker.

Про азы как получить токен и настроить web-push уведомления я уже описал вот в этой статье, посему об этом здесь речи не будет.

Описание начну с javascript, которого мы подключим к странице. Инициализируем FCM:

Также сразу зададим глобальную переменную для нашего токена:

Запросим у браузера разрешение на показ уведомлений. Дополнительно моя функция запишет учетные данные в IndexedDB, чтобы с ними мог работать сервис воркер (у него нет прямого доступа к кукам). IndexedDB на первый взгляд(особого опыта работы с ней нет) весьма странная штука. Я умудрился заблочить документ транзакцией, что не позволяло даже из браузера удалить созданную базу. Перезапуск не помогал, а вот отключение javascript — вполне. Также у меня были конкретные проблемы при обновлении данных в документе. В общем, чтобы не вдаваться(сейчас) в подробности работы indexedDB наиболее адекватное решение было удалять и создавать заново базу. Т.к. процесс удаления и создания базы происходит только при изменении её версии, то повесил этот параметр к линуксовому времени(epoch). В случае, если indexedDB недоступно — будет произведена запись в firebase напрямую. При работе с базами данных особое внимание уделите завершению транзакций и отладке ошибок. Например, если indexedDB не существует и мы попытаемся его удалить — возникнет ошибка. Важно, чтобы при этом не крашился скрипт. Аналогично при создании базы. Плюс ко всему нельзя совершать две параллельных транзакции с одним документом в firebase. Ну и для записи в firebase не забудьте поставить разброс, а то все клиенты махом в нее ломанутся.

Для получение данных из куков используем функцию:

Запись токенов в MySQL осуществляется со стороны javascript функцией:

Со стороны бэкэнда(php) скриптом:

Также решил добавить функцию отправки уведомлений прямо из javascript (без обращению к бэкэнду):

На этом наш скрипт готов. Можно приступать к написанию service worker. Он должен лежать в корне сайта и иметь имя firebase-messaging-sw.js. Инициализируем приложение и базу данных:

Опишем событие установки service worker, если необходимо. Если нет, можно этот пункт опустить:

Аналогично с событием активации service worker(в смысле можно опустить). Я не опускал, т.к. у меня здесь происходит дополнительная синхронизация с firebase:

Собственна сама функция синхронизации:

Как видно, она обращается к другой функции записи в firebase:

В своей статье о настройках прав и авторизации в firebase я вести не буду, об этом когда-нибудь напишу отдельно. Это того заслуживает.

Событие получение push от сервера firebase cloud messaging. В моем случае они фильтруются по тэгу и вызывают соответствующую функцию. Здесь важно вернуть в промис event.waitUntil промис showNotification, иначе помимо вашего пуша, будет показываться и стандартный «сайт был обновлен в фоновом режиме» или т.п.:

Опишем обработку событий клика по уведомлению, я разделил в action знаком | команду и аргумент. При клике на кнопку — обрабатываю событие, при клике на само уведомление — закрываю его:

Событие закрытия окна уведомлений, если не нужно — можно опустить:

Функция создания стандартного окна уведомления, переданные данные хранятся в data.json().notification и data.json().data:

Теперь создадим нестандартное окно уведомлений, с массивом actions. POST-запрос уходит в бэкэнд по клику на соответствующую кнопку. В данном случае скрипт на php подключается к Asterisk AMI и рвет заданный канал связи:

Или с двумя кнопками массива actions(заберет заявку в ServiceDesk или просто откроет):

Для отправки POST-запроса(можно и GET отправлять) использую объект Request в service worker:

Функция закрытия уведомления по тэгу + закрывает системное уведомление(сайт был обновлен в фоне), если оно есть:

Пара скринов:

Это слайд-шоу требует JavaScript.

Собственно сервер и клиент готовы, теперь осталось реализовать сервер-серверную часть. Разберем на примере работы АТС. Можно слать уведомления напрямую из Asterisk, но у меня была еще цель слать уведомления о звонке в отдел, потому сделал веб-хук на бэкэнде:

Для того, чтобы активировать веб-хук добавим в диалплан Asterisk в любой из моих макросов, исполняемых перед вызовом локального абонента строчку:

Или же вариант целиком макроса, нужно включить в экстеншн:

Очередность выполнения макросов и экстеншнов можно посмотреть, подключившись к консоли Asterisk командой:

.

Ну и собственно скрипт для работы с Asterisk AMI:

Пример использования (видео подтупливает, т.к. снято с удаленного ПК):