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 misc.pally import BillStatus from schemas.di import APIDependenciesDTO router = APIRouter(prefix="/checkout/pally") logger = logging.getLogger(__name__) @router.post("/callback") 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" try: amount = int(req_amount) await deps.user_repository.increase_user_balance(session, bill.creator_id, amount=amount) await successful_payment_notification(bot, bill.creator_id, amount) referal = bill.user.referal_id 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) 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, ) return "OK"