Metadata-Version: 2.4
Name: tbank-securepay
Version: 0.3.0
Summary: Обёртка над REST API интернет-эквайринга Т‑Кассы (eacq): Init, Confirm, Cancel, СБП, SberPay, T‑Pay и др. См. https://developer.tbank.ru/eacq/api
Author: TinkoffKassaAPI contributors
License: MIT
Project-URL: Documentation, https://developer.tbank.ru/eacq/api
Project-URL: Payments, https://www.tbank.ru/kassa/dev/payments/
Keywords: tbank,tinkoff,kassa,eacq,acquiring,payments,tkassa,securepay
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.27
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Dynamic: license-file

# tbank-securepay

Клиент для REST API интернет-эквайринга **Т‑Кассы** (Т‑Банк, [eacq](https://developer.tbank.ru/eacq/api)): `Init`, `FinishAuthorize`, `Confirm`, `Cancel`, `GetState`, `CheckOrder`, SberPay / T‑Pay / Mir Pay / СБП и др.

**PyPI:** `tbank-securepay` · **импорт:** `import tbank_securepay` (имя совпадает с хостом API `securepay.tinkoff.ru`).

Пакеты вроде `tbank-kassa`, `tbank-kassa-api`, `django-tbank-kassa` на PyPI — другие проекты.

- Каталог методов в портале разработчика: [developer.tbank.ru/eacq/api](https://developer.tbank.ru/eacq/api)
- Доп. материалы по сценариям: [tbank.ru/kassa/dev/payments](https://www.tbank.ru/kassa/dev/payments/)

Для запросов с вложенными объектами (`Receipt`, `DATA` и т.д.) правила подписи `Token` отличаются — см. [раздел про токен](https://developer.tbank.ru/eacq/intro/developer/token); текущая реализация `append_token` учитывает только «плоские» поля верхнего уровня.

## Установка

С [PyPI](https://pypi.org/project/tbank-securepay/):

```bash
pip install tbank-securepay
```

Из каталога с репозиторием:

```bash
pip install .
```

Режим разработки (редактируемый код сразу доступен импорту):

```bash
pip install -e ".[dev]"
```

## Использование

Учётные данные (`TerminalKey` и пароль терминала) задаёт ваше приложение — библиотека их не читает из `.env`.

### Контекстный менеджер (рекомендуется)

Клиент держит внутри **`httpx.Client`** или **`httpx.AsyncClient`**. Если вы **не** передаёте свой экземпляр `httpx`, библиотека создаёт его сама и при выходе из контекста **корректно закрывает** соединения (`close()` / `aclose()`).

Синхронно:

```python
from tbank_securepay import PaymentInitParams, TKassaClient

with TKassaClient(terminal_key="...", password="...") as client:
    result = client.payment_init(
        PaymentInitParams(amount=1000, order_id="order-1", description="Оплата заказа")
    )
    if result.success:
        print(result.payment_url)
```

Асинхронно — та же идея: **`async with`** вызывает `await client.aclose()` при выходе (для клиента, созданного библиотекой). Это обычный контекстный протокол поверх `httpx`, для asyncio он уместен и предсказуем.

```python
import asyncio
from tbank_securepay import AsyncTKassaClient, PaymentInitParams

async def main():
    async with AsyncTKassaClient(terminal_key="...", password="...") as client:
        r = await client.payment_init(
            PaymentInitParams(amount=1000, order_id="o-1", description="Оплата")
        )
        print(r.success, r.payment_url)

asyncio.run(main())
```

Если вы передали **свой** `client=httpx.Client(...)` или `httpx.AsyncClient(...)`, библиотека **не** закрывает его при выходе из `with` / `async with` — закрывайте сами (или используйте его как контекстный менеджер снаружи).

### Без контекста

`TKassaClient` внутри держит `httpx.Client`. Метод **`close()`** (и у async-версии **`await aclose()`**) вызывает **`httpx`-закрытие** пула соединений: сокеты и keep-alive освобождаются **сразу**, а не «когда-нибудь при выходе процесса».

**Когда `close()` по сути не обязателен:** одноразовый скрипт, который сделал один запрос и сразу завершился — после `exit` ОС всё равно заберёт дескрипторы. В таком случае вызов можно опустить (многие так и делают в черновых скриптах).

**Когда закрывать нужно или разумно:** долгоживущий процесс (веб-сервер, воркер), **много раз** создаёте и бросаете клиентов, тесты, ограничения на число открытых соединений. Тогда без закрытия пул может жить до конца процесса и держать лишние ресурсы.

Практичнее не помнить про `close()`, а использовать **`with TKassaClient(...)`** — выход из блока сам вызовет `close()` для клиента, созданного библиотекой.

```python
client = TKassaClient("...", "...")
try:
    st = client.get_state("123456789")
    print(st.status, st.raw)
finally:
    client.close()  # явное закрытие, если не используете with
```

### Статус: GetState и CheckOrder

```python
with TKassaClient(terminal_key="...", password="...") as client:
    by_payment = client.get_state("00000000000000000001")
    print(by_payment.success, by_payment.status, by_payment.payments)

    by_order = client.check_order("my-shop-order-42")
    print(by_order.raw)
```

### Init, отмена, списание, статус (типизированные параметры)

```python
from tbank_securepay import (
    PaymentCancelParams,
    PaymentConfirmParams,
    PaymentInitParams,
    PaymentResendParams,
    TKassaClient,
)

with TKassaClient(terminal_key="...", password="...") as client:
    init = client.payment_init(
        PaymentInitParams(amount=1000, order_id="o-1", description="Заказ")
    )
    st = client.payment_status(init)  # GetState по PaymentId, если есть
    same = client.payment_status("o-1")  # или просто order_id (строка) → CheckOrder

    client.payment_cancel(
        PaymentCancelParams(payment_id="00000000000000000001", amount=1000)
    )
    client.payment_confirm(
        PaymentConfirmParams(payment_id="00000000000000000001", amount=1000)
    )
    client.payment_resend(PaymentResendParams(payment_id="00000000000000000001"))
```

Имена ``InitPaymentParams`` / ``InitPaymentResult`` и метод ``init_payment`` — алиасы к ``PaymentInitParams`` / ``PaymentInitResult`` и ``payment_init``.

### Произвольный метод API: `post`

Для редких полей и методов без типизированной обёртки используйте ``post`` / ``cancel`` / ``confirm`` с ``**kwargs`` (см. документацию API). Типичные сценарии отмены и списания удобнее через ``payment_cancel`` / ``payment_confirm``.

```python
with TKassaClient(terminal_key="...", password="...") as client:
    data = client.post(
        "Cancel",
        {"PaymentId": "00000000000000000001", "Amount": 1000},
    )
    print(data.get("Success"), data.get("Status"))
```

### Свой `httpx` (таймауты, прокси, лимиты)

```python
import httpx
from tbank_securepay import TKassaClient

transport = httpx.HTTPTransport(retries=2)
with httpx.Client(timeout=30.0, transport=transport) as http:
    with TKassaClient("...", "...", client=http) as kassa:
        r = kassa.get_state("00000000000000000001")
        print(r.raw)
```

Асинхронный вариант с общим `AsyncClient`:

```python
import httpx
from tbank_securepay import AsyncTKassaClient

async def run():
    async with httpx.AsyncClient(timeout=30.0) as http:
        async with AsyncTKassaClient("...", "...", client=http) as kassa:
            return await kassa.check_order("order-1")

# asyncio.run(run())
```

### Примеры в репозитории

Из корня после `pip install -e .`:

```bash
python examples/create_payment.py <terminal_key> <terminal_password>
python examples/check_payment.py <terminal_key> <terminal_password> <order_id>
```

В этих скриптах клиент тоже открывается через **`with TKassaClient(...)`**.

## Лицензия

MIT
