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( InvId: str = Form(...), OutSum: str = Form(...), Commission: str = Form(...), TrsId: str = Form(...), Status: str = Form(...), CurrencyIn: str = Form(...), custom: str | None = Form(None), SignatureValue: str = Form(...), session: AsyncSession = Depends(get_db), bot: Bot = Depends(get_bot), deps: APIDependenciesDTO = Depends(get_deps), ): oid = custom or "" raw_string = f"{OutSum}:{InvId}:{settings.pally_token}" expected_signature = hashlib.md5(raw_string.encode("utf-8")).hexdigest().upper() if SignatureValue != expected_signature: logger.critical("Invalid signature for TrsId %s", TrsId) raise HTTPException(403, detail="Invalid signature.") if Status != BillStatus.SUCCESS: logger.info("Bill %s skipped: status=%s", TrsId, Status) return "OK" logger.info("Received successfully paid bill %s", TrsId) if not oid.isdigit(): logger.critical("Invalid custom field format for TrsId %s", TrsId) 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", TrsId) 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(float(OutSum)) 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 TrsId %s (Creator: %s)", TrsId, bill.creator_id, ) await deps.bills_repository.update_bill_status( session, int(bill.id), status=DepositStatus.SUCCESS ) return "OK"