- Coming soon…
- Ui компоненты (блоки)
- Workflow engine
- Единый доступ к цифровым сервисам экосистемы сбербанка
- Интерфейс rest [документация сбербанка]
- История изменений api юkassa
- Как делать не стали
- Как работают ui-контейнеры?
- Как решили делать
- Мобильное приложение
- О чем пойдет речь
- Ошибки валидации на клиенте и сервере
- Подключение платежного шлюза сбербанк. как реализовать подключение?
- События
- Специфика и мотивация
- Справочники
- Транспорт данных
- Фрэймворки
- Экраны
Coming soon…
Мы очень старались писать лаконично, но это первая техническая статья про платформу Сбербанк Онлайн и она должна была многое охватить.
Пишите в комментариях, что непонятно, что интересно – постараемся писать меньше, но чаще и в цель. У нас много интересных вызовов, и поэтому много материала.
Ui компоненты (блоки)
UI компонент – независимый компонент, который реализует клиентскую логику и наполняет документ данными. По сути, это ассоциация между управляющей командой в протоколе и куском кода и разметки в приложении. На первом экране три компонента:
- Счет списания
- Тот же компонент для счета зачисления
- Сумма перевода
Иногда что-то может пойти не так: например, в старую версию приложения передался новый процесс или старая версия блока была удалена в клиентском приложении, но осталась в одном из процессов серверного приложения. В этом случае приложение выполняет мягкую деградацию: блок заменяется на системный (простая группа полей), который не обладает никакой дополнительной логикой, а просто показывает поля в составе. Подробнее будет ниже.
В таком случае форма будет менее красивой, но пользователь хотя бы сможет заполнить данные и отправить их на сервер. Затем сервер провалидирует ввод и вернёт ошибки, которые можно исправить.
Workflow engine
Движок внутри приложений (веб и мобильного) знает, что начался процесс работы с документом и что согласно протоколу ему придёт ряд атрибутов: шаги, экраны, UI-контейнеры и типы полей. На этих данных рисуется базовый интерфейс – нижнее и верхнее меню, основные кнопки, UI на простых типах полей, если они используются.
При этом движок не знает, сколько именно в сценарии будет шагов процесса, как шаги будут разбиты по экранам и какие там будут поля.
Если сценарий изменится, например, потребуется отобразить новое поле, то его будет достаточно добавить в ответ сервера, и клиентское приложение его отобразит. Для этого выпускать релиз фронтального приложения не потребуется.
Единый доступ к цифровым сервисам экосистемы сбербанка
✓ Единая точка взаимодействия с потребителями API.
✓ Удобный интерфейс и стандартизированные сценарии подключения потребителей.
✓ Надежные механизмы защиты и безопасности при взаимодействии системы Потребителя и системы Поставщика.
✓ Автоматизированные проверки приложения, осуществляющего вызов API, проверка доступных лимитов, проверка срока действия подписки, соответствие запроса и ответа схеме API, проверка организаций и многое другое.
✓ Гибкие возможности настройка продукта: установить лимиты вызовов, настроить видимость карточки сервиса, управлять доступом и подключениями, задавать разные тарифы для разных потребителей.
Размещение API доступно юридическим лицам или индивидуальным предпринимателям, у которых имеется УЗ СбербизнесID.
Размещение API выполняется по договору с Владельцем площадки (ПАО Сбербанк) на возмездной основе. Подписать договор можно при первом входе по СбербизнесID (пользователю с признаком ЕИО).
Сервис должен соответствовать требованиям и пройтимодерацию (проверку).
Между Порталом и Системой Заказчика должно быть организовано защищённое соединение по технологии mTLS.
Поставщик API должен организовать информационную поддержку для своих потребителей и указать все необходимые контакты в карточке сервиса.
Иные условия и положения описаны в документах:Политика конфиденциальности, Пользовательское соглашение, Договор об оказании услуг по размещению API.
Подключение API доступно юридическим лицам или индивидуальным предпринимателям, у которых имеется УЗ СбербизнесID. Физические лица могут выполнить подключение на свободно распространяемые API, если таковые будут размещены в каталоге.
Владелец API и потребитель API самостоятельно определяют взаимоотношения, цены и порядок расчетов 1.
Заключение договора и взаиморасчеты между Поставщиком и Потребителем выполняются вне данной площадки.
Иные условия и положения описаны в документах:Политика конфиденциальности, Пользовательское соглашение.
Интерфейс rest [документация сбербанка]
URL-адреса для доступа к запросам REST представлены в таблице ниже.
История изменений api юkassa
В России приостановлены операции по картам Visa, MasterCard, JCB и AmericanExpress, поэтому в работе Apple Pay и Google Pay есть ограничения:
В ЮKassa добавлена поддержка ФФД 1.2 для работы с онлайн-кассами. Возможность передачи новых реквизитов для маркировки будет реализована позже.
Способ оплаты СберБанк Онлайн выводится из эксплуатации:
Запуск новой версии API. Что изменилось:
Обновлены мобильные SDK:
- параметр стал необязательным;
- значение параметра теперь зависит от способа ввода данных банковской карты.
В виджете ЮKassa при оплате банковской картой пользователь может проходить аутентификацию по 3-D Secure во всплывающем окне, оставаясь при этом на вашем сайте.
Виджет ЮKassa теперь поддерживает оплату через Сбербанк Онлайн.
Теперь ЮKassa поддерживает работу с онлайн-кассами Кит Инвест.
Запуск портала документации API ЮKassa для разработчиков.
Как делать не стали
После того как мы обозначили граничные условия, расскажем, какие существующие решения мы анализировали.
Программирование на JSON
Логику проще описать императивно кодом, чем выдумывать (и изучать!) новый декларативный язык, который всегда будет ограничен сильнее, чем родной язык платформы. Кроме этого, надо предусмотреть песочницу, обработку ошибок, какой-то этап пилотирования – псевдокод должен постепенно распространяться на пользовательские устройства и при любых сбоях откатываться назад. Всё это усложняет разработку без ощутимых преимуществ.
CSS 3000
Не используем описание стилей компонентов, поскольку они могут разниться от форм-фактора, платформы и даже режима работы (портретная/ландшафтная ориентация, responsive в web). Декларации стилей в конечной реализации всегда будут качественнее, ближе к реальности и корректнее работать с краевыми случаями.
Фиксация модели данных в интерфейсе приложения
Этот способ еще называется «прибить гвоздями». Смысл в том, что интерфейс приложения строится на уникальных идентификаторах объектов, которые передаются с сервера. В такой схеме любые изменения на стороне сервера приводят к переработкам клиентской части.
Невозможно повторно использовать код. Сложно поддерживать.Единственное, почему стоит выбирать такой способ на своем проекте, – уверенность на 99%, что API не будет меняться. Ну или если проект совсем небольшой и проектировать API дороже, чем быстро переделать пользовательский интерфейс под изменения в API.
Стили
Добавляем к каждому объекту признак стиля. UI приложений строим на основании этого признака. Стилей ограниченное число, поэтому появляется возможность строить интерфейс динамически. Но с увеличением функциональности UI приходится увеличивать количество стилей.
В этом варианте становится возможно управлять отображением отдельных элементов, но повышается сложность реализации связанности между разными полями. И главное – с ростом вариативности UI у вас будет постоянная необходимость расширять протокол API.
JSON API
У JSON API детально описаны рекомендации по структурированию данных и описанию взаимосвязей между ними, но нет ничего, что могло бы описывать представление. Наша задача затрагивает в том числе визуальное расширение – добавление новых полей ввода, так что такой вариант нам не подходит.
Web Components / React Components API
Концепция веб-компонентов, которая в том числе значительно повлияла на API компонентов React, нам подходит уже намного лучше: с одной стороны, у нас есть контроль за отображением, с другой стороны – есть возможность привязывать данные к элементам UI.К сожалению, всё слишком сильно завязано на HTML CSS JS. Напрямую не используешь, но запомним – потом пригодится.
Как работают ui-контейнеры?
Анализ потребностей дизайнеров и бизнес-заказчиков показал, что все потребности не получится удовлетворить простым расширением атрибутивного состава полей.
Поэтому нужны были точки расширения. Этими точками расширения стали UI-компоненты – это нативная реализация кода в самих приложениях, который идентифицируется движком по названию. По сути, это группировка поля/нескольких полей в логический блок, который может отображать кастомный UI.
Два режима работы фрэймворка
Когда движок парсит модель данных, он сравнивает список имен UI-контейнеров с реестром, который хранится внутри приложения. Если приложение не находит имени компоненты, то интерфейс строится на простых типах полей. Процесс будет полностью рабочим, но на стандартных UI-элементах.
Слева – как может отображаться контейнер для ввода суммы на списке из простых типов полей. Справа – если в сборке приложения есть UI-контейнер. Несмотря на то, что в режиме списка простых полей нет слайдера и есть отдельное поле вместо иконки с выбором валюты, – мы можем передать все данные с PL и процесс будет рабочим.
И тут мы получаем одно из основных преимуществ движка – доставить пользователю изменения без обновления приложения. В сборке есть маппинг имен компонентов на классы, в которых запрограммирован UI этих компонентов и пользовательский интерфейс строится на нем.
Каких правил мы стараемся придерживаться при работе с UI-компонентами:
- Поддерживать работу функционала в режиме списка простых типов полей. У любого прикладного проекта есть соблазн превратить динамический протокол в статический. Поэтому мы всех просим сначала разработать функционал на типовом UI-контейнере, а потом обогащать UX/UI добавлением кастомных контейнеров на этой модели данных. Это не только позволит в будущем обновлять процессы на старых сборках, но и автоматически поддерживает логическую целостность API.
- Не менять модель данных (JSON) для UI-контейнера, если он уже готов (проходит финальное тестирование или уже в продакшене). Так как логика на PL жестко связана с моделью данных, её изменение сломает функционал на версиях мобильного приложения, которые не обновляются. Тем не менее, модель можно расширять при условии сохранения обратной совместимости.
- Называть свой UI-компонент системным именем. Так как имя UI-компонента – обязательный атрибут протокола и должен быть минимум один на каждом экране, мы ввели специальное системное имя, которые реализует простой список полей.
- Не реализовывать бизнес-логику на UI-компонентах. Логику необходимо реализовывать на сервере, почему – писали выше.
Как решили делать
UI-контейнеры
Объекты упаковываются в контейнеры, презентационную логику приложения строим на этих контейнерах. Основное преимущество – можем группировать несколько простых объектов в один контейнер. Это дает свободу в программировании UX/UI на клиенте, например, можем управлять скрытием/отображением одного поля при заполнении данных в другом. При этом базовых типов объектов – ограниченное число, и весь бизнес-транспорт реализуется на них.
Мы выбрали именно этот подход. Сначала мы опишем протокол API, а потом – как устроены фрэймворки внутри мобильных и веб-приложений.
Мобильное приложение
Данные меняются динамически.
Самые популярные операции в мобильном приложении – платёж и перевод. Реквизиты поставщиков услуг, набор полей, которые необходимо заполнить пользователю, – это динамическая информация, которая может часто меняться.
При этом пользователи могут не обновлять приложение, после того как установили его на устройство. Просто потому что могут. Чаще на это есть весомые причины, например, для обновления приложения нужно обновить версию ОС, а для этого купить новый телефон. Поэтому нам нужно решение, которое позволит менять данные без релиза приложения.
Мобильный интернет: наши приложения должны работать везде, даже где интернет нестабильный и медленный. Поэтому мы всегда боремся за размер и количество сообщений между мобильными приложениями и сервер-сайдом.
Лучший клиентский опыт: мы выбрали для себя основную технологию разработки мобильных приложений – разработка на нативных языках. Только так можно получить лучший клиентский опыт.
Если обобщить все эти требования – приложения должны разрабатываться на нативных языках, иметь повторно используемые компоненты внутри себя, но при этом вся бизнес-логика должна управляться со стороны сервера.
О чем пойдет речь
Мы расскажем, как в мобильном и веб приложениях Сбербанк Онлайн работают платежные сценарии, а именно про API между приложениями и сервер-сайдом.
Почему фокус на API? Все просто – это фактически единственный мостик, который соединяет клиентские приложения и бэкенд. Если проект небольшой, то мы можем легко менять API и переписывать под него приложения. Но если проект масштабный (такой, как у нас), то даже небольшие изменения API требуют вовлечения большого количества ресурсов как на фронте, так и на бэкенде, и становятся очень дорогими.
Сначала мы немного расскажем о наших возможностях и ограничениях, чтобы было понятно, почему мы выбирали то, а не иное решение, а потом представим сам протокол API на верхнем уровне.
Ошибки валидации на клиенте и сервере
Так как основной элемент интерфейса – поле ввода данных, логично валидировать его на клиенте. Вместе с полями передаются правила валидации и сообщения, которые отображаются, если валидация не прошла.
"validator":
"value":
"message":
"type":
Примерно так выглядит структура ответа:
Подключение платежного шлюза сбербанк. как реализовать подключение?
В процессе интеграции sbercredit. Аналогичные проблемы.
В документации запросы странного вида, такие не выдает ни http_build_query, ни key-value подстановка.
Плюс запросы GET, но с требованием POST-заголовка application/x-www-form-urlencoded)
Примеры POST-запросов в документации неадекватные, и завести их так и не удалось ни в каком виде.
Оказалось что API принимает только GET, и http_build_query вполне хватит.
Проблема была в документации: запросы составлялись по их документации, но… ничего не работало. И API не умеет говорить ничего, кроме system error)
Разобрал их API по кусочкам, оказалось что оно документации мало соответствует — многие необязательные поля на деле обязательны.
Сейчас следующий круг ада: API принимает запрос, отдает данные для перехода на шлюз, но… теперь шлюз отдает ошибки в web-интерфейсе)
Оказалось поле muasure было обязательным. При этом в документации в примерах запросов оно пустое, и API на пустое поле ошибок не выдает. Такие дела.
События
Так как приложения ничего не знают о процессе, логично, чтобы события (кнопки, которые видит пользователь) тоже были частью ответа от сервера.
События мы разделили на два типа.
1) Основные – они есть почти на каждом экране в привычных местах для пользователя. Как пример, это события «назад» и «продолжить». Первое осуществляет переход на шаг назад, а второе собирает заполненные данные с клиентской формы и отправляет их на сервер вместе с командой «Перейти на следующий шаг».
2) И специальные – для нестандартных действий, которые мы заранее спрогнозировать не можем, да и смысла закладывать их в часть движка нет, так как они редко используются.
В нашем случае на экране только основные события – «продолжить» и «назад». Они реализованы на уровне платформы.
У всех событий есть ряд атрибутов, такие как сам тип события, title и признак видимости. И никакого UI на сервер-сайде вроде размера кнопки, положения и цвета. Эта логика реализуется на фронте.
"events":
"name":
"type":
"title":
"description":
Специфика и мотивация
Приложения большие.
Когда мы писали эту статью, приложение Сбербанк Онлайн на Android занимало около 800 000 строк кода, на iOS – 500 000 строк кода. И это только наш код, без подключаемых библиотек.
Обратная совместимость и много пользователей. MAU – 32 млн активных пользователей мобильного приложения. И если мы не сделаем обратную совместимость на уровне API, очень многим пользователям по всей стране придется качать приложения заново. Это очень нехорошо. Кстати, это одна из причин, почему у нас так много кода.
Сбербанк Онлайн разрабатывает много небольших команд. Вы, наверное, слышали про Agile в Сбербанке. Это правда, мы работаем по Agile в командах по 9 человек.
Приложение банковское: несмотря на то, что функциональность банковских приложений растет очень быстро, основное, что происходит в дистанционном банкинге – это последовательный процесс (обработка клиентских заявок). Такие процессы мы называем workflow. Заявки эти могут быть разного рода и обрабатываются они огромным количеством взаимосвязанных сервисов в периметре банка.
Два типа команд. Есть платформенные – они отвечают за разработку ядра приложения. И есть фичёвые команды – они создают прикладной функционал для конечных пользователей, используя архитектуру и инструменты, которые даёт платформа.
Омниканальность. Крайне важная история. Чтобы не разрабатывать бэк несколько раз – отдельно для мобильных приложений и отдельно, например, для веб-версии и банкоматов, нужно сделать так, чтобы API был максимально схожим для всех каналов (как минимум должна быть одинаковой структура ответа).
Справочники
Со справочниками все стандартно. Если он небольшой, то мы его присылаем полностью в ответе от сервера и называем статическим. Сделано это для того, чтобы минимизировать количество запросов к сервер-сайду и время отклика на действие пользователя в интерфейсе.
Если справочник большой, то он реализуется в виде отдельного rest-сервиса. В интерфейсе это выглядит как текстовое поле, по мере заполнения которого возвращается список возможных вариантов из справочника.
"references":
"referenceId":
Транспорт данных
Для начала договоримся об основных принципах – как передаём данные. За основу возьмём самый простой подход – пары «ключ-значение». Ключом пусть будет строка из букв латинского алфавита, значение – тоже строки, но уже произвольные.
Формы для заполнения бывают сложные, с вложенными элементами и подразделами, значит, надо допускать вложенность. Можно именовать ключи в формате camelCase, но они могут быть плохо читаемым (например, в логах) или даже «портиться» в системах, нечувствительных к регистру. Нужно ввести разделитель.
Самый очевидный разделитель – точка – во многих языках используется для доступа к свойствам объекта. При неаккуратном использовании ключи с таким разделителем будут создавать словари (или объекты), в которых возможны коллизии. Например, “foo.bar” = “foobar” и “foo.bar.baz” = “foobarbaz” в javascript может повлечь перезапись свойства “bar” объекта “foo” со строки на объект.
Что делать с повторяемыми полями? Вводим дополнительное правило: между парой разделителей могут быть либо латинские буквы, либо цифры. Получаются конструкции вида: children:5:name:first.
Пожив некоторое время с такой структурой, обнаруживаем ограничение: множественный выбор оказывается нетривиальным в реализации и требует дополнительных ухищрений на бэкэнде, чтобы держать высокую нагрузку.
Решение: значение – либо строка, либо список строк. Так решение выглядит типовым, но в то же время накладные расходы оказываются незначительными.
Фрэймворки
Теперь немного о том, как с этим протоколом работают фрэймворки внутри приложений. Условно фрэймворки можно разделить на две основные части: workflow engine обработчик UI-контейнеров. Такое разделение вызвано не только архитектурой приложений, но и организационной структурой.
Экраны
Экран – это разделение процесса на этапы в клиентском приложении. Как правило, экраны используются, чтобы форма была проще для восприятия. В нашем случае всё просто: один шаг – один экран.
Для экранов мы ввели два правила:
- переход между экранами может быть только линейным, без ветвлений;
- переход между экранами не требует взаимодействий с бэкэндом.
Это означает, что экраны, по сути, становятся простыми группами и могут передаваться с бэкэнда сразу при входе на шаг.