Files
youkassa-mock/README.md
2026-03-12 06:54:38 +00:00

419 lines
8.8 KiB
Markdown
Raw Permalink 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.
# YooKassa Mock v2
Легковесный mock-сервер для эмуляции базового сценария работы YooKassa.
## Что умеет
- создавать платеж
- возвращать `confirmation_url`
- показывать checkout-страницу
- завершать платеж как:
- `succeeded`
- `canceled`
- отправлять webhook
- повторять webhook при ошибке
- поддерживать `Idempotence-Key`
- отдавать статус платежа по `payment_id`
---
# Файлы
- `main.py` — FastAPI приложение
- `requirements.txt` — зависимости
- `Dockerfile` — образ
- `docker-compose.yml` — запуск контейнера
- `.env` — переменные окружения
---
# Запуск
## 1. Сборка и старт
~~~bash
docker compose up -d --build
~~~
## 2. Проверка здоровья
~~~bash
curl -s http://127.0.0.1:${YMK_PUBLIC_PORT}/health
~~~
Пример ответа:
~~~json
{"status":"ok","payments_total":0,"idempotence_keys_total":0}
~~~
---
# Переменные окружения
Пример `.env`:
~~~env
YMK_PUBLIC_PORT=8083
WEBHOOK_URL=http://192.168.149.101:8000/api/tickets/webhook/yookassa
MOCK_HOST=192.168.149.101
MOCK_PORT=8083
MOCK_REQUIRE_AUTH=0
MOCK_SHOP_ID=test_shop
MOCK_SECRET_KEY=test_secret
WEBHOOK_RETRY_COUNT=3
WEBHOOK_RETRY_DELAY_SEC=1
WEBHOOK_DELAY_SEC=0
~~~
## Описание
### `YMK_PUBLIC_PORT`
Внешний порт хоста, на который публикуется контейнер.
### `WEBHOOK_URL`
URL для отправки webhook после смены статуса платежа.
### `MOCK_HOST`
Хост, который будет подставляться в `confirmation_url`.
### `MOCK_PORT`
Порт, который будет подставляться в `confirmation_url`.
### `MOCK_REQUIRE_AUTH`
- `0` — Basic Auth не обязателен
- `1` — Basic Auth обязателен
### `MOCK_SHOP_ID`
Логин для Basic Auth, если auth включен.
### `MOCK_SECRET_KEY`
Пароль для Basic Auth, если auth включен.
### `WEBHOOK_RETRY_COUNT`
Количество попыток отправки webhook.
### `WEBHOOK_RETRY_DELAY_SEC`
Пауза между retry webhook.
### `WEBHOOK_DELAY_SEC`
Искусственная задержка перед первой отправкой webhook.
---
# API
## 1. POST `/v3/payments`
Создание платежа.
### Обязательное
- заголовок `Idempotence-Key`
- `confirmation.return_url`
- `amount.value`
### Пример запроса
~~~bash
curl -s -X POST http://127.0.0.1:8083/v3/payments \
-H 'Content-Type: application/json' \
-H 'Idempotence-Key: test-001' \
-d '{
"amount": {
"value": "100.00",
"currency": "RUB"
},
"confirmation": {
"type": "redirect",
"return_url": "http://192.168.149.101:3000/payment/return"
},
"capture": true,
"description": "Заказ №1"
}'
~~~
### Пример успешного ответа
~~~json
{
"id": "fdb332f8-bb1d-4def-bc1d-d5b00a7e287a",
"status": "pending",
"paid": false,
"amount": {
"value": "100.00",
"currency": "RUB"
},
"confirmation": {
"type": "redirect",
"confirmation_url": "http://192.168.149.101:8083/checkout?payment_id=fdb332f8-bb1d-4def-bc1d-d5b00a7e287a"
},
"created_at": "2026-03-12T06:35:47.512Z",
"description": "Заказ №1",
"metadata": {},
"capture": true,
"recipient": {
"account_id": "test_shop",
"gateway_id": "100700"
},
"refundable": false,
"test": true
}
~~~
### Идемпотентность
Если повторно вызвать `POST /v3/payments` с тем же `Idempotence-Key`, мок вернет тот же платеж, а не создаст новый.
---
## 2. GET `/v3/payments/{payment_id}`
Получение статуса платежа.
### Пример
~~~bash
curl -s http://127.0.0.1:8083/v3/payments/fdb332f8-bb1d-4def-bc1d-d5b00a7e287a
~~~
### Пример ответа
~~~json
{
"id": "fdb332f8-bb1d-4def-bc1d-d5b00a7e287a",
"status": "succeeded",
"paid": true,
"amount": {
"value": "100.00",
"currency": "RUB"
},
"confirmation": {
"type": "redirect",
"confirmation_url": "http://192.168.149.101:8083/checkout?payment_id=fdb332f8-bb1d-4def-bc1d-d5b00a7e287a"
},
"created_at": "2026-03-12T06:35:47.512Z",
"description": "Заказ №1",
"metadata": {},
"capture": true,
"recipient": {
"account_id": "test_shop",
"gateway_id": "100700"
},
"refundable": true,
"test": true
}
~~~
---
## 3. GET `/checkout?payment_id=<id>`
HTML-страница оплаты.
Что показывает:
- `payment_id`
- статус
- сценарий
- описание
- сумму
На странице есть три кнопки:
- `Оплатить успешно`
- `Отменить оплату`
- `Ошибка оплаты`
---
## 4. POST `/process/{payment_id}`
Меняет статус платежа, отправляет webhook, делает redirect на `return_url`.
### Входные варианты
Через form-data / x-www-form-urlencoded поле `action`:
- `success`
- `cancel`
- `fail`
### Пример success
~~~bash
curl -i -X POST http://127.0.0.1:8083/process/fdb332f8-bb1d-4def-bc1d-d5b00a7e287a \
-d 'action=success'
~~~
### Пример cancel
~~~bash
curl -i -X POST http://127.0.0.1:8083/process/294ec8cd-c1fb-44b4-91cc-04d669343390 \
-d 'action=cancel'
~~~
### Поведение
- `success` → статус `succeeded`, `paid=true`
- `cancel` → статус `canceled`, `paid=false`
- `fail` → статус `canceled`, `paid=false`
После этого сервис делает:
- webhook на `WEBHOOK_URL`
- `303 See Other` на `return_url`
---
## 5. GET `/health`
Проверка состояния сервиса.
### Пример
~~~bash
curl -s http://127.0.0.1:8083/health
~~~
### Ответ
~~~json
{
"status": "ok",
"payments_total": 2,
"idempotence_keys_total": 2
}
~~~
---
# Webhook
После `success`:
~~~json
{
"event": "payment.succeeded",
"type": "notification",
"object": {
"id": "payment_id",
"status": "succeeded",
"paid": true,
"amount": {
"value": "100.00",
"currency": "RUB"
},
"description": "Заказ №1",
"metadata": {}
}
}
~~~
После `cancel` / `fail`:
~~~json
{
"event": "payment.canceled",
"type": "notification",
"object": {
"id": "payment_id",
"status": "canceled",
"paid": false,
"amount": {
"value": "250.00",
"currency": "RUB"
},
"description": "Заказ №2",
"metadata": {
"mock_scenario": "cancel"
}
}
}
~~~
---
# Retry webhook
Если endpoint webhook отвечает ошибкой или недоступен:
- мок делает повторные попытки
- количество попыток задается `WEBHOOK_RETRY_COUNT`
- задержка между попытками задается `WEBHOOK_RETRY_DELAY_SEC`
Логи смотреть так:
~~~bash
docker logs --tail 100 yookassa-mock
~~~
---
# Сценарии через metadata
При создании платежа можно задать сценарий по умолчанию:
~~~json
"metadata": {
"mock_scenario": "cancel"
}
~~~
Допустимые значения:
- `success`
- `cancel`
- `fail`
Если в `POST /process/{payment_id}` не передать `action`, будет использован `mock_scenario`.
---
# Basic Auth
Если включить:
~~~env
MOCK_REQUIRE_AUTH=1
~~~
Тогда endpoints `/v3/payments` и `/v3/payments/{payment_id}` будут требовать Basic Auth.
Логин/пароль берутся из:
- `MOCK_SHOP_ID`
- `MOCK_SECRET_KEY`
---
# Ограничения
Это мок, не полная копия YooKassa.
Сейчас нет:
- persistent storage
- списка платежей
- ручного cancel endpoint в стиле реального API
- полной схемы YooKassa
- реальной проверки секретов YooKassa
- capture/authorize flow с отдельным подтверждением списания
- рефандов
---
# Текущее состояние проверки
Проверено вручную:
- создание платежа — OK
- `confirmation_url` — OK
- `GET /v3/payments/{id}` — OK
- идемпотентность — OK
- `pending -> succeeded` — OK
- `pending -> canceled` — OK
- redirect на `return_url` — OK
- retry webhook — OK
Проблема сейчас только одна:
`WEBHOOK_URL` отвечает `404 Not Found`, значит endpoint на основном backend отсутствует или указан неверно.