Files
backend/app/routes/subscription_routes.py

186 lines
8.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from typing import List, Optional
from fastapi import APIRouter, HTTPException, Depends
from pydantic import BaseModel
from app.services import DatabaseManager
from instance.configdb import get_database_manager
from uuid import UUID
import logging
from sqlalchemy.exc import SQLAlchemyError
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
router = APIRouter()
class BuySubscriptionRequest(BaseModel):
telegram_id: int
plan_name: str
class SubscriptionResponse(BaseModel):
id: str
user_id: int
plan_name: str
vpn_server_id: Optional[str]
status: str
start_date: str
end_date: str
created_at: str
# Эндпоинт для покупки подписки
@router.post("/subscription/buy", response_model=dict)
async def buy_subscription(
request_data: BuySubscriptionRequest,
database_manager: DatabaseManager = Depends(get_database_manager)
):
"""
Покупка подписки.
"""
try:
logger.info(f"Получен запрос на покупку подписки: {request_data.dict()}")
result = await database_manager.buy_sub(request_data.telegram_id, request_data.plan_name)
logger.info(f"Результат buy_sub: {result}")
if result == "ERROR":
raise HTTPException(status_code=500, detail="Internal server error")
elif result == "INSUFFICIENT_FUNDS":
raise HTTPException(status_code=400, detail="INSUFFICIENT_FUNDS")
elif result == "TARIFF_NOT_FOUND":
raise HTTPException(status_code=400, detail="TARIFF_NOT_FOUND")
elif result == "ACTIVE_SUBSCRIPTION_EXISTS":
raise HTTPException(status_code=400, detail="ACTIVE_SUBSCRIPTION_EXISTS")
elif result == "USER_NOT_FOUND":
raise HTTPException(status_code=404, detail="USER_NOT_FOUND")
elif result == "SUBSCRIPTION_CREATION_FAILED":
raise HTTPException(status_code=500, detail="Failed to create subscription")
elif result == "PAYMENT_FAILED_AFTER_SUBSCRIPTION":
raise HTTPException(status_code=402, detail="SUBSCRIPTION_CREATED_BUT_PAYMENT_FAILED")
elif result == "SUBSCRIPTION_CREATED_BUT_PAYMENT_FAILED":
raise HTTPException(status_code=402, detail="SUBSCRIPTION_CREATED_BUT_PAYMENT_FAILED")
# Если успешно, генерируем URI
if isinstance(result, dict) and result.get('status') == 'OK':
uri_result = await database_manager.generate_uri(request_data.telegram_id)
logger.info(f"Результат генерации URI: {uri_result}")
return {
"status": "success",
"subscription_id": result.get('subscription_id'),
"uri": uri_result[0] if uri_result and isinstance(uri_result, list) else uri_result
}
else:
return {"status": "success", "message": "Subscription created"}
except HTTPException as http_exc:
logger.error(f"HTTPException в buy_subscription: {http_exc.detail}")
raise http_exc
except Exception as e:
logger.error(f"Неожиданная ошибка в buy_subscription: {str(e)}")
raise HTTPException(status_code=500, detail=f"Unexpected error: {str(e)}")
# Эндпоинт для получения последней подписки
@router.get("/subscription/{telegram_id}/last", response_model=SubscriptionResponse)
async def last_subscription(telegram_id: int, database_manager: DatabaseManager = Depends(get_database_manager)):
"""
Возвращает последнюю подписку пользователя.
"""
logger.info(f"Получение последней подписки для пользователя: {telegram_id}")
try:
subscription = await database_manager.get_last_subscriptions(telegram_id=telegram_id)
if not subscription :
logger.warning(f"Подписки для пользователя {telegram_id} не найдены")
raise HTTPException(status_code=404, detail="No subscriptions found")
plan = await database_manager.get_plan_by_id(subscription.plan_id)
if not plan:
logger.warning(f"Тариф для пользователя {telegram_id} не найдены")
raise HTTPException(status_code=404, detail="No plan found")
return {
"id": str(subscription.id),
"user_id": subscription.user_id,
"plan_name": plan.name,
"vpn_server_id": subscription.vpn_server_id,
"status": subscription.status.value,
"start_date": subscription.start_date.isoformat(),
"end_date": subscription.end_date.isoformat(),
"created_at": subscription.created_at.isoformat(),
}
except SQLAlchemyError as e:
logger.error(f"Ошибка базы данных при получении подписки для пользователя {telegram_id}: {e}")
raise HTTPException(status_code=500, detail="Database error")
except HTTPException as e:
# Пропускаем HTTPException, чтобы FastAPI обработал её автоматически
raise e
except Exception as e:
logger.error(f"Неожиданная ошибка: {e}")
raise HTTPException(status_code=500, detail="Internal Server Error")
@router.get("/subscriptions/{telegram_id}", response_model=List[SubscriptionResponse])
async def get_subscriptions(telegram_id: int, database_manager: DatabaseManager = Depends(get_database_manager)):
"""
Возвращает список подписок пользователя.
"""
logger.info(f"Получение подписок для пользователя: {telegram_id}")
try:
# Получаем подписки без ограничений или с указанным лимитом
subscriptions = await database_manager.get_last_subscriptions(telegram_id=telegram_id)
if not subscriptions:
logger.warning(f"Подписки для пользователя {telegram_id} не найдены")
raise HTTPException(status_code=404, detail="No subscriptions found")
# Формируем список подписок для ответа
return [
{
"id": sub.id,
"plan": sub.plan,
"vpn_server_id": sub.vpn_server_id,
"expiry_date": sub.expiry_date.isoformat(),
"created_at": sub.created_at.isoformat(),
"updated_at": sub.updated_at.isoformat(),
}
for sub in subscriptions
]
except SQLAlchemyError as e:
logger.error(f"Ошибка базы данных при получении подписок для пользователя {telegram_id}: {e}")
raise HTTPException(status_code=500, detail="Database error")
except Exception as e:
logger.error(f"Неожиданная ошибка: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get("/uri", response_model=dict)
async def get_uri(telegram_id: int, database_manager: DatabaseManager = Depends(get_database_manager)):
"""
Возвращает список подписок пользователя.
"""
logger.info(f"Получение подписок для пользователя: {telegram_id}")
try:
# Получаем подписки без ограничений или с указанным лимитом
uri = await database_manager.generate_uri(telegram_id)
if uri == "SUB_ERROR":
raise HTTPException(status_code=404, detail="SUB_ERROR")
if not uri:
logger.warning(f"Не удалось сгенерировать URI для пользователя с telegram_id {telegram_id}, данные -> {uri}")
raise HTTPException(status_code=404, detail="URI not found")
return {"detail": uri[0]}
except HTTPException as e:
# Пропускаем HTTPException, чтобы FastAPI обработал её автоматически
raise e
except SQLAlchemyError as e:
logger.error(f"Ошибка базы данных при получении подписок для пользователя {telegram_id}: {e}")
raise HTTPException(status_code=500, detail="Database error")
except Exception as e:
logger.error(f"Неожиданная ошибка: {e}")
raise HTTPException(status_code=500, detail=str(e))