Skip to content

💸 RESTful API эмулятора платёжного сервиса

License

Notifications You must be signed in to change notification settings

tmrrwnxtsn/const-payments-api

Repository files navigation

Эмулятор платёжного сервиса

Go Report Card codebeat badge Go Reference

Тестовое задание на стажировку в Константу.

Содержание

Задание

Сервис должен принимать запросы через REST API, сохранять/изменять состояния платежей в базе данных. Код должен быть написан на Go. В качестве базы данных, пожалуйста, используй любую реляционную.

Мы будем работать с двумя сущностями: пользователь и транзакция. Для простоты допустим, что база пользователей хранится вне нашего сервиса. О пользователе мы можем знать только его ID (число) и email. Транзакции хранятся в нашем сервисе. Вот что нам надо хранить о каждой транзакции

  • ID транзакции (число)
  • ID пользователя
  • email пользователя
  • сумма
  • валюта
  • дата и время создания
  • дата и время последнего изменения
  • статус

Статус может принимать одно из следующих значений: НОВЫЙ, УСПЕХ, НЕУСПЕХ, ОШИБКА. Цикл жизни платежа выглядит следующим образом: пользователь создает платеж, он создается в статусе НОВЫЙ. После платежная система должна уведомить нас о том, прошел ли платеж на ее стороне (п. 2 ниже), после чего мы меняем статус в нашей базе. Статусы УСПЕХ и НЕУСПЕХ являются терминальными - если платеж находится в них, его статус должно быть невозможно поменять. Переход в статусы УСПЕХ и НЕУСПЕХ должен осуществляться только после получения запроса из п.2 ОШИБКА - это статус, когда в момент создания платежа что-то пошло не так. Будет хорошо, если сделаешь, чтобы случайное количество платежей при создании переходили в этот статус.

API должно поддерживать следующие действия:

  • Создание платежа (на вход принимает id пользователя, email пользователя, сумму и валюту платежа);
  • Изменение статуса платежа платежной системой (хорошо, если будет к этому запросу будет применяться авторизация);
  • Проверка статуса платежа по ID;
  • Получение списка всех платежей пользователя по его ID;
  • Получение списка всех платежей пользователя по его e-mail;
  • Отмена платежа по его ID. API должно вернуть ошибку, если отмена невозможна (например потому что платеж в том статусе, в котором отменить нельзя).

Подготовка

Сервис состоит из двух компонентов: API сервер и база данных PostgreSQL, поэтому для его успешной работы необходимо установить следующее ПО:

  • Go >=1.17;
  • PostgreSQL >=13 при запуске API сервера с использованием собственного сервера БД или Docker >=20.10.14, если собственный сервер БД отсутствует.

Запуск

После установки необходимого ПО необходимо скачать исходный код сервиса и перейти в директорию с исходным кодом:

git clone https://github.com/tmrrwnxtsn/const-payments-api.git
cd const-payments-api

Есть несколько вариантов запуска системы, все из которых происходят благодаря Makefile. Перед запуском рекомендуется обратить внимание на переменные, указанные в этом файле, и изменить их, если потребуется. Также следует обратить внимание на конфигурационный файл configs/local.yml и внести необходимые правки. Если возникнет необходимость задать соответствующие переменные среды окружения, то они должны добавляться с префиксом APP_, например, APP_BIND_ADDR ( см. docker-compose.yml).

Пожалуй, самый "безболезненный" и простой способ. Оба компонента системы (API сервер и БД) разворачиваются в отдельных Docker-контейнерах. Настройки компонентов указываются в docker-compose.yml.

# запуск компонентов в отдельных Docker-контейнерах (без тестовых данных)
make compose-up

2. Docker

Имеется возможность разворачивать в Docker-контейнерах как API сервер, так и БД.

# запуск БД в Docker-контейнере
make db-start

# применение миграций к БД
make migrate-up-docker

# загрузка тестовых данных в БД 
make testdata-docker

# сборка образа API сервера
make build-docker

# запуск API сервера в Docker-контейнере на основе собранного образа
make run-docker

3. Local

Также есть возможность запустить API сервер локально (у себя на хосте), используя различные подключения к БД ( локальная/внешняя/Docker).

# применение миграций к БД
make migrate-up

# загрузка тестовых данных в БД 
make testdata

# компиляция и запуск бинарника с API сервером на хосте 
make run

# компиляция
make build

# запуск бинарника API сервера
make run

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

Эндпойнты

После успешного запуска сервиса одним из представленных способов, RESTful API сервер будет доступен по адресу http://localhost:8080 (если были использованы настройки по умолчанию, указанные в configs/local.yml). Сервер поддерживает следующие эндпойнты:

  • POST /api/transactions/: создание платежа (транзакции)
  • GET /api/transactions/: получение списка всех платежей (транзакций) пользователя по его ID или e-mail.
  • GET /api/transactions/:id/status/: проверка статуса платежа (транзакции) по ID
  • PATCH /api/transactions/:id/status/: изменение статуса платежа (транзакции) системой
  • DELETE /api/transactions/:id: отмена платежа (транзакции) по ID
  • GET /swagger/index.html: Swagger-документация

Тесты

Перед запуском тестов на хосте необходимо создать тестовую БД, применить к ней миграции и указать соответствующий URL в internal/store/sqlstore/store_test.go , либо задать в переменных среды (APP_DSN_TEST):

// internal/store/sqlstore/store_test.go

package sqlstore_test

import (
	"github.com/tmrrwnxtsn/const-payments-api/internal/config"
	"os"
	"testing"
)

var dsn string

func TestMain(m *testing.M) {
	dsn = os.Getenv(config.EnvVariablesPrefix + "DSN_TEST")
	if dsn == "" {
		dsn = "postgres://127.0.0.1/const_payments_db_test?sslmode=disable&user=postgres&password=qwerty"
	}

	os.Exit(m.Run())
}

После этого можно переходить к запуску тестов:

# выполнение тестов сервиса (с информацией о покрытии в %)
make test

# получить детальную информацию о покрытии участков кода тестами (cover.out, cover.html)
make test-cover

Структура

Ниже представлена структура сервиса (по папкам) с кратким описанием.

├── cmd                 основные приложения проекта
│   └── server          приложение API сервера
├── configs             конфигурационные файлы для различных сред развёртывания
├── docs                сгенерированная Swagger-документация 
├── internal            внутренний код приложения
│   ├── config          работа с конфигурационными данными
│   ├── handler         маршрутизация HTTP-запросов
│   ├── model           модели/сущности приложения
│   ├── server          HTTP-сервер, используемый для обработки запросов
│   ├── service         слой бизнес-логики для работы с платежами (транзакциями)
│   │   └── mocks       моки бизнес-логики работы с платежами (транзакциями)
│   └── store           слой хранения данных
│       ├── sqlstore    хранилище данных
│       └── teststore   тестовое хранилище данных (проверка логики хранения данных)
├── migrations          миграции базы данных
├── scripts             скрипты для операций над сервисом
└── testdata            тестовые данные для БД

Компоновка пакетов в данном проекте осуществлялась в соответствии с популярным макетом организации Go-проектов – Standard Go Project Layout.

Зависимости

  • Маршрутизация: gin
  • Доступ к базе данных: sqlx
  • Драйвер PostgreSQL: pgx
  • Миграции базы данных: golang-migrate
  • Валидация данных: ozzo-validation
  • Логгирование: logrus
  • Генерация Swagger-документации: swag
  • Генерация моков: golang/mock