main content

Cómo diseñar un sistema de pagos online seguro para tu aplicación web a medida

Llevo años metido hasta el cuello en integraciones de pago, y hay una verdad incómoda que aprendí pronto: cada aplicación que mueve dinero juega a dos cosas a la vez, dar una experiencia limpia al usuario y evitar que mañana te despiertes con un boquete en producción. El Banco de España cifró en más de 100 millones de euros las operaciones fraudulentas con tarjeta en el e-commerce español durante 2023, y te aseguro que esos millones se reparten en miles de comercios que pensaban que su integración estaba "bastante bien".

Voy a contarte cómo monto un sistema de pagos online cuando arranco una aplicación web a medida desde cero. Hablaremos de la pasarela, de la arquitectura de webhooks, del cumplimiento PCI DSS y PSD2, de tokenización, de prevención de fraude y de los flujos que más cicatrices me han dejado: suscripciones y reembolsos.

Por qué el diseño del sistema de pagos merece una estrategia propia

En un SaaS genérico te dan el motor de pagos masticado. En una aplicación a medida la arquitectura es tuya, y con ella la responsabilidad. La regla que sigo desde hace tiempo: si un error de diseño en pagos te puede costar el negocio, trátalo con el mismo cariño que tratarías la autenticación.

Riesgos de improvisar la integración

  • Exposición de datos sensibles: el día que alguien guarda PANs en una tabla "temporal" sin las medidas PCI DSS adecuadas, ya empezó la cuenta atrás. Las sanciones pueden subir a 500.000 euros por incidente, y eso sin contar el daño reputacional.
  • Fraude por ausencia de autenticación fuerte: sin 3D Secure y SCA, las tasas de contracargos se disparan por encima del 1 %. A partir de ese umbral las redes empiezan a pegarte penalizaciones, y no son simbólicas.
  • Transacciones fantasma: lo aprendí cuando un cliente nuestro cobró dos veces a 400 usuarios en una noche por un webhook mal idempotente. Sin idempotencia y sin gestión correcta de webhooks, vas a cobrar dos veces o, peor, vas a entregar el servicio sin haber cobrado.

Cumplimiento normativo: PCI DSS y PSD2/SCA

Antes de tocar una línea de código, hay que entender el terreno regulatorio. Si crees que basta con poner "cumplimos PCI-DSS" en el footer, lee la letra pequeña.

PCI DSS: el estándar de seguridad de datos de tarjeta

El Payment Card Industry Data Security Standard (PCI DSS) aplica a cualquier entidad que almacene, procese o transmita datos de titular de tarjeta. La versión vigente, PCI DSS v4.0.1, publicada en junio de 2024, aprieta más en cifrado, autenticación multifactor y monitorización continua.

Niveles de cumplimiento para comercios:

Nivel Transacciones anuales Requisito principal
1 > 6 millones Auditoría anual por QSA
2 1-6 millones SAQ + escaneo trimestral ASV
3 20.000-1 millón (e-commerce) SAQ + escaneo trimestral ASV
4 < 20.000 (e-commerce) SAQ recomendado

En la práctica, para una aplicación a medida lo sensato es reducir el alcance PCI al mínimo delegando los datos de tarjeta en la pasarela vía tokenización. Eso te baja al cuestionario SAQ-A o SAQ A-EP, y te quitas auditorías de encima.

PSD2 y autenticación reforzada (SCA)

La Directiva de Servicios de Pago 2 (PSD2), transpuesta en España vía Real Decreto-ley 19/2018, exige Autenticación Reforzada del Cliente (SCA) para la mayoría de pagos electrónicos. Necesitas verificar al menos dos de tres factores:

  1. Conocimiento: algo que el usuario sabe (PIN, contraseña).
  2. Posesión: algo que el usuario tiene (teléfono móvil, tarjeta física).
  3. Inherencia: algo que el usuario es (huella, reconocimiento facial).

