BackendSpace / app /api /routes /stripe_routes.py
2nzi's picture
update stripe routes
0068f7d verified
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))