Concepto clave
Las facturas de Stripe son documentos que representan transacciones de pago entre tu negocio y tus clientes. A diferencia de los cargos simples, las facturas están diseñadas para sistemas de suscripción y billing recurrente. Piensa en ellas como recibos profesionales que se generan automáticamente cuando un cliente se suscribe, renueva o realiza un pago único.
Las Billing APIs son el conjunto de herramientas que Stripe proporciona para gestionar todo el ciclo de facturación: desde crear suscripciones hasta enviar recordatorios de pago. La magia está en cómo se integran con los webhooks, que son notificaciones en tiempo real que Stripe envía a tu servidor cuando ocurren eventos importantes, como un pago exitoso o una factura fallida.
Cómo funciona en la práctica
Imagina que tienes una plataforma SaaS con planes mensuales. Cuando un cliente elige un plan, creas una suscripción en Stripe. Stripe genera automáticamente una factura y la marca como "draft" (borrador). Al momento del pago, si es exitoso, la factura se marca como "paid" (pagada) y se envía un webhook a tu backend. Si falla, Stripe reintenta el pago y notifica a tu sistema para que puedas tomar acciones, como desactivar el acceso del cliente.
Paso a paso:
- Crear un producto y un precio en el Dashboard de Stripe o mediante API.
- Cuando un cliente se suscribe, usar la API para crear una suscripción asociada a ese precio.
- Stripe genera una factura inicial y la intenta cobrar inmediatamente.
- Tu backend recibe un webhook con el evento
invoice.payment_succeededoinvoice.payment_failed. - Basado en el webhook, actualizas el estado del usuario en tu base de datos (ej: activar o pausar su cuenta).
Código en acción
Crear una suscripción y manejar el webhook de factura pagada:
// Crear una suscripción en Stripe (Node.js con la librería stripe)
const stripe = require('stripe')('sk_test_...');
async function createSubscription(customerId, priceId) {
const subscription = await stripe.subscriptions.create({
customer: customerId,
items: [{
price: priceId,
}],
payment_behavior: 'default_incomplete',
expand: ['latest_invoice.payment_intent'],
});
return {
subscriptionId: subscription.id,
invoiceId: subscription.latest_invoice.id,
clientSecret: subscription.latest_invoice.payment_intent.client_secret,
};
}Manejar el webhook de factura pagada:
# Ejemplo en Python con Flask
from flask import Flask, request, jsonify
import stripe
app = Flask(__name__)
stripe.api_key = 'sk_test_...'
@app.route('/webhook', methods=['POST'])
def webhook():
payload = request.get_data(as_text=True)
sig_header = request.headers.get('Stripe-Signature')
try:
event = stripe.Webhook.construct_event(
payload, sig_header, 'whsec_...'
)
except ValueError as e:
return 'Invalid payload', 400
except stripe.error.SignatureVerificationError as e:
return 'Invalid signature', 400
# Manejar el evento de factura pagada
if event['type'] == 'invoice.payment_succeeded':
invoice = event['data']['object']
customer_id = invoice['customer']
# Actualizar tu base de datos: activar acceso del usuario
# Ej: update_user_access(customer_id, active=True)
print(f'Factura {invoice["id"]} pagada para cliente {customer_id}')
return jsonify({'status': 'success'}), 200Errores comunes
- No verificar la firma del webhook: Cualquiera puede enviar peticiones a tu endpoint /webhook. Siempre valida la firma con
stripe.Webhook.construct_eventpara asegurar que viene de Stripe. - Confundir invoice.paid con invoice.payment_succeeded:
invoice.paidse dispara cuando una factura se marca como pagada, peroinvoice.payment_succeededes más específico para pagos exitosos. Usainvoice.payment_succeededpara activar acceso de usuarios. - No manejar reintentos de pagos fallidos: Stripe reintenta pagos automáticamente, pero si fallan varias veces, la suscripción se cancela. Configura webhooks para
invoice.payment_failedy notifica al cliente o pausa su cuenta. - Olvidar expandir objetos anidados: Al crear una suscripción, si necesitas el
client_secretdel payment intent, usaexpand: ['latest_invoice.payment_intent']. De lo contrario, tendrás que hacer otra llamada a la API.
Checklist de dominio
- Puedo crear una suscripción con la API de Stripe y manejar la factura inicial.
- Sé configurar un endpoint de webhook y verificar la firma de Stripe.
- Reconozco y manejo los eventos clave:
invoice.payment_succeeded,invoice.payment_failed,customer.subscription.updated. - Entiendo la diferencia entre facturas en estado draft, open, paid, y void.
- Puedo listar todas las facturas de un cliente y filtrar por estado.
- Sé cómo enviar facturas por correo automáticamente desde el Dashboard o mediante API.
- Puedo manejar casos edge: reembolsos, descuentos, y impuestos en facturas.
Implementa un sistema de webhooks para manejar facturas fallidas
En este ejercicio, crearás un endpoint de webhook que maneje facturas con pagos fallidos y notifique al usuario. Sigue estos pasos:
- Configura un servidor local con ngrok o despliega en un servicio como Heroku/Railway.
- Crea un endpoint
/webhookque acepte peticiones POST. - Implementa la verificación de la firma del webhook usando la librería de Stripe.
- Cuando recibas el evento
invoice.payment_failed, extrae el ID del cliente y el ID de la factura. - Simula el envío de una notificación al cliente (puede ser un log en consola o un email simulado).
- Opcional: Si la factura ha fallado más de 2 veces, simula la pausa de la cuenta del usuario.
Usa el siguiente código base para empezar:
from flask import Flask, request, jsonify
import stripe
app = Flask(__name__)
stripe.api_key = 'sk_test_...' # Reemplaza con tu clave de prueba
webhook_secret = 'whsec_...' # Reemplaza con tu secreto de webhook
@app.route('/webhook', methods=['POST'])
def handle_webhook():
# Tu código aquí
pass
if __name__ == '__main__':
app.run(port=4242)
Pistas- Recuerda que el payload del webhook viene en request.get_data(as_text=True).
- Usa stripe.Webhook.construct_event para verificar la firma y parsear el evento.
- El objeto invoice dentro del evento tiene campos como 'customer' y 'attempt_count'.
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.