Las exenciones (importes inferiores a 30 euros, pagos recurrentes tras la primera autenticación, análisis de riesgo de la transacción o TRA) son un arma de doble filo: bien gestionadas reducen fricción, mal gestionadas generan rechazos del emisor que se traducen en abandono. Dedícales un rato.

Elección de la pasarela de pago

La pasarela es quien procesa la transacción de verdad. Elegir mal aquí lo pagas durante años en comisiones, en quebraderos de cabeza o en límites de modelo de negocio.

Stripe

Stripe se ha quedado como opción por defecto en startups y empresas tecnológicas, y se entiende: API limpia, documentación que se lee, ecosistema amplio (Elements, Checkout, Billing) y cobertura de más de 135 divisas. Tokenización nativa, SCA gestionada y Stripe Radar para fraude.

Ventajas para apps a medida:

  • API RESTful con SDKs en más de 10 lenguajes.
  • Stripe Elements incrusta campos de tarjeta seguros sin que los datos pasen por tu servidor (un alivio para tu alcance PCI).
  • Soporte nativo para suscripciones, pagos diferidos, Connect (marketplaces) y payouts.

Consideraciones:

  • Comisiones estándar en Europa del 1,5 % + 0,25 EUR por transacción con tarjeta europea.
  • La personalización visual de Elements tiene techo, aunque el Payment Element unificado ha mejorado mucho.

Redsys

Redsys es la pasarela que manda en el e-commerce español. CaixaBank, BBVA, Santander y Sabadell canalizan sus TPV virtuales por aquí, así que si tu público es nacional, es la opción natural y te ahorrarás conversaciones raras con el banco.

Ventajas:

  • Reconocimiento entre consumidores españoles.
  • Integración directa con entidades locales, lo que suele traducirse en comisiones negociables con tu banco.
  • Soporte para Bizum, que en España pesa.

Consideraciones:

  • La documentación ha mejorado, pero históricamente daba ganas de llorar.
  • Te toca gestionar firmas HMAC-SHA256 a mano, y ahí es muy fácil equivocarse (yo me he equivocado).
  • Menos flexibilidad para marketplaces o suscripciones con lógica fina.

Adyen

Adyen apunta a empresa de cierto tamaño. Unifica pagos online, presencial y móvil en una plataforma. Spotify, Uber o Mango son clientes suyos.

Ventajas:

  • Motor de optimización de rutas que elige el adquirente con mayor tasa de aceptación.
  • RevenueProtect para reglas de fraude granulares.
  • Soporte para más de 250 métodos de pago globales.

Consideraciones:

  • Si no manejas volumen medio-alto, las tarifas no compensan.
  • La integración inicial pide más trabajo que la de Stripe.

Criterios para decidir

  • Volumen y mercado geográfico: solo España y volumen moderado, Redsys suele salir mejor de cuenta. Internacional, Stripe o Adyen.
  • Complejidad del modelo de negocio: marketplaces, suscripciones con prueba gratuita, pagos divididos o cobros a la carta encajan mejor con Stripe o Adyen.
  • Recursos de desarrollo: mira documentación, SDKs y experiencia previa del equipo. Una API que tu equipo no entiende es una bomba de relojería.

Tokenización: la base de la seguridad en pagos

Tokenizar es sustituir los datos sensibles del titular (PAN, fecha de expiración, CVV) por un identificador opaco e irreversible. Ese token solo significa algo dentro de la pasarela que lo emitió. Para tu base de datos es ruido.

Cómo funciona el flujo tokenizado

  1. El usuario teclea los datos de su tarjeta en un iframe o componente seguro de la pasarela (Stripe Elements, formulario incrustado de Redsys).
  2. El navegador del usuario manda esos datos directamente a los servidores de la pasarela, sin tocar tu backend.
  3. La pasarela te devuelve un token (de un solo uso o reutilizable).
  4. Tu backend toma el token y crea el cargo, la suscripción o el setup intent.

