Integración de Stripe Simplificada: Ejemplos de Código para Desarrolladores

June 11, 2025

¡Hola, colegas desarrolladores! Si alguna vez han necesitado añadir capacidades de pago a su aplicación, es muy probable que Stripe haya aparecido en su radar. Es una herramienta fantástica, de verdad, pero a veces configurarlo todo correctamente puede parecer un poco como luchar con un pulpo: muchas piezas en movimiento, y no estás muy seguro de cuál agarrar a continuación.

Ahí es donde entra esta guía. No estoy aquí solo para repetir la documentación oficial (¡aunque es excelente!). Mi objetivo es ofrecerles un camino claro y sin complicaciones para integrar Stripe, completo con fragmentos de código amigables y de uso real en algunos lenguajes populares. Piensen en ello como una conversación útil con un amigo que ya ha pasado por esto, lo ha hecho, y quiere ahorrarles algunos dolores de cabeza.

¿Por qué Stripe? (Y por qué es importante hacerlo bien)

Antes de sumergirnos en el código, hablemos rápidamente de por qué Stripe es a menudo la opción preferida por muchos. Es robusto, seguro y tiene herramientas para desarrolladores fantásticas. Pero tener una herramienta potente no es suficiente; necesitas manejarla con eficacia. Un sistema de pago bien integrado no se trata solo de cobrar dinero; se trata de proporcionar una experiencia fluida y confiable para tus usuarios y reducir posibles puntos de fricción para tu negocio.

Los detalles: Configurando tu entorno Stripe

Lo primero es lo primero, necesitarás una cuenta de Stripe. Dirígete a stripe.com y regístrate. Una vez dentro, encontrarás tus claves API en el panel de control para desarrolladores. Tendrás dos conjuntos: una clave 'publicable' (para tu frontend, seguro de compartir) y una clave 'secreta' (para tu backend, ¡guárdala bajo llave!).

Para el desarrollo local, es una buena idea configurar un archivo .env para almacenar tu clave secreta. ¡Nunca la codifiques directamente!

Ejemplo de archivo .env:

STRIPE_SECRET_KEY=sk_test_TU_CLAVE_SECRETA
STRIPE_PUBLISHABLE_KEY=pk_test_TU_CLAVE_PUBLICABLE

Creando una sesión de pago básica

La forma más común de manejar pagos con Stripe hoy en día es a través de las Sesiones de Checkout. Esto quita gran parte de la carga de cumplir con la normativa PCI y la estilización de la interfaz de usuario a Stripe, lo cual es una gran ventaja para nosotros, los desarrolladores.

Tu frontend simplemente redirigirá al usuario a una página alojada por Stripe y, después del pago, será redirigido de nuevo a tu sitio.

Así es como se inicia una sesión de checkout desde tu backend:

Ejemplo en Node.js (usando express):

// backend/server.js
const express = require('express');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const app = express();

app.use(express.json()); // Para analizar application/json

app.post('/create-checkout-session', async (req, res) => {
  try {
    const session = await stripe.checkout.sessions.create({
      payment_method_types: ['card'],
      line_items: [
        {
          price_data: {
            currency: 'usd',
            product_data: {
              name: 'Producto Asombroso',
            },
            unit_amount: 2000, // $20.00
          },
          quantity: 1,
        },
      ],
      mode: 'payment',
      success_url: 'http://localhost:3000/success?session_id={CHECKOUT_SESSION_ID}',
      cancel_url: 'http://localhost:3000/cancel',
    });
    res.json({ id: session.id });
  } catch (error) {
    console.error('Error al crear la sesión de checkout:', error);
    res.status(500).json({ error: error.message });
  }
});

app.listen(4242, () => console.log('¡Servidor Node escuchando en el puerto 4242!'));

Ejemplo en Python (usando Flask):

# backend/app.py
from flask import Flask, jsonify, request, redirect, url_for
import stripe
import os

app = Flask(__name__)

stripe.api_key = os.getenv('STRIPE_SECRET_KEY')

