Spaces:
Sleeping
Sleeping
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 | |
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)) | |
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)) | |
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)) | |
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)) | |