main content

Cómo integrar pasarelas de pago en una aplicación web a medida

Tu aplicación funciona y los usuarios la usan a diario. El primer roce serio aparece cuando hay que cobrar. He visto proyectos perfectamente diseñados naufragar en este punto: no se trata de pegar un botón "Pagar" y rezar, sino de orquestar webhooks, idempotencia, autenticación reforzada y un puñado de obligaciones legales que no se esquivan.

Lo que sigue es un recorrido por las decisiones que tomarías al integrar pasarelas de pago en una aplicación web a medida con criterio de ingeniería, no de checklist.

Por qué la integración a medida no es una excentricidad

Si tu producto vive en WordPress o Shopify, un plugin probablemente baste. En software a medida ese atajo deja de tener sentido: tu modelo de datos, tu flujo de carrito y tu lógica de negocio no encajan con las suposiciones de un plugin genérico.

Las razones para integrar la pasarela de pago directamente en el código suelen ser estas:

  • Control del flujo. Decides cada pantalla, cada mensaje de error, cada redirección.
  • Menos abandono. Cuando el usuario no abandona tu dominio para pagar, el carrito retiene mejor. Baymard Institute publica tasas de abandono cercanas al 70%, y la fricción del checkout pesa.
  • Modelos complejos sin contorsionismos. Suscripciones con prorrateo, split payments en marketplace, cobros diferidos. Un plugin se rompe; una integración propia se pliega.
  • Datos donde toca. Los pagos viven junto al resto de tu información, sin sincronizar a base de cron jobs.

Las cuatro pasarelas de pago que entran en la conversación

Antes de tocar una línea de código, hay que elegir proveedor de pasarela de pago. En el mercado español y europeo, casi todas las decisiones se reducen a cuatro candidatos.

Stripe

La referencia para equipos de desarrollo. Documentación clara, API coherente, SDKs para cualquier lenguaje serio. Acepta tarjeta, SEPA, Apple Pay, Google Pay y un largo etcétera. Su fee europeo se mueve en torno al 1,4% + 0,25 € para tarjetas del EEE (algo más caro fuera). El settlement por defecto es de 7 días en muchos países, configurable a 2 si justificas histórico.

Redsys

La pasarela de pago bancaria por excelencia en España. La operan CaixaBank, BBVA, Santander y prácticamente cualquier banco nacional. Es menos elegante de integrar que Stripe (firmas HMAC SHA256, parámetros en Base64, un terminal por comercio), pero los usuarios la reconocen y tu comisión la negocias con el banco —puedes bajar del 0,8% si tu volumen acompaña—. Si tu cliente final es muy español y muy tradicional, esto pesa.

PayPal / Braintree

PayPal aún convierte mejor de lo esperado en tickets bajos y usuarios reacios a teclear tarjeta. Braintree (propiedad de PayPal) es su API moderna y unifica tarjeta + PayPal en una sola integración. Buena segunda opción, rara vez primera.

Adyen

Pensada para volumen grande. La usan Spotify, Uber, Booking. Las cuotas mínimas y el setup tienen sentido al procesar seis o siete cifras mensuales; por debajo, no compensa.

¿Cuál elegir?

Heurística rápida: público internacional o equipo que valora la DX, Stripe. Cliente final muy español, Redsys (a menudo combinado con PayPal). Más de seis dígitos al mes, Adyen.

Para el marco general de estas decisiones, échale un ojo a cómo elegir el stack tecnológico para tu proyecto web.

El recorrido concreto de una integración

Estos son los pasos que sigo en proyectos reales. Asume backend en Node, Python o Go; los principios se traducen sin drama a otros entornos.

1. Define el modelo de cobro antes de tocar nada

Las preguntas que evitan reescribir todo en el sprint 4:

  • ¿Pago único, suscripción recurrente o mezcla?
  • ¿Pagos aplazados o fraccionados (BNPL tipo Klarna)?
  • ¿Marketplace con varios beneficiarios?
  • ¿En qué divisas operas y cómo gestionas el FX?
  • ¿Factura automática? ¿Con qué numeración?

Las respuestas condicionan no solo la pasarela de pago, sino la arquitectura. Un PaymentIntent de Stripe para cobro único no se parece a un Subscriptions + Customer Portal, ni mucho menos a un Connect con destination charges.

2. Sandbox y credenciales antes de programar

Toda pasarela de pago seria tiene entorno de pruebas. Stripe te da pk_test_... y sk_test_...; Redsys entrega código de comercio de pruebas, clave de firma y terminal. Nunca empieces contra producción.

3. SDK oficial o librería de comunidad

  • Stripe: npm install stripe, pip install stripe, gems para Ruby, paquetes en Packagist. SDK oficial en todos los lenguajes serios.
  • Redsys: sin SDK oficial. Librerías de comunidad (redsys-easy en Node, sermepa en PHP) o firma HMAC propia siguiendo la guía oficial.
  • Braintree: SDK decente en todos los lenguajes principales.

Regla innegociable: los pagos se procesan en backend. El frontend solo recoge datos en componentes seguros de la pasarela de pago (Stripe Elements, iframe Redsys, hosted fields Braintree).

4. El patrón de flujo que casi siempre funciona

  1. El usuario pulsa "Pagar".
  2. El frontend envía al backend importe, productos y moneda (idealmente recalculas el total en servidor; nunca confíes en el cliente).
  3. El backend pide a la pasarela de pago un PaymentIntent o sesión de pago.
  4. La pasarela responde con un client_secret o URL.
  5. El frontend muestra el formulario seguro o redirige.
  6. El usuario teclea tarjeta en un entorno controlado por la pasarela de pago.
  7. La pasarela cobra y notifica vía webhook.
  8. Tu backend actualiza el pedido cuando llega el evento, no antes.

