Explanation to the Bot
Важно.
Демо презентация ТГ-бота "Обменник". Данная работа является исключительно учебно-исследовательской с целью познакомиться с Telegram Bot-API, оттачивания навыков построения backend части на языке Java с использованием семейства фреймворков Spring и Hibernate, а так же (в меньшей степени) построение frontend части с использованием фреймворков bootstrap и jquery.
Некоторый функционал не реализован целенаправленно, для невозможности использования данного приложения в качестве реально-существующего крипто-обменника.
Однако это не должно Вам помешать ознакомиться с работой приложения, Вы можете создавать ордера в боте и увидеть, а затем обработать их из веб-интерфейса приложения!😉

Links.
Ссылка непосредственно на бота в Телеграм

Консоль управления ордерами
Управление платёжными аккаунтами
Admin Page

Credential:
*Важно! Доступ к этим учётным данным имеют все посетители данной страницы. Система безопасности сконфигурирована таким образом, что при одновременном использовании одних учётных данных на разных устройствах, валидной будет считаться та сессия, которая была создана последней. Если в процессе изучения интерфейсов, Вы получили ошибку аутентификации - это нормальное поведение, значит другой пользователь вошёл в систему с этим же логином и паролем. Просто обновите страницу - и авторизуйтесь заново.

Admin Page - Изначально задумывался как интерфейс управления бизнес-логикой бота, для изменения таких параметров как: Но как описывалось выше:

Некоторый функционал не реализован целенаправленно, для невозможности использования данного приложения в качестве реально-существующего крипто-обменника.


Описание.
Tech.
Backend.
В качестве архитектуры приложения использован паттерн MVC с реализацией паттерна "Репозиторий" для хранения объектов бизнес-логики. Каждый запрос (сообщение/команда) пришедший из Telegram-api обрабатывается в отдельном потоке. Для экономии ресурсов среды в которой развёрнуто приложение - количество потоков ограниченно размером пула тредов, т.е не является бесконечным.

Для доступа к БД используется динамически расширяемый пулл коннектов Tomcat. Маппинг значений таблиц БД в объекты приложения и для обеспечения транзакционности операций - Hibernate. Все запросы реализованы на HQL без использования Spring Data JPA. В качестве непосредственно БД используется - PostgreSQL.

Аутентификация пользователей производится через Spring Security на основе сессий и Remember-me токена. Короткое время жизни сессионного токена в совокупности с более продолжительным временем жизни Remember токена - позволили получить неплохой уровень безопасности. При первичной аутентификации, регистрационные данные передаются через защищённое HTTPS соединение, а на стороне бекэнда, пароль шифруется алгоритмом BCrypt что могло бы позволить избежать компрометирования паролей при утечке данных из БД.

Авторизация реализована на основе ролей. В приложении существует несколько REST контроллеров, доступ к которым определяется наличием соответствующих ролей у пользователей.
Frontend.
Задачи сверстать красивый фронтэнд не ставил перед собой, основное требование - функциональность. Однако по ходу разработки был добавлен адаптивный дизайн с использованием Bootstrap, для мобильных устройств.

В качестве основного объекта наблюдения выступают данные полученные с бекенда. Для комфортного отображения этих данных была использована библиотека DataTables в режиме работы с сервером. Основное отличие server-side режима от классического в том что при классическом использовании - DataTable ожидает поступления всего массива данных за одну передачу. В случае еслиб этот проект оказался бы не учебно-исследовательским, таких данных могло бы быть неоценимо много, что рано или поздно не позволило бы приложению работать. В режиме server-side, DataTable запрашивает только тот объем данных, который установлен в параметрах, а для поиска используется не загруженный фрагмент, а производится отправка данных на сервер, где и осуществляется поиск и фильтрация.

Связь между Backend и Frontend частями выполняется через AJAX.

Business logic.
Обобщённая задача.
Представление о том, как мог бы работать обменник с ручной обработкой операций. Должны быть реализованы такие функции:
Создание ордера.
Создание нового ордера производится за несколько этапов среди которых должен быть следующий функционал: Дополнительно к указанию объема, был реализован конвертер криптовалюты в фиат и на оборот, переводящий на лету объемы.
Например: при создании ордера на покупку можно указать не количество монет, необходимых для приобретения, а количество фиата, который пользователь готов потратить. В этом случае на каждом шаге, приложение будет производить перерасчёт объемов покупки по актуальным ценам с учётом маржи обменника.

После заполнения всех необходимых данных, пользователю предоставляется 1 минута для проверки введённых данных, и их подтверждения, после чего для ордера фиксируется конечная цена монеты, и статус ордера изменяется на "созданный".

