Update routes/subscription.py
Browse files- routes/subscription.py +20 -53
routes/subscription.py
CHANGED
@@ -8,23 +8,24 @@ router = APIRouter()
|
|
8 |
|
9 |
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
|
10 |
logger = logging.getLogger(__name__)
|
|
|
11 |
stripe.api_key = "sk_test_51N6K5JB9VMe0qzbOjlJvMEsfdQyrFgV49vRaeErtmhrzHV3Cu3f5jMDJmrhKdI5uqvpHubjkmwDQgMOtCEmz19t800AouH7W6g"
|
12 |
stripe.api_version = "2023-10-16"
|
13 |
|
14 |
-
###
|
15 |
class PriceRequest(BaseModel):
|
16 |
-
amount: int # Value in cents (e.g.,
|
17 |
-
stylist_name: str #
|
18 |
-
|
19 |
class SubscriptionRequest(BaseModel):
|
20 |
user_id: str
|
21 |
stylist_id: str
|
22 |
-
price_id: str #
|
23 |
|
24 |
class CancelSubscriptionRequest(BaseModel):
|
25 |
subscription_id: str
|
26 |
|
27 |
-
### 1
|
28 |
@router.post("/create_price")
|
29 |
def create_price(data: PriceRequest):
|
30 |
try:
|
@@ -38,7 +39,7 @@ def create_price(data: PriceRequest):
|
|
38 |
|
39 |
price = stripe.Price.create(
|
40 |
unit_amount=data.amount,
|
41 |
-
currency="
|
42 |
recurring={"interval": "month"},
|
43 |
product=product.id,
|
44 |
)
|
@@ -49,14 +50,14 @@ def create_price(data: PriceRequest):
|
|
49 |
"product_id": product.id,
|
50 |
"product_name": product_name,
|
51 |
"product_description": product_description,
|
52 |
-
"amount": data.amount / 100, # Converting to
|
53 |
-
"currency": "
|
54 |
}
|
55 |
except Exception as e:
|
56 |
logger.error(f"Error creating price: {e}")
|
57 |
raise HTTPException(status_code=500, detail="Error creating price.")
|
58 |
|
59 |
-
### 2
|
60 |
@router.post("/create_checkout_session")
|
61 |
def create_checkout_session(data: SubscriptionRequest):
|
62 |
try:
|
@@ -87,6 +88,7 @@ def create_checkout_session(data: SubscriptionRequest):
|
|
87 |
logger.error(f"Error creating checkout session: {e}")
|
88 |
raise HTTPException(status_code=500, detail="Error creating checkout session.")
|
89 |
|
|
|
90 |
@router.post("/webhook")
|
91 |
async def stripe_webhook(request: Request):
|
92 |
payload = await request.body()
|
@@ -114,65 +116,30 @@ async def stripe_webhook(request: Request):
|
|
114 |
stylist_share = int(amount * 0.8) # 80% for the stylist
|
115 |
platform_share = amount - stylist_share # 20% for the platform
|
116 |
|
117 |
-
logger.info(f"✅ Payment confirmed: {amount / 100:.2f}
|
118 |
logger.info(f"👤 User ID: {user_id}")
|
119 |
logger.info(f"✂️ Stylist ID: {stylist_id}")
|
120 |
-
logger.info(f"💰 Stylist will receive: {stylist_share / 100:.2f}
|
121 |
-
logger.info(f"🏢 Platform will receive: {platform_share / 100:.2f}
|
122 |
-
|
123 |
-
# Verifique se o payment_intent está presente
|
124 |
-
payment_intent = invoice.get("payment_intent")
|
125 |
-
if payment_intent:
|
126 |
-
logger.info(f"Payment Intent: {payment_intent}")
|
127 |
-
try:
|
128 |
-
transfer = stripe.Transfer.create(
|
129 |
-
amount=stylist_share, # Amount in cents
|
130 |
-
currency="brl",
|
131 |
-
destination=stylist_id, # The stylist's connected Stripe account ID
|
132 |
-
description="Subscription payment",
|
133 |
-
source_transaction=payment_intent # Use the payment_intent as source_transaction
|
134 |
-
)
|
135 |
-
logger.info(f"✅ Transfer successful! Transfer ID: {transfer.id}")
|
136 |
-
except Exception as e:
|
137 |
-
logger.error(f"⚠️ Error transferring funds to stylist using payment_intent: {e}")
|
138 |
-
else:
|
139 |
-
# Tente usar charge ID, caso payment_intent não esteja disponível
|
140 |
-
charge_id = invoice.get("charge")
|
141 |
-
if charge_id:
|
142 |
-
logger.info(f"Charge ID: {charge_id}")
|
143 |
-
try:
|
144 |
-
transfer = stripe.Transfer.create(
|
145 |
-
amount=stylist_share, # Amount in cents
|
146 |
-
currency="brl",
|
147 |
-
destination=stylist_id, # The stylist's connected Stripe account ID
|
148 |
-
description="Subscription payment",
|
149 |
-
source_transaction=charge_id # Use the charge ID if payment_intent is missing
|
150 |
-
)
|
151 |
-
logger.info(f"✅ Transfer successful! Transfer ID: {transfer.id}")
|
152 |
-
except Exception as e:
|
153 |
-
logger.error(f"⚠️ Error transferring funds to stylist using charge: {e}")
|
154 |
-
else:
|
155 |
-
logger.error("⚠️ No payment intent or charge found, unable to transfer funds.")
|
156 |
-
|
157 |
return {
|
158 |
-
"status": "Payment processed successfully
|
159 |
"user_id": user_id,
|
160 |
"stylist_id": stylist_id,
|
161 |
-
"total_paid": amount / 100, # Convert cents to
|
162 |
"stylist_share": stylist_share / 100,
|
163 |
"platform_share": platform_share / 100,
|
164 |
-
"transfer_id": transfer.id if 'transfer' in locals() else None
|
165 |
}
|
166 |
|
167 |
return {"status": "Event received, no action needed."}
|
168 |
|
169 |
-
### 4
|
170 |
@router.post("/cancel_subscription")
|
171 |
def cancel_subscription(data: CancelSubscriptionRequest):
|
172 |
try:
|
173 |
subscription = stripe.Subscription.modify(
|
174 |
data.subscription_id,
|
175 |
-
cancel_at_period_end=True, #
|
176 |
)
|
177 |
return {"status": "Subscription will be canceled at period end"}
|
178 |
except Exception as e:
|
|
|
8 |
|
9 |
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
|
10 |
logger = logging.getLogger(__name__)
|
11 |
+
|
12 |
stripe.api_key = "sk_test_51N6K5JB9VMe0qzbOjlJvMEsfdQyrFgV49vRaeErtmhrzHV3Cu3f5jMDJmrhKdI5uqvpHubjkmwDQgMOtCEmz19t800AouH7W6g"
|
13 |
stripe.api_version = "2023-10-16"
|
14 |
|
15 |
+
### **DATA MODELS** ###
|
16 |
class PriceRequest(BaseModel):
|
17 |
+
amount: int # Value in cents (e.g., $25.00 -> 2500)
|
18 |
+
stylist_name: str # Name of the stylist
|
19 |
+
|
20 |
class SubscriptionRequest(BaseModel):
|
21 |
user_id: str
|
22 |
stylist_id: str
|
23 |
+
price_id: str # Now using a pre-created price
|
24 |
|
25 |
class CancelSubscriptionRequest(BaseModel):
|
26 |
subscription_id: str
|
27 |
|
28 |
+
### **1️⃣ CREATE DYNAMIC PRICE** ###
|
29 |
@router.post("/create_price")
|
30 |
def create_price(data: PriceRequest):
|
31 |
try:
|
|
|
39 |
|
40 |
price = stripe.Price.create(
|
41 |
unit_amount=data.amount,
|
42 |
+
currency="usd",
|
43 |
recurring={"interval": "month"},
|
44 |
product=product.id,
|
45 |
)
|
|
|
50 |
"product_id": product.id,
|
51 |
"product_name": product_name,
|
52 |
"product_description": product_description,
|
53 |
+
"amount": data.amount / 100, # Converting cents to dollars
|
54 |
+
"currency": "USD",
|
55 |
}
|
56 |
except Exception as e:
|
57 |
logger.error(f"Error creating price: {e}")
|
58 |
raise HTTPException(status_code=500, detail="Error creating price.")
|
59 |
|
60 |
+
### **2️⃣ CREATE CHECKOUT SESSION** ###
|
61 |
@router.post("/create_checkout_session")
|
62 |
def create_checkout_session(data: SubscriptionRequest):
|
63 |
try:
|
|
|
88 |
logger.error(f"Error creating checkout session: {e}")
|
89 |
raise HTTPException(status_code=500, detail="Error creating checkout session.")
|
90 |
|
91 |
+
### **3️⃣ WEBHOOK TO PROCESS PAYMENTS** ###
|
92 |
@router.post("/webhook")
|
93 |
async def stripe_webhook(request: Request):
|
94 |
payload = await request.body()
|
|
|
116 |
stylist_share = int(amount * 0.8) # 80% for the stylist
|
117 |
platform_share = amount - stylist_share # 20% for the platform
|
118 |
|
119 |
+
logger.info(f"✅ Payment confirmed: ${amount / 100:.2f} USD")
|
120 |
logger.info(f"👤 User ID: {user_id}")
|
121 |
logger.info(f"✂️ Stylist ID: {stylist_id}")
|
122 |
+
logger.info(f"💰 Stylist will receive: ${stylist_share / 100:.2f} USD")
|
123 |
+
logger.info(f"🏢 Platform will receive: ${platform_share / 100:.2f} USD")
|
124 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
return {
|
126 |
+
"status": "Payment processed successfully!",
|
127 |
"user_id": user_id,
|
128 |
"stylist_id": stylist_id,
|
129 |
+
"total_paid": amount / 100, # Convert cents to dollars
|
130 |
"stylist_share": stylist_share / 100,
|
131 |
"platform_share": platform_share / 100,
|
|
|
132 |
}
|
133 |
|
134 |
return {"status": "Event received, no action needed."}
|
135 |
|
136 |
+
### **4️⃣ CANCEL SUBSCRIPTION** ###
|
137 |
@router.post("/cancel_subscription")
|
138 |
def cancel_subscription(data: CancelSubscriptionRequest):
|
139 |
try:
|
140 |
subscription = stripe.Subscription.modify(
|
141 |
data.subscription_id,
|
142 |
+
cancel_at_period_end=True, # Cancels at the end of the current cycle
|
143 |
)
|
144 |
return {"status": "Subscription will be canceled at period end"}
|
145 |
except Exception as e:
|