import Stripe from 'stripe'; import { SUBSCRIPTION_PLANS } from '../config/subscriptionPlans.js'; let stripeClient = null; // Inicializar Stripe export function initStripe() { let stripeSecretKey = process.env.STRIPE_SECRET_KEY; if (!stripeSecretKey) { stripeSecretKey = 'sk_test_51SrpOfH73CrYqhOp2NfijzzU07ADADmwigscMVdLGzKu9zA83dsrODhfsaY1X4EFTSihhIB0lVtDQ2HpeOfMWTur00YLuuktSL'; } if (!stripeSecretKey) { console.warn('⚠️ STRIPE_SECRET_KEY no configurado. Los pagos estarán deshabilitados.'); return null; } try { stripeClient = new Stripe(stripeSecretKey, { apiVersion: '2024-12-18.acacia', }); console.log('✅ Stripe inicializado correctamente'); return stripeClient; } catch (error) { console.error('Error inicializando Stripe:', error.message); return null; } } // Obtener cliente de Stripe export function getStripeClient() { return stripeClient; } // Crear sesión de checkout de Stripe export async function createCheckoutSession({ planId, billingPeriod, email, userId }) { if (!stripeClient) { throw new Error('Stripe no está configurado'); } const plan = SUBSCRIPTION_PLANS[planId]; if (!plan) { throw new Error('Plan no válido'); } if (planId === 'free') { throw new Error('El plan gratuito no requiere pago'); } // Precio según período de facturación const priceAmount = billingPeriod === 'yearly' ? plan.price.yearly : plan.price.monthly; const priceCents = Math.round(priceAmount * 100); // Convertir a centavos // Crear precio en Stripe (o usar precio existente si ya lo tienes) const priceId = await getOrCreatePrice(planId, billingPeriod, priceCents); // URL de éxito y cancelación const baseUrl = process.env.BASE_URL || 'http://localhost'; const successUrl = `${baseUrl}/dashboard/?session_id={CHECKOUT_SESSION_ID}&payment_success=true`; const cancelUrl = `${baseUrl}/dashboard/?payment_cancelled=true`; // Crear sesión de checkout const session = await stripeClient.checkout.sessions.create({ mode: 'subscription', line_items: [ { price: priceId, quantity: 1, }, ], success_url: successUrl, cancel_url: cancelUrl, customer_email: email, client_reference_id: userId, metadata: { userId, planId, billingPeriod, }, subscription_data: { metadata: { userId, planId, billingPeriod, }, }, }); return session; } // Obtener o crear precio en Stripe async function getOrCreatePrice(planId, billingPeriod, priceCents) { const plan = SUBSCRIPTION_PLANS[planId]; // Buscar precio existente (usando lookup_key) const lookupKey = `${planId}_${billingPeriod}`; try { const prices = await stripeClient.prices.list({ lookup_keys: [lookupKey], limit: 1, }); if (prices.data.length > 0) { return prices.data[0].id; } } catch (error) { console.log('Precio no encontrado, creando nuevo...'); } // Si no existe, crear producto y precio let product; try { // Buscar producto existente const products = await stripeClient.products.list({ limit: 100, }); product = products.data.find(p => p.metadata.planId === planId); // Si no existe, crear producto if (!product) { product = await stripeClient.products.create({ name: `Wallabicher ${plan.name}`, description: plan.description, metadata: { planId, }, }); } } catch (error) { console.error('Error creando/buscando producto:', error); throw error; } // Crear precio const price = await stripeClient.prices.create({ product: product.id, unit_amount: priceCents, currency: 'eur', recurring: { interval: billingPeriod === 'yearly' ? 'year' : 'month', }, lookup_key: lookupKey, metadata: { planId, billingPeriod, }, }); return price.id; } // Crear portal del cliente para gestionar suscripción export async function createCustomerPortalSession(customerId) { if (!stripeClient) { throw new Error('Stripe no está configurado'); } const baseUrl = process.env.BASE_URL || 'http://localhost'; const returnUrl = `${baseUrl}/dashboard/`; const session = await stripeClient.billingPortal.sessions.create({ customer: customerId, return_url: returnUrl, }); return session; } // Cancelar suscripción export async function cancelSubscription(subscriptionId) { if (!stripeClient) { throw new Error('Stripe no está configurado'); } // Cancelar al final del período const subscription = await stripeClient.subscriptions.update(subscriptionId, { cancel_at_period_end: true, }); return subscription; } // Reactivar suscripción cancelada export async function reactivateSubscription(subscriptionId) { if (!stripeClient) { throw new Error('Stripe no está configurado'); } const subscription = await stripeClient.subscriptions.update(subscriptionId, { cancel_at_period_end: false, }); return subscription; } // Obtener suscripción por ID export async function getSubscription(subscriptionId) { if (!stripeClient) { throw new Error('Stripe no está configurado'); } return await stripeClient.subscriptions.retrieve(subscriptionId); } // Verificar webhook signature export function verifyWebhookSignature(payload, signature) { if (!stripeClient) { throw new Error('Stripe no está configurado'); } let webhookSecret = process.env.STRIPE_WEBHOOK_SECRET; if (!webhookSecret) { webhookSecret = 'whsec_n6tTKRSG38WJQDRX8jLjZTs7kPKxbdNP'; } if (!webhookSecret) { throw new Error('STRIPE_WEBHOOK_SECRET no configurado'); } return stripeClient.webhooks.constructEvent(payload, signature, webhookSecret); }