El punto clave: tu servidor jamás ve ni guarda datos reales de tarjeta. Eso te recorta drásticamente el alcance PCI DSS, y es probablemente la decisión que más dolor te ahorra en años.

Network tokens vs. gateway tokens

Los network tokens los emiten las propias redes (Visa, Mastercard) y se actualizan solos cuando el titular recibe tarjeta nueva por caducidad o reemisión. Eso mejora la tasa de aceptación en cobros recurrentes, que es donde más vidas se han perdido. Stripe y Adyen los soportan de forma transparente.

3D Secure: autenticación en el punto de pago

3D Secure (3DS) es el protocolo que implementa la autenticación SCA en el momento del pago. La versión actual, 3DS2, introduce el flujo sin fricción (frictionless flow): si el análisis de riesgo del emisor lo permite, el usuario ni se entera de que ha habido autenticación.

Integración de 3DS2 en tu aplicación

  • Stripe: Payment Intents con confirmation_method: automatic. Stripe orquesta 3DS2 solo y muestra el desafío únicamente cuando el emisor lo pide.
  • Redsys: la versión REST soporta 3DS2 nativo. Tienes que enviar datos del navegador (browser info) para que el emisor pueda hacer su análisis de riesgo.
  • Adyen: su Drop-in o componentes web integran el flujo 3DS2.

Impacto en la conversión

Datos de Stripe publicados en 2024 dicen que un 3DS2 bien implementado con flujo frictionless autentica hasta el 85 % de las transacciones sin que el usuario tenga que hacer nada, frente al antiguo 3DS1 donde el 100 % requería un paso extra. Eso es abandono de carrito que no pierdes.

Arquitectura del flujo de pago

Un sistema de pagos serio para una aplicación a medida necesita una arquitectura preparada para estados asíncronos, condiciones de carrera y fallos parciales. Si solo modelas el camino feliz, vas a sufrir.

Patrón recomendado: intent-based payment flow

  1. Creación del intent: cuando el usuario confirma la compra, tu backend crea un Payment Intent (o equivalente) en la pasarela. Ese objeto representa la intención de cobro con un estado inicial (requires_payment_method o requires_confirmation).
  2. Confirmación en el frontend: el frontend recoge el método de pago (token) y confirma el intent. Si toca 3DS, la pasarela lanza el desafío.
  3. Procesamiento asíncrono: la pasarela procesa el cargo. El resultado final (éxito, fallo, autenticación requerida) llega tanto por la respuesta síncrona como por webhook.
  4. Actualización del estado en tu sistema: tu backend actualiza pedido o suscripción según el estado final.

Diagrama de estados del pago

[Creado] -> [Pendiente de método] -> [Pendiente de confirmación]
    -> [Pendiente de autenticación (3DS)] -> [Procesando]
    -> [Exitoso] | [Fallido] | [Cancelado]
    -> [Reembolsado] | [Parcialmente reembolsado] | [Disputado]

Cada transición la registro siempre con timestamp, origen (API o webhook) e identificador de la transacción en la pasarela. Cuando un cliente te llama enfadado porque "se cobró dos veces", esa tabla vale oro.

Webhooks: la columna vertebral de la fiabilidad

Los webhooks son notificaciones HTTP que la pasarela te manda cada vez que ocurre algo relevante (pago completado, fallo, reembolso, disputa). Son imprescindibles porque:

  • La respuesta síncrona se pierde si el navegador del usuario se cierra antes de recibir la confirmación.
  • Eventos como disputas (chargebacks) o pagos con métodos asíncronos (transferencia, SEPA Direct Debit) solo te llegan por webhook.

