Skip to main content

image project

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, живой прогон
Логи logging, loguru, секреты в лог не уходят

Чем отличается от официального 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)

Логи

Каждое обращение к API пишется стандартным logging в логгер yookassax. Приложениям на loguru отдельная поддержка не нужна: записи подхватывает InterceptHandler.

import logging

logging.getLogger("yookassax").setLevel(logging.INFO)
ЮKassa ответ: POST /payments -> 200 за 0.412 c, id: 3225ad37-000f-5001-8000-108ff2fd923d
ЮKassa повтор: POST /payments, попытка 2 через 0.503 c, причина: ServerError

Заголовок Authorization в лог не попадает никогда, тела запроса и ответа — только на DEBUG: там персональные данные плательщика.

Доступные ресурсы

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.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for yookassax 2.3
File Size Uploaded
yookassax-2.3.tar.gz 874.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for yookassax 2.3
File Interpreter ABI Platform
yookassax-2.3-py3-none-any.whl Python 3 none any Details

Total release size: 943.1 kB

Release files / yookassax-2.3.tar.gz

Download URL yookassax-2.3.tar.gz
Size 874.9 kB
Tags Source
SHA-256 checksum
How to use checksums
9d6e9cee068658d394d34b5765d235a78b8034227dabab8f0e52d2a69e0aaf78
BLAKE2b-256 checksum
How to use checksums
bd553c0ca8b69e8acbe0863b7263474c7e87e54b3683f8c18661011baa015a9b
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

Release files / yookassax-2.3-py3-none-any.whl

Download URL yookassax-2.3-py3-none-any.whl
Size 68.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
960bc4d841a93941bf4cb46d8d538e4f3568c8b07d68c9fe1effa8c63e79ed4c
BLAKE2b-256 checksum
How to use checksums
ee233c9dd230287b58b289123c46ba0cb3d7dd34088d7404817ea04b673a310c
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

Release history Release notifications | RSS feed

This release

2.3 This release

2 release files

2.2

2 release files

2.1

2 release files

2.0

2 release files

1.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page