Skip to content

Repository files navigation

Payment Processing Service

Сервис принимает платёж через REST, кладёт задачу в очередь и асинхронно её обрабатывает: эмулирует платёжный шлюз и шлёт результат на webhook клиента.

Стек: FastAPI, PostgreSQL, RabbitMQ, Docker Compose.

Запуск

cp .env.example .env
docker compose up --build

Поднимутся четыре контейнера: postgres, rabbitmq, api, consumer.

Если порт 8000 занят — поменяйте маппинг в docker-compose.yml, например "8888:8000".

Как это работает

  1. Клиент шлёт POST /api/v1/payments с заголовком Idempotency-Key.
  2. API сохраняет платёж в БД и запись в outbox (в одной транзакции).
  3. Фоновый relay читает outbox и публикует событие в RabbitMQ.
  4. Consumer забирает сообщение, «обрабатывает» платёж (2–5 сек, 90% успех) и вызывает webhook.

Повторный запрос с тем же Idempotency-Key не создаст дубль — вернётся уже существующий платёж.

Примеры запросов

Создать платёж:

curl -X POST http://localhost:8000/api/v1/payments \
  -H "Content-Type: application/json" \
  -H "X-API-Key: secret-api-key-change-me" \
  -H "Idempotency-Key: order-123" \
  -d '{
    "amount": "1500.00",
    "currency": "RUB",
    "description": "Test payment",
    "metadata": {"order_id": "123"},
    "webhook_url": "https://webhook.site/your-unique-id"
  }'

Ответ — 202, платёж в статусе pending. Дальше consumer сам доведёт до succeeded или failed.

Посмотреть статус:

curl http://localhost:8000/api/v1/payments/{payment_id} \
  -H "X-API-Key: secret-api-key-change-me"

Все эндпоинты требуют заголовок X-API-Key. Ключ задаётся в .env (API_KEY).

Webhook

Когда платёж обработан, consumer делает POST на webhook_url:

{
  "payment_id": "uuid",
  "status": "succeeded",
  "amount": "1500.00",
  "currency": "RUB",
  "description": "Test payment",
  "metadata": {"order_id": "123"},
  "processed_at": "2026-08-17T12:00:00Z"
}

Если webhook не ответил — 3 попытки с паузами 1, 2 и 4 секунды. Не помогло — сообщение уходит в DLQ (payments.new.dlq), смотреть в RabbitMQ UI → Queues.

Локально без Docker

Нужны PostgreSQL и RabbitMQ на машине.

python -m venv .venv && source .venv/bin/activate
pip install -e ".[test]"

cp .env.example .env   # поправьте URL под localhost
alembic upgrade head

uvicorn app.main:app --reload          # терминал 1
faststream run app.consumer.main:app   # терминал 2

Тесты

pip install -e ".[test]"
pytest

Переменные окружения

Переменная Зачем
DATABASE_URL PostgreSQL, формат postgresql+asyncpg://user:pass@host:5432/db
RABBITMQ_URL RabbitMQ, формат amqp://guest:guest@host:5672/
API_KEY Значение для заголовка X-API-Key
OUTBOX_POLL_INTERVAL_SECONDS Как часто relay проверяет outbox (секунды, по умолчанию 2)

Примеры значений — в .env.example.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages