"""Зачисление оплаты по инвойсу (CryptoBot / Heleket).""" from __future__ import annotations from dataclasses import dataclass from typing import Any from remnawave import RemnawaveSDK from services.db import Database from services.purchase import purchase_tariff from services.tariffs import Tariff, get_tariff @dataclass(frozen=True, slots=True) class FulfillResult: ok: bool message: str already: bool = False async def fulfill_paid_invoice( *, db: Database, sdk: RemnawaveSDK, tariffs: list[Tariff], local: dict[str, Any], ) -> FulfillResult: """Идемпотентно зачислить оплаченный инвойс.""" invoice_id = int(local["invoice_id"]) provider = str(local.get("provider") or "cryptobot") if local.get("status") == "paid": return FulfillResult(ok=True, message="Уже зачислено", already=True) if not db.mark_invoice_paid(invoice_id, provider=provider): return FulfillResult(ok=True, message="Уже зачислено", already=True) kind = local["kind"] amount = float(local["amount_rub"]) telegram_id = int(local["telegram_id"]) try: db.log_payment_event( provider=provider, event_type=f"fulfill:{kind}", telegram_id=telegram_id, amount=amount, invoice_ref=str(invoice_id), status="ok", ) except Exception: # noqa: BLE001 pass meta_prefix = f"{provider}:{invoice_id}" if kind == "topup": if provider == "lava": balance_kind = "lava_topup" via = "Lava" elif provider == "anypay": balance_kind = "anypay_topup" via = "AnyPay" else: balance_kind = "crypto_topup" via = f"криптой ({provider})" balance = db.add_balance( telegram_id, amount, kind=balance_kind, meta=meta_prefix, ) return FulfillResult( ok=True, message=( f"✅ Баланс пополнен\n\n" f"+{amount:.0f} ₽ через {via}\n" f"Доступно: {balance:.0f} ₽" ), ) if kind == "tariff": tariff = get_tariff(tariffs, str(local.get("tariff_id") or "")) if not tariff: balance = db.add_balance( telegram_id, amount, kind="crypto_topup", meta=f"{meta_prefix}:unknown_tariff", ) return FulfillResult( ok=True, message=( "Оплата получена, тариф не найден — зачислено на баланс: " f"{balance:.0f} ₽" ), ) result = await purchase_tariff( db=db, sdk=sdk, telegram_id=telegram_id, tariff=tariff, charge_balance=False, payment_meta=meta_prefix, ) return FulfillResult(ok=result.ok, message=result.message) return FulfillResult(ok=False, message="Неизвестный тип счёта")