Интеграция на Python
Готовый, протестированный набор для серверной интеграции (Python 3.11+, только стандартная библиотека). Он реализует стабильный Idempotency-Key, безопасные повторы, проверку подписи вебхука, выдачу «ровно один раз», срок заказа и правило позднего платежа.
Скачать набор: eleven-pay-merchant-kit.zip (каталоги python/, node/, test-vectors/, curl/). Порядок — тот же, что в Счетах Cashier.
Пилотный режим
Реального приёма платежей через счета Cashier пока нет. Тесты и демонстрации набора работают на имитациях и ничего не отправляют в сеть. Базовый адрес API вам выдают при подключении.
Состав набора
| Файл | Назначение |
|---|---|
eleven_pay_client.py | HTTP-клиент: создание/чтение счёта, опрос; ключ идемпотентности обязателен |
order_store.py | где решается «оплачено один раз»: заказы, ключи, события, очередь разбора |
checkout_service.py | адаптер сайта: настройки из окружения и CheckoutService |
webhook_verify.py, webhook_receiver.py | проверка подписи и приём вебхука |
offline_demo.py | демонстрация на имитациях, без сети и учётных данных |
test_*.py | тесты (python -m unittest discover -s . -p "test_*.py") |
order_store.py — набросок на SQLite: в продакшене это таблицы вашей базы, а важны сами механизмы (условное обновление WHERE status = 'awaiting_payment', запись event id, очередь выдачи).
Настройка (переменные окружения)
| Переменная | Обязательна | Значение |
|---|---|---|
ELEVENPAY_BASE_URL | да | базовый адрес API (https); значения по умолчанию нет |
ELEVENPAY_API_KEY | да | ключ ep_live_… из секрет-хранилища сервера |
ELEVENPAY_WEBHOOK_SECRET | да | секрет подписи вебхука |
ELEVENPAY_ORDER_TTL_SECONDS | нет (1800) | срок заказа на вашей стороне, 60–604800 |
ELEVENPAY_POLL_DEADLINE_SECONDS | нет (600) | предел ожидания опроса |
ELEVENPAY_LATE_PAYMENT_POLICY | нет (review) | review — на ручной разбор; fulfil — выдать |
Использование
import os
from checkout_service import OrderNotPayable, StartUncertain, build_service
from eleven_pay_client import ApiError
from order_store import OrderStore
service = build_service(os.environ, store=OrderStore("orders.sqlite3"))
# 1. Заказ создаёт ВАШ сайт: сумма из вашего каталога, срок — ваш.
service.place_order("order_1001", 1500)
# 2. Попросить Eleven Pay отправить счёт плательщику (телефон очищается только от оформления).
try:
started = service.start_payment("order_1001", "+7 700 123 45 67")
print(started.reference, started.payer_step, started.replayed)
except StartUncertain:
# Ответа нет: счёт мог быть создан. Повторите ПОЗЖЕ тем же вызовом (тот же ключ).
pass
except OrderNotPayable as error:
print(error.reason) # unknown_order | paid | expired
except ApiError as error:
print(error.status, error.code) # см. таблицу ошибок
# 3. Прогресс страницы (опционально): один запрос или ограниченный опрос.
result = service.refresh("order_1001") # RefreshResult(outcome, payer_step)
result = service.await_payment("order_1001") # "awaiting" по истечении предела = ещё не оплачено
# 4. Ваш срок: истёкшие неоплаченные заказы (ничего не отменяет в Eleven Pay).
expired = service.expire_stale()payer_step — стабильный ключ для вашего интерфейса: sending_request, approve_in_kaspi, paid, not_sent, unconfirmed. Показывайте «подтвердите в приложении» только при approve_in_kaspi.
Приём вебхука
Вызывайте handle_webhook с сырыми байтами тела и заголовками. Верните его статус как HTTP-ответ: 401 — подпись неверна, 200 — принято (в том числе дубликат, поздний платёж, разбор), 500 — наша ошибка (Eleven Pay повторит).
# внутри вашего обработчика POST /webhooks/eleven-pay (любой фреймворк)
status, outcome = service.handle_webhook(dict(request_headers), raw_body_bytes)
return status # тело ответа не требуетсяИсходы: fulfilled, duplicate, already_paid, late_payment, needs_review, ignored_event_type. Выдачу выполняет ваш отдельный процесс по очереди fulfilment_outbox (запись делается в той же транзакции, что и смена статуса заказа).
Что проверять перед запуском
python -m unittest discover -s . -p "test_*.py"— зелёный;python offline_demo.py— проходит.- Тест на ваших данных: двойной клик, дубликат вебхука, поддельная подпись, просроченный заказ, поздний платёж (Чек-лист, Локальное тестирование).
- Ваша база заменила SQLite-набросок, а ключ идемпотентности хранится вместе с заказом.