Concepto clave
En Stripe, los Productos y Precios son entidades separadas pero relacionadas que forman la base de cualquier sistema de suscripciones. Piensa en un producto como el "que" estas vendiendo (por ejemplo, "Suscripcion Premium") y el precio como el "como" y "cuanto" (por ejemplo, "$20 mensuales con facturacion recurrente"). Esta separacion es crucial porque te permite:
- Cambiar precios sin afectar la descripcion del producto
- Ofrecer multiples opciones de pago para el mismo producto
- Mantener un historial claro de cambios de precios
Una analogia del mundo real seria un gimnasio: el producto es "Membresia Gold" (que incluye acceso a todas las instalaciones), mientras que los precios podrian ser "$50/mes", "$500/año", o "$15/semana". Cada precio es una forma diferente de acceder al mismo producto.
Como funciona en la practica
El flujo tipico para crear un producto con precios en Stripe sigue estos pasos:
- Configurar el SDK: Inicializar Stripe con tu clave secreta
- Crear el Producto: Definir nombre, descripcion y metadatos
- Crear el Precio: Asociarlo al producto, definir moneda, monto y tipo (recurrente o unico)
- Verificar: Confirmar que ambas entidades se crearon correctamente
Este proceso se puede hacer a traves del Dashboard de Stripe, pero usando el SDK tienes control programatico completo, lo que es esencial para integraciones automatizadas o sistemas con muchos productos.
Codigo en accion
Antes de comenzar, asegurate de tener instalado el SDK de Stripe:
npm install stripeAhora, veamos como crear un producto con un precio recurrente:
// Configuracion inicial - ANTES
const stripe = require('stripe')('sk_test_tu_clave_secreta');
// Crear producto y precio por separado
async function createProductAndPrice() {
try {
// 1. Crear el producto
const product = await stripe.products.create({
name: 'Suscripcion Premium',
description: 'Acceso completo a todas las funciones',
metadata: {
plan_type: 'premium',
max_users: '10'
}
});
// 2. Crear el precio asociado
const price = await stripe.prices.create({
product: product.id,
unit_amount: 2000, // $20.00 en centavos
currency: 'usd',
recurring: {
interval: 'month',
interval_count: 1
}
});
console.log('Producto creado:', product.id);
console.log('Precio creado:', price.id);
return { product, price };
} catch (error) {
console.error('Error:', error);
}
}
createProductAndPrice();Ahora, una version mejorada que maneja errores y validaciones:
// Version mejorada - DESPUES
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
async function createSubscriptionProduct(productData, priceData) {
// Validaciones basicas
if (!productData.name || !productData.description) {
throw new Error('Nombre y descripcion del producto son requeridos');
}
if (priceData.unit_amount < 50) { // Minimo $0.50
throw new Error('El monto minimo es 50 centavos');
}
try {
// Crear producto con metadatos estructurados
const product = await stripe.products.create({
name: productData.name,
description: productData.description,
metadata: {
...productData.metadata,
created_at: new Date().toISOString(),
created_by: 'api'
}
});
// Crear precio con configuracion completa
const price = await stripe.prices.create({
product: product.id,
unit_amount: priceData.unit_amount,
currency: priceData.currency || 'usd',
recurring: {
interval: priceData.interval || 'month',
interval_count: priceData.interval_count || 1,
trial_period_days: priceData.trial_days || null
},
metadata: {
product_name: productData.name,
billing_type: 'recurring'
}
});
// Log estructurado para monitoreo
console.log({
event: 'product_created',
product_id: product.id,
price_id: price.id,
amount: priceData.unit_amount / 100,
currency: priceData.currency
});
return {
success: true,
product_id: product.id,
price_id: price.id,
product: product,
price: price
};
} catch (error) {
// Manejo especifico de errores de Stripe
if (error.type === 'StripeInvalidRequestError') {
console.error('Error de validacion de Stripe:', error.message);
}
throw error;
}
}
// Uso ejemplo
const productData = {
name: 'Plan Empresarial',
description: 'Para equipos de hasta 50 usuarios',
metadata: { max_users: '50', features: 'advanced_analytics' }
};
const priceData = {
unit_amount: 9900, // $99.00
currency: 'usd',
interval: 'month',
trial_days: 14
};
createSubscriptionProduct(productData, priceData);Errores comunes
- Usar montos incorrectos: Stripe trabaja en centavos/minimas unidades monetarias. $20 se escribe como 2000, no como 20. Siempre divide entre 100 para mostrar al usuario.
- Olvidar asociar el precio al producto: Si creas un precio sin el parametro 'product', no estara vinculado a nada y no podras usarlo para suscripciones.
- No validar datos de entrada: Siempre valida nombre, descripcion y montos antes de llamar a la API. Stripe rechazara solicitudes mal formadas.
- Exponer claves secretas: Nunca hardcodees tu clave secreta. Usa variables de entorno como en el ejemplo mejorado.
- Ignorar el manejo de errores: Stripe devuelve errores especificos. Capturalos y manejalos apropiadamente en tu aplicacion.
Checklist de dominio
- Puedo explicar la diferencia entre Producto y Precio en mis propias palabras
- Se configurar el SDK de Stripe con variables de entorno
- Puedo crear un producto con metadatos relevantes para mi negocio
- Se crear precios recurrentes con diferentes intervalos (mensual, anual)
- Implemento validacion de datos antes de llamar a la API
- Manejo errores especificos de Stripe en mi codigo
- Uso montos correctos (en centavos/minimas unidades monetarias)
Crear un sistema de planes de suscripcion escalable
Implementa una funcion que cree multiples productos con sus respectivos precios para un sistema de SaaS. Sigue estos pasos:
- Crea una constante
plansque contenga tres planes diferentes: Basic ($10/mes), Pro ($30/mes), y Enterprise ($100/mes). Cada plan debe tener nombre, descripcion, precio mensual, y metadatos con features. - Implementa la funcion
createAllPlans()que itere sobre el arrayplansy cree cada producto y precio usando el SDK de Stripe. - Agrega validacion para asegurar que los precios sean multiplos de 100 (para evitar centavos fraccionarios).
- Implementa logging que muestre el ID de cada producto y precio creado exitosamente.
- Maneja errores de forma que si falla un plan, el proceso continue con los siguientes.
- Al final, la funcion debe retornar un array con los resultados de cada creacion.
Entrega el codigo completo listo para ejecutar.
Pistas- Usa Promise.allSettled() para manejar multiples operaciones asincronas que pueden fallar independientemente
- Recuerda que los metadatos del producto deben incluir informacion util para tu backend, como 'plan_tier' o 'max_users'
- Considera agregar un precio anual opcional para cada plan usando el mismo producto pero diferente configuracion de recurring
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.