La consecuencia más importante de este patrón: los datos de tarjeta nunca tocan tu servidor. Eso te mantiene en SAQ A o SAQ A-EP para PCI DSS, que es donde quieres estar.

5. Webhooks: la pieza que casi todo el mundo subestima

Un webhook es una llamada HTTP que la pasarela de pago hace a tu servidor para notificar eventos: payment_intent.succeeded, charge.failed, charge.dispute.created. Sin manejo decente, el sistema tarde o temprano duplica pedidos o pierde cobros.

Tres principios para un endpoint webhook sano a los seis meses:

  • Verifica la firma. Stripe firma con HMAC SHA256 usando un secret del endpoint. Sin verificación, cualquiera marca pedidos como pagados.
  • Idempotencia real. Guarda event.id y descarta duplicados. Las pasarelas de pago reintentan: si tu lógica no es idempotente, el mismo payment_intent.succeeded llega dos o tres veces.
  • Responde 200 rápido. Procesa lo pesado en cola (SQS, Redis). Si tardas más de 10 segundos, Stripe reintenta y se acumulan eventos.

Si vas a diseñar endpoints así, ayuda buenas prácticas para diseñar APIs en aplicaciones a medida.

6. Casos límite que duelen si los ignoras

Un pago falla por motivos que no contemplaste en el sprint planning: tarjeta caducada, fondos insuficientes, 3DS2 rechazado, red caída a mitad, usuario que cierra pestaña tras teclear el CVV.

Lo que más arde:

  • Usuario cierra navegador. Webhook como fuente de verdad, no la redirección de vuelta. Nunca marques pagado en el callback de retorno.
  • Doble click en "Pagar". idempotency_key en la llamada al PaymentIntent (Stripe lo soporta nativamente).
  • Reembolsos parciales. Tu esquema debe permitir varios por pedido y reconciliar el neto.
  • Disputas y chargebacks. Llegan semanas después. Sin charge.dispute.created tratado, te enteras por el extracto.

7. Prueba como si entraras en producción mañana

Tarjetas de test específicas: 4242 4242 4242 4242 (éxito), 4000 0000 0000 0002 (rechazo), 4000 0027 6000 3184 (3DS2 obligatorio). End-to-end con webhooks (Stripe CLI o ngrok en local). Móvil obligatorio: más del 50% de las transacciones online en España vienen de smartphone y los formularios de pago se rompen con preocupante frecuencia en pantallas pequeñas.

PCI DSS y SCA: lo que no es opcional

PCI DSS

Con componentes alojados por la pasarela de pago (Stripe Elements, redirección Redsys, hosted fields Braintree) entras en SAQ A o SAQ A-EP: cuestionario anual, sin auditoría QSA, sin pentest obligatorio. Cumple buenas prácticas de servidor (TLS 1.2+, sin PAN ni CVV ni en logs) y estás dentro.

Si necesitas tocar datos de tarjeta directamente —pista: casi nunca es buena idea— te toca SAQ D: auditoría formal, segmentación de red, escaneos trimestrales ASV. Evítalo.

SCA y 3DS2

PSD2 obligó a autenticación reforzada en pagos electrónicos europeos. Traducción práctica: 3D Secure 2.0, segundo factor por parte del emisor (push de la app del banco, SMS, biometría). Las pasarelas de pago modernas gestionan el requires_action de forma transparente, pero tu frontend tiene que manejar ese estado intermedio sin dejar al usuario en blanco. Exenciones existen (TRA, low-value, MIT) pero las decide el emisor, no tú.

Errores recurrentes al integrar una pasarela de pago

  • No verificar firmas de webhooks. Cualquiera con tu URL puede marcar pedidos pagados.
  • Confiar en la redirección de vuelta. Si el usuario cierra pestaña, pierdes la confirmación. Webhook como única fuente fiable.
  • Hardcodear claves. Variables de entorno, secretos en Vault/SSM/Doppler. Nunca claves en repositorio (y si has subido una, rotación inmediata).
  • No probar en móvil. El 60% del tráfico, el 60% de los bugs.
  • Olvidar la conciliación. Compara mensualmente lo registrado en tu sistema contra el panel de la pasarela de pago. Las discrepancias salen antes de lo que crees.
  • No diseñar para escala. Lo que aguanta 50 cobros al día puede caer con 5.000: revisa rate limits del proveedor, cola de webhooks, locks pesimistas en pedidos.

Cuándo tiene sentido externalizar

Una integración básica con Stripe Checkout y pagos únicos es abordable por un equipo competente en días. La cosa cambia con suscripciones con upgrades prorrateados, marketplaces con split payments, multidivisa con conversión propia o regulación específica (apuestas, financieras, SEPA Direct Debit con mandatos).

En esos escenarios, trabajar con alguien que ya ha estrellado la cabeza contra esos problemas ahorra semanas. En Tangram Consulting integramos pasarelas de pago a medida desde la elección del proveedor hasta la monitorización en producción y la conciliación contable.

Decisiones que pagas mañana si las tomas hoy a la ligera

Un cobro digital parece resuelto al ver el primer payment_intent.succeeded. La calidad de la integración se mide después: el día que un usuario reclama un cargo duplicado, cuando un chargeback aparece sin contexto, la primera vez que un webhook se reintenta cinco veces porque tu endpoint tardó once segundos. Elige pasarela de pago con criterio, blinda los webhooks, mantente lejos de SAQ D y prueba hasta aburrirte. El resto es ingeniería conocida.