Buenas prácticas para webhooks

  • Verifica la firma: toda pasarela firma sus webhooks. Valida la firma antes de procesar el evento. Stripe usa HMAC-SHA256 con un secreto de endpoint; Redsys firma con la clave de comercio. Si te saltas este paso, te puedo asegurar que alguien terminará intentando inyectarte eventos falsos.
  • Responde con 200 rápido: procesa la lógica de negocio en una cola asíncrona, con worker. Si tu endpoint tarda más de 5-10 segundos, la pasarela considera el webhook fallido y lo reintenta.
  • Gestiona reintentos y duplicados: las pasarelas reenvían webhooks si no reciben confirmación. Idempotencia obligatoria (ver siguiente sección).
  • Registra todos los eventos: guarda el payload completo. Cuando algo se rompe a las tres de la mañana, ese log es lo único que te salva.

Ejemplo de flujo de webhook seguro

Pasarela -> POST /webhooks/stripe
  1. Verificar firma del header Stripe-Signature
  2. Parsear el evento
  3. Comprobar si el event_id ya fue procesado (idempotencia)
  4. Encolar tarea asíncrona con el evento
  5. Responder 200 OK
  ---
  Worker:
  6. Procesar evento (actualizar pedido, enviar email, etc.)
  7. Marcar event_id como procesado

Idempotencia: evitando cobros duplicados

La idempotencia garantiza que una operación produce el mismo resultado por mucho que la ejecutes. En pagos no es opcional: un reintento de red o un webhook duplicado no pueden generar un segundo cobro. El día que un chargeback colectivo te aterriza por cobros duplicados, ya no hay vuelta atrás bonita.

Estrategias de idempotencia

  • Claves de idempotencia en la API: Stripe permite mandar un header Idempotency-Key con cada petición. Si la pasarela ve dos peticiones con la misma clave, devuelve el resultado de la primera sin ejecutar la segunda.
  • Deduplicación por event_id en webhooks: guarda el id único de cada evento y descarta duplicados antes de procesarlos.
  • Estado canónico en tu base de datos: antes de entregar producto o activar suscripción, comprueba el estado del pedido. Si ya está pagado, no repitas la acción. Suena obvio, hasta que no lo es.

Prevención de fraude

Más allá de 3DS2 y SCA, conviene poner capas adicionales. El fraude es como el agua: encuentra el punto débil y se cuela.

Herramientas de la pasarela

  • Stripe Radar: scoring con modelos de machine learning entrenados sobre datos de millones de comercios. Permite reglas personalizadas (bloquear pagos de ciertos países, exigir 3DS desde cierto importe).
  • Adyen RevenueProtect: similar a Radar, con reglas por mercado, canal o tipo de producto.
  • Redsys: módulo de scoring de fraude configurable desde el panel del TPV virtual.

Controles adicionales en tu aplicación

  • Verificación de dirección (AVS): compara la dirección que da el usuario con la del emisor. Tira más en mercados anglosajones.
  • Verificación de CVV/CVC: pide siempre el código de seguridad en el primer uso de una tarjeta. Sin excepciones.
  • Límites de velocidad: pon un techo de intentos fallidos por usuario o IP en una ventana (por ejemplo, 5 intentos en 15 minutos). Cuando ves a alguien probando 200 tarjetas en 10 minutos, ya es tarde.
  • Análisis de comportamiento: detecta múltiples tarjetas asociadas a una misma cuenta, compras altas justo tras crear cuenta, o cambios frecuentes de dirección de envío.
  • Listas negras: mantén una base de emails, IPs o BINs vinculados a fraude previo.

Flujo de reembolsos

Todo sistema necesita un flujo de reembolsos bien pensado. Un reembolso mal gestionado genera disputas innecesarias, errores contables y, sobre todo, clientes que no vuelven.

Tipos de reembolso

  • Reembolso total: devuelves el importe completo de la transacción original.
  • Reembolso parcial: devuelves parte. Útil para devolver un artículo dentro de un pedido con varios productos.
  • Crédito en cuenta: en vez de devolver al método de pago original, acreditas saldo en la cuenta del usuario. Esto pide gestión contable adicional, así que valora si te compensa.

