Мобильное приложение и SDK
Содержание раздела
- Зачем это бизнесу
- Что такое SDK и для каких платформ
- Как приложение подключается к платформе
- Путь клиента в приложении
- Карта лояльности в приложении
- События приложения и цепочки
- Push-уведомления
- Безопасность и приватность
- Что нужно от команды разработки приложения
- Чем наш SDK отличается от типовых мобильных SDK
- Кто что может
Платформа работает не только с кассой и сайтом, но и с собственным мобильным приложением организации. Клиент устанавливает приложение, входит по номеру телефона и коду из SMS и видит в телефоне всё, что связано с программой лояльности: виртуальную карту со штрихкодом, баланс бонусов, историю покупок, акции, личные промокоды и подарочные карты. Чтобы команде разработки не пришлось писать обмен с платформой с нуля, платформа поставляет готовые библиотеки — SDK (Software Development Kit) для Android, Flutter и iOS.
Глава написана для владельца и маркетолога бизнеса и для руководителя разработки приложения. В ней описано, что даёт приложение, как оно подключается к платформе, что видит клиент и что нужно сделать команде разработки. Подробное техническое руководство разработчики получают вместе с библиотекой.
Зачем это бизнесу#
- Карта всегда с собой. Клиент показывает на кассе штрихкод с экрана телефона, и пластик ему не нужен. Виртуальная карта выпускается автоматически при входе в приложение или одной кнопкой в самом приложении.
- Клиент сам видит свою выгоду. Баланс бонусов, история начислений и списаний, уровень, покупки с полученными скидками — без звонков в поддержку и вопросов на кассе.
- Акции и промокоды на виду. Приложение показывает публичные акции всем, а после входа — и персональные: акции его сегмента, ко дню рождения, личные промокоды из рассылок и цепочек.
- Подарочные карты и заказы в одном месте. Остаток на подарочной карте и чеки с позициями, скидками и бонусами доступны клиенту в любой момент.
- Клиентская база растёт сама. Каждый, кто вошёл по номеру телефона, становится клиентом программы. Если человек уже покупал на кассе, приложение подхватывает его профиль с бонусами и историей — дубля не появляется.
- Поведение в приложении запускает сценарии. Вход в приложение, открытие приложения, просмотр экрана или товара и собственные события приложения запускают цепочки: приветственные бонусы, промокод тем, кто смотрел товар, выпуск карты при первом входе.
- Данные клиента заполняет сам клиент. Имя, дату рождения и пол он указывает в приложении, там же управляет согласиями на рассылки. Всё сразу попадает в карточку клиента.
Что такое SDK и для каких платформ#
SDK — библиотека, которую разработчики встраивают в приложение. Она берёт на себя всё общение с платформой: регистрирует установку приложения, проводит вход клиента по коду из SMS, хранит и продлевает сессию, запрашивает данные клиента и отправляет события приложения — с повторами при плохой связи и с соблюдением лимитов платформы. Разработчикам остаётся сделать экраны.
| Платформа | Язык | Минимальная версия ОС | Сторонние зависимости | Статус |
|---|---|---|---|---|
| Android | Kotlin, работает и из Java | Android 7.0 | Без Firebase, сервисов Google и библиотек AndroidX. Внутри — стандартная сетевая библиотека OkHttp и библиотеки языка Kotlin | Готова, версия 0.2.1 |
| Flutter | Dart, один код для Android и iOS | Android 7.0; iOS — по требованиям Flutter | Без Firebase. Внутри — несколько распространённых пакетов Flutter: сеть, защищённое хранилище, папки приложения | Готова, версия 0.2.1 |
| iOS | Swift; приложение может быть на Swift 5 или 6 | iOS 15; приложению-примеру нужна iOS 16 | Нет. Только системные средства iOS: сессия хранится в Keychain, при сворачивании приложения очередь событий уходит в фоне | Версия 0.2.1 написана вместе с приложением-примером и проверена автотестами; сборка на Mac и проверка на iPhone впереди |
Firebase для push-уведомлений подключает само приложение, а не библиотека, — см. «Push-уведомления».
Что умеют все три библиотеки:
| Возможность | Что делает |
|---|---|
| Устройство | Регистрирует установку приложения, сообщает платформе модель телефона, версии ОС и приложения, язык; выдаёт идентификатор устройства для обращений в поддержку |
| Вход | Запрос кода по SMS, вход, незаметное продление сессии, выход |
| Профиль | Профиль и уровень клиента; изменение имени, фамилии, даты рождения, пола и согласий на рассылки |
| Бонусы | Баланс и постраничная история операций |
| Карты лояльности | Карты клиента с данными для штрихкода, выпуск виртуальной карты |
| Акции и промокоды | Акции для гостя и для клиента, в том числе для конкретной точки продаж; личные промокоды клиента |
| Подарочные карты | Подарочные карты клиента с балансом, статусом и сроком |
| Заказы | История покупок и подробности заказа |
| События | Автоматические «установлено» и «открыто», просмотр экрана и товара, собственные события приложения; очередь событий переживает перезапуск приложения |
| Push-уведомления | Передаёт платформе токен Firebase устройства и разбирает push платформы: ссылку при нажатии, источник (цепочка, кампания, тест, уведомление о бонусах), кампанию и дополнительные данные шаблона |
Библиотеки ведут себя одинаково: одни и те же методы, ошибки и правила, поэтому руководство и поддержка у них общие. Совместимость с платформой проверяется автоматически: каждое изменение API приложения на сервере сверяется с описанием, по которому работают библиотеки.
Как приложение подключается к платформе#
Клиентский ключ#
Приложение работает от имени клиентской интеграции (см. «Интеграции»):
- Администратор организации открывает «Интеграции», нажимает «Создать интеграцию» и выбирает тип «Клиентская».
- В карточке интеграции создаёт API-ключ. Ключ клиентской интеграции начинается с
pk_live_. В форме уже выбран «Полный доступ («*»)» — его и оставьте: платформа заменит его набором прав приложения. - Передаёт разработчикам ключ и адрес платформы, например
https://loyalty.example.com. Если API опубликовано за прокси с префиксом пути, адрес передаётся вместе с префиксом:https://example.com/api.
Ключ вшивается в сборку приложения: разработчики указывают его при запуске SDK, с сервера он не подгружается. Извлечь ключ из опубликованного приложения может любой желающий, поэтому платформа и выдаёт приложению особый, ограниченный ключ.
Права ключа#
Клиентский ключ получает только права приложения — 12 штук. Кассовых прав в этом наборе нет, и выдать их клиентскому ключу нельзя.
| Право в форме ключа | Код | Что позволяет приложению |
|---|---|---|
| Устройства: регистрация | devices:write |
Зарегистрировать установку приложения и обновлять сведения об устройстве |
| Вход по SMS-коду | auth:write |
Запросить код, войти, продлить сессию, выйти |
| Профиль: чтение | profile:read |
Показать профиль, уровень, баланс и согласия клиента |
| Профиль: изменение | profile:write |
Изменить имя, фамилию, дату рождения, пол и согласия на рассылки |
| Бонусы: баланс и история | bonuses:read |
Показать баланс и историю бонусных операций |
| Карты лояльности: чтение | loyalty-cards:read |
Показать карты клиента со штрихкодом и программы, открытые для самовыпуска |
| Карты лояльности: выпуск виртуальной | loyalty-cards:write |
Выпустить виртуальную карту в программе, где разрешён самовыпуск |
| Акции: чтение | promotions:read |
Показать акции: гостю — публичные, клиенту — ещё и персональные |
| Личные промокоды | promo-codes:read |
Показать личные промокоды клиента по действующим акциям |
| Подарочные карты | gift-cards:read |
Показать подарочные карты клиента |
| История заказов | orders:read |
Показать покупки клиента и подробности заказа |
| События приложения | events:write |
Отправлять события приложения |
С любыми правами клиентский ключ не может: проводить и возвращать заказы, начислять и списывать бонусы, искать клиентов по телефону, читать данные других клиентов. Каждый клиент видит только свои данные и только после входа по коду из SMS. Серверный ключ (sk_live_) в приложении не заработает: SDK откажется запускаться с ним, а платформа отклонит его запросы к API приложения.
Сайт: «Разрешённые домены»#
Если ключ работает на сайте в браузере — например, во Flutter-приложении, собранном для веба, или в приложении-оболочке над сайтом, — адрес сайта нужно добавить в «Разрешённые домены» интеграции. Запрос с сайта, которого нет в списке, платформа отклонит: так чужой сайт не сможет пользоваться вашим ключом. Нативным приложениям Android и iOS домены не нужны. Как записывать адреса, описано в разделе «Интеграции».
Лимиты частоты#
Платформа ограничивает частоту запросов приложения. Так ключ, извлечённый из приложения, нельзя использовать для перебора кодов или для рассылки SMS за ваш счёт.
| Что ограничено | Предел |
|---|---|
| Запросы одного устройства | 120 в минуту |
| Запросы с одного IP-адреса | 3000 в минуту — с запасом для мобильных операторов, у которых много абонентов выходят в интернет через один адрес |
| Регистрация устройства и вход с одного IP-адреса | 30 в минуту |
| Пакеты событий с одного устройства | 20 в минуту, до 50 событий в пакете |
| SMS-коды на один телефон | 3 за 10 минут и 10 за сутки |
| SMS-коды с одного устройства | 5 за 10 минут и 20 за сутки |
SDK соблюдает лимиты сам: события собирает в пакеты, а фоновые запросы — регистрацию устройства и отправку событий — при ответе «слишком часто» повторяет после паузы, которую назвала платформа. Если клиент слишком часто запрашивает код, приложение показывает, через сколько можно повторить. Повторную отправку кода приложение предлагает не раньше чем через 60 секунд.
Журнал запросов#
Запросы приложения видны в разделе «Журнал запросов». В фильтре «Авторизация» выберите «Приложение» — запросы клиента, который вошёл, — или «Приложение (устройство)» — запросы до входа. В колонке «Субъект» видно, кто обращался: «Приложение / Иван Петров» или «Приложение / устройство Pixel 8». Тела запросов входа (телефон, код, токены) в журнале скрыты целиком. Сообщая об ошибке, разработчики приложения называют Correlation ID из ответа платформы — по нему запрос находится однозначно.
Смена ключа#
Ключ хранится в самом приложении, поэтому его смена — это выпуск новой версии приложения:
- Отзыв ключа или отключение интеграции сразу останавливает все установленные копии приложения. Клиенты будут видеть ошибку, пока не обновят приложение до версии с новым ключом. Отключайте интеграцию приложения только при утечке или инциденте.
- Плановая смена ключа проходит в три шага: выпустите второй ключ в той же интеграции, опубликуйте версию приложения с новым ключом и только после того, как клиенты обновятся, отзовите старый ключ.
- При первом запуске версии с новым ключом SDK заново регистрирует устройство, и клиенту нужно один раз снова войти по коду из SMS. Бонусы, карты и история покупок при этом не меняются.
Путь клиента в приложении#
Установка и первый запуск. SDK регистрирует установку как устройство, и платформа заводит для него анонимный профиль — без телефона и email. Он не виден в списке клиентов, в выгрузках и рассылках. Уходит событие «Приложение установлено», на которое можно настроить цепочку.
До входа. Гость видит публичные акции. Его события — открытие приложения, просмотр экранов и товаров — собираются в анонимном профиле.
Вход по телефону. Клиент вводит номер и получает SMS с кодом из 6 цифр. Код действует 5 минут, на ввод даётся 5 попыток, и подходит он только на том устройстве, где его запросили. SMS уходит через аккаунт организации у SMS-провайдера (см. «Подключение SMS») и только на номера, которые он принимает (у Eskiz.uz — номера Узбекистана); коды входа уходят раньше рассылок. Текст SMS задаёт системный шаблон
system.app-login-codeв разделе «Шаблоны». Стартовый текст задаёт платформа: шаблон появляется сам при первом запросе кода — копией текста платформы на языке организации, с целью кода и названием организации, как требует модерация Eskiz, например:Код для входа в приложение {{tenant.name}}: {{auth.code}}. Никому не сообщайте.(узбекский —{{tenant.name}} ilovasiga kirish uchun kod: {{auth.code}}. Uni hech kimga bermang., английский —Login code for the {{tenant.name}} app: {{auth.code}}. Do not share it.). Вместо{{tenant.name}}клиент видит название организации (до 30 символов), вместо{{auth.code}}— код. Дальше это шаблон организации: текст можно изменить, шаблон — даже переименовать, платформа находит его не по названию; изменённый текст платформа не перепишет. Шаблон с прежним текстом по умолчанию — «Код для входа: …» или «Acme: код для входа …» — получает текст платформы сам, если организация его не меняла.Название организации — часть текста SMS. Если организацию переименовали, клиенты получают код с новым названием (в течение минуты), и у провайдера, который модерирует тексты, новый текст нужно утвердить заново — до этого коды не приходят. Изменённый текст кода входа тоже утверждается заново — в том числе когда администратор платформы обновляет текст по умолчанию у организаций, которые свою копию не меняли.
Перед запуском приложения: подключите SMS в «Каналах» и, если провайдер модерирует тексты, утвердите у него текст кода входа с настоящим названием организации (у Eskiz — см. «Eskiz.uz: модерация текстов») — неутверждённый текст провайдер не отправит, и клиенты не смогут войти. Когда шаблон
system.app-login-codeуже есть, готовый текст показывает его блок «Текст для модерации»; до первого запроса кода шаблона нет — возьмите текст выше на языке организации и подставьте название организации вместо{{tenant.name}}. Если SMS организации не подключены или провайдер отклонил настройки, код не выпускается: приложение сразу получает ошибку «доставка SMS недоступна» (кодAPP_AUTH_SMS_UNAVAILABLEв SDK) и может показать её клиенту, а не ждать SMS, которое не придёт. В форме ключа клиентской интеграции об этом заранее предупреждает «SMS не подключены — вход в приложение по SMS-коду не работает» (см. «Интеграции»).Объединение с историей. Если этот телефон уже есть у клиента — он покупал на кассе или на сайте, — анонимный профиль объединяется с ним так же, как объединяются дубли, и устройство переходит к клиенту с его бонусами, картами и покупками. В журнале объединений появляется запись с инициатором «Вход в приложении». Если телефона в базе нет, анонимный профиль сам становится клиентом: получает телефон, согласия по умолчанию и бонусный счёт, а цепочки получают событие «Клиент создан» с источником «Мобильное приложение». При любом входе — и нового клиента, и того, кто уже был в базе, — цепочки получают событие «Вход в приложении»; первый ли это вход, подсказывает поле условия «Первый вход в приложение».
Сессия. Клиент остаётся в приложении, пока пользуется им хотя бы раз в 90 дней: SDK продлевает сессию сам.
Выход. После выхода устройство снова работает как гость, с новым анонимным профилем.
После входа клиенту доступны разделы:
| Раздел приложения | Что показывает |
|---|---|
| Профиль | Телефон, email, имя, фамилию, дату рождения, пол, уровень и баланс бонусов. Имя, фамилию и пол клиент меняет сам. Дату рождения он указывает один раз: от неё зависят акции ко дню рождения, поэтому исправить её может только оператор. Телефон и email в приложении не меняются |
| Согласия | Переключатели по каналам рассылок — те же согласия, что на вкладке «Подписки» карточки клиента |
| Бонусы | Баланс, замороженные бонусы, сколько всего начислено, списано и сгорело; история операций постранично |
| Карты лояльности | Карты клиента со статусом, номером и штрихкодом; лимит карт на клиента |
| Акции | Публичные и персональные акции клиента; список можно сузить до конкретной точки продаж |
| Промокоды | Личные промокоды клиента по действующим акциям со сроком действия |
| Подарочные карты | Последние 4 символа кода, баланс, валюта, статус и срок |
| Заказы | История покупок: точка, суммы, скидки, начисленные и списанные бонусы, позиции, сработавшие акции и подарки |
Несколько устройств и выход везде#
У клиента может быть несколько устройств, например телефон и планшет, — на каждом своя сессия. На одном устройстве одновременно вошёл только один человек. Если на телефоне войдёт другой клиент, прежняя сессия этого устройства завершится, а профили двух людей не объединяются.
Все устройства клиента видны в карточке клиента, в блоке «Приложение»: модель, версии ОС и приложения, вошёл ли клиент, время последней активности и состояние push. Кнопка «Разлогинить везде» завершает все сессии клиента в приложении — например, если он потерял телефон. При следующем обращении к платформе приложение на каждом устройстве выйдет из аккаунта, и клиенту придётся снова войти по коду из SMS. Устройства отвязываются от клиента и пропадают из карточки, push клиенту на них больше не уходят, а после нового входа возобновятся сами. Бонусы, карты, заказы и данные профиля при этом не меняются.
Карта лояльности в приложении#
Приложение показывает все карты клиента — пластиковые, виртуальные и внешние — со статусом и номером. Карта, которую выдал оператор в админке, касса или внешняя система, сразу видна и в приложении. Новую виртуальную карту клиент получает одним из трёх способов:
| Способ | Как настроить | Кому и когда |
|---|---|---|
| Цепочка на событие «Вход в приложении» — основной способ | Триггер «Вход в приложении» → действие «Выпустить виртуальную карту» → «Конец». Чтобы выдавать карту только при первом входе, перед действием ставится условие «Первый вход в приложение» равно «Да». Готовый пример — в разделе «Цепочки» → «Карта при входе в приложение» | Любому клиенту, через секунду-другую после входа: и новому, и тому, кто раньше покупал на кассе и впервые вошёл по своему телефону. Клиенты, входившие до публикации цепочки, получат карту при следующем входе |
| Цепочка на событие «Клиент создан» | Триггер «Клиент создан» → условие «Источник создания клиента» равно «Мобильное приложение» → действие «Выпустить виртуальную карту» | Только новому клиенту, через секунду-другую после первого входа. Клиент, который уже был в базе (например, покупал на кассе), так карту не получит: нового клиента не появилось |
| Самовыпуск | Флажок программы карт «Клиент может выпустить карту сам из приложения», см. «Самовыпуск в мобильном приложении» | Клиент сам нажимает «Выпустить карту» в приложении. Кнопка видна, если у клиента нет действующей карты этой программы и не исчерпан лимит карт на клиента |
Цепочка не выпускает вторую карту той же программы, если действующая карта у клиента уже есть: повторный запуск этот шаг пропускает. Поэтому две цепочки — на «Вход в приложении» и на «Клиент создан» — не выдадут новому клиенту две карты, но достаточно одной, на «Вход в приложении». Заблокированную карту цепочка без условия «Первый вход в приложение» при следующем входе заменит новой. Анонимному профилю (до входа) карта не выпускается. В истории карты инициатор — «Система» у карты из цепочки и «Клиент (приложение)» у карты, выпущенной самим клиентом.
Карта из цепочки появляется не в момент входа, а через секунду-другую. Поэтому после входа приложение должно перечитать список карт клиента, а не ждать карту в ответе на вход. Отдельно сообщать о входе приложению не нужно: событие «Вход в приложении» платформа формирует сама, когда проверяет код из SMS.
Штрихкод на экране#
Платформа передаёт приложению номер карты и вид кода, а рисует код само приложение. Вид кода задаётся в программе карт полем «Символика»: Code 128, EAN-13 или QR-код (см. «Программы карт»). Приложение получает вид кода вместе со списком карт, поэтому после смены символики в программе новый код появится без обновления приложения. В штрихкоде только номер карты — ни имени, ни телефона клиента в нём нет.
События приложения и цепочки#
| Что происходит в приложении | Событие в цепочках | Кто отправляет |
|---|---|---|
| Первый запуск приложения с SDK | «Приложение установлено» | SDK, автоматически |
| Вход по коду из SMS | «Вход в приложении» — в группе «Покупки и клиенты», при каждом входе | Сервер платформы, после проверки кода |
| Запуск приложения или возврат к нему | «Приложение открыто» | SDK, автоматически |
| Показ экрана | «Просмотр экрана в приложении» | Приложение, с именем экрана |
| Показ карточки товара | «Просмотр товара в приложении» | Приложение, с артикулом товара |
| Важное для бизнеса действие | «Операция приложения» с именем, например purchase_intent |
Приложение, с именем операции |
- Имена экранов и операций разработчики согласуют с маркетологом: именно эти имена маркетолог выбирает в цепочке. Имя — латиница, цифры и знаки
_ . : -, до 64 символов. - Доставка. События копятся в очереди на телефоне и уходят пакетами — примерно раз в 10 секунд и сразу, когда приложение уходит в фон. Без связи они ждут её и не теряются при перезапуске приложения. Если пакет отправился дважды, повтор платформа отбрасывает.
- Запуск цепочки. В триггере «По событию» и в узле «Ожидание» в варианте «до события» есть группа событий «Приложение» (см. «Цепочки» → «События мобильного приложения»). События приложения получают только опубликованные цепочки; только что опубликованная цепочка начинает их получать в течение минуты.
- До входа событие приходит от анонимного профиля. У него нет телефона и email, поэтому письма и SMS из цепочки ему не уйдут. Для сценариев с сообщениями выбирайте события, которые случаются после входа.
- Каждое событие запускает цепочку заново. Если цепочка начисляет бонусы или выдаёт промокод за событие приложения, ограничьте повторы условием — например, проверкой сегмента «Уже получил награду», в который цепочка добавляет клиента.
- «Вход в приложении» формирует сервер. Приложение не может его подделать, и оно всегда приходит от клиента, а не от анонимного профиля. Приветственную награду надёжнее давать на это событие с условием «Первый вход в приложение» равно «Да» — тогда повторные входы её не повторят.
- Внешние системы — CRM, аналитика — получают события приложения через вебхук «Событие мобильного приложения» (см. «Вебхуки»). Вход в приложение по вебхуку не передаётся.
Примеры сценариев:
| Сценарий | Как собрать |
|---|---|
| Приветствие при первом входе в приложение | «Вход в приложении» → условие «Первый вход в приложение» равно «Да» → «Выпустить виртуальную карту» → «Начислить бонусы». Сработает и для нового клиента, и для покупателя кассы, впервые вошедшего в приложение |
| Интерес к товару | «Просмотр товара в приложении» → условие «не состоит в сегменте „Промокод за просмотр“» → «Ожидание» 1 день → «Выдать промокод» → «Добавить в сегмент „Промокод за просмотр“». Промокод клиент увидит в приложении, в разделе промокодов, пока действует акция |
Что видно в админке: в карточке клиента — блок «Приложение» с устройствами, временем последней активности и состоянием push, вкладка «Сообщения» с отправленными push; у анонимного профиля — метка «Аноним приложения»; объединение при входе — во вкладке «Объединения» и в журнале объединений; запуски цепочек по событиям приложения — на вкладке «Выполнения» цепочки, со ссылкой на клиента.
Push-уведомления#
Платформа отправляет push в приложение через Firebase Cloud Messaging — и на Android, и на iPhone. Push приходят из четырёх мест: узел «Отправить сообщение» в цепочках, кампании по каналу Push, уведомления о бонусах («Начислено бонусов: 150. Баланс: 1 250») и тестовая отправка из карточки клиента. Текст, картинку, ссылку и звук задаёт push-шаблон.
SDK с версии 0.2.1 знают все четыре источника, в том числе «уведомление о бонусах», а в истории бонусов — источник «цепочка» у начислений и списаний действием цепочки. Приложения, собранные на SDK 0.2.0, показывают push уведомлений о бонусах как обычно, но источник у них — «неизвестный», как и у операций цепочек в истории бонусов. Если такое приложение выбирает экран по источнику push, а не по ссылке при нажатии, обновите в нём SDK до 0.2.1 или задайте ссылку в шаблонах уведомлений.
Что нужно с каждой стороны#
| Кто | Что делает |
|---|---|
| Администратор организации | Загружает в разделе «Каналы» ключ сервисного аккаунта того же проекта Firebase, к которому подключено приложение |
| Команда приложения | Подключает Firebase Messaging в приложение: Android — файл google-services.json; iPhone — GoogleService-Info.plist, возможности Push Notifications и Background Modes → Remote notifications и APNs-ключ Apple, загруженный в Firebase; Flutter — пакеты firebase_core и firebase_messaging. Просит у клиента разрешение на уведомления (Android 13 и новее, iPhone) и согласие на push-рассылки — его сохраняет в профиле клиента через SDK. При каждом запуске и при обновлении токена передаёт токен Firebase в SDK. Показывает уведомления, пришедшие, пока приложение открыто, и открывает экран по ссылке при нажатии. Картинку в уведомлении на iPhone показывает расширение уведомлений приложения (Notification Service Extension) |
| SDK | Отправляет токен платформе только при изменении и сам повторяет отправку при плохой связи; хранит токен и после выхода клиента. Разбирает push платформы: идентификатор сообщения, источник, ссылку при нажатии, кампанию и дополнительные данные шаблона; чужие push (от других сервисов приложения) пропускает. Firebase SDK не содержит и разрешение на уведомления не запрашивает |
Без согласия клиента на канал Push платформа push не отправляет: системное разрешение на уведомления согласием на рассылки не считается.
Ссылка при нажатии#
Ссылку задаёт поле «Ссылка при нажатии» push-шаблона — адрес со схемой приложения, например acme://bonuses или acme://promo/{{promo.code}}. Какой экран открыть, решает приложение: SDK отдаёт ему ссылку из нажатого уведомления. Разработчики проверяют схему и адрес ссылки перед переходом. Домены с кириллицей в ссылках шаблонов записывайте в виде punycode (xn--…): библиотеки не переводят их сами, и на разных платформах такой адрес выглядит по-разному. Ссылки и дополнительные данные шаблона согласуйте с разработчиками так же, как имена событий.
Смена клиента на устройстве#
Токен принадлежит установке приложения, а не клиенту. После выхода устройство работает как гость, и push прежнего клиента на него не уходят; после входа другого клиента приходят уже его push. То же после «Разлогинить везде» в карточке клиента. В приложении для этого ничего делать не нужно.
Как проверить#
- В карточке тестового клиента, в блоке «Приложение», у устройства метка «Push подключены» (если «Нет токена» — приложение не передало токен; «Push не поддерживаются» — передан токен Apple вместо токена Firebase).
- У клиента включено согласие на Push (вкладка «Подписки» или переключатель в приложении).
- «Отправить тестовый push» в блоке «Приложение» — уведомление приходит на телефон, а в окне виден результат по каждому устройству (см. «Клиенты» → «Тестовый push»).
- Нажатие на уведомление открывает экран по ссылке из шаблона.
Приложения-примеры Firebase не содержат и настоящие push не получают: токен в них вводится вручную, а кнопка «Имитировать push» открывает раздел примера так же, как нажатие на уведомление со ссылкой loyaltysample://cards.
Безопасность и приватность#
- Ключ приложения ограничен. Клиентский ключ даёт только 12 прав приложения. Кассовые операции с ним невозможны, даже если ключ извлекут из приложения.
- Клиент видит только свои данные. Платформа определяет клиента по его сессии, а не по данным запроса, поэтому подставить чужой идентификатор нельзя.
- Сессия с коротким сроком и сменой токенов. Токен доступа действует 1 час. Токен продления меняется при каждом продлении, и повторное использование старого токена платформа считает кражей и завершает сессию.
- Привязка к устройству. Код входа, запрошенный на одном телефоне, не подойдёт на другом, а токены сессии работают только вместе с идентификатором устройства, для которого выданы.
- Коды из SMS не хранятся в открытом виде. Платформа хранит только криптографический отпечаток кода, в журнале сообщений вместо кода — маска. Ответ на запрос кода одинаков для известных и новых номеров, поэтому перебором номеров нельзя узнать, кто зарегистрирован.
- Секреты не попадают в журнал запросов. Телефон, код и токены входа скрыты целиком, push-токены устройств — тоже. В админке push-токен не показывается — только состояние push устройства.
- Ключ Firebase организации хранится зашифрованным. После загрузки в «Каналах» его содержимое не показывается никому — только проект, сервисный аккаунт и последние символы идентификатора ключа.
- На телефоне данные защищены. Токены хранятся зашифрованными — в защищённом хранилище Android и в Keychain на iPhone — и не переносятся резервной копией на другой телефон. SDK не пишет в логи ключ, токены, телефоны и коды.
- Сведений об устройстве — минимум. Платформа получает платформу, модель, версии ОС и приложения, язык и, если приложение подключило уведомления, push-токен. Рекламные идентификаторы, геолокацию и идентификаторы оборудования SDK не собирает.
- Старые данные удаляются. Анонимный профиль, с устройств которого 90 дней не было обращений, удаляется автоматически; события приложения хранятся 180 дней.
- Выход везде. Оператор завершает все сессии клиента кнопкой «Разлогинить везде» в карточке клиента.
Что нужно от команды разработки приложения#
Порядок интеграции#
- Ключ и адрес. Администратор организации создаёт клиентскую интеграцию и ключ и передаёт разработчикам ключ
pk_live_…и адрес платформы. Для разработки удобна тестовая организация с демо-данными (см. «Настройки» → «Демо-данные»): в ней есть клиенты, акции и программы карт, а клиентская интеграция создаётся так же. - Подключение SDK. Android — зависимость Gradle
dev.relen.loyalty:loyalty-sdk, Flutter — пакетloyalty_sdk, iOS — пакет SwiftLoyaltySDK. Библиотека поставляется вместе с руководством для разработчиков. - Запуск SDK. При старте приложения SDK получает адрес платформы и ключ. С этого момента работают регистрация устройства и события «Приложение установлено» и «Приложение открыто».
- Вход. Экраны телефона и кода, показ состояния «гость» или «клиент», возврат на экран входа, когда сессия завершена.
- Экраны лояльности. Карта со штрихкодом, баланс и история бонусов, акции и промокоды, подарочные карты, история заказов, профиль и согласия — в том объёме, который нужен бизнесу.
- События. Список экранов, товаров и операций согласуется с маркетологом под задуманные цепочки.
- Push. Firebase Messaging в приложении, разрешение на уведомления и согласие на push, передача токена в SDK, переход по ссылке при нажатии (см. «Push-уведомления»); администратор организации подключает тот же проект Firebase в «Каналах».
- Проверка. Устройство тестового клиента — в блоке «Приложение» его карточки с меткой «Push подключены», запросы — в «Журнале запросов» с фильтром «Приложение», тестовая цепочка на событие приложения запускается, тестовый push доходит до телефона.
- Публикация. Перед выпуском в магазины приложений ключ тестовой организации заменяется ключом рабочей, а настройки Firebase приложения — настройками рабочего проекта Firebase, если для разработки был отдельный.
Объём работы#
Библиотека берёт на себя сеть, устройство, вход, токены и очередь событий, поэтому команде приложения остаётся только нарисовать экраны и вызвать готовые методы. Приложение-пример показывает каждый вызов целиком, его код можно брать за основу. Flutter-версия закрывает Android и iOS одним кодом. Объём зависит от дизайна и того, сколько разделов нужно бизнесу: от одной карты с балансом до полного набора с заказами, акциями и подарочными картами.
Приложения-примеры#
Вместе с каждой библиотекой поставляется приложение-пример в фирменном стиле платформы. Оно вызывает все функции библиотеки и показывает результат каждого вызова и подробности каждой ошибки: вход по коду, профиль и согласия, баланс и историю бонусов, карты и выпуск виртуальной карты, акции и промокоды, подарочные карты, заказы, события и сведения об устройстве. Пример запускается на телефоне с вашим ключом и адресом платформы. iOS-пример ставится на iPhone с компьютера Mac через Xcode: для показа хватает бесплатного Apple ID, но такая установка действует 7 дней, потом её повторяют. Это самый быстрый способ показать возможности приложения до начала разработки и проверить настройки организации: программы карт, цепочки, акции.
Чем наш SDK отличается от типовых мобильных SDK#
Типовые мобильные SDK CDP-платформ — это транспорт: они регистрируют устройство и доставляют события и уведомления, а данные лояльности приложение получает через «операции», которые интегратор описывает и настраивает сам. Наш SDK сделан под программу лояльности:
- Логика лояльности уже внутри. Баланс, история бонусов, карты, акции, личные промокоды, подарочные карты, заказы и профиль — готовые методы с готовыми данными. Описывать запросы и разбирать ответы не нужно.
- Карта, баланс и акции из коробки. Вход по коду из SMS, карты со штрихкодом, баланс и персональные акции работают сразу после подключения SDK: описывать «операции» на стороне платформы не нужно.
- Без тяжёлых зависимостей. Android-библиотека обходится без Firebase, сервисов Google и AndroidX, Flutter-пакет — без Firebase, iOS-библиотека не использует сторонних библиотек вовсе. Приложение не получает лишних конфликтов версий и лишнего веса.
- События сразу в цепочки. Событие приложения запускает цепочку той же платформы, где живут бонусы, карты, промокоды и сегменты: выпуск карты, начисление бонусов и выдача промокода собираются в одном конструкторе.
- Свои приложения-примеры. Каждая функция показана в работающем приложении, которое можно запустить со своим ключом.
- Совместимость под контролем. Каждое изменение API приложения на сервере автоматически сверяется с описанием, по которому работают библиотеки.
Кто что может#
| Задача | Кто выполняет |
|---|---|
| Создать клиентскую интеграцию и ключ, задать «Разрешённые домены» | Администратор организации |
| Смотреть запросы приложения в «Журнале запросов» | Администратор организации |
| Собирать цепочки на события приложения и выпуск карты | Администратор платформы, Администратор организации, Маркетолог |
| Включить самовыпуск в программе карт | Администратор платформы, Администратор организации, Маркетолог |
| Изменить текст SMS с кодом входа своей организации | Администратор платформы, Администратор организации, Маркетолог |
| Изменить стартовый текст SMS с кодом входа, который получают организации | Администратор платформы |
| Подключить SMS через провайдера (раздел «Каналы») | Администратор организации |
| Подписать внешнюю систему на события приложения | Администратор платформы, Администратор организации |
| Видеть устройства клиента в карточке | Администратор платформы, Администратор организации, Оператор, Поддержка, Наблюдатель |
| Нажать «Разлогинить везде» | Администратор платформы, Администратор организации, Оператор |
| Подключить Firebase для push (раздел «Каналы») | Администратор организации |
| Отправить тестовый push клиенту | Администратор платформы, Администратор организации |
| Готовить push-шаблоны и push-кампании | Администратор платформы, Администратор организации, Маркетолог |