from fastapi import APIRouter, HTTPException, Request from fastapi.responses import JSONResponse import stripe from app.core.config import settings from pydantic import BaseModel router = APIRouter() stripe.api_key = settings.STRIPE_SECRET_KEY # Utilisation des variables d'environnement pour les price IDs STRIPE_PRICE_IDS = { 'starter': settings.STRIPE_PRICE_ID_STARTER, 'pro': settings.STRIPE_PRICE_ID_PRO, 'business': settings.STRIPE_PRICE_ID_BUSINESS } class SubscriptionRequest(BaseModel): plan_id: str user_id: str class PaymentSuccessRequest(BaseModel): session_id: str @router.post("/create-subscription") async def create_subscription(request: SubscriptionRequest): try: price_id = STRIPE_PRICE_IDS.get(request.plan_id) print(f"Plan ID reçu: {request.plan_id}") print(f"Price ID trouvé: {price_id}") print(f"Mode Stripe: {stripe.api_key.startswith('sk_test_') and 'TEST' or 'LIVE'}") if not price_id: raise HTTPException(status_code=400, detail=f"Plan non trouvé: {request.plan_id}") session = stripe.checkout.Session.create( payment_method_types=['card'], line_items=[{ 'price': price_id, 'quantity': 1, }], mode='subscription', success_url=f"{settings.FRONTEND_URL}/generate?session_id={{CHECKOUT_SESSION_ID}}", cancel_url=f"{settings.FRONTEND_URL}/tokens", metadata={ 'user_id': request.user_id, 'plan_id': request.plan_id } ) return {"sessionId": session.id} except Exception as e: print(f"Erreur complète: {str(e)}") raise HTTPException(status_code=400, detail=str(e)) @router.post("/webhook") async def stripe_webhook(request: Request): payload = await request.body() sig_header = request.headers.get("stripe-signature") try: event = stripe.Webhook.construct_event( payload, sig_header, settings.STRIPE_WEBHOOK_SECRET ) if event["type"] == "checkout.session.completed": session = event["data"]["object"] user_id = session["metadata"]["user_id"] plan_id = session["metadata"]["plan_id"] # Au lieu de mettre à jour Firebase, on renvoie les informations return { "status": "success", "user_id": user_id, "plan_id": plan_id } return {"status": "success"} except Exception as e: raise HTTPException(status_code=400, detail=str(e)) @router.post("/create-webhook") async def create_webhook_endpoint(): try: endpoint = stripe.WebhookEndpoint.create( url=f"{settings.FRONTEND_URL}/api/webhook", enabled_events=[ "checkout.session.completed", "customer.subscription.created", "customer.subscription.deleted", "invoice.paid", "invoice.payment_failed" ], description="Endpoint pour la gestion des abonnements" ) # Sauvegarder la clé secrète dans les variables d'environnement webhook_secret = endpoint.secret return { "status": "success", "endpoint_id": endpoint.id, "webhook_secret": webhook_secret # À stocker dans .env } except Exception as e: raise HTTPException(status_code=400, detail=str(e)) @router.post("/payment-success") async def handle_payment_success(request: PaymentSuccessRequest): try: print("=== Début du traitement payment-success ===") # Récupérer la session Stripe session = stripe.checkout.Session.retrieve(request.session_id) # Vérifier que le paiement n'a pas déjà été traité if session.metadata.get('processed') == 'true': return { "status": "already_processed", "message": "Ce paiement a déjà été traité" } # Vérifier que le paiement est bien complété if session.payment_status != 'paid': raise HTTPException( status_code=400, detail="Le paiement n'est pas complété" ) user_id = session.metadata.get('user_id') plan_id = session.metadata.get('plan_id') if not user_id or not plan_id: raise HTTPException( status_code=400, detail="Informations utilisateur manquantes" ) # Marquer la session comme traitée stripe.checkout.Session.modify( session.id, metadata={'processed': 'true'} ) return { "status": "success", "user_id": user_id, "plan_id": plan_id } except Exception as e: print(f"Erreur lors du traitement: {str(e)}") raise HTTPException(status_code=400, detail=str(e))