Consideraciones técnicas

  • Los reembolsos se ejecutan contra el cargo original mediante su identificador en la pasarela. Nunca, jamás, crees un cargo negativo nuevo.
  • El reembolso tarda entre 5 y 10 días laborables en aparecer en la cuenta del titular, según el emisor. Avisa al usuario del plazo o tu soporte se va a saturar de tickets idénticos.
  • Registra cada reembolso con: motivo, importe, fecha, usuario que lo aprobó (si fue manual) y referencia de la transacción original.
  • Para reembolsos por encima de cierto umbral, exige aprobación de administrador. Te ahorra sustos.

Multi-divisa: aceptar pagos internacionales

Si tu app opera en varios mercados, multi-divisa deja de ser opcional.

Estrategias de multi-divisa

  • Presentación en divisa local, liquidación en una divisa: enseñas precios en la divisa del usuario y recibes los fondos en tu divisa base (euros, normalmente). La pasarela hace la conversión al tipo del día. Stripe y Adyen lo soportan nativamente.
  • Cuentas multi-divisa: mantienes balances separados por divisa, sin conversiones automáticas. Tiene sentido cuando tienes gastos operativos en esas divisas.
  • Precios fijos por mercado: defines precios específicos por país, sin depender del tipo de cambio. Control total a cambio de mantenimiento constante.

Consideraciones fiscales

El IVA y otros impuestos indirectos cambian por país. En la UE, la normativa OSS (One-Stop Shop) simplifica la declaración del IVA en ventas B2C transfronterizas, pero obliga a cobrar el tipo del país del comprador. Stripe Tax o servicios especializados como TaxJar te automatizan el cálculo, y créeme que no quieres llevarlo a mano.

Suscripciones y facturación recurrente

Las suscripciones suben el nivel de complejidad: ciclos de facturación, prueba, upgrades, downgrades, pausas, cancelaciones. Cada estado nuevo es una oportunidad de meter la pata.

Componentes clave de un sistema de suscripciones

  • Plan/Precio: define importe, frecuencia (mensual, anual, semanal) y divisa.
  • Suscripción: liga al cliente con un plan y gestiona el ciclo de vida.
  • Factura: se genera en cada ciclo de facturación.
  • Método de pago por defecto: el token de la tarjeta o mandato SEPA que se cargará automáticamente.

Gestión de fallos en cobros recurrentes (dunning)

Cuando un cobro recurrente falla (tarjeta caducada, fondos insuficientes, límite excedido), tienes que tener un flujo de recuperación. Si no lo tienes, estás regalando dinero:

  1. Reintentos automáticos: la pasarela reintenta según una programación (por ejemplo, a los 3, 5 y 7 días).
  2. Notificación al usuario: emails avisando del fallo y pidiendo actualización del método de pago.
  3. Periodo de gracia: mantén el servicio activo unos días mientras se resuelve.
  4. Cancelación o pausa: si los reintentos se agotan sin éxito, cancela o pausa la suscripción automáticamente.

Stripe Billing hace todo este flujo con Smart Retries, que usa machine learning para elegir el momento óptimo del reintento. La tasa de recuperación cambia bastante.

Prorratas y cambios de plan

Cuando un usuario cambia de plan a mitad de ciclo, hay que decidir cómo se reparte la diferencia:

  • Prorrateo inmediato: cobras o acreditas la diferencia proporcional al tiempo restante del ciclo.
  • Aplicación al siguiente ciclo: el cambio entra cuando arranca el nuevo periodo.
  • Crédito: generas crédito por el tiempo no consumido del plan anterior.

Seguridad adicional: más allá de la pasarela

Cifrado en tránsito y en reposo

  • TLS 1.2 o superior: toda comunicación (servidor-pasarela y navegador-app) tiene que ir por HTTPS con TLS 1.2 mínimo. La 1.3 es preferible por rendimiento y seguridad.
  • Cifrado de datos sensibles en reposo: aunque no guardes datos de tarjeta, otros datos de pago (importes, identificadores de transacción, facturación) deben ir cifrados. AES-256 para cifrado simétrico.

