import aiohttp import logging from typing import Dict, Any, Optional from enum import Enum class BillingErrorCode(Enum): INSUFFICIENT_FUNDS = "INSUFFICIENT_FUNDS" USER_NOT_FOUND = "USER_NOT_FOUND" PAYMENT_FAILED = "PAYMENT_FAILED" SERVICE_UNAVAILABLE = "SERVICE_UNAVAILABLE" class BillingAdapter: def __init__(self, base_url: str): self.base_url = base_url self.logger = logging.getLogger(__name__) self.session = None async def get_session(self): if self.session is None: self.session = aiohttp.ClientSession() return self.session async def withdraw_funds(self, user_id: int, amount: float, description: str = "") -> Dict[str, Any]: """ Списание средств через биллинг-сервис """ try: session = await self.get_session() payload = { "user_id": user_id, "amount": amount, "description": description or f"Payment for subscription" } self.logger.info(f"Withdrawing {amount} from user {user_id}") async with session.post(f"{self.base_url}/billing/payments/withdraw", json=payload) as response: if response.status == 200: result = await response.json() if result.get("success"): return {"status": "success"} else: error = result.get("error", "WITHDRAWAL_FAILED") self.logger.error(f"Withdrawal failed: {error}") return {"status": "error", "code": error} else: self.logger.error(f"Billing service error: {response.status}") return {"status": "error", "code": "SERVICE_UNAVAILABLE"} except aiohttp.ClientError as e: self.logger.error(f"Billing service connection error: {str(e)}") return {"status": "error", "code": "SERVICE_UNAVAILABLE"} except Exception as e: self.logger.error(f"Unexpected error in withdraw_funds: {str(e)}") return {"status": "error", "code": "PAYMENT_FAILED"} async def get_balance(self, user_id: int) -> Dict[str, Any]: """ Получение баланса пользователя """ try: session = await self.get_session() async with session.get(f"{self.base_url}/billing/balance/{user_id}") as response: if response.status == 200: result = await response.json() return {"status": "success", "balance": result.get("balance", 0)} elif response.status == 404: return {"status": "error", "code": "USER_NOT_FOUND"} else: return {"status": "error", "code": "SERVICE_UNAVAILABLE"} except Exception as e: self.logger.error(f"Error getting balance: {str(e)}") return {"status": "error", "code": "SERVICE_UNAVAILABLE"} async def close(self): if self.session: await self.session.close()