Files
payment-processing-test/README.md
T

101 lines
3.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Асинхронный сервис процессинга платежей
Микросервис принимает платежи по HTTP, атомарно сохраняет платёж и outbox-событие в PostgreSQL, публикует событие в RabbitMQ и асинхронно отправляет результат на webhook.
## Запуск
Требования: Docker с Compose plugin.
```bash
docker compose up --build
```
После запуска доступны:
- API и Swagger UI: <http://localhost:8000/docs>
- RabbitMQ Management: <http://localhost:15672> (`guest` / `guest`)
- API key по умолчанию: `local-secret`; для другого значения задайте `API_KEY`
Миграции выполняются контейнером `migrate` до запуска API и consumer.
## API
Создать платёж:
```bash
curl -i -X POST http://localhost:8000/api/v1/payments \
-H 'Content-Type: application/json' \
-H 'X-API-Key: local-secret' \
-H 'Idempotency-Key: order-123-attempt-1' \
-d '{
"amount": "1250.50",
"currency": "RUB",
"description": "Заказ 123",
"metadata": {"order_id": 123},
"webhook_url": "https://example.com/payment-webhook"
}'
```
Ответ имеет статус `202 Accepted`:
```json
{
"payment_id": "8f814d58-8a52-493f-aafb-98b383aa0325",
"status": "pending",
"created_at": "2026-09-16T08:00:00Z"
}
```
Повторный запрос с тем же `Idempotency-Key` вернёт тот же платёж и не создаст новое outbox-событие.
Получить платёж:
```bash
curl http://localhost:8000/api/v1/payments/8f814d58-8a52-493f-aafb-98b383aa0325 \
-H 'X-API-Key: local-secret'
```
Webhook получает JSON следующего вида:
```json
{
"payment_id": "8f814d58-8a52-493f-aafb-98b383aa0325",
"amount": "1250.50",
"currency": "RUB",
"status": "succeeded",
"processed_at": "2026-09-16T08:00:04Z",
"metadata": {"order_id": 123}
}
```
## Надёжность
- `payments` и `outbox` записываются в одной транзакции.
- Publisher читает outbox через `FOR UPDATE SKIP LOCKED` и помечает событие после publisher confirm RabbitMQ.
- Доставка события имеет семантику at-least-once. Consumer идемпотентен по состоянию платежа.
- Обработка и webhook выполняются до трёх раз с задержками 1 и 2 секунды.
- После исчерпания попыток сообщение отклоняется без requeue и RabbitMQ переносит его через `payments.dlx` в `payments.dead`.
- Если процесс остановился после обновления статуса, но до webhook, повторная доставка продолжит только webhook.
## Локальная разработка
```bash
python -m venv .venv
. .venv/bin/activate
pip install -e '.[dev]'
cp .env.example .env
ruff check .
ty check
pytest
```
Для локального запуска без Docker измените в `.env` адреса PostgreSQL и RabbitMQ на `localhost`, затем выполните:
```bash
alembic upgrade head
uvicorn app.main:app --reload
faststream run app.consumer:app
```
Основные параметры эмуляции (`PROCESSING_*`), retry и polling outbox перечислены в `.env.example`.