import stripe import globales stripe.api_key = globales.llave def create_checkout_session(price_id, customer_email=None, customer_id=None, firebase_user=None, unidades=None, mode=None): """ Crea una nueva Checkout Session para un pago único. Busca o crea un cliente en Stripe si no se provee customer_id ni customer_email, usando firebase_user como método de búsqueda principal si está disponible. Args: price_id (str): El ID del precio en Stripe para el artículo que se va a comprar. customer_email (str, opcional): Email para pre-rellenar o asociar con un cliente existente. customer_id (str, opcional): ID de un cliente existente en Stripe para asociar la sesión. firebase_user (str, opcional): ID de usuario de Firebase. Se usará para buscar un cliente de Stripe si customer_id/email no están presentes. Returns: str: La URL de la Checkout Session, o None si hay un error. """ try: # --- Lógica para obtener o crear el Customer de Stripe --- final_customer_id = customer_id # Empezamos con el customer_id si ya lo tenemos if not final_customer_id: # Si no tenemos un customer_id directo, intentamos buscar/crear found_customer = None # Prioridad 1: Buscar por firebase_user en metadata if firebase_user: search_query = f"metadata['firebase_user']:'{firebase_user}'" print(f"Buscando cliente por Firebase UID: {firebase_user}") existing_customers_by_firebase = stripe.Customer.search(query=search_query, limit=1) if existing_customers_by_firebase.data: found_customer = existing_customers_by_firebase.data[0] print(f"Cliente encontrado por Firebase UID: {found_customer.id}") final_customer_id = found_customer.id # Prioridad 2: Si no se encontró por firebase_user, y tenemos un email, buscar por email if not final_customer_id and customer_email: print(f"Cliente no encontrado por Firebase UID. Buscando por email: {customer_email}") existing_customers_by_email = stripe.Customer.list(email=customer_email, limit=1) if existing_customers_by_email.data: found_customer = existing_customers_by_email.data[0] print(f"Cliente encontrado por email: {found_customer.id}") final_customer_id = found_customer.id # Opcional: Si lo encontraste por email pero falta el firebase_user, actualízalo if firebase_user and (not found_customer.metadata or found_customer.metadata.get('firebase_user') != firebase_user): print(f"Actualizando firebase_user para cliente {found_customer.id}") updated_metadata = found_customer.metadata.copy() if found_customer.metadata is not None else {} updated_metadata['firebase_user'] = firebase_user stripe.Customer.modify(found_customer.id, metadata=updated_metadata) # Si después de las búsquedas, todavía no tenemos un customer_id, y tenemos email, creamos uno nuevo if not final_customer_id and customer_email: print(f"Cliente no encontrado. Creando nuevo cliente con email: {customer_email}") customer_metadata = {} if firebase_user: customer_metadata['firebase_user'] = firebase_user new_customer = stripe.Customer.create( email=customer_email, metadata=customer_metadata if customer_metadata else None # Asegura que no se envíe un diccionario vacío si no hay metadata ) final_customer_id = new_customer.id print(f"Nuevo cliente creado: {final_customer_id}") elif not final_customer_id and not customer_email and firebase_user: # Si no hay email, pero hay firebase_user, también podríamos crear un cliente # Esto es menos común pero posible si el email no es obligatorio para ti. print(f"Cliente no encontrado. Creando nuevo cliente (sin email) con Firebase UID: {firebase_user}") customer_metadata = {'firebase_user': firebase_user} new_customer = stripe.Customer.create( metadata=customer_metadata ) final_customer_id = new_customer.id print(f"Nuevo cliente creado (sin email): {final_customer_id}") # Nota: Si no hay customer_id, customer_email, ni firebase_user, final_customer_id seguirá siendo None # y la sesión de checkout se creará sin un cliente asociado explícitamente. Stripe puede crearlo # automáticamente en el checkout si se recopila el email. print("Estoy por entrar y el mode es: ", mode) # --- Parámetros de la Checkout Session --- session_params = { 'line_items': [{ 'price': price_id, 'quantity': 1, #maneja cantidades cuando es subscription }], 'mode': mode, #payment o subscription #'payment_method_types': ['card'], 'success_url': 'https://app.splashmix.ink/', 'cancel_url': 'https://app.splashmix.ink/buy', 'locale': 'auto', # 'client_reference_id': 'HERC', 'metadata': { 'imagenes': unidades }, 'payment_intent_data': { 'setup_future_usage': None # En Python usamos None en lugar de null } } # Asociar el cliente encontrado/creado a la sesión if final_customer_id: session_params['customer'] = final_customer_id session_params['metadata']['stripe_customer_id'] = final_customer_id # Útil para webhooks # Pre-rellenar el email si está disponible y no se asoció un customer_id directamente # (Stripe recomienda usar 'customer' en lugar de 'customer_email' si ya tienes el ID del cliente) elif customer_email: session_params['customer_email'] = customer_email # Añadir firebase_user a la metadata de la sesión si está presente if firebase_user: session_params['metadata']['firebase_user'] = firebase_user # Limpiar metadata si quedó vacía (Stripe no acepta diccionarios vacíos) if not session_params['metadata']: del session_params['metadata'] session = stripe.checkout.Session.create(**session_params) print(f"Checkout Session creada exitosamente. ID: {session.id}") print(f"URL de redirección: {session.url}") return session.url except stripe.error.StripeError as e: print(f"Error de Stripe al crear la Checkout Session: {e}") return None except Exception as e: print(f"Ocurrió un error inesperado al crear la Checkout Session: {e}") return None def create_stripe_customer(email, firebase_user=None, site=None): """ Busca un cliente existente en Stripe, priorizando el Firebase User ID usando Customer.search. Si el cliente no existe por Firebase User ID, intenta buscar por email. Si el cliente tampoco existe por email, lo crea. Args: email (str): La dirección de correo electrónico del cliente. (Se usará para buscar si el cliente ya existe si no se encuentra por Firebase UID). firebase_user (str, opcional): El ID de usuario de Firebase. **Identificador principal para la búsqueda.** Se agregará a 'metadata'. site (str, opcional): El nombre del sitio de origen. Se agregará a 'metadata'. Returns: tuple: (stripe.Customer, str) donde el string indica "found_by_firebase_user", "found_by_email" o "created". None: Si ocurre un error. """ try: customer_found_status = None found_customer = None # --- 1. Intentar buscar un cliente existente por firebase_user (PRIORIDAD ALTA con Customer.search) --- if firebase_user: # Usamos stripe.Customer.search para buscar en metadata. # Asegúrate de escapar comillas si el firebase_user pudiera contenerlas, # aunque los UIDs de Firebase no suelen tenerlas. search_query = f"metadata['firebase_user']:'{firebase_user}'" print(f"Buscando cliente con query: {search_query}") # Para depuración # search retorna un StripeSearchResultObject, que se itera como una lista existing_customers_by_firebase = stripe.Customer.search(query=search_query, limit=1) if existing_customers_by_firebase.data: found_customer = existing_customers_by_firebase.data[0] customer_found_status = "found_by_firebase_user" print(f"Cliente existente encontrado por Firebase User ID. ID: {found_customer.id}") # --- 2. Si no se encontró por firebase_user, intentar buscar por email --- if not found_customer: print(f"Cliente no encontrado por Firebase UID. Buscando por email: {email}") # Para depuración existing_customers_by_email = stripe.Customer.list(email=email, limit=1) if existing_customers_by_email.data: found_customer = existing_customers_by_email.data[0] customer_found_status = "found_by_email" print(f"Cliente existente encontrado por email. ID: {found_customer.id}") # Opcional: Si lo encontraste por email pero tiene un firebase_user nuevo o nulo, actualízalo # o si el site difiere, también actualizarlo. updated_metadata = found_customer.metadata.copy() if found_customer.metadata is not None else {} needs_update = False if firebase_user and updated_metadata.get('firebase_user') != firebase_user: updated_metadata['firebase_user'] = firebase_user needs_update = True if site and updated_metadata.get('site') != site: updated_metadata['site'] = site needs_update = True if needs_update: print(f"Actualizando metadata para cliente {found_customer.id}") found_customer = stripe.Customer.modify(found_customer.id, metadata=updated_metadata) # Si se encontró un cliente (por cualquiera de los métodos), lo retornamos if found_customer: return found_customer, customer_found_status # --- 3. Si el cliente no existe (ni por firebase_user ni por email), crearlo --- print(f"Cliente con email '{email}' y/o firebase_user '{firebase_user}' no encontrado. Creando nuevo cliente...") customer_params = { 'email': email, } customer_metadata = {} if firebase_user: customer_metadata['firebase_user'] = firebase_user if site: customer_metadata['site'] = site if customer_metadata: customer_params['metadata'] = customer_metadata customer = stripe.Customer.create(**customer_params) print(f"Nuevo cliente creado exitosamente. ID: {customer.id}") return customer, "created" except stripe.error.StripeError as e: print(f"Error de Stripe al buscar o crear el cliente: {e}") return None except Exception as e: print(f"Ocurrió un error inesperado: {e}") return None