Интегрировал биллинг при оплате подписки
This commit is contained in:
@@ -1,55 +1,79 @@
|
||||
import aiohttp
|
||||
import logging
|
||||
from typing import Optional, Dict, Any
|
||||
from typing import Dict, Any, Optional
|
||||
from enum import Enum
|
||||
|
||||
class BillingService:
|
||||
def __init__(self, base_url: str, api_key: str):
|
||||
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.api_key = api_key
|
||||
self.logger = logging.getLogger(__name__)
|
||||
self.session = None
|
||||
|
||||
async def get_session(self):
|
||||
if self.session is None:
|
||||
self.session = aiohttp.ClientSession(
|
||||
headers={'Authorization': f'Bearer {self.api_key}'}
|
||||
)
|
||||
self.session = aiohttp.ClientSession()
|
||||
return self.session
|
||||
|
||||
async def process_payment(self, telegram_id: int, amount: float, plan_name: str) -> Dict[str, Any]:
|
||||
"""Обработка платежа через биллинг-сервис"""
|
||||
async def withdraw_funds(self, user_id: int, amount: float, description: str = "") -> Dict[str, Any]:
|
||||
"""
|
||||
Списание средств через биллинг-сервис
|
||||
"""
|
||||
try:
|
||||
session = await self.get_session()
|
||||
|
||||
payload = {
|
||||
"user_id": telegram_id,
|
||||
"user_id": user_id,
|
||||
"amount": amount,
|
||||
"plan_name": plan_name,
|
||||
"currency": "USD"
|
||||
"description": description or f"Payment for subscription"
|
||||
}
|
||||
|
||||
async with session.post(f"{self.base_url}/payments/process", json=payload) as response:
|
||||
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:
|
||||
return await response.json()
|
||||
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": "BILLING_SERVICE_ERROR"}
|
||||
return {"status": "error", "code": "SERVICE_UNAVAILABLE"}
|
||||
|
||||
except Exception as e:
|
||||
except aiohttp.ClientError as e:
|
||||
self.logger.error(f"Billing service connection error: {str(e)}")
|
||||
return {"status": "error", "code": "CONNECTION_ERROR"}
|
||||
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 check_payment_status(self, payment_id: str) -> Dict[str, Any]:
|
||||
"""Проверка статуса платежа"""
|
||||
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}/payments/{payment_id}") as response:
|
||||
|
||||
async with session.get(f"{self.base_url}/billing/balance/{user_id}") as response:
|
||||
if response.status == 200:
|
||||
return await response.json()
|
||||
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"}
|
||||
return {"status": "error", "code": "SERVICE_UNAVAILABLE"}
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"Billing service check error: {str(e)}")
|
||||
return {"status": "error"}
|
||||
self.logger.error(f"Error getting balance: {str(e)}")
|
||||
return {"status": "error", "code": "SERVICE_UNAVAILABLE"}
|
||||
|
||||
async def close(self):
|
||||
if self.session:
|
||||
|
||||
Reference in New Issue
Block a user