Особенности ордера на покупку.
Для снижения количества операций по картам фиатных банков - выбор карты производится случайным образом из всего списка карт привязанных к выбранному банку. Более подробно об этом будет рассказано в разделе "Работа с фиатными аккаунтами".
Так же при создании ордера, случайным образом генерируется "платёжный код", который необходимо указать при переводе. Код нужен для идентификации платежа, потому что мы не запрашиваем номер карты\телефона пользователя с которого будет произведён платёж при создании ордера.
"Платёжный код" - уникален. Т.е не может быть два одновременно открытых ордера с одинаковым кодом. Но может быть одинаковый код для открытого и закрытых ордеров.

Особенности ордера на продажу.
При создании ордера ему будет присвоен платёжный аккаунт выбранного фиатного банка с неисчерпанным лимитом проводимых объемов, для избежания процедуры блокировки банком платёжного аккаунта.

Что будет после создания ордера?
После того, как пользователь проверяет введённые им данные, и подтверждает создание ордера - у ордера изменяется статус на "CREATED", и устанавливается таймер автоматического закрытия.
После чего, данный ордер будет автоматически (без обновления страницы оператором) отображён в "Консоли управления заявками".
Пользователю будет предоставлено 10 минут для исполнения своих платёжных обязательств.
Дальнейшая работа возлагается на оператора. Если оператор видит поступление расчётных средств на указанный счёт - он берет заявку в работу. При этом для заявки отключается таймер автоматического закрытия, а статус изменяется на "PROCESSING", о чём приходит уведомление пользователю в Телеграм.
Далее оператор выполняет уже свои платёжные обязательства (перевод криптовалюты в случае покупки, или перевод фиата в случае продажи) и закрывает ордер с комментарием в котором содержится информация о транзакции (TxId или Номер операции в фиатном банке).
После чего статус ордера будет изменён на "COMPLETED" и пользователю придёт уведомление о завершении заявки с комментарием оператора.

Если ордер закрыт ошибочно?
Поскольку оператор является живым человеком, ему свойственны ошибки. Для минимизации негативных последствий таких ошибок - сделана возможность повторного открытия закрытых или завершённых заявок.
После повторного отрытия заявки - пользователь получит уведомление в Телеграм об изменении статуса, и комментарий оператора.
Для ордера будет запушён таймер автоматического закрытия, а статус изменён на "CREATED". В целом, ордер будет обладать всеми атрибутами первично созданной заявки. Его так же как и новый ордер можно взять в работу, закрыть без реализации, или ничего не делать, и он автоматически закроется по истечению таймера.


Работа с фиатными аккаунтами
В приложении существуют два взаимосвязанных объекта: "Банк" и "Платёжный аккаунт".
Объект класса "Банк" имеет только название и свой уникальный ID. Если говорить упрощённо он нужен только для фильтрации платёжных аккаунтов.
"Платёжный аккаунт" значительно более сложный объект. В нём имеются поля: Логика работы с платёжными аккаунтами основана на том, что у одного владельца мобильного номера, предоставляющего в аренду обменнику этот номер, может быть несколько карт разных банков, привязанных к предоставляемому в аренду номеру телефона. Исходя из этого предположения, в UI части приложения реализована возможность связи нескольких банков и одного платёжного аккаунта (номера телефона). Так же основываясь на предположении о том, что крупные платежи и большие обороты денежных средств по картам могут привлечь избыточное внимание со стороны банка, в приложении реализованны системы лимитирования объемов.
Лимиты могут быть двух типов:
Откуда берутся данные для глобального лимита?
При каждом завершении ордера (статус "COMPLETE"), объем фиатной валюты добавляется в соответсвующее поле платёжного аккаунта.

Когда происходит связывание ордера и платёжного аккаунта?
На последнем этапе создание ордера, когда пользователь проверит введённые им данные. При создании ордера пользователь сперва определяет объем операции, затем основываясь на этой информации, ему предоставляется список банков сформированный таким образом, что в нём присутствуют только те банки к которым привязаны платёжные аккаунты способные обработать введённый объем.

Заключение.
Была проведена интересная работа по исследованию Telegram Bot Api, возможно когда-нибудь в дальнейшем она будет переделана например на микросервесную архитектуру, а в качестве источника данных для таблиц будет выступать не REST контроллер, а например обновление будет производиться через Web-Socket. Если у вас имеются предложения или вопросы по работе приложения, Вы можете обратиться сюда.
Благодарю за внимание и проявленный интерес.