Template
106 lines
3.2 KiB
Python
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="Неизвестный тип счёта")
|