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": "support@stylists-hub.com" }, 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))