Rapporto Web Push SDK#
Общая информация#
Данный комплект для разработки программного обеспечения (далее – SDK) предназначен для отправки сообщений в браузер/на мобильные устройства пользователей через сервисы отправки push-уведомлений. Распространение SDK осуществляется компанией Rapporto в форме SaaS.
Основные возможности библиотеки:
приём и отображение push-сообщений, отправленных в браузер/на мобильное устройство с помощью Push API через соответствующие сервисы, в том числе содержащих расширенный медиаконтент (изображения, кнопки);
сохранение принятых сообщений в локальной базе данных;
отслеживание доставки и открытия push-сообщений с отправкой соответствующих запросов на сервер.
Для внедрения SDK в мобильное приложение необходимо:
Добавить в приложение файл конфигурации
ZGRConfig.json
и скомпилированную в виде npm-пакета библиотеку@rapporto/web-push-sdk
. ФайлZGRConfig.json
следует разместить в папке public.Запросить у Службы технической поддержки данные, необходимые для подключения к репозиторию Nexus компании Rapporto. При настройке доступа к репозиторию рекомендуется по возможности использовать корпоративный прокси-сервер для пакетов (например, Nexus или Artifactory). Это повысит общую безопасность и существенно облегчит работу: данные учетной записи не будут распространяться между разработчиками, а также не потребуется настраивать локальное подключение к репозиторию.
Пример подключения репозитория в непрерывной интеграции (CI) с использованием предварительно настроенных переменных
RAPPORTO_NPM_REGISTRY
,RAPPORTO_NPM_REGISTRY_USERNAME
иRAPPORTO_NPM_REGISTRY_PASSWORD
:npm config set @rapporto:registry "${RAPPORTO_NPM_REGISTRY}" npm config set //${RAPPORTO_NPM_REGISTRY#https://}:_auth=$(echo -n "${RAPPORTO_NPM_REGISTRY_USERNAME}:${RAPPORTO_NPM_REGISTRY_PASSWORD}" | base64)
Пример подключения в локальном терминале с интерактивным вводом логина, пароля и любого адреса email:
npm adduser --auth-type=legacy --scope=@rapporto --registry=${RAPPORTO_NPM_REGISTRY}
Подключение зависимости в package.json:
"dependencies": { "@rapporto/web-push-sdk": "^1.0.0" }
Выполнить инициализацию механизма регистрации подписки на веб push-уведомления, следуя нижеприведенным указаниям.
Системные требования#
Информация о минимальных версиях поддерживаемых браузеров доступна по ссылке.
Быстрый старт#
Подключение библиотеки Web-push-sdk
Основным классом @rapporto/web-push-sdk
является ZGRMessaging
. Порождающий шаблон проектирования – одиночка (singleton).
import { ZGRMessaging } from '@rapporto/web-push-sdk'
const messaging = new ZGRMessaging()
Инициализация приложения для получения веб push-уведомлений#
Этап 1. Запрос у пользователя разрешения на отправку ему веб push-уведомлений
В ZGRMessaging
доступно свойство isPushesGranted
:
const isPushGranted = messaging.isPushesGranted
if(!isPushGranted) {
showAlertAndRequestPermission()
} else {
registerSW()
}
Этап 2. Регистрация файла service-worker.js
После успешной регистрации необходимо вызвать функцию sendNotificationToken()
:
navigator.serviceWorker.register('/service-worker.js')
.then(serviceWorkerRegistration => {
messaging.sendNotificationToken()
})
Этап 3. Получение подписки из центра авторизации и её отправка на сервер
После успешной отправки информации на сервер SDK создаёт в функции sendNotificationToken
событие getSubscription
, в котором передает приложению необходимую для получения подписки публичную часть VAPID-ключа. Полученная подписка отсылается на сервер вызовом функции savePushSubscription()
:
self.addEventListener('getSubscription', getSubscriptionHandler)
async function getSubscriptionHandler(event) {
const key = event.detail
const subs = await subscribeUserToPush(key)
messaging.savePushSubscription(subs)
}
Этап 4. Регистрация пользователя
После ввода логина/номера телефона пользователя необходимо отправить их на сервер, вызвав функцию saveUser(userPhone, userId)
:
messaging.saveUser(userPhone, userId)
Получение и отображение веб push-соообщений#
Получение и отображение веб push-соообщений с отправкой на сервер статуса DELIVERED
(«Доставлено») на примере простых и RICH/SECURE push-сообщений:
1async function broadcastClients(message) {
2 const clients = await self.clients.matchAll();
3 clients.forEach(client => client.postMessage(message));
4}
5
6self.addEventListener('push', onPushEventHandler)
7
8function onPushEventHandler(event) {
9
10 async function onPush(event) {
11 // wake up SW on all pages
12 await self.clients.claim();
13
14 const data = event.data.json();
15 const pushDeliveredMsg = { type: "pushDelivered", body: data };
16
17 // Execute receive push actions
18 const onPushActions = [
19 broadcastClients(pushDeliveredMsg),
20 ];
21
22 // RICH/SECURE push-сообщения
23 if(data.zgrExtraOptions) {
24 const options = JSON.parse(data.zgrExtraOptions)
25
26 if(options !== [] && (options[0] === 'RICH' || options[0] === 'SECURE')) {
27
28 const notificationUpdateDataObj = { type: 'notifUpdate', body: data.zgrNotificationId };
29 onPushActions.push(
30 broadcastClients(notificationUpdateDataObj)
31 )
32 }
33 }
34 // ordinary
35 else {
36 const message = data.zgrNotificationText
37 const title = data.zgrNotificationTitle
38
39 let imageUrl = ''
40 if(data.zgrNotificationContentCategory && data.zgrNotificationContentCategory.toLowerCase() === 'image'){
41 imageUrl = data.zgrNotificationContentUrl
42 }
43
44 const zActions = data.zgrNotificationActions ? this.setActionsArray(data.zgrNotificationActions) : []
45 const notificationOptions = { body: message, icon: imageUrl, data: data, actions: zActions, };
46
47 onPushActions.push(
48 await self.registration.showNotification(title, notificationOptions)
49 )
50 }
51
52 await Promise.all(onPushActions)
53 }
54
55 event.waitUntil(
56 onPush(event)
57 )
58}
59
60// обновление данных в случае RICH/SECURE push-сообщений
61async function onNotificationUpdateEventHandler(event) {
62 const updateData = event.data.object
63 const message = updateData.zgrNotificationText
64 const title = updateData.zgrNotificationTitle
65
66 let imageUrl = ''
67 if(updateData.zgrNotificationContentCategory && updateData.zgrNotificationContentCategory.toLowerCase() === 'image'){
68 imageUrl = updateData.zgrNotificationContentUrl
69 }
70
71 const zActions = updateData.zgrNotificationActions ? this.setActionsArray(updateData.zgrNotificationActions) : []
72
73 self.registration.showNotification(title, {
74 body: message,
75 icon: imageUrl,
76 actions: zActions
77 });
78}
79
80self.addEventListener('message', function(event) {
81 switch (event.data.command) {
82 ...
83 case 'update':
84 return self.onNotificationUpdateEventHandler(event)
85 ...
86}
1if ('serviceWorker' in navigator && 'PushManager' in window) {
2
3 navigator.serviceWorker.addEventListener('message', function(event) {
4 const messageType = event.data.type
5 if(messageType == 'pushDelivered') {
6 pushDeliveredHandler(event)
7 } else if(messageType == 'pushClicked') {
8 pushClickedHandler(event)
9 } else if(messageType == 'notifUpdate') {
10 notifUpdateHandler(event)
11 }
12 })
13}
14
15async function pushDeliveredHandler(event) {
16 const data = event.data
17 messaging.receiveNotification(data)
18}
19
20// в случае RICH/SECURE push-сообщений
21async function notifUpdateHandler(event) {
22 const data = event.data
23 messaging.updateRichNotificationData(data)
24}
25
26self.addEventListener('notificationUpdate', notificationUpdateHandler);
27
28async function notificationUpdateHandler(event) {
29 const data = event.detail
30 const updateObj = { 'command': 'update', 'object': data }
31
32 navigator.serviceWorker.controller.postMessage(updateObj)
33}
Обработка событий#
Обработка событий нажатия на контент уведомления или кнопку с отправкой на сервер статуса OPENED
(«Открыто»):
1self.addEventListener('notificationclick', onNotificationClickEventHandler)
2
3function onNotificationClickEventHandler(event) {
4 const clickedNotification = event.notification
5 const notificationData = event.notification.data;
6
7 const dataObj = { type: 'pushClicked', body: notificationData }
8 broadcastClients(dataObj)
9
10 const action = event.action
11 if(action) {
12
13 self.clients.openWindow(action);
14
15 } else {
16
17 event.waitUntil(
18 // Retrieve a list of the clients of this service worker.
19 self.clients.matchAll().then(function(clientList) {
20 // If there is at least one client, focus it.
21 if (clientList.length > 0) {
22 return clientList[0].focus();
23 }
24
25 // Otherwise, close notification.
26 return clickedNotification.close();
27 }))
28 }
29}
async function pushClickedHandler(event) {
const data = event.data
messaging.clickNotification(data)
}
Профили пользователей#
Получение профиля
messaging.fetchUser()
Функция возвращает экземпляр класса ZGRUser
:
export class ZGRUser {
this.externalUserId = 'some string value' ? ''
this.phoneNumber = 'some string value' ? ''
}
Отправка внешнего идентификатора пользователя и/или номера телефона пользователя в ZGR
messaging.saveUser(userPhone, userId)
Функция возвращает экземпляр класса ZGRUser
.
Обновление номера телефона в профиле
messaging.saveUserPhone(phoneNumber)
Функция возвращает экземпляр класса ZGRUser
.
Персонализация#
Персонализация (привязка externalUserId)
messaging.personalize(externalUserId)
Функция возвращает экземпляр класса ZGRUser
.
Обезличивание (выход)
messaging.depersonalize()
Настройки подписок#
Получение настроек с подписками
messaging.fetchInstallation()
Функция возвращает экземпляр класса ZGRInstallation
:
1export class ZGRInstallation {
2
3 this.isPrimary = true ? false /*< Primary device attribute */
4 this.isPushOsEnabled = true ? false /*< System level permission for push notifications */
5 this.isPushEnabled = true ? false /*< User level permission for push notifications */
6
7 this.subscriptions = [ZGRSubscription, ZGRSubscription, ...] | []
8
9}
10
11export class ZGRSubscription {
12
13 this.identifier = Int value
14 this.type = 'PERMISSION' | 'SETTINGS'
15
16 this.name = 'some string value'
17 this.title = 'some string value'
18 this.desc = 'some string value' ? ''
19 this.value = 'some string value' ? ''
20}
Изменение настроек и параметров подписок
Доступно изменение свойств в классах ZGRInstallation
и ZGRSubscription
. Описание атрибутов приведено в соответствующем блоке.
messaging.saveInstallation(installation)
Сохраняет на сервере переданный в качестве параметра экземпляр класса ZGRInstallation
.
Локальная история уведомлений#
Включение режима хранения локальной истории уведомлений
messaging.isLocalDBEnabled = true
Получение всех сохраненных уведомлений из базы данных
messaging.fetchAllNotifications()
Возвращает массив уведомлений, экземпляров класса ZGRNotification
:
1export class ZGRNotification {
2
3 this.identifier = 'some string value'
4 this.title = 'some string value' ? ''
5 this.text = 'some string value' ? ''
6 this.contentUrl = 'some string value, that can be converted into url' ? ''
7 this.contentCategory = 'html' | 'image' | 'other' | 'none' | ''
8 this.customPayload = some object /*< Additional data for your's own purposes. Array, Dictionary or any other top-level object. */
9 this.actions = [ZGRAction, ZGRAction, ...] | [] /*< Array of actions for buttons in push notification. */
10}
11
12export class ZGRAction {
13
14 this.identifier = 'some string value' ? ''
15 this.title = 'some string value' ? ''
16 this.urlString = 'some string value, that can be converted into url' ? ''
17 this.type = 'default' | 'dismiss' | 'other'
18}
При передаче contentUrl
необходимо заполнить contentCategory
.
Важно
Не все браузеры поддерживают функционал кнопок в push-сообщениях. Актуальная информация доступна в соответствующей документации.
Удаление уведомления из базы данных
messaging.delete(notification)
Удаление массива уведомлений из базы данных
messaging.deleteNotificationsArray(notificationsArray)
Обновление статуса уведомления в базе данных
messaging.updateNotification(notification, status)