Create subscription.py
Browse files- routes/subscription.py +91 -0
routes/subscription.py
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import stripe
|
2 |
+
from fastapi import APIRouter, HTTPException, Request
|
3 |
+
from pydantic import BaseModel
|
4 |
+
|
5 |
+
router = APIRouter()
|
6 |
+
|
7 |
+
stripe.api_key = "sk_test_51N6K5JB9VMe0qzbOjlJvMEsfdQyrFgV49vRaeErtmhrzHV3Cu3f5jMDJmrhKdI5uqvpHubjkmwDQgMOtCEmz19t800AouH7W6g"
|
8 |
+
stripe.api_version = "2023-10-16"
|
9 |
+
|
10 |
+
### MODELOS DE DADOS ###
|
11 |
+
class SubscriptionRequest(BaseModel):
|
12 |
+
user_id: str
|
13 |
+
estilista_id: str
|
14 |
+
amount: int # Valor em centavos (ex: R$50,00 -> 5000)
|
15 |
+
|
16 |
+
class CancelSubscriptionRequest(BaseModel):
|
17 |
+
subscription_id: str
|
18 |
+
|
19 |
+
### 1. CRIAR PRODUTO E PREÇO DINÂMICO ###
|
20 |
+
def create_price(amount_in_cents: int):
|
21 |
+
try:
|
22 |
+
product = stripe.Product.create(name="Stylist Subscription")
|
23 |
+
price = stripe.Price.create(
|
24 |
+
unit_amount=amount_in_cents,
|
25 |
+
currency="brl",
|
26 |
+
recurring={"interval": "month"},
|
27 |
+
product=product.id,
|
28 |
+
)
|
29 |
+
return price.id
|
30 |
+
except Exception as e:
|
31 |
+
raise HTTPException(status_code=500, detail=str(e))
|
32 |
+
|
33 |
+
### 2. INICIAR O CHECKOUT ###
|
34 |
+
@router.post("/create_checkout_session")
|
35 |
+
def create_checkout_session(data: SubscriptionRequest):
|
36 |
+
price_id = create_price(data.amount) # Criar um preço dinâmico
|
37 |
+
|
38 |
+
try:
|
39 |
+
session = stripe.checkout.Session.create(
|
40 |
+
success_url="http://localhost:4242/success",
|
41 |
+
cancel_url="http://localhost:4242/cancel",
|
42 |
+
payment_method_types=["card"],
|
43 |
+
mode="subscription",
|
44 |
+
line_items=[{"price": price_id, "quantity": 1}],
|
45 |
+
metadata={
|
46 |
+
"user_id": data.user_id,
|
47 |
+
"estilista_id": data.estilista_id,
|
48 |
+
},
|
49 |
+
)
|
50 |
+
return {"url": session.url}
|
51 |
+
except Exception as e:
|
52 |
+
raise HTTPException(status_code=500, detail=str(e))
|
53 |
+
|
54 |
+
### 3. WEBHOOK PARA PROCESSAR PAGAMENTO BEM-SUCEDIDO ###
|
55 |
+
@router.post("/webhook")
|
56 |
+
async def stripe_webhook(request: Request):
|
57 |
+
payload = await request.body()
|
58 |
+
sig_header = request.headers.get("Stripe-Signature")
|
59 |
+
|
60 |
+
try:
|
61 |
+
event = stripe.Webhook.construct_event(payload, sig_header, "seu_webhook_secret")
|
62 |
+
except ValueError:
|
63 |
+
raise HTTPException(status_code=400, detail="Invalid payload")
|
64 |
+
except stripe.error.SignatureVerificationError:
|
65 |
+
raise HTTPException(status_code=400, detail="Invalid signature")
|
66 |
+
|
67 |
+
if event["type"] == "invoice.payment_succeeded":
|
68 |
+
invoice = event["data"]["object"]
|
69 |
+
estilista_id = invoice["metadata"]["estilista_id"]
|
70 |
+
user_id = invoice["metadata"]["user_id"]
|
71 |
+
amount_paid = invoice["amount_paid"]
|
72 |
+
|
73 |
+
# 80% do valor fica pendente para o estilista
|
74 |
+
amount_for_stylist = int(amount_paid * 0.8)
|
75 |
+
|
76 |
+
# Aqui você salvaria o saldo pendente do estilista no banco de dados
|
77 |
+
save_pending_balance(estilista_id, amount_for_stylist)
|
78 |
+
|
79 |
+
return {"success": True}
|
80 |
+
|
81 |
+
### 4. CANCELAR UMA ASSINATURA ###
|
82 |
+
@router.post("/cancel_subscription")
|
83 |
+
def cancel_subscription(data: CancelSubscriptionRequest):
|
84 |
+
try:
|
85 |
+
subscription = stripe.Subscription.modify(
|
86 |
+
data.subscription_id,
|
87 |
+
cancel_at_period_end=True, # Cancela no final do ciclo atual
|
88 |
+
)
|
89 |
+
return {"status": "Subscription will be canceled at period end"}
|
90 |
+
except Exception as e:
|
91 |
+
raise HTTPException(status_code=500, detail=str(e))
|