# 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=` 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 отсутствует или указан неверно.