File size: 5,152 Bytes
0068f7d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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))