Сервис денежных транзакций

24 Oct 2020

Всем привет! Сегодня хотел бы поделиться опытом создания простейшего сервиса денежных транзакций. Сразу скажу, что сервис не предназначен для использования в production. Похожий сервис я реализовывал в качестве тестового задания. Само задание выглядело так:

  • Реализовать возможность перевода средств между кошельками пользователей.
  • С каждой транзакции брать комиссию 1.5% в пользу системы.
  • Поддержка 2х валют: BTC(Bitcoin) и ETH(Ethereum).
  • Подготовить данные для демонстрации (несколько пользователей и кошельков)
  • Работа с системой осуществляется через REST API.
  • Подготовить docker сборку.

Также явно не указано, но подразумевалось наличие тестов. Предположительно задание можно было сделать за 3-4 часа. Но, в результате, работа заняла около 8 часов.

Общее

Проект разработан на Symfony 5.1 c использованием Doctrine, FOSRestBundle и PHPUnit.

Создал 3 сущности: Wallet, Transaction, User. Транзакция производится между source и destination кошельками. Кошелек привязан к пользователю. Пользователь может иметь несколько кошельков. Валюта указывается для кошелька и транзакции. Валюта должна совпадать. Схема базы данных выглядит так:

https://dbdiagram.io/d/5f45434e7b2e2f40e9deb90a

Значения валют и комиссий положил в Enum.

REST API сделал с помощью FOSRestBundle. Для обработки запроса используется TransactionRequest. Создание транзакций обрабатывается в TransactionController и затем передается в сервис TransactionCreator. Для красивого отображения ошибок используется ValidationErrorResponse и ExceptionListener.

Авторизация пользователей сделана по логину паролю. Была идея использовать bearer token, но решил, что для данного примера это избыточно. Для авторизации используется механизм EventSubscriber

Sample data

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

Тесты

Реализовал тесты на создание транзакций.

Позитивные сценарии:

Негативные сценарии:

Docker

Подготовил Docker сборку на основании этого руководства. Docker compose включает в себя nginx, php-fpm и mysql контейнеры.

Установка

Проект запускается в Docker. Необходимо клонировать репозиторий, запустить docker-compose, затем загрузить sample data.

git clone https://github.com/antonshell/money-transactions-service.git
cd money-transactions-service
docker-compose up
docker-compose exec php-fpm php bin/console sample-data:load

Использование

1 . Для проверки работы сервиса можно выполнить такой запрос:

curl --request GET \
  --url http://127.0.0.1:18680/

2 . Создание транзакции от пользователя #1 для пользователя #2:

curl --request POST \
  --url http://127.0.0.1:18680/transaction \
  --header 'content-type: application/json' \
  --header 'password: user1' \
  --header 'username: user1@test.com' \
  --data '{
    "source": 1,
    "destination": 3,
    "amount": 1
}'

3 . От пользователя #2 для пользователя #1:

curl --request POST \
  --url http://127.0.0.1:18680/transaction \
  --header 'content-type: application/json' \
  --header 'password: user2' \
  --header 'username: user2@test.com' \
  --data '{
    "source": 3,
    "destination": 1,
    "amount": 1
}'

4 . Получение списка пользователей и кошельков. В реальном проекте этот метод должен быть доступен только администратору.

curl --request GET \
  --url http://127.0.0.1:18680/dashboard

Пример доступен на github. На этом пока все. Спасибо за внимание!