@app.route('/create-checkout-session', methods=['POST'])
def create_checkout_session():
    try:
        session = stripe.checkout.Session.create(
            payment_method_types=['card'],
            line_items=[
                {
                    'price_data': {
                        'currency': 'usd',
                        'product_data': {
                            'name': 'Producto Asombroso',
                        },
                        'unit_amount': 2000,
                    },
                    'quantity': 1,
                }
            ],
            mode='payment',
            success_url='http://localhost:3000/success?session_id={CHECKOUT_SESSION_ID}',
            cancel_url='http://localhost:3000/cancel',
        )
        return jsonify(id=session.id)
    except Exception as e:
        print(f'Error al crear la sesión de pago: {e}')
        return jsonify(error=str(e)), 500

if __name__ == '__main__':
    app.run(port=4242)

En el frontend, después de llamar a este endpoint, redirigirías a tu usuario:

Ejemplo de Front-end (usando Stripe.js):

<!-- frontend/index.html -->
<!DOCTYPE html>
<html>
<head>
  <title>Compra mi producto asombroso</title>
  <script src="https://js.stripe.com/v3/"></script>
</head>
<body>
  <h1>Compra mi producto asombroso</h1>
  <button id="checkout-button">Pagar</button>

  <script type="text/javascript">
    const stripe = Stripe('pk_test_TU_CLAVE_PUBLICABLE'); // Reemplaza con tu clave pública

    const checkoutButton = document.getElementById('checkout-button');

    checkoutButton.addEventListener('click', async () => {
      try {
        const response = await fetch('/create-checkout-session', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
        });
        const session = await response.json();

        if (session.id) {
          const result = await stripe.redirectToCheckout({
            sessionId: session.id,
          });

          if (result.error) {
            alert(result.error.message);
          }
        } else if (session.error) {
            alert(session.error.message);
        }

      } catch (error) {
        console.error('Error al iniciar el pago:', error);
        alert('No se pudo iniciar el pago. Por favor, inténtalo de nuevo.');
      }
    });
  </script>
</body>
</html>

Manejo post-pago: Los Webhooks son tus amigos

Después de un pago exitoso, ¿cómo sabe tu backend lo que ha ocurrido? No puedes depender únicamente de la success_url, ya que los usuarios podrían cerrar su navegador. La respuesta son los webhooks.

Stripe envía eventos a tu endpoint de webhook especificado cada vez que sucede algo significativo (como un pago exitoso, un reembolso, una actualización de suscripción, etc.). Tu servidor escucha estos eventos y actúa en consecuencia.

Configurando un endpoint de Webhook

Primero, necesitarás una URL pública para que Stripe envíe eventos. Para el desarrollo local, herramientas como ngrok son invaluables. Crean un túnel seguro desde una URL pública a tu máquina local. Consulta la documentación de ngrok para configurarlo.

