Rapporto Web Push SDK#

Общая информация#

Данный комплект для разработки программного обеспечения (далее – SDK) предназначен для отправки сообщений в браузер/на мобильные устройства пользователей через сервисы отправки push-уведомлений. Распространение SDK осуществляется компанией Rapporto в форме SaaS.

Основные возможности библиотеки:

  • приём и отображение push-сообщений, отправленных в браузер/на мобильное устройство с помощью Push API через соответствующие сервисы, в том числе содержащих расширенный медиаконтент (изображения, кнопки);

  • сохранение принятых сообщений в локальной базе данных;

  • отслеживание доставки и открытия push-сообщений с отправкой соответствующих запросов на сервер.

Для внедрения SDK в мобильное приложение необходимо:

  1. Добавить в приложение файл конфигурации ZGRConfig.json и скомпилированную в виде npm-пакета библиотеку @rapporto/web-push-sdk. Файл ZGRConfig.json следует разместить в папке public.

  2. Запросить у Службы технической поддержки данные, необходимые для подключения к репозиторию 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"
       }
    
  3. Выполнить инициализацию механизма регистрации подписки на веб 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-сообщений:

service-worker.js#
 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}
main.jsx#
 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 («Открыто»):

service-worker.js#
 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}
main.jsx#
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)