File size: 11,923 Bytes
11cdb7c
4579ff3
d90d6a6
4579ff3
2695e7b
b45248f
5cfc6de
 
5607f58
 
5cfc6de
 
 
 
 
5607f58
 
5cfc6de
 
 
 
 
5607f58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7caa31a
5607f58
 
5cfc6de
 
 
f0bd081
5cfc6de
7caa31a
ccebef1
5607f58
001330e
f79115e
79f7172
e984961
b45248f
7e0ea75
 
 
 
5cfc6de
 
5607f58
 
 
 
 
 
 
5cfc6de
5607f58
 
 
 
 
 
 
 
 
5cfc6de
 
 
 
 
 
 
 
 
 
 
 
64e0349
 
03e7a68
64e0349
f2528b2
 
 
64e0349
 
 
f2528b2
 
 
03e7a68
64e0349
 
f2528b2
64e0349
 
 
f2528b2
 
03e7a68
f2528b2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
03e7a68
64e0349
 
 
 
03e7a68
 
 
 
 
 
f2528b2
03e7a68
64e0349
 
 
03e7a68
f2528b2
64e0349
 
03e7a68
64e0349
 
03e7a68
5cfc6de
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
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