Files

106 lines
3.2 KiB
Python

"""Зачисление оплаты по инвойсу (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"✅ <b>Баланс пополнен</b>\n\n"
f"+{amount:.0f} ₽ через {via}\n"
f"Доступно: <b>{balance:.0f} ₽</b>"
),
)
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"<b>{balance:.0f} ₽</b>"
),
)
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="Неизвестный тип счёта")