Gestión de secretos

  • Las claves API de la pasarela (secret keys) jamás en código fuente ni en repositorios. Lo digo en mayúsculas mentalmente.
  • Usa un gestor de secretos: AWS Secrets Manager, Google Cloud Secret Manager, HashiCorp Vault o variables de entorno cifradas de tu plataforma de despliegue.
  • Rota las claves cada cierto tiempo y emplea claves restringidas (restricted keys) con los permisos mínimos.

Registro y auditoría

  • Registra cada operación con información suficiente para auditoría. Jamás escribas datos sensibles de tarjeta, ni siquiera enmascarados, en logs de texto plano.
  • Alertas automáticas para anomalías: picos de fallos, tasas de contracargo elevadas, volumen raro de reembolsos.
  • Conserva los registros al menos 7 años por obligaciones fiscales y prevención de blanqueo en España.

Pruebas del sistema de pagos

  • Entorno sandbox: toda pasarela ofrece sandbox con tarjetas ficticias. Úsalo en desarrollo y QA, siempre.
  • Pruebas de regresión: automatiza pruebas de los flujos principales (pago exitoso, fallo de tarjeta, 3DS, reembolso, webhook) y lánzalas en cada despliegue.
  • Pruebas de carga: simula picos (un lanzamiento, una campaña tipo Black Friday) para verificar que el sistema escala sin duplicar transacciones ni perder webhooks.
  • Chaos testing: mete fallos controlados (latencia en la pasarela, webhooks duplicados, respuestas 500) y comprueba que tu sistema se recupera. La primera vez que lo haces, sufres; después duermes mejor.

Lista de verificación antes del lanzamiento

Antes de poner el sistema en producción, repaso esta checklist sin saltarme nada:

  • Los datos de tarjeta nunca tocan tu servidor (tokenización vía iframe/componente de la pasarela).
  • Toda comunicación usa TLS 1.2+.
  • Los webhooks validan la firma criptográfica antes de procesar.
  • Las operaciones de pago son idempotentes.
  • 3DS2/SCA está integrado y las exenciones se gestionan.
  • Existe un flujo de reembolso probado (total y parcial).
  • Las claves API viven en un gestor de secretos, no en el código.
  • Hay alertas configuradas para tasas de error y contracargos anómalos.
  • Los logs de pago no contienen datos sensibles de tarjeta.
  • El sistema se ha probado en sandbox con todos los escenarios de error documentados por la pasarela.
  • Se han hecho pruebas de carga simulando picos de tráfico.
  • La política de privacidad y los términos reflejan el procesamiento de pagos.

Construir un sistema de pagos que inspire confianza y escale con tu negocio

Diseñar un sistema de pagos online seguro para una aplicación a medida no consiste en enchufar una API y pintar un formulario de tarjeta. Es un ejercicio de arquitectura donde se cruzan seguridad, normativa, experiencia de usuario, fiabilidad y escalabilidad. Cada decisión, desde la pasarela elegida hasta cómo manejas los reintentos en suscripciones, te toca el bolsillo y la confianza del cliente.

Mi receta tras unas cuantas integraciones en producción: apóyate en estándares (PCI DSS, PSD2, 3DS2), delega los datos sensibles en pasarelas certificadas vía tokenización y construye una arquitectura orientada a eventos que digiera bien estados asíncronos, idempotencia y fallos parciales. Lo demás se aprende a base de cicatrices, y mejor no coleccionarlas tú.

Si quieres un equipo con experiencia en diseñar e implementar sistemas de pago seguros para aplicaciones web a medida, contacta con Tangram Consulting y te ayudaremos a definir la arquitectura que mejor encaje con tu modelo de negocio.