Seguridad de los pagos: qué no debes guardar nunca y por qué se firman los webhooks
La mayoría de los incidentes en cobros online no vienen de un ataque sofisticado, sino de dos decisiones de diseño: guardar datos de tarjeta que no hacían falta y confiar en lo que dice el navegador del cliente.
Aceptar tarjetas obliga a cumplir el estándar PCI DSS. La buena noticia es que la mayor parte de ese cumplimiento se puede delegar: si tu servidor nunca ve un número de tarjeta, casi todo el trabajo se lo lleva tu proveedor. La mala es que hay dos formas fáciles de estropearlo.
Datos que no puedes guardar, ni cifrados
El estándar distingue entre datos que pueden almacenarse con protección y datos que no pueden almacenarse nunca después de autorizar el pago:
- El código de verificación de tres o cuatro dígitos del reverso o el anverso.
- El contenido completo de la banda magnética o del chip.
- El PIN o su bloque cifrado.
Cifrarlos no lo arregla: la prohibición es sobre el almacenamiento, no sobre el formato. El número de tarjeta sí puede almacenarse bajo condiciones estrictas, pero la pregunta correcta casi siempre es otra: ¿para qué lo quieres? Si es para cobros recurrentes, lo que necesitas es un token, no el número.
SAQ A: el objetivo razonable para casi todos
El cuestionario de autoevaluación más ligero, conocido como SAQ A, está pensado para comercios que externalizan por completo la captura de datos de tarjeta: el formulario lo sirve el proveedor de pago dentro de un iframe o mediante redirección, y tu página nunca toca el número.
La diferencia práctica es enorme: pasas de tener que proteger, segmentar y auditar tu propia infraestructura a responder un cuestionario corto. La contrapartida es que el formulario deja de ser tuyo, con las limitaciones de diseño que eso implica, y que cualquier atajo —capturar el número «solo un momento» para reenviarlo— te saca de ese régimen sin avisar.
Tokens: dos cosas distintas con el mismo nombre
- Un token del proveedor sustituye el número de tarjeta dentro de tu sistema. Sirve para volver a cobrar sin volver a pedir la tarjeta, pero solo funciona con ese proveedor.
- Un token de red, el que hay detrás de Apple Pay o Google Pay, lo emite la propia red de tarjetas y viene acompañado de un criptograma que cambia en cada operación. Si alguien lo intercepta, no le sirve para nada.
En ambos casos la idea es la misma: el dato sensible deja de circular. Es la misma lógica que hace que un permiso de acceso deba vivir en tu servidor y no en el móvil, como se explica en pagos dentro de apps.
Por qué se firman los webhooks
Cuando un pago se completa, el navegador del cliente vuelve a tu web con una URL de retorno. Esa URL no es una fuente fiable: la controla el cliente, y cualquiera puede visitarla. Si tu sistema marca el pedido como pagado porque el navegador ha vuelto a `/gracias`, tienes un problema de seguridad, no un detalle de implementación.
La fuente fiable es el webhook: una llamada de servidor a servidor desde tu proveedor de pagos, firmada. La firma habitual es un HMAC-SHA256 del cuerpo exacto del mensaje con un secreto compartido, enviado en una cabecera. Verificarlo bien tiene cuatro reglas:
- Firmar y verificar sobre el cuerpo en crudo, antes de parsear el JSON. Un reordenamiento de claves cambia la firma.
- Comparar en tiempo constante, no con una comparación de cadenas normal.
- Comprobar la antigüedad del mensaje si viene con marca de tiempo, para que una petición capturada no valga meses después.
- Ser idempotente: el mismo evento puede llegar varias veces. Procesarlo dos veces no debe conceder dos veces el acceso ni emitir dos facturas.
Y una regla más: si la firma no valida, la respuesta correcta es un error, no un «lo proceso igualmente por si acaso».
El importe lo decide el servidor
El último clásico: aceptar el importe que llega desde el cliente. Un formulario, un parámetro en la URL o un campo oculto son editables. El importe a cobrar debe salir siempre del catálogo en el servidor; lo que envía el cliente es, como mucho, la referencia del producto. Las tres fases del cobro —y dónde encaja cada validación— están descritas en cómo funciona un cobro con tarjeta.
Registros: menos es más
Los sistemas de pago generan muchos registros, y ahí acaban filtrándose datos por descuido: cabeceras de firma completas, cuerpos de webhook sin recortar, correos y direcciones en texto plano. Registra identificadores y estados, no contenidos, y define cuánto tiempo se conservan. Un registro que nadie consulta y nadie borra es solo superficie de ataque.
En resumen
La seguridad de un cobro se juega en decisiones aburridas: no guardar lo que no necesitas, no creerte al navegador, verificar firmas como se debe y ser idempotente. Nada de eso es visible para el cliente, y todo se nota el día que algo va mal. Puedes ver el resto de artículos sobre seguridad y normativa o cómo se representan los estados de un pago en la demo.
¿Estás montando suscripciones?
Mira las tarifas y prueba el panel con datos de ejemplo antes de integrar nada.