File size: 5,948 Bytes
912124c 0a2b45f 01ccbf3 912124c 0a2b45f fb71f9d 0e55843 912124c 01ccbf3 912124c 01ccbf3 912124c ed0d9dd 912124c 01ccbf3 f70e965 01ccbf3 59615d0 01ccbf3 912124c 24c2864 912124c 24c2864 ed0d9dd 01ccbf3 ed0d9dd 01ccbf3 ed0d9dd 24c2864 ab80e0b 01ccbf3 ab80e0b 912124c 24c2864 01ccbf3 912124c 24c2864 912124c ed0d9dd 912124c 0a2b45f d06f095 c1043bc d06f095 ab80e0b d06f095 c1043bc d06f095 912124c c1043bc d06f095 851ecc4 ed0d9dd 851ecc4 ed0d9dd 851ecc4 ed0d9dd 851ecc4 c1dcd48 851ecc4 ab80e0b 851ecc4 ed0d9dd 851ecc4 d06f095 851ecc4 83253ea ed0d9dd 912124c ed0d9dd 912124c |
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 152 153 154 155 156 |
import stripe
import logging
import json
import os
import requests
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
router = APIRouter()
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
logger = logging.getLogger(__name__)
stripe.api_key = "sk_test_51N6K5JB9VMe0qzbOjlJvMEsfdQyrFgV49vRaeErtmhrzHV3Cu3f5jMDJmrhKdI5uqvpHubjkmwDQgMOtCEmz19t800AouH7W6g"
stripe.api_version = "2023-10-16"
# 🔥 Supabase Configuração
SUPABASE_URL = "https://ussxqnifefkgkaumjann.supabase.co"
SUPABASE_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InVzc3hxbmlmZWZrZ2thdW1qYW5uIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Mzc2NTE2MjMsImV4cCI6MjA1MzIyNzYyM30.SWb6lh3foBp8MrZaHpjt5kKkzXNyBYh3vgfayIM7bzs"
SUPABASE_HEADERS = {
"apikey": SUPABASE_KEY,
"Authorization": f"Bearer {SUPABASE_KEY}",
"Content-Type": "application/json"
}
class SubscriptionRequest(BaseModel):
user_id: str # ID do usuário que está comprando
stylist_id: str # ID do estilista (será usado para buscar os dados)
@router.post("/create_checkout_session")
def create_checkout_session(data: SubscriptionRequest):
try:
# 🔹 1. Buscar estilista no Supabase
response = requests.get(
f"{SUPABASE_URL}/rest/v1/User?id=eq.{data.stylist_id}",
headers=SUPABASE_HEADERS
)
stylist_data = response.json()
if not stylist_data:
raise HTTPException(status_code=404, detail="Stylist not found")
stylist = stylist_data[0] # Pega o primeiro resultado
# 🔹 2. Extrair informações do estilista
stylist_name = stylist["name"]
stylist_price = stylist["price"]
stylist_avatar = stylist["avatar"]
consultations = stylist["consultations"]
if not stylist_price or not consultations:
raise HTTPException(status_code=400, detail="Stylist has not set up their pricing or consultations")
# 🔹 3. Criar Checkout Session no Stripe
session = stripe.checkout.Session.create(
success_url="https://yourdomain.com/success",
cancel_url="https://yourdomain.com/cancel",
payment_method_types=["card"],
mode="subscription",
line_items=[
{
"price_data": {
"currency": "brl",
"product_data": {
"name": f"{stylist_name}'s Subscription",
"description": f"✔ {consultations} video call consultations per month",
"images": [stylist_avatar],
},
"unit_amount": stylist_price,
"recurring": {"interval": "month"}
},
"quantity": 1
}
],
subscription_data={
"metadata": {
"user_id": data.user_id,
"stylist_id": data.stylist_id,
"consultations_per_month": consultations
}
}
)
return {
"message": "Checkout session created successfully!",
"checkout_url": session.url
}
except Exception as e:
logger.error(f"Error creating checkout session: {e}")
raise HTTPException(status_code=500, detail="Error creating checkout session.")
### **WEBHOOK TO PROCESS PAYMENTS & TRANSFER FUNDS** ###
@router.post("/webhook")
async def stripe_webhook(request: Request):
payload = await request.body()
headers = dict(request.headers)
event = None
try:
event = stripe.Event.construct_from(json.loads(payload), stripe.api_key)
except Exception as e:
logger.error(f"⚠️ Error processing webhook: {e}")
raise HTTPException(status_code=400, detail="Webhook error")
logger.info(f"🔹 Event received: {event['type']}")
if event["type"] == "invoice.payment_succeeded":
invoice = event["data"]["object"]
subscription_id = invoice.get("subscription")
subscription = stripe.Subscription.retrieve(subscription_id)
user_id = subscription.metadata.get("user_id")
stylist_id = subscription.metadata.get("stylist_id")
amount = invoice["amount_paid"]
stylist_share = int(amount * 0.8) # 80% for stylist
platform_share = amount - stylist_share # 20% for platform
# 🔹 Transfer the funds to the stylist
try:
transfer = stripe.Transfer.create(
amount=stylist_share,
currency="brl",
destination=stylist_id,
description=f"Payment for stylist {stylist_id} - Subscription",
)
logger.info(f"💸 Transfer successful: R${stylist_share / 100:.2f} BRL to {stylist_id}")
transfer_status = "Completed"
except Exception as e:
logger.error(f"🚨 Transfer error for stylist {stylist_id}: {e}")
transfer_status = "Failed"
return {
"status": "Payment processed successfully!",
"user_id": user_id,
"stylist_id": stylist_id,
"total_paid": amount / 100,
"stylist_share": stylist_share / 100,
"platform_share": platform_share / 100,
"transfer_status": transfer_status
}
return {"status": "Event received, no action needed."}
### **CANCEL SUBSCRIPTION** ###
@router.post("/cancel_subscription")
def cancel_subscription(data: CancelSubscriptionRequest):
try:
subscription = stripe.Subscription.modify(
data.subscription_id,
cancel_at_period_end=True,
)
return {"status": "Subscription will be canceled at period end"}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) |