Crear facturas manualmente es tedioso y propenso a errores. Ya sea que factures a clientes mensualmente, proceses pedidos de e-commerce o gestiones pagos de suscripción, automatizar tu pipeline de facturación ahorra tiempo, reduce errores y asegura un branding consistente. En este tutorial, construiremos un sistema completo de automatización de facturas con Node.js que integra con Stripe, genera PDFs profesionales vía TongoRender y los entrega por email.
Arquitectura del Sistema
- Fuente de datos — API de Stripe para datos de pago (adaptable a cualquier sistema de facturación)
- Motor de plantillas — Plantilla de factura HTML/CSS con inyección dinámica de datos
- Renderizador PDF — API de TongoRender para convertir HTML a PDF profesional
- Entrega — Nodemailer para entrega por email con PDF adjunto
Paso 1: Obtener Datos de Pago de Stripe
const Stripe = require('stripe');
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
async function getMonthlyInvoices(year, month) {
const startTimestamp = Math.floor(new Date(year, month - 1, 1).getTime() / 1000);
const endTimestamp = Math.floor(new Date(year, month, 0, 23, 59, 59).getTime() / 1000);
const charges = await stripe.charges.list({
created: { gte: startTimestamp, lte: endTimestamp },
limit: 100,
expand: ['data.customer'],
});
return charges.data
.filter(charge => charge.status === 'succeeded')
.map(charge => ({
id: charge.id,
amount: charge.amount / 100,
currency: charge.currency.toUpperCase(),
customerName: charge.customer?.name || 'Desconocido',
customerEmail: charge.customer?.email,
description: charge.description || 'Cargo por servicio',
date: new Date(charge.created * 1000).toISOString().split('T')[0],
}));
}
Paso 2: Diseño de la Plantilla de Factura
function invoiceHTML(invoice, companyInfo) {
return `
<!DOCTYPE html>
<html lang="es">
<head>
<style>
body { font-family: 'Segoe UI', sans-serif; color: #333; padding: 40px; }
.header { display: flex; justify-content: space-between; margin-bottom: 40px; }
.company-name { font-size: 24px; font-weight: 700; color: #1a1a2e; }
.invoice-title { font-size: 32px; color: #e63946; text-align: right; }
table { width: 100%; border-collapse: collapse; margin: 30px 0; }
th { background: #1a1a2e; color: white; padding: 12px 15px; text-align: left; }
td { padding: 12px 15px; border-bottom: 1px solid #eee; }
.total-row td { font-weight: 700; border-top: 2px solid #1a1a2e; }
</style>
</head>
<body>
<div class="header">
<div>
<div class="company-name">${companyInfo.name}</div>
<div>${companyInfo.address}</div>
<div>RFC: ${companyInfo.taxId}</div>
</div>
<div>
<div class="invoice-title">FACTURA</div>
<div>Número: ${invoice.number}</div>
<div>Fecha: ${invoice.date}</div>
<div>Vencimiento: ${invoice.dueDate}</div>
</div>
</div>
<table>
<thead>
<tr><th>Descripción</th><th>Cant.</th><th>Precio Unit.</th><th>Monto</th></tr>
</thead>
<tbody>
${invoice.items.map(item => \`
<tr>
<td>${item.description}</td>
<td>${item.quantity}</td>
<td>${item.unitPrice.toFixed(2)}</td>
<td>${(item.quantity * item.unitPrice).toFixed(2)}</td>
</tr>
\`).join('')}
<tr class="total-row">
<td colspan="3" style="text-align:right">Total</td>
<td>${invoice.total.toFixed(2)} ${invoice.currency}</td>
</tr>
</tbody>
</table>
</body>
</html>`;
}
Paso 3: Generar PDF y Enviar por Email
async function generateInvoicePDF(invoice, companyInfo) {
const html = invoiceHTML(invoice, companyInfo);
const response = await fetch('https://api.tongorender.io/v1/pdf', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.TONGORENDER_API_KEY,
},
body: JSON.stringify({ html, format: 'A4', printBackground: true }),
});
return Buffer.from(await response.arrayBuffer());
}
async function sendInvoiceEmail(to, invoice, pdfBuffer) {
await transporter.sendMail({
from: '"Facturación" <facturacion@empresa.com>',
to,
subject: `Factura #${invoice.number}`,
text: `Adjunto encontrará la factura #${invoice.number} por ${invoice.total.toFixed(2)}.`,
attachments: [{ filename: `factura-${invoice.number}.pdf`, content: pdfBuffer }],
});
}
Mejores Prácticas
- Idempotencia — Registra qué facturas han sido generadas para evitar enviar duplicados al reintentar.
- Manejo de errores — Envuelve cada factura en try-catch. Una falla no debería detener todo el lote.
- Rate limiting — Espacia las llamadas a la API con un pequeño retraso para mantenerte dentro de los límites.
- Almacenamiento — Siempre guarda una copia del PDF antes de enviarlo por email.
- Cumplimiento fiscal — Incluye todos los campos legalmente requeridos: RFC, número secuencial de factura, montos desglosados e impuestos aplicables.
La renderización confiable de PDF de TongoRender asegura que tus facturas luzcan profesionales siempre.
Automatiza tus facturas con TongoRender — 100 renderizaciones gratuitas al mes, sin necesidad de tarjeta de crédito.