Files
malenia/api/routes/pally.py

107 lines
3.5 KiB
Python

import hashlib
import logging
import math
from aiogram import Bot
from fastapi import Depends, Form, HTTPException
from fastapi.routing import APIRouter
from sqlalchemy.ext.asyncio import AsyncSession
from api.core.deps import get_bot, get_db, get_deps
from api.core.notifications import successful_payment_notification
from config import settings
from db.models.bills import DepositStatus
from db.models.transactions import BalanceTxType
from misc.pally import BillStatus
from schemas.di import APIDependenciesDTO
router = APIRouter(prefix="/pally")
logger = logging.getLogger(__name__)
@router.post("/result")
async def pally_callback(
id: str = Form(...),
bill_id: str = Form(...),
status: str = Form(...),
req_amount: str = Form(...),
currency: str = Form(...),
order_id: str | None = Form(None),
signature: str = Form(...),
session: AsyncSession = Depends(get_db),
bot: Bot = Depends(get_bot),
deps: APIDependenciesDTO = Depends(get_deps),
):
oid = order_id or ""
raw_string = f"{id}{status}{req_amount}{currency}{oid}{settings.pally_token}"
md5_hash = hashlib.md5(raw_string.encode("utf-8")).hexdigest()
expected_signature = hashlib.sha1(md5_hash.encode("utf-8")).hexdigest()
if signature != expected_signature:
logger.critical("Invalid signature for bill %s", bill_id)
raise HTTPException(403, detail="Invalid signature.")
if status != BillStatus.SUCCESS or not req_amount.isdigit():
logger.info("Bill %s skipped: status=%s, req_amount=%s", bill_id, status, req_amount)
return "OK"
logger.info("Received successfully paid bill %s", bill_id)
if not oid.isdigit():
logger.critical("Invalid order_id format for bill %s", bill_id)
return "OK"
bill = await deps.bills_repository.get_bill_by_id(session, int(oid))
if not bill:
logger.critical("Bill %s is not found in db", bill_id)
return "OK"
if bill.status != DepositStatus.PENDING:
logger.warning("bill=%s is already paid according to the db", bill.id)
return "OK"
try:
amount = int(req_amount)
if bill.amount != amount:
logger.warning("requested amount for bill=%s is not equal to db entry", bill.id)
return "OK"
await deps.user_repository.increase_user_balance(
session,
bill.creator_id,
amount=amount,
tx_type=BalanceTxType.DEPOSIT,
description="personal balance deposit via PALLY",
)
await successful_payment_notification(bot, bill.creator_id, amount)
user = await deps.user_repository.get_user_by_id(session, bill.creator_id)
referal = user.referal_id if user else None
if referal is not None:
referal_amount = math.floor(amount * (settings.referal_bonus / 100))
await deps.user_repository.increase_user_balance(
session,
referal,
referal_amount,
tx_type=BalanceTxType.REFERRAL_BONUS,
description=f"referal reward for referal_id={bill.creator_id}",
)
await successful_payment_notification(bot, referal, referal_amount)
except Exception:
logger.exception(
"Exception caught while processing balances for bill %s (Creator: %s)",
bill_id,
bill.creator_id,
)
await deps.bills_repository.update_bill_status(
session, int(bill.id), status=DepositStatus.SUCCESS
)
return "OK"