connect / routes /hello.py
habulaj's picture
Update routes/hello.py
4cd3fe5 verified
import os
import stripe
import requests
import logging
from fastapi import APIRouter, HTTPException, Header
from fastapi import Query
from pydantic import BaseModel
router = APIRouter()
# Configuração das chaves do Stripe e Supabase
stripe.api_key = os.getenv("STRIPE_KEY")
stripe.api_version = "2023-10-16"
SUPABASE_URL = "https://ussxqnifefkgkaumjann.supabase.co"
SUPABASE_KEY = os.getenv("SUPA_KEY")
if not stripe.api_key or not SUPABASE_KEY:
raise ValueError("❌ STRIPE_KEY ou SUPA_KEY não foram definidos no ambiente!")
SUPABASE_HEADERS = {
"apikey": SUPABASE_KEY,
"Authorization": f"Bearer {SUPABASE_KEY}",
"Content-Type": "application/json"
}
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class AccountRequest(BaseModel):
email: str
name: str # Name of the individual account owner
class CreateCustomerRequest(BaseModel):
email: str
phone: str
name: str
def verify_token(user_token: str) -> str:
"""
Valida o token JWT no Supabase e retorna o user_id se for válido.
"""
headers = {
"Authorization": f"Bearer {user_token}",
"apikey": SUPABASE_KEY,
"Content-Type": "application/json"
}
response = requests.get(f"{SUPABASE_URL}/auth/v1/user", headers=headers)
if response.status_code == 200:
user_data = response.json()
user_id = user_data.get("id")
if not user_id:
raise HTTPException(status_code=400, detail="Invalid token: User ID not found")
return user_id
else:
raise HTTPException(status_code=401, detail="Invalid or expired token")
import os
import stripe
import requests
import logging
from fastapi import APIRouter, HTTPException, Header
from pydantic import BaseModel
router = APIRouter()
# Configuração das chaves do Stripe e Supabase
stripe.api_key = os.getenv("STRIPE_KEY")
stripe.api_version = "2023-10-16"
SUPABASE_URL = "https://ussxqnifefkgkaumjann.supabase.co"
SUPABASE_KEY = os.getenv("SUPA_KEY")
if not stripe.api_key or not SUPABASE_KEY:
raise ValueError("❌ STRIPE_KEY ou SUPA_KEY não foram definidos no ambiente!")
SUPABASE_HEADERS = {
"apikey": SUPABASE_KEY,
"Authorization": f"Bearer {SUPABASE_KEY}",
"Content-Type": "application/json"
}
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class CreateCustomerRequest(BaseModel):
email: str
phone: str
name: str
def verify_token(user_token: str) -> str:
"""
Valida o token JWT no Supabase e retorna o user_id se for válido.
"""
headers = {
"Authorization": f"Bearer {user_token}",
"apikey": SUPABASE_KEY,
"Content-Type": "application/json"
}
response = requests.get(f"{SUPABASE_URL}/auth/v1/user", headers=headers)
if response.status_code == 200:
user_data = response.json()
user_id = user_data.get("id")
if not user_id:
raise HTTPException(status_code=400, detail="Invalid token: User ID not found")
return user_id
else:
raise HTTPException(status_code=401, detail="Invalid or expired token")
@router.post("/create_customer")
def create_customer(
data: CreateCustomerRequest,
user_token: str = Header(None, alias="User-key")
):
try:
if not user_token:
raise HTTPException(status_code=401, detail="Missing User-key header")
# 🔹 Validar o token e obter user_id
user_id = verify_token(user_token)
logger.info(f"🔹 User verified. user_id: {user_id}")
# 🔹 Verificar se o usuário já tem um stripe_id no Supabase
user_data_url = f"{SUPABASE_URL}/rest/v1/User?id=eq.{user_id}"
response = requests.get(user_data_url, headers={
"Authorization": f"Bearer {user_token}", # Alterado para usar o token do usuário
"apikey": SUPABASE_KEY,
"Content-Type": "application/json"
})
if response.status_code == 200 and response.json():
user_data = response.json()[0]
stripe_id = user_data.get("stripe_id")
if stripe_id:
logger.info(f"✅ User already has a Stripe customer: {stripe_id}")
return {"customer_id": stripe_id}
# 🔹 Verificar se já existe um cliente com o mesmo e-mail no Stripe
logger.info(f"🔹 Checking if email {data.email} already exists in Stripe...")
existing_customers = stripe.Customer.list(email=data.email, limit=1)
if existing_customers.data:
error_message = f"Customer with email {data.email} already exists."
logger.warning(f"⚠️ {error_message}")
raise HTTPException(status_code=400, detail=error_message)
# 🔹 Criar o cliente no Stripe
customer = stripe.Customer.create(
email=data.email,
phone=data.phone,
name=data.name
)
stripe_id = customer.id
logger.info(f"✅ New Stripe customer created: {stripe_id}")
# 🔹 Atualizar o usuário no Supabase com o stripe_id
update_data = {"stripe_id": stripe_id}
supabase_url = f"{SUPABASE_URL}/rest/v1/User"
update_headers = {
"Authorization": f"Bearer {user_token}", # Alterado para usar o token do usuário
"apikey": SUPABASE_KEY,
"Content-Type": "application/json"
}
# 🔹 Adicionar query params corretamente
response = requests.patch(
f"{supabase_url}?id=eq.{user_id}",
headers=update_headers,
json=update_data
)
logger.info(f"🔹 Supabase PATCH response: {response.status_code} - {response.text}")
if response.status_code not in [200, 204]:
logger.warning(f"⚠️ Rolling back: Deleting Stripe customer {stripe_id} due to Supabase failure.")
stripe.Customer.delete(stripe_id)
error_message = f"Error updating Supabase: {response.text}"
raise HTTPException(status_code=500, detail=error_message)
logger.info(f"✅ Successfully updated user {user_id} with stripe_id {stripe_id}")
return {"customer_id": stripe_id}
except HTTPException as http_err:
raise http_err
except Exception as e:
error_message = str(e) if str(e) else "An unknown error occurred. Please try again."
logger.error(f"❌ Error creating customer: {error_message}")
raise HTTPException(status_code=500, detail=error_message)
@router.post("/create_account")
def create_account(account_data: AccountRequest):
try:
account = stripe.Account.create(
type="express",
email=account_data.email,
country="BR", # 🇧🇷 Brasil (obrigatório para plataformas BR)
business_type="individual",
business_profile={
"mcc": "7298",
"name": account_data.name,
"product_description": "We connect stylists with clients through subscription services.",
"support_email": "[email protected]"
},
default_currency="brl", # 💰 Real brasileiro
capabilities={
"transfers": {"requested": True},
"card_payments": {"requested": True}
}
# ⚠️ Não incluindo settings de payout pois no Brasil apenas 'daily' é suportado
# e é aplicado automaticamente pelo Stripe
)
return {"account_id": account.id}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/check_onboarding/{account_id}")
def check_onboarding(account_id: str):
try:
account = stripe.Account.retrieve(account_id)
if account.requirements.currently_due:
return {"status": "incomplete", "pending_requirements": account.requirements.currently_due}
return {"status": "complete"}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
### **2️⃣ CREATE ACCOUNT LINK FOR ONBOARDING** ###
class AccountLinkRequest(BaseModel):
account_id: str
@router.get("/terms")
def get_terms(type: str = Query(..., regex="^(use|privacy)$")):
try:
term_type = "Terms of Use" if type == "use" else "Privacy Policy"
url = f"{SUPABASE_URL}/rest/v1/Configuration?type=eq.{term_type}&select=text,date"
response = requests.get(url, headers=SUPABASE_HEADERS)
if response.status_code != 200:
raise HTTPException(status_code=500, detail="Erro ao acessar a tabela Configuration")
data = response.json()
if not data:
raise HTTPException(status_code=404, detail="Termo não encontrado")
return {
"type": term_type,
"text": data[0]["text"],
"last_updated": data[0]["date"]
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/account_link")
def create_account_link(link_data: AccountLinkRequest):
try:
account_link = stripe.AccountLink.create(
account=link_data.account_id,
return_url="https://ameddes.com/onboarding?success=true", # Updated return URL
refresh_url="https://ameddes.com/onboarding?success=false", # Updated refresh URL
type="account_onboarding",
)
return {"url": account_link.url}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))