Исходный код tbank.direct_debit.aio

from __future__ import annotations

from typing import Optional, Sequence

import httpx

from tbank.core.auth import BearerAuth
from tbank.core.client import BaseAsyncClient
from tbank.core.client import ensure_idempotency_key as _idem
from tbank.core.client import page_params as _page
from tbank.core.errors import TBankAPIError
from tbank.core.retry import RetryPolicy
from tbank.core.transport import AsyncTransport, CertTypes, VerifyTypes
from tbank.core.urls import SANDBOX_SECURED_URL, SECURED_URL
from tbank.direct_debit._endpoints import RULE_DETAILS as _RULE_DETAILS
from tbank.direct_debit._endpoints import V1 as _V1
from tbank.direct_debit._endpoints import V2 as _V2
from tbank.direct_debit._endpoints import enum_list as _enum_list
from tbank.direct_debit.enums import RuleType
from tbank.direct_debit.errors import error_from_direct_debit_response
from tbank.direct_debit.models import (
    AgreementDetails,
    AgreementFile,
    AgreementListResponse,
    AgreementUrl,
    CreatePaymentRequest,
    CreatePaymentRequestResult,
    CreateRuleResult,
    PaymentRequestDetails,
    PaymentRequestFile,
    PaymentRequestListResponse,
    RuleCreate,
    RuleDetails,
    RuleDetailsListResponse,
    RuleListResponse,
    RuleUpdate,
)


[документация] class DirectDebitClient(BaseAsyncClient): """Асинхронный клиент безакцептных списаний: соглашения, правила (рекуррентные и триггерные) и платёжные требования. Весь домен работает на secured-хосте и требует **mTLS-сертификата** (`cert`). Методы создания принимают ключ идемпотентности `idempotency_key` (по умолчанию генерируется автоматически). Суммы — `Decimal` в рублях, провод — `camelCase`. """ decimal_body = True def __init__( self, token: str, *, base_url: Optional[str] = None, sandbox: bool = False, cert: Optional[CertTypes] = None, verify: VerifyTypes = True, retry: Optional[RetryPolicy] = None, transport: Optional[AsyncTransport] = None, ) -> None: resolved = base_url or (SANDBOX_SECURED_URL if sandbox else SECURED_URL) transport = transport or AsyncTransport( base_url=resolved, auth=BearerAuth(token), cert=cert, verify=verify, retry=retry, ) super().__init__(transport) def _error_from_response(self, response: httpx.Response) -> TBankAPIError: return error_from_direct_debit_response(response) # --- Правила ---
[документация] async def list_rules( self, agreement_id: str, *, offset: Optional[int] = None, limit: Optional[int] = None, ) -> RuleListResponse: """Список правил соглашения.""" return await self._get( f"{_V1}/rules", RuleListResponse, params=_page(offset, limit, agreementId=agreement_id), )
[документация] async def list_rules_v2( self, *, agreement_id: Optional[str] = None, rule_types: Optional[Sequence[RuleType]] = None, offset: Optional[int] = None, limit: Optional[int] = None, ) -> RuleDetailsListResponse: """Список правил с полной карточкой (v2).""" return await self._get( f"{_V2}/rules", RuleDetailsListResponse, params=_page( offset, limit, agreementId=agreement_id, ruleTypes=_enum_list(rule_types), ), )
[документация] async def create_rule( self, rule: RuleCreate, *, idempotency_key: Optional[str] = None ) -> CreateRuleResult: """Создать правило (рекуррентное или триггерное).""" return await self._send( "POST", f"{_V1}/rules", CreateRuleResult, body=rule, idempotency_key=_idem(idempotency_key), )
[документация] async def get_rule(self, rule_id: str) -> RuleDetails: """Карточка правила.""" return await self._get(f"{_V1}/rules/{rule_id}", _RULE_DETAILS)
[документация] async def update_rule(self, rule_id: str, rule: RuleUpdate) -> RuleDetails: """Обновить правило.""" return await self._send( "PUT", f"{_V1}/rules/{rule_id}", _RULE_DETAILS, body=rule )
[документация] async def delete_rule(self, rule_id: str) -> None: """Удалить правило.""" await self._send("DELETE", f"{_V1}/rules/{rule_id}")
# --- Платёжные требования ---
[документация] async def list_payment_requests( self, *, start_date: Optional[str] = None, end_date: Optional[str] = None, offset: Optional[int] = None, limit: Optional[int] = None, ) -> PaymentRequestListResponse: """Список платёжных требований за период (`YYYY-MM-DD`).""" return await self._get( f"{_V1}/requests", PaymentRequestListResponse, params=_page(offset, limit, startDate=start_date, endDate=end_date), )
[документация] async def create_payment_request( self, request: CreatePaymentRequest, *, idempotency_key: Optional[str] = None ) -> CreatePaymentRequestResult: """Создать платёжное требование.""" return await self._send( "POST", f"{_V1}/requests", CreatePaymentRequestResult, body=request, idempotency_key=_idem(idempotency_key), )
[документация] async def get_payment_request(self, request_id: str) -> PaymentRequestDetails: """Карточка платёжного требования.""" return await self._get(f"{_V1}/requests/{request_id}", PaymentRequestDetails)
[документация] async def revoke_payment_request( self, request_id: str, *, idempotency_key: Optional[str] = None ) -> None: """Отозвать платёжное требование.""" await self._send( "POST", f"{_V1}/requests/{request_id}/revoke", idempotency_key=_idem(idempotency_key), )
[документация] async def get_payment_request_file(self, request_id: str) -> PaymentRequestFile: """PDF платёжного требования (base64).""" return await self._get(f"{_V1}/requests/{request_id}/file", PaymentRequestFile)
# --- Соглашения ---
[документация] async def list_agreements( self, *, offset: Optional[int] = None, limit: Optional[int] = None ) -> AgreementListResponse: """Список соглашений о безакцептном списании.""" return await self._get( f"{_V1}/agreements", AgreementListResponse, params=_page(offset, limit) )
[документация] async def get_agreement(self, agreement_id: str) -> AgreementDetails: """Карточка соглашения.""" return await self._get(f"{_V1}/agreements/{agreement_id}", AgreementDetails)
[документация] async def get_agreement_file(self, agreement_id: str) -> AgreementFile: """PDF-файл соглашения (base64).""" return await self._get(f"{_V1}/agreements/{agreement_id}/file", AgreementFile)
[документация] async def get_agreement_url(self) -> AgreementUrl: """Ссылка на форму подписания соглашения для контрагента.""" return await self._get(f"{_V1}/agreements/url", AgreementUrl)