Una vez que ngrok esté funcionando, normalmente lo iniciarías como ngrok http 4242 (asumiendo que tu servidor se ejecuta en el puerto 4242). Te dará una URL pública (por ejemplo, https://tu-subdominio-aleatorio.ngrok-free.app).

Ahora, en tu panel de control de Stripe, ve a Desarrolladores > Webhooks y 'Añadir endpoint'. Pega tu URL de ngrok (por ejemplo, https://tu-subdominio-aleatorio.ngrok-free.app/webhook) y selecciona los eventos que quieres escuchar (checkout.session.completed es un buen comienzo para pagos).

Verificando las firmas de Webhook

Es absolutamente crucial verificar la firma del webhook. Esto asegura que el evento realmente provino de Stripe y no ha sido alterado.

Stripe incluye una firma en el encabezado Stripe-Signature. Necesitarás tu secreto de webhook (que se encuentra en los detalles de tu endpoint de webhook en el panel de control de Stripe) para verificar esto.

Ejemplo de Webhook en Node.js:

// backend/server.js (añadir a tu server.js existente)

// IMPORTANTE: Asegúrate de que este endpoint sea específico y vaya antes del análisis JSON
// general si estás usando body-parser o express.json globalmente, ya que los webhooks necesitan el cuerpo 'raw'.

app.post('/webhook', express.raw({type: 'application/json'}), async (req, res) => {
  const sig = req.headers['stripe-signature'];
  let event;
  const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET; // Obtener esto de la configuración de webhook de Stripe

  try {
    event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
  } catch (err) {
    console.error(`Error de Webhook: ${err.message}`);
    return res.status(400).send(`Error de Webhook: ${err.message}`);
  }

  // Manejar el evento
  switch (event.type) {
    case 'checkout.session.completed':
      const checkoutSession = event.data.object;
      // Cumplir con la compra, actualizar tu base de datos, enviar correo de confirmación, etc.
      console.log(`Sesión de checkout completada para: ${checkoutSession.id}`);
      // Accede al cliente, los artículos de la línea, etc., desde el objeto checkoutSession
      break;
    // ... manejar otros tipos de eventos
    default:
      console.log(`Tipo de evento no manejado ${event.type}`);
  }

  // Devolver una respuesta 200 para confirmar la recepción del evento
  res.send();
});

Ejemplo de Webhook en Python:

# backend/app.py (añadir a tu app.py existente)

@app.route('/webhook', methods=['POST'])
def webhook_received():
    request_data = request.data.decode('utf-8')
    signature = request.headers.get('stripe-signature')
    webhook_secret = os.getenv('STRIPE_WEBHOOK_SECRET') # Obtener esto de la configuración de webhook de Stripe

    try:
        event = stripe.Webhook.construct_event(
            payload=request_data,
            sig_header=signature,
            secret=webhook_secret
        )
    except ValueError as e:
        # Payload inválido
        print(f'Payload inválido: {e}')
        return jsonify({'error': 'Payload inválido'}), 400
    except stripe.error.SignatureVerificationError as e:
        # Firma inválida
        print(f'Firma inválida: {e}')
        return jsonify({'error': 'Firma inválida'}), 400

    # Manejar el evento
    if event['type'] == 'checkout.session.completed':
        checkout_session = event['data']['object']
        # Completar la compra, actualizar tu base de datos, enviar correo de confirmación, etc.
        print(f'Sesión de pago completada para: {checkout_session.id}')
    # ... manejar otros tipos de eventos

    return jsonify({'status': 'éxito'}), 200

Mejores prácticas rápidas a tener en cuenta

  • El manejo de errores es clave: Siempre envuelve tus llamadas a la API de Stripe en bloques try...catch. Los pagos son fundamentales y querrás manejar de forma elegante cualquier cosa que pueda salir mal.
  • Idempotencia: Al realizar llamadas a la API (especialmente aquellas que crean recursos como cargos), utiliza una clave de idempotencia. Esto garantiza que si una solicitud se envía accidentalmente varias veces (por ejemplo, debido a un fallo en la red), Stripe la procesa solo una vez. La mayoría de las librerías cliente se encargan de esto por ti, pero es bueno tenerlo en cuenta.
  • Modo de prueba vs. Modo en vivo: Desarrolla y prueba siempre a fondo en el modo test. Utiliza los números de tarjeta de prueba proporcionados por Stripe. Solo cambia a los secretos del modo live cuando estés absolutamente listo para transacciones reales.
  • HTTPS no es negociable: Para aplicaciones en vivo, siempre asegúrate de que tu dominio use HTTPS. Esto protege la información sensible de pago.
  • Almacena solo lo necesario: Evita almacenar detalles sensibles de tarjetas en tus servidores. Deja que Stripe se encargue de eso. Si necesitas referenciar clientes o métodos de pago, usa los IDs de cliente o los IDs de método de pago de Stripe.

Para concluir

Stripe es una plataforma increíblemente potente, y su integración no tiene por qué ser una tarea monumental. Al desglosarlo en pasos manejables –configurar tus claves, crear sesiones de pago y, lo que es crucial, manejar webhooks–, puedes poner en marcha tu flujo de pagos de manera bastante fluida.

Recuerda, esto es solo un punto de partida. Stripe ofrece mucho más: suscripciones, facturación, cuentas conectadas y flujos de pago más complejos. Pero con estas piezas fundamentales en su lugar, estás en camino de construir un procesamiento de pagos robusto y confiable en tus aplicaciones. ¡Feliz codificación!

Compartir este artículo