yookassax
Русский | English
Неофициальная библиотека. Проект не связан с ЮKassa и ЮMoney, ими не поддерживается и их продуктом не является. Официальный SDK лежит здесь. ЮKassa и ЮMoney — товарные знаки своих владельцев.
Неофициальный клиент ЮKassa для Python в двух режимах: синхронном и асинхронном. Типизированные модели, разбор уведомлений, идемпотентность и повторы из коробки.
pip install yookassax
Требуется Python 3.10 или новее. Единственная зависимость: httpx.
Быстрый старт
Синхронно:
from yookassax import YooKassa
with YooKassa(shop_id="123456", secret_key="live_...") as kassa:
payment = kassa.payments.create({
"amount": {"value": "100.00", "currency": "RUB"},
"confirmation": {"type": "redirect", "return_url": "https://example.com/done"},
"capture": True,
"description": "Заказ 42",
})
print(payment.confirmation_url)
Асинхронно, то же самое:
from yookassax import AsyncYooKassa
async with AsyncYooKassa(shop_id="123456", secret_key="live_...") as kassa:
payment = await kassa.payments.create({
"amount": {"value": "100.00", "currency": "RUB"},
"confirmation": {"type": "redirect", "return_url": "https://example.com/done"},
"capture": True,
})
Наборы методов у режимов одинаковые, это проверяется тестом. Переход с одного
на другой сводится к добавлению await.
Примеры
Все сценарии из официальной документации, оба режима, два языка: русский, English.
| Настройка клиента | аутентификация, магазин, подписки |
| Платежи | создание, подтверждение, отмена, списки |
| Возвраты | полные и частичные |
| Чеки | 54-ФЗ, маркированные товары |
| Сделки | безопасная сделка целиком |
| Выплаты | карта, СБП, кошелёк, самозанятые |
| Самозанятые | регистрация и подтверждение |
| Персональные данные | получатели выплат |
| Банки СБП | справочник |
| Счета | ссылка на оплату |
| Способы оплаты | подписки и автоплатежи |
| Кассовые ссылки | статические QR-коды |
| Уведомления | FastAPI, Django, Flask |
| Ошибки и повторы | идемпотентность, обрывы связи |
| Модели ответов | все 73 модели и сверка со спецификацией |
| Партнёрская программа | OAuth, работа от имени чужого магазина |
| Коды ответа HTTP | что означает каждый и что делать |
| Тестовый магазин | отладка, подмена HTTP, живой прогон |
Чем отличается от официального SDK
Ключи хранятся в экземпляре клиента. Официальный SDK держит их в
Configuration на уровне класса. Если приложение работает с несколькими
магазинами из одного процесса, два платежа могут переписать токен друг другу
между настройкой и вызовом, и платёж уйдёт через чужой магазин. Здесь каждый
клиент носит свои ключи, и такой гонки не существует.
Асинхронный режим настоящий. Официальный SDK синхронный, внутри requests.
Вызов из асинхронного обработчика останавливает весь воркер: пока идёт
обращение к API, процесс не обслуживает никого.
Ключ идемпотентности проставляется сам на всех изменяющих запросах. Повтор после обрыва связи идёт с тем же ключом, поэтому второго платежа не возникает.
Повторы на кодах 202, 429 и 500 с экспоненциальной паузой и дрожанием. Ошибки данных (400, 404) не повторяются: второй такой же запрос даст тот же ответ.
Способ оплаты разбирается в модель своего типа. Все 19 из спецификации:
PaymentMethodBankCard, PaymentMethodSberLoan,
PaymentMethodElectronicCertificate и так далее. Различать через isinstance,
подробности.
Модели типизированы и терпимы к новым полям. ЮKassa добавляет поля в
ответы; строгая модель превратила бы это в отказ обслуживать платежи. Всё
неизвестное складывается в raw и доступно через extra. Но не молча: на
каждое такое поле один раз выдаётся UnknownFieldWarning, иначе о новом поле
никто и не узнает.
Билдеров нет. Тело запроса это обычный словарь: он принимает новые поля API сразу, а не после обновления библиотеки.
Работа с платежами
payment = kassa.payments.create({...})
payment.is_pending # ждём оплату
payment.is_waiting_for_capture # деньги захолдированы, нужен capture или cancel
payment.is_succeeded # деньги у магазина
payment.is_canceled # деньги у плательщика
payment.amount.value # Decimal("100.00"), не float
payment.created_at # datetime с часовым поясом
payment.confirmation_url # куда вести плательщика, либо None
kassa.payments.capture(payment.id)
kassa.payments.cancel(payment.id)
Списки
page = kassa.payments.list(status="succeeded", limit=50)
for payment in page:
print(payment.id)
if page.has_more:
next_page = kassa.payments.list(status="succeeded", cursor=page.next_cursor)
Или без ручного перелистывания:
for payment in kassa.payments.iterate(status="succeeded"):
print(payment.id)
В асинхронном режиме то же самое через async for.
Уведомления
Тело уведомления ЮKassa не подписывает, поэтому единственная встроенная проверка это адрес отправителя. Её недостаточно: решение о деньгах принимайте по ответу API, а не по телу уведомления.
from fastapi import Request, Response
from yookassax import webhooks
@app.post("/webhook")
async def handle(request: Request):
if not webhooks.is_trusted_ip(request.headers.get("X-Real-IP", "")):
return Response(status_code=403)
notification = webhooks.parse(await request.json())
if notification.is_payment_succeeded:
payment = await kassa.payments.get(notification.object.id)
if payment.is_succeeded:
...
return {"ok": True}
Берите достоверный адрес отправителя. За обратным прокси это тот, который
прокси проставляет сам, обычно X-Real-IP из nginx. Левый элемент
X-Forwarded-For подставляет клиент, и проверка теряет смысл.
Отвечайте 200 быстро: иначе ЮKassa повторит доставку, и обработчик получит то же событие ещё раз.
Ошибки
from yookassax import BadRequest, Forbidden, TransportError, YooKassaError
try:
payment = kassa.payments.create({...})
except Forbidden:
# магазину не разрешена операция, частый случай: не подключён рекуррент
...
except BadRequest as error:
print(error.code, error.description, error.parameter)
except TransportError:
# ответа не было вообще, состояние платежа неизвестно
...
except YooKassaError:
...
TransportError стоит отдельно от остальных намеренно: если создание платежа
упало с ним, неизвестно, создан платёж или нет.
Новые поля в ответах
Поле, которого нет в модели, разбор не роняет, но и не скрывает:
payment = kassa.payments.get(payment_id)
# UnknownFieldWarning: Payment: в ответе API есть поля, которых нет в модели:
# loyalty_bonus. Значения доступны через extra(), но, возможно, стоит обновить
# yookassax.
payment.extra("loyalty_bonus")
Предупреждение указывает на строку вашего кода и выдаётся один раз на пару "модель плюс поле" за жизнь процесса: страница из ста платежей даст одну строку, а не сто. Отключается штатным фильтром:
import warnings
from yookassax import UnknownFieldWarning
warnings.filterwarnings("ignore", category=UnknownFieldWarning)
Доступные ресурсы
payments, refunds, receipts, payouts, webhooks, settings,
payment_methods, deals, invoices, personal_data, self_employed,
pos_links, sbp_banks.
Покрыты все маршруты официальной спецификации OpenAPI. Полнота проверяется тестом.
OAuth
Для работы с чужими магазинами:
kassa = YooKassa(oauth_token="токен, выданный магазином")
Одновременно с shop_id и secret_key не задаётся: клиент откажется
собираться, чтобы не выбирать за вас.
Как получить такой токен, подписаться на уведомления по API и что делать, когда магазин отозвал права, - в примерах по партнёрской программе.
Эндпоинт, которого ещё нет в библиотеке
from yookassax import Operation
operation = Operation(
method="POST",
path="/new_endpoint",
body={"key": "value"},
idempotent=True,
)
result = kassa.send(operation)
Для ИИ-ассистентов
В каталоге docs лежит llms.txt: полный справочник по
библиотеке одним файлом, чтобы вставить в контекст модели. Английская
версия: llms.en.txt.
Разработка
pip install -e ".[dev]"
pytest
ruff check .
mypy src
Тесты не ходят в сеть. Отдельно есть прогон по живому API, он требует ключи тестового магазина и без них пропускается:
export YOOKASSA_SHOP_ID=... YOOKASSA_SECRET_KEY=test_...
pytest tests/integration
Лицензия
MIT.
Metadata
Release files for yookassax 2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| yookassax-2.2.tar.gz | 868.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| yookassax-2.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 934.2 kB
Release files / yookassax-2.2.tar.gz
| Download URL | yookassax-2.2.tar.gz |
|---|---|
| Size | 868.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f34b345dd1ae26b1d7e165c97de6e190665ab8db1de85d43db68fffa4e528208
|
|
BLAKE2b-256 checksum How to use checksums |
f644a61c694c3fb71de56d6bbec89fc57db8f718e5149d62b11f76dc15e58496
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 30, 2026.
Transparency logRelease files / yookassax-2.2-py3-none-any.whl
| Download URL | yookassax-2.2-py3-none-any.whl |
|---|---|
| Size | 65.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b329e00ef78536a9b0b54d146d1d7354798294f6bbb4c0fd92d6dbc5f2abc66f
|
|
BLAKE2b-256 checksum How to use checksums |
ba76fab7c426c3ec3ccc06a7bc64e8fdd7293f395b227b240e50d042ccfb85d9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 30, 2026.
Transparency log