В данном разделе описано как работает подсистема импорта данных из внешних провайдеров через CASHOFF API. Описание содержит следующие составляющие:
- добавление связи CASHOFF с провайдером через профиль
- авторизация профиля в провайдере
- процесс импорта данных
- получение загруженных данных из CASHOFF
Цикл работы с профилями при импорте данных
Глобально цикл состоит из следующих шагов:
- Добавление нового профиля. При добавлении указывается пользователь и провайдер.
- Запуск обновления данных. В рамках обновления данных из ЛК провайдера данные будут импортированы в CASHOFF.
- Авторизация в ЛК провайдера. Это первый, обязательный, этап обновления. На этом шаге либо клиенту нужно будет предоставить данные для авторизации (логин/пароль/смс и т.п.), либо CASHOFF использует сохраненные у него данные авторизации/сессию для восстановления подключения к провайдеру.
- Импорт данных. Выполняется после успешной авторизации
CASHOFF позволяет выполнить шаги 1-3 двумя разными способами: полностью через серверное API или через готовые визуальные модули.
После успешного добавления и первичного импорта данных можно повторно обновлять профиль выполняя шаги 2-4.
Сам процесс авторизации и импорта данных происходит асинхронно: соответствующие API методы только запускают выполнение действия, взаимодействие с провайдером же происходит в фоновом режиме.
Результат выполнения действий отслеживается через статус профиля (поле status), а прогресс через поля update_current_stage и update_progress. Основной способ отслеживания - нотификаций, в частности событие profile.updated, которое описано ниже в разделе "Уведомление о изменении профиля".
Загруженные на шаге 4 данные доступны на постоянной основе и могут в любое время получены через API. К примеру для списка продуктов это запрос GET /accounts, а операций - GET /transactions. Запрашивать можно и в момент импорта, однако данные в таком случае будут только частично обновлены.
Запуск импорта через серверное API
При таком способе визуальные формы для клиента необходимо реализовывать самостоятельно в приложении, а все шаги импорта выполняется через различные API методы. Данный раздел преимущественно посвящен именно этому способу.
Запуск импорта через визуальные модули
CASHOFF предоставляет готовый визуальный модуль profile-update, через который клиент может выбрать провайдера для подключения, авторизоваться и наблюдать процесс импорта данных. Приложению остается только забрать данные (шаг 4). Подробнее о использовании визуальных модулей написано в разделе Встраиваемые UI модули.
Данный модуль последовательно выполняет шаги 1-3, но при этом начать можно с любого шага. Например можно самостоятельно реализовать в приложении выбор провайдера, а визуальный модуль использовать только для процесса обновления и авторизации.
Так же его можно использовать исключительно для авторизации: показывать модуль при статусе профиля updating. Такой подход позволяет избавить приложение от необходимости работать с авторизационными данными клиента от провайдеров.
Данный модуль можно использовать как образец реализации интерфейса подключения и обновления профиля.
В итоге приложению остается только отслеживать завершение обновления профиля (серверными нотификациями или с помощью сообщений на клиенте) и получить данные из CASHOFF. Повторные обновления можно производить так же при помощью этого модуля.
Добавление нового профиля
Добавление профиля происходит запросом POST /profiles/add, в котором нужно указать идентификатор провайдера:
{ "provider_key": "sber" }
Запрос в таком виде только создаст новый профиль, но не выполнит шаги 2 и 3.
Эти действия выполняются отдельными запросами, POST /profiles/{profile_id}/update и POST /profiles/{profile_id}/session/auth соответственно, но их можно выполнить и разом при создании:
{ "provider_key": "sber", "start_update": true, "auth_data": { "login": "VApTr56Ui9", "password": "8Apq0Ohy1" } }
В данном запросе атрибут start_update запустит обновление, а auth_data предоставит данные для первого шага авторизации. Пример ответа:
{ "profile": { "id": 1291399, "user_id": 1330891, "provider": { "id": 72, "key": "sber", "name": "Сбербанк", "type": "bank", "logo": "https://cashoff.ru/static/build/cashoff/v-7c7f6a8a477c1b3e3d20a0ca10147158/img/logo/fi/sber_36.svg" }, "session": { "key": "ac1db988825748b595526852e02c2712", "status": "ok" }, "status": "updating", "created": "2019-03-28T08:52:23Z", "changed": "2019-03-28T08:52:23Z" }, "update_status": "ok" }
Переданные при создании профиля данные авторизации (auth_data) используются только если одновременно запускается обновление (start_update). Если обновление не запускается, то будет сохранен только логин (для контроля уникальности профиля у пользователя), а пароль не перенесется к моменту следующего запуска обновления.
CASHOFF не позволяет одному и тому же пользователю добавлять несколько одинаковых профилей (профили с одинаковым провайдером и логином). При повторном добавлении будет возвращена ошибка profile_exists, а в атрибуте extra.existing_profile_id можно будет найти идентификатор существующего дублирующего профиля. Подобная же ошибка будет при запросе POST /profiles/{profile_id}/session/auth, если изначально запрос создания профиля не включал логин, а тут он пришел и нашелся дублирующий профиль.
Запуск обновления профиля
Обновление запускается с помощью запроса POST /profiles/{profile_id}/update. Ответ придет с полем status, в котором будет указано что обновление либо успешно запущено (ok), либо код причины невозможности запуска.
Обновление состоит из двух ключевых фаз:
- Авторизация. Сначала идет попытка подключения по сохраненным данным (есть еще активная сессия). Если это не получается, то запускается сам процесс авторизации
- Импорт данных. Данная фаза возможна только после успешной авторизации.
Авторизация в ЛК провайдера
В процессе авторизации CASHOFF с помощью предоставляемых клиентом данных пытается авторизоваться в ЛК провайдера. В авторизации есть ряд ключевых моментов, которые нужно учитывать:
- Последовательность шагов авторизации не фиксирована: многие ЛК поддерживают вход как с смс, так и без, могут запрашивать проверочные вопросы, а так же выдавать дополнительные шаги в зависимости от введенных данных. Как результат набор шагов и их количество могут меняться в зависимости от пользователя, даже в рамках одного профиля.
- Пользователь может ошибаться при вводе данных авторизации, по этому каждый шаг может завершиться ошибкой введенных данных (например не правильный пароль). Такую ошибку необходимо показать пользователю и для продолжения обновления он должен будет повторить ввод данных текущего шага.
С учетом этих моментов общая схема авторизации выглядит следующим образом:
- CASHOFF проверяет статус сохраненной у него сессии в ЛК провайдера.
- Сессия "жива" (по ней можно получить данные): авторизация завершена, переход к шагу 6.
- Сессия не "жива": начинается непосредственно процесс авторизации.
- CASHOFF определяет текущий шаг авторизации и указывает в профиле какой шаг нужно выполнить сейчас (session.auth_step).
- Приложение показывает пользователю форму из session.auth_step. может само выбрать провайдера
- Пользователь вводит данные в форму, приложение отправляет форму в CASHOFF.
- CASHOFF применяет данные для авторизации в ЛК. Далее может быть один из следующих исходов:
- Шаг выполнен успешно, больше шагов нет: авторизация завершена, переход к шагу 6.
- Шаг выполнен успешно, но есть следующий: профиль получает новую форму (session.auth_step) и с ней повторяет шаги 3-5.
- Шаг выполнен неуспешно: форма (session.auth_step) остается та же, приложение показывает пользователю ошибку и он повторяет ввод данных (шаг 4).
- Авторизация завершена, начинается импорт данных.
Таким образом авторизация представляет собой цикл из шагов 2-5, который предваряется проверкой статуса имеющейся сессии и завершается переходом в импорт данных.
Данные на шаге 5 передаются в CASHOFF с помощью запроса POST /profiles/{profile_id}/session/auth и должны соответствовать текущему шагу (session.auth_step):
{ "auth_data": { "sms": "1234" } }
Т.к. авторизация является частью процесса обновления, то каждый раз при отправке данных профиль будет переходить в статус updating, взаимодействовать фоново с провайдером и по результату переходить в какой-то из статусов: auth, error, ok.
Завершение фазы авторизации можно отследить по тому, что update_current_stage <> auth.
В CASHOFF есть ограничение в 15 минут на выполнение шага 4: если с момента установки текущего шага авторизации не придет в течении 15 минут запрос с данным для него, то процесс авторизации (вместе с обновлением) будет сброшен и обновление нужно будет начинать заново. Любая отправка данных, даже не позволившая пройти шаг, приведет к обновлению таймера. По этому суммарно время авторизации не ограничено этими 15 минутами - это ограничение только на попытку (на стороне CASHOFF, провайдеры всё равно могут накладывать свои ограничения).
Описания шагов авторизации
Каждый шаг авторизации провайдера представляет собой форму с набором полей. Типовая форма первого шага выглядит следующим образом:
{ "key": "initial", "fields": [ { "key": "login", "type": "text", "label": "Логин" }, { "key": "password", "type": "password", "label": "Пароль" } ] }
У данной формы ключ initial, и в ней содержится поля: login и password. По ней необходимо вывести пользователю форму с двумя полями, "Логин" и "Пароль". Поля формы с type=password должны маскировать вводимые в них данные.
Если в форме указан атрибут help, то его содержимое нужно вывести пользователю над полями - это вспомогательный текст содержащий 1-2 предложения, который поясняет особенности ввода данных на данной форме.
Если заполнен атрибут session.status_message, то его текст нужно вывести в качестве ошибки формы.
Результат ввода по этой форме, будучи отправленным в cashoff, выглядит следующим образом:
{ "auth_data": { "login": "1234", "password": "qwerty" } }
Импорт данных
После успешной авторизации обновление переходит к импорту данных. Сигналом окончания обновления будет переход профиля в статус ok (успешное завершение) или fatal (обновление прервалось ошибкой). Во втором случае текст ошибки будет доступен в поле session.status_message - это готовое сообщение для пользователя.
Набор данных зависит от типа провайдера, подробнее о списке загружаемых данных в зависимости от типа провайдера написано в разделе Провайдеры.
В CASHOFF обновление данных выполняется где возможно инкрементно: при каждом обновлении запрашиваются только данные за те даты, за которые они еще не загружены.
Указание выполняемых при импорте данных действий
При запуске обновления можно указать, какие данные нужно импортировать - за это отвечает атрибут update_stages (есть как в методе запуска обновления, так и в методе создания профиля). В нём перечисляются шаги, которые нужно выполнить в рамках обновления, а так же можно на некоторых шагах затребовать выполнение дополнительных действий. Атрибут может заполняться в двух форматах: сокращенном (список идентификаторов шагов) и развернутом (для каждого шага можно указать доп. действия). Пример сокращенного:
["auth", "accounts"]
(запрошена авторизация и загрузка списка продуктов). Пример развернутого:
{ "auth": {}, "accounts": { "payment_rub": true } }
(то же самое, только для продуктов запрошено определение того, с какого продукта можно совершать рублевые платежи через CASHOFF).
При указании списка шагов шаг auth можно опустить, т.к. он выполняется автоматически при необходимости. Однако его необходимо указать, если цель обновления - только обновить авторизацию:
["auth"]
Такое обновление используется в тех случаях, когда данные импортировать не нужно, а работа с профилем будет выполняться напрямую (например вызовы методов, создающие платежи), а не через импорт данных в рамках обновления..
Если атрибут не заполнен, то шаги по умолчанию проставляются согласно типу провайдера.
На каком конкретно этапе обновления сейчас находится профиль можно узнать через поле update_current_stage. К примеру в случае авторизации там будет auth, а в случае загрузки списка продуктов - accounts.
Ошибки в процессе обновления данных
Импорт данных может завершиться ошибкой, вызванной как парсером, так и провайдером. В таких случаях профиль получает статус status=error, а текст ошибки будет в поле session.status_message; код причины ошибки можно найти в атрибуте last_attempt_error.
При ошибке обновление прерывается. Далее можно либо сбросить текущий статус (POST /profiles/{profile_id}/reset), либо запустить обновление заново (POST /profiles/{profile_id}/update) (по сути это сброс + запуск).
Сброс очистит текст ошибки и переведет авторизацию на первый шаг. При сбросе уже загруженные данные останутся не тронутыми, он касается только непосредственно состояния профиля.
Уведомления об изменении профиля
В CASHOFF предусмотрено событие profile.updated, уведомления по которому отправляется при изменении профиля. Изменение включают в себя изменение профиля (статуса и текущего этапа обновления), состояния сессии
Уведомления не отправляются при изменении загруженных по профилю данных, в частности продуктов, операций и чеков. Данное событие является основным способом отслеживания процесса импорта данных.
В теле уведомления profile.updated приходит полная информация по профилю, аналогичная выдаче запроса GET /profiles/{profile_id}.
Ниже представлены примеры уведомлений по различным этапам импорта данных
Требуется ввод данных авторизации (смс)
|
Обновление успешно завершено
|
Неверные данные авторизации
|
Ошибка обновления профиля
|