Guía definitiva para integrar pasarelas de pago con PHP (2025)

Gracias por darme amor compartiendo en tu app favorita:

En el mundo del desarrollo web moderno, las pasarelas de pago se han consolidado como un pilar esencial. Permiten a negocios, tiendas online y plataformas digitales gestionar cobros de forma segura y eficiente. Y aunque hoy lo damos por sentado, el proceso ha evolucionado significativamente.

Esta guía te llevará, paso a paso, desde los fundamentos históricos y conceptuales hasta la implementación técnica en PHP, brindándote el contexto y las herramientas necesarias para una integración profesional.


1. Comprendiendo el rol de una pasarela de pago

El uso de pasarelas de pago está ampliamente extendido y su uso va más allá del desarrollo web, estando presente en el mundo del desarrollo de videojuegos, software como servicio o SaS, desarrollo móvil y un largo etcétera.

Indistintamente del lenguaje de desarrollo, plataforma de desarrollo y la pasarela de pago elegida, siempre están presentes los mismos conceptos esenciales que definen todo lo que debes saber.

Empezando por entender lo qué es y lo que no es.


¿Qué es una pasarela de pago?

Imagina que ofreces un curso online y necesitas aceptar pagos con tarjeta de crédito o débito. La manipulación directa de datos financieros sensibles no solo es un riesgo de seguridad, sino que también está sujeta a estrictas regulaciones (como PCI DSS).

Aquí es donde entra en juego la pasarela de pago: un servicio intermediario que facilita transacciones financieras de forma segura.

Su función principal incluye:

  • Recopilación segura de datos: Se encarga de recoger la información de pago del cliente (número de tarjeta, fecha de caducidad, CVV) de manera cifrada.
  • Comunicación con entidades financieras: Actúa como un puente entre tu negocio, el banco emisor de la tarjeta y el banco adquirente (el banco de tu negocio).
  • Validación y autorización: Verifica la autenticidad de la tarjeta y la disponibilidad de fondos, solicitando la autorización de la transacción.
  • Confirmación de transacción: Una vez aprobada, envía la confirmación del pago a tu comercio.

En esencia, la pasarela de pago protege los datos sensibles del usuario y garantiza la seguridad y la legalidad de cada transacción.


Historia y evolución de los pagos online

En los albores del comercio electrónico, los pagos online se gestionaban predominantemente a través de pasarelas bancarias tradicionales. Estas, como Redsys en España o First Data en Estados Unidos, operaban con protocolos complejos y requerían acuerdos directos con entidades bancarias, lo que a menudo resultaba en procesos de integración lentos y costosos para los desarrolladores y las empresas, además del abono de comisiones o tasas que aumentaban los costes operacionales.

La verdadera revolución llegó con la aparición de empresas como PayPal (fundada en 1998, popularizada en los 2000) y, más tarde, Stripe (2010). Estas plataformas democratizaron el acceso a los pagos online al ofrecer:

  • APIs y SDKs modernos: Facilitaron enormemente la integración para los desarrolladores.
  • Experiencia de usuario simplificada: Hicieron el proceso de pago más intuitivo y rápido para los clientes finales.
  • Menos burocracia: Redujeron drásticamente la necesidad de acuerdos directos con múltiples bancos.
CaracterísticaPasarelas Bancarias TradicionalesPayPal / Stripe / Mercado Pago
ConfiguraciónCompleja, requiere acuerdos bancariosRápida, basada en registro y verificación
TecnologíaProtocolos propios, SOAP, a veces XMLAPIs REST, SDKs modernos, JSON
Alcance InternacionalLimitado, enfoque regionalGlobal, multilenguaje y multidivisa
Opciones de PagoPrincipalmente tarjetas de crédito/débitoTarjetas, wallets (PayPal, Apple Pay), transferencias, BNPL (Buy Now Pay Later)
Facilidad para DesarrolladoresMedia a BajaAlta, excelente documentación y soporte

2. Librerías (SDKs) vs. Integración manual: ¿Cuál elegir?

La forma en que te conectas con una pasarela de pago impacta directamente en la complejidad y el tiempo de desarrollo.

Habitualmente encontraremos dos caminos:

Librerías gratuitas disponibles en la entidad propietaria de la pasarela de pago que puedes descargar, integrar y usar en tu desarrollo, aunque esto suele llevar emparejado qué tipo de entorno usas (lenguaje o incluso base de datos, así como versión del lenguaje si es interpretado).

Y, a veces sí, a veces no, la posibilidad de integración manual utilizando API Restful y JSON. Si bien la opción anterior facilita mucho el trabajo, te restringe las posibilidades sobre lo que puedes y no puedes hacer. Pero, la integración manual, si bien te da todas las posibilidades de integración, requiere la programación de todo el proceso, lo que lo hace más sensible a actualizaciones de la pasarela.


¿Por qué usar librerías (SDKs)?

La mayoría de las pasarelas de pago modernas ofrecen SDKs (Software Development Kits) oficiales. Un SDK es un conjunto de herramientas de software que simplifica la interacción con la API de la pasarela.

Al utilizar un SDK, te beneficias de:

  • Simplificación del código: Reduce la cantidad de código que tienes que escribir.
  • Manejo de objetos: Facilita la creación y manipulación de objetos de la pasarela (pagos, clientes, sesiones, etc.).
  • Gestión de errores: Provee mecanismos estandarizados para detectar y manejar errores.
  • Validación de seguridad: Se encarga de aspectos críticos como la firma de solicitudes, la gestión de tokens y la verificación de la integridad de los datos.
  • Funciones adicionales: Incluye funcionalidades para webhooks, reembolsos, suscripciones, etc.

Ejemplo práctico con Stripe (PHP SDK):

Stripe, una de las pasarelas más populares, ofrece un SDK oficial para PHP que se instala fácilmente con Composer.

usuario@mi_equipo ~/mi_proyecto$ composer require stripe/stripe-php

Una vez instalado, el código para crear un intento de pago es conciso y claro:

<?php
require_once('vendor/autoload.php');
// Asegúrate de incluir el autoload de Composer

\Stripe\Stripe::setApiKey('sk_test_tu_clave_secreta_aqui');
// ¡Usar siempre en el backend!

try {
    $paymentIntent = \Stripe\PaymentIntent::create([
        'amount' => 2000, 
        // Monto en la unidad más pequeña de la moneda (ej. céntimos para EUR)
        'currency' => 'eur',
        'payment_method_types' => ['card'],
        // Métodos de pago aceptados
        'description' => 'Pago por curso online',
    ]);

    // Aquí puedes devolver client_secret al frontend para confirmar el pago
    echo json_encode(['clientSecret' => $paymentIntent->client_secret]);

} catch (\Stripe\Exception\ApiErrorException $e) {
    // Manejar errores de la API
    http_response_code(500);
    echo json_encode(['error' => $e->getMessage()]);
}
?>

¿Cuándo optar por la integración manual?

En ciertos escenarios, especialmente con pasarelas bancarias tradicionales o servicios muy específicos que carecen de SDKs robustos en PHP, la integración manual se vuelve necesaria.

Esto implica:

  • Comprensión profunda de la API: Debes entender a fondo la documentación de la API REST o SOAP de la pasarela.
  • Construcción manual de solicitudes: Formatear las peticiones (JSON, XML, o incluso x-www-form-urlencoded) y enviarlas.
  • Firma digital de mensajes: Un aspecto crítico de seguridad para muchas pasarelas tradicionales, donde debes firmar digitalmente las peticiones con claves proporcionadas.
  • Manejo detallado de respuestas: Parsear las respuestas, extraer los datos relevantes y gestionar cada código de error o éxito.

En el entorno del desarrollo web, SOAP (acrónimo de Simple Object Access Protocol) es un protocolo estándar que define cómo dos aplicaciones o sistemas pueden intercambiar información estructurada de manera fiable en un entorno distribuido y descentralizado. Es decir, es un conjunto de reglas para la comunicación entre diferentes piezas de software, a menudo en diferentes plataformas, sistemas operativos o lenguajes de programación.

Si bien la integración manual ofrece un mayor control sobre cada aspecto de la comunicación, también conlleva mayor complejidad, tiempo de desarrollo y un riesgo elevado de introducir errores si no se maneja con extremo cuidado.


3. API Keys: La clave de acceso a tu pasarela

Las API Keys son credenciales digitales esenciales que autentican tu aplicación ante la pasarela de pago, permitiéndole realizar operaciones en tu nombre.


Tipos de API Keys

Existen principalmente dos tipos de claves:

  • Clave Pública (Publishable Key / Frontend Key):
    • Se utiliza de forma segura en el frontend de tu aplicación (por ejemplo, en JavaScript) para tareas como generar tokens de tarjeta o inicializar flujos de pago.
    • No compromete la seguridad si es expuesta, ya que solo permite operaciones que no implican acceso a datos sensibles o movimientos de fondos directos.
  • Clave Secreta (Secret Key / Backend Key):
    • Debe ser guardada y utilizada exclusivamente en tu backend (servidor).
    • Permite realizar operaciones críticas como crear cargos, emitir reembolsos, acceder a datos de transacciones, gestionar suscripciones, etc.
    • Su exposición representa un riesgo de seguridad crítico, ya que un atacante podría realizar operaciones fraudulentas en tu cuenta.

Entorno sandbox o de pruebas

Para el desarrollo y las pruebas, todas las pasarelas de pago ofrecen un entorno sandbox (también conocido como entorno de pruebas o staging). Este entorno es una réplica funcional de la pasarela de producción, pero con datos simulados.

Características del entorno sandbox:

  • API Keys de prueba: Se te asignan claves públicas y secretas específicas para este entorno.
  • Simulación de pagos: Puedes simular pagos exitosos, fallidos, rechazos, devoluciones, etc., utilizando tarjetas de prueba proporcionadas por la pasarela.
  • No se mueven fondos reales: Todas las transacciones son ficticias, lo que te permite testear el flujo completo sin riesgos financieros.
  • Aislamiento total: Está completamente aislado del entorno de producción, garantizando que tus pruebas no afecten a transacciones reales.

Es crucial distinguir y configurar correctamente las claves de prueba y producción en tu aplicación, asegurándote de usar las correctas en cada entorno.


4. Fase de desarrollo: Rigurosas pruebas en el entorno sandbox

La fase de desarrollo, centrada en el entorno sandbox, es crítica para asegurar una integración robusta y libre de errores.


La importancia de las pruebas

Antes de siquiera pensar en pasar a producción, debes:

  • Validar el flujo de pago completo: Desde el inicio (creación del intento de pago) hasta la confirmación final y la actualización de estado en tu sistema.
  • Testear escenarios diversos: No solo pagos exitosos. Prueba pagos rechazados (por fondos insuficientes, tarjeta caducada, etc.), pagos fraudulentos simulados, reembolsos, y cualquier otro escenario que tu pasarela soporte.
  • Verificar la recepción y procesamiento de webhooks: Confirma que tu endpoint de webhook recibe los eventos correctamente y que tu lógica de negocio los procesa e actualiza el estado de los pedidos o usuarios de manera fiable.
  • Confirmar la seguridad: Asegúrate de que las claves secretas nunca se expongan en el frontend y de que todas las comunicaciones sensibles estén cifradas (HTTPS).

Cómo realizar pruebas efectivas

  • Usa tarjetas de prueba: Las pasarelas proporcionan números de tarjeta específicos (ej. 4242… para Visa) con diferentes comportamientos (éxito, fallo, 3D Secure, etc.). Úsalas para simular todos los escenarios.
  • Automatiza pruebas: Implementa pruebas unitarias para las funciones de comunicación con la pasarela y pruebas funcionales/de integración para el flujo de pago completo. Herramientas como PHPUnit son ideales para esto.
  • Registra logs detallados: Configura un sistema de logging robusto en tu backend. Registra todas las solicitudes a la pasarela, las respuestas, los eventos de webhook y cualquier error. Esto es invaluable para la depuración (debugging).
  • Simula fallos de conexión: Aunque más avanzado, considera cómo se comporta tu sistema si la comunicación con la pasarela falla temporalmente. Implementa mecanismos de reintento o manejo de fallos elegantes.

5. Acceso a producción y validación técnica

Una vez que tu integración funciona impecablemente en el entorno sandbox, llega el momento de prepararse para el entorno real.


¿Por qué no se pasa directamente a producción?

La transición de sandbox a producción no es simplemente un cambio de API Keys. Implica un proceso de validación por parte de la pasarela porque:

  • Dinero real en juego: Las transacciones moverán fondos reales, lo que exige una fiabilidad y seguridad máximas.
  • Cumplimiento normativo (PCI DSS): La pasarela debe asegurar que tu sistema cumple con los estándares de seguridad de datos de la industria de tarjetas de pago (PCI DSS), incluso si no manejas datos de tarjeta directamente.
  • Gestión correcta de webhooks: Es fundamental que tu sistema procese los webhooks de manera fiable para evitar discrepancias en los estados de los pedidos.
  • Manejo robusto de errores: La pasarela verifica que tu aplicación gestiona adecuadamente los errores de transacción y los reintentos.
  • Información legal y fiscal: Deberás proporcionar documentación de tu negocio para cumplir con las regulaciones locales e internacionales.

Proceso habitual para el acceso a producción

  1. Solicitud de activación de producción: Dentro del panel de control de tu pasarela, inicia el proceso para activar el modo «Live» o «Producción».
  2. Envío de documentación: La pasarela te pedirá información de tu empresa (registro fiscal, datos bancarios, etc.) y, en algunos casos, detalles sobre cómo has implementado la seguridad y el flujo de pago.
  3. Revisión y testeo por la pasarela: En ocasiones, la pasarela puede requerir una demostración del flujo de pago en tu sitio o revisar tus logs de pruebas para asegurarse de que todo está configurado correctamente.
  4. Aprobación y entrega de API Keys reales: Una vez que cumples con todos los requisitos, la pasarela aprueba tu cuenta y te proporciona las API Keys reales para el entorno de producción.
  5. Lanzamiento controlado: Es recomendable realizar un lanzamiento gradual o «controlado», monitoreando de cerca las primeras transacciones reales para detectar cualquier problema inesperado.

6. Gestión operativa desde el panel de la pasarela

Más allá de la integración técnica, el panel de gestión de la pasarela es tu centro de control operativo.


¿Qué es el panel de gestión?

Es una interfaz web (normalmente un dashboard) proporcionada por la pasarela de pago que te permite:

  • Visualizar transacciones: Ver un registro detallado de todos los pagos, reembolsos y disputas.
  • Emitir reembolsos: Procesar devoluciones de forma manual.
  • Descargar reportes: Obtener informes financieros, fiscales y de conciliación.
  • Revisar logs y eventos: Examinar los registros de la API y los eventos de webhook para depuración o auditoría.
  • Gestionar configuración: Actualizar URLs de webhooks, configurar notificaciones, ajustar reglas de fraude, etc.

Por qué es importante

Aunque tu sistema tenga procesos automatizados (por ejemplo, para reembolsos), el panel es indispensable para:

  • Resolución de incidencias: Investigar pagos fallidos, disputas o transacciones inusuales.
  • Conciliación financiera: Cuadrar los ingresos con los reportes bancarios.
  • Monitorización en tiempo real: Obtener una visión general del rendimiento de tus pagos.
  • Operaciones manuales: Realizar reembolsos específicos o acciones que no estén automatizadas en tu sistema.

7. Cambios y mantenimiento: Actualizando sin romper

El software evoluciona, y tu integración de pagos no será la excepción. Realizar cambios o actualizaciones de forma segura es vital.


Buenas prácticas para el mantenimiento

Como cualquier otro aspecto en programación, es conveniente tener protocolizado el cómo de harán las actualizaciones una vez ya se está en producción y la pasarela activa.

  • Modo mantenimiento: Para cambios críticos en tu flujo de pago, considera activar un modo de mantenimiento en tu sitio web. Esto evita que los usuarios intenten realizar pagos durante un estado inconsistente de tu sistema.
  • Pruebas exhaustivas en sandbox: Siempre prueba cualquier cambio (actualización de SDKs, modificaciones en la lógica de pago, nuevas funcionalidades) primero en tu entorno sandbox o staging.
  • Verificar webhooks: Las actualizaciones de código pueden, inadvertidamente, romper la recepción o el procesamiento de webhooks (por ejemplo, cambios en URLs, formatos de datos esperados o problemas con la verificación de firmas). Siempre revalida el funcionamiento de tus webhooks después de cualquier despliegue.
  • Documentar cambios: Mantén un registro claro de todas las modificaciones realizadas en la integración de la pasarela de pago. Esto facilita futuras actualizaciones y la resolución de problemas.
  • Monitoreo Post-Despliegue: Después de cualquier actualización en producción, monitorea de cerca las transacciones y los logs para detectar anomalías tempranamente.

8. Flujo Completo de un Pago Paso a Paso (PHP)

Entender el ciclo de vida de un pago es fundamental. Aquí detallamos un flujo típico:


Explicación detallada

  1. El Usuario inicia el pago (frontend):
    • El cliente hace clic en «Pagar» en tu sitio web.
    • Tu frontend (usando JavaScript y la clave pública de la pasarela) recopila los datos de pago del usuario (ej. número de tarjeta) de forma segura a través de un campo de entrada proporcionado por la pasarela (o un formulario hosteado).
    • Estos datos nunca tocan tu servidor directamente. La pasarela genera un token de pago o un ID de sesión de pago y lo devuelve a tu frontend.
  2. Preparar el pedido y solicitar cargo (Backend – PHP):
    • Tu frontend envía el token de pago (o ID de sesión) al backend de tu aplicación (tu script PHP).
    • En tu script PHP (usando la clave secreta de la pasarela), creas un «intento de pago» o «cargo» para este pedido. Envías a la pasarela:
      • El token de pago recibido del frontend.
      • El monto total y la moneda del pedido.
      • Una descripción o concepto del pago.
      • Un ID de referencia único para tu pedido (para poder conciliarlo más tarde).
      • URLs de retorno (éxito y fracaso): dónde redirigir al usuario después de la interacción con la pasarela.
  3. Redirección a la pasarela (si aplica):
    • Para flujos como 3D Secure, o pasarelas que usan páginas hosteadas, la pasarela puede requerir que redirijas al usuario a una página externa para completar la autenticación o introducir detalles adicionales.
  4. Confirmación y redirección del usuario:
    • Una vez que el usuario completa el proceso en la pasarela (o si la autenticación se hace en segundo plano), la pasarela lo redirige de vuelta a una de las URLs de retorno que le proporcionaste (URL de éxito o URL de fracaso).
    • ¡Importante! La información de la URL de retorno no es la fuente definitiva de verdad sobre el pago. Es solo una indicación para el usuario.
  5. Recepción y procesamiento del webhook (backend):
    • Este es el paso más crítico. Casi inmediatamente después de que el pago se autoriza (o falla), la pasarela de pago realiza una llamada HTTP (webhook) a un endpoint específico en tu backend (una URL que configuraste previamente en el panel de la pasarela).
    • Este webhook contiene la información oficial y definitiva sobre el resultado del pago (éxito, fallo, reembolso, etc.).
    • Tu script PHP que recibe el webhook debe:
      • Verificar la firma del webhook para asegurar que proviene de la pasarela y no ha sido alterado (¡esencial!).
      • Procesar el evento: Actualizar el estado del pedido en tu base de datos (por ejemplo, de «pendiente» a «pagado» o «fallido»), enviar correos de confirmación al cliente, iniciar el procesamiento del pedido, etc.

9. Qué es un webhook y por qué es vital

Los webhooks son el mecanismo fundamental para garantizar la fiabilidad y la coherencia en la integración de pasarelas de pago.


¿Qué es un webhook?

Un webhook es una llamada HTTP automatizada que una aplicación (en este caso, la pasarela de pago) realiza a otra aplicación (tu servidor) cuando ocurre un evento específico. En el contexto de los pagos, esto significa que cuando una transacción cambia de estado (se completa con éxito, falla, se reembolsa, se disputa, etc.), la pasarela «llama» a una URL específica en tu backend y envía un paquete de datos con la información del evento.


¿Por qué no fiarse solo de la redirección del usuario?

La redirección del usuario después de un pago (al regresar a tu URL de éxito o fracaso) no es una fuente de verdad fiable por varias razones:

  • Problemas de conexión: El usuario podría cerrar el navegador, perder la conexión a internet, o la página podría no cargar completamente después de la redirección.
  • Manipulación de URL: Un usuario malintencionado podría intentar manipular los parámetros de la URL para simular un pago exitoso.
  • Inconsistencia: La redirección es un evento del frontend, mientras que el webhook es una notificación directa y fiable del servidor de la pasarela al tuyo.

El webhook es la fuente oficial de la verdad sobre el estado de una transacción. Tu sistema siempre debe confiar en la información recibida a través del webhook para actualizar el estado de los pedidos y la lógica de negocio.


10. Resumen de buenas prácticas para una integración exitosa

Para concluir, aquí tienes una lista de las mejores prácticas que te garantizarán una integración segura, eficiente y robusta:

  • Prioriza el uso de SDKs oficiales: Siempre que estén disponibles y sean adecuados para PHP, utiliza los SDKs proporcionados por la pasarela. Ahorrarás tiempo, reducirás errores y te beneficiarás de funcionalidades ya probadas.
  • Separa estrictamente claves de test y producción: Nunca mezcles las API Keys. Implementa una lógica en tu código para cargar las claves correctas según el entorno (desarrollo, staging, producción).
  • NUNCA expongas claves privadas en el frontend: Las claves secretas deben residir exclusivamente en tu servidor backend y ser accesibles solo por tu código PHP.
  • Valida siempre los webhooks con firmas: Implementa la verificación de la firma del webhook para asegurarte de que la notificación proviene legítimamente de la pasarela y no ha sido alterada por un tercero malicioso.
  • Realiza pruebas exhaustivas en sandbox: Dedica tiempo suficiente a probar todos los escenarios posibles (éxito, fallo, reembolso, diferentes métodos de pago) en el entorno de pruebas antes de ir a producción.
  • Implementa un logging detallado: Registra todas las interacciones con la pasarela (solicitudes, respuestas, webhooks) para facilitar la depuración y auditoría.
  • Controla el flujo en producción con el panel de la pasarela: Utiliza el dashboard de la pasarela para monitorear transacciones, resolver incidencias y realizar conciliaciones financieras.
  • Diseña un manejo robusto de errores y reintentos: Tu aplicación debe saber cómo reaccionar ante fallos temporales de comunicación o errores en las transacciones, y si es necesario, implementar lógicas de reintento.
  • Mantente actualizado: Las APIs de las pasarelas evolucionan. Mantén tus SDKs y tu código actualizados para aprovechar las mejoras y nuevas funcionalidades.

Anexo 1: Errores comunes y soluciones habituales

Integrar pasarelas de pago, aunque parezca sencillo con los SDKs modernos, a menudo presenta desafíos. Aquí te detallo algunos de los errores más comunes que los desarrolladores cometen y sus soluciones habituales.


1. Claves de API incorrectas o expuestas

  • Error común: Usar las claves de sandbox en producción o viceversa. Exponer la clave secreta en el código JavaScript del frontend.
  • Problema que causa: Transacciones que no se procesan, errores de autenticación, o un riesgo de seguridad crítico si la clave secreta se hace pública.
  • Solución habitual:
    • Verifica el entorno: Asegúrate de que las claves (sk_live_... para producción y sk_test_... para sandbox en Stripe, por ejemplo) coinciden con el entorno en el que estás ejecutando el código.
    • Carga segura de claves: Nunca incrustes claves directamente en tu código frontend. Carga la clave secreta desde variables de entorno (.env), un servicio de secretos (como AWS Secrets Manager o Azure Key Vault), o un archivo de configuración fuera del repositorio público y accesible solo por tu backend PHP.
    • Acceso frontend: La clave pública es la única que debe usarse en el frontend para inicializar componentes de pago o generar tokens.

2. No validar firmas de webhooks

  • Error común: Confiar en que una llamada a tu endpoint de webhook es legítima sin verificar su procedencia.
  • Problema que causa: Vulnerabilidad a ataques de falsificación (spoofing) donde un atacante podría enviar datos falsos para manipular el estado de tus pedidos (por ejemplo, marcar un pedido como «pagado» sin que lo esté).
  • Solución habitual:
    • Implementa la verificación de firma: Todas las pasarelas (Stripe, PayPal, etc.) envían una firma digital en las cabeceras del webhook. Tu script PHP debe verificar esta firma usando la clave de secreto de webhook proporcionada por la pasarela (distinta de tus API Keys). Si la firma no coincide, rechaza la solicitud.
  • Código de ejemplo (con Stripe):
<?php

require_once('vendor/autoload.php');

$endpoint_secret = 'whsec_tu_secreto_webhook_aqui';// Obtenido del panel de Stripe
$payload = @file_get_contents('php://input');$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];$event = null;

try {
   $event = \Stripe\Webhook::constructEvent( $payload, $sig_header, $endpoint_secret );
} 
catch(\UnexpectedValueException $e) {
   // Carga útil no válida
   http_response_code(400);
   exit();
} 
catch(\Stripe\Exception\SignatureVerificationException $e) {
   // Firma no válida
   http_response_code(400);
   exit();
}

// Procesa el evento...
http_response_code(200);

?>

3. Depender exclusivamente de la redirección del usuario

  • Error común: Actualizar el estado del pedido en tu base de datos basándote únicamente en la redirección del usuario a la URL de «éxito» o «fracaso».
  • Problema que causa: Inconsistencias en el estado de los pedidos si el usuario cierra la pestaña, pierde la conexión, o manipula la URL. Esto puede llevar a pedidos pagados que no se registran o pedidos no pagados que se marcan como tal.
  • Solución habitual:
    • Confía siempre en los webhooks: Considera el webhook como la única fuente de verdad sobre el estado de una transacción. La redirección es para la experiencia del usuario, el webhook es para la lógica de negocio.
    • Lógica de reconciliación: Si un usuario llega a tu página de éxito, puedes mostrar un mensaje provisional y luego usar el webhook para confirmar el estado final. Si el webhook no llega en un tiempo razonable, puedes tener una lógica para verificar el estado de la transacción directamente con la API de la pasarela.

4. Bloquear el proceso de webhook con lógica compleja

  • Error común: Realizar operaciones que consumen mucho tiempo (envío de correos electrónicos, actualizaciones complejas de bases de datos, llamadas a APIs externas) directamente dentro del endpoint del webhook.
  • Problema que causa: La pasarela de pago puede reenviar el webhook varias veces si no recibe una respuesta HTTP 200 OK rápidamente. Esto puede causar que tu lógica de negocio se ejecute varias veces para un solo evento, llevando a duplicidades (por ejemplo, múltiples confirmaciones de pedido o reembolsos).
  • Solución habitual:
    • Responde inmediatamente: Tu endpoint de webhook debe hacer lo mínimo indispensable: verificar la firma, parsear el evento y responder con HTTP 200 OK lo antes posible.
    • Procesamiento asíncrono: Pon la lógica pesada (actualizaciones de BD, envío de emails, notificaciones) en una cola de tareas asíncronas (como RabbitMQ, Redis con Laravel Queues, o un sistema similar) que se procese en segundo plano. Esto asegura que el webhook se confirme rápidamente y evita reintentos.

5. No manejar idempotencia

  • Error común: Reintentar crear un cargo o procesar un webhook sin considerar si la operación ya se ha completado.
  • Problema que causa: Cobros duplicados o estados de pedido inconsistentes, especialmente en entornos donde las solicitudes pueden reintentarse o los webhooks pueden llegar duplicados.
  • Solución habitual:
    • Usar claves de Idempotencia: Las pasarelas de pago permiten enviar una clave de idempotencia (un UUID único) con las solicitudes de creación de cargos. Si la misma solicitud se envía varias veces con la misma clave, la pasarela garantiza que solo se procese una vez.
    • Almacenar ID de evento de webhook: Al procesar webhooks, almacena el ID del evento de webhook en tu base de datos. Antes de procesar un webhook, verifica si ese ID ya ha sido procesado. Si es así, ignóralo.

6. Olvidar HTTPS

  • Error común: Configurar tu endpoint de webhook o tus formularios de pago para usar HTTP en lugar de HTTPS.
  • Problema que causa: Riesgos de seguridad importantes, ya que los datos podrían interceptarse en tránsito. Además, la mayoría de las pasarelas modernas requieren HTTPS para los webhooks y cualquier interacción directa con el cliente.
  • Solución habitual:
    • Siempre HTTPS: Asegúrate de que tu sitio web completo, y especialmente tus endpoints de webhook, están configurados con HTTPS y que tienes un certificado SSL/TLS válido.

7. Manejo inadecuado de errores de la API

  • Error común: No capturar y manejar excepciones o códigos de error específicos devueltos por la API de la pasarela.
  • Problema que causa: Fallos en la aplicación, mensajes de error genéricos para el usuario, o incapacidad de diagnosticar problemas.
  • Solución habitual:
    • Implementa bloques try-catch: Siempre envuelve las llamadas a la API de la pasarela en bloques try-catch para capturar excepciones específicas (Stripe\Exception\ApiErrorException para Stripe, por ejemplo).
    • Manejo específico de errores: Analiza los códigos de error devueltos por la pasarela (ej. «card_declined», «invalid_cvc») y presenta mensajes amigables al usuario final o implementa lógicas de reintento cuando sea apropiado.
    • Logging de errores: Registra los errores detalladamente en tus logs para depuración.

8. No validar datos de entrada del usuario

  • Error común: Confiar en que los datos recibidos del frontend o las respuestas básicas de la pasarela son suficientes.
  • Problema que causa: Vulnerabilidades de seguridad (inyección SQL, XSS) o problemas de lógica de negocio si los datos no son los esperados.
  • Solución habitual:
    • Validación en backend: Siempre valida y sanea todos los datos recibidos del frontend en tu backend PHP, incluso si ya fueron validados en el frontend. Asegúrate

Anexo 2: Integración frontend con Angular y dependencia del backend

Integrar una pasarela de pago en una aplicación Angular implica una clara división de responsabilidades entre el frontend y tu backend PHP. Angular se encargará de la interacción con el usuario y la comunicación segura con la pasarela, mientras que PHP gestionará las operaciones sensibles y cruciales.


1. El rol de Angular (frontend)

En una aplicación Angular, tu objetivo principal es recopilar de forma segura los datos de pago del usuario y obtener un token o un ID de sesión de la pasarela.

Nunca debes manejar directamente información sensible como números de tarjeta en tu código Angular, ya que esto te haría sujeto a las normativas PCI DSS, lo cual es complejo y costoso de cumplir.

Pasos clave en angular:

  • Instalación del SDK de frontend: La mayoría de las pasarelas de pago ofrecen librerías JavaScript específicas para el frontend. Por ejemplo, Stripe.js para Stripe, o el SDK de PayPal.Bashnpm install @stripe/stripe-js
  • Inicialización con clave pública: En tu componente Angular, inicializarás la pasarela usando tu clave pública (que no compromete la seguridad).
import { loadStripe } from '@stripe/stripe-js';

// ... y en tu componente

const stripe = await loadStripe('pk_test_tu_clave_publica');
  • Creación de Elementos de Pago: Utilizarás los «elementos» o «campos» seguros proporcionados por la pasarela. Estos son iframes que inyectan de forma segura los campos de entrada (tarjeta, fecha, CVC) directamente desde la pasarela, lo que significa que los datos de la tarjeta nunca pasan por tu servidor Angular.
<div id="card-element"> </div>

// ... y en tu componente TypeScript

const elements = stripe.elements();
const card = elements.create('card');
card.mount('#card-element');
  • Generación de tokens / Confirmación de pago: Cuando el usuario envía el formulario, Angular interactúa con la pasarela (a través de su SDK de JS) para:
  • Generar un token: Recopila los datos del card-element y los envía a la pasarela, que devuelve un token de un solo uso que representa la información de la tarjeta.
  • Confirmar un PaymentIntent: Para pasarelas como Stripe, puedes confirmar un PaymentIntent directamente desde el frontend (usando el client_secret proporcionado por tu backend), gestionando así procesos como 3D Secure.

2. La dependencia crucial del backend (PHP)

Tu backend PHP es el cerebro de la operación de pago. Es el único lugar donde se deben manejar las API Keys secretas y donde se realizan las operaciones sensibles que implican dinero real.

Flujo de dependencia Angular <=> PHP:

Solicitud de inicio de pago (Angular => PHP):

Angular (o tu frontend) no inicia el proceso de pago directamente con la pasarela. En su lugar, hace una llamada HTTP (típicamente POST) a una API personalizada en tu backend PHP.

Esta API PHP recibirá información sobre el pedido (ID del producto, cantidad, ID de usuario) desde Angular, pero no datos sensibles de la tarjeta.

Ejemplo de API PHP para iniciar PaymentIntent (Stripe):

// api/create-payment-intent.php
require_once('vendor/autoload.php');

\Stripe\Stripe::setApiKey('sk_test_tu_clave_secreta');
// Siempre en backend

$data = json_decode(file_get_contents('php://input'), true);
$amount = $data['amount'];

// Validar y sanear siempre
$currency = $data['currency'];

try {
   $paymentIntent = \Stripe\PaymentIntent::create([
      'amount' => $amount,
      'currency' => $currency,
      'payment_method_types' => ['card'],
   ]);
   echo json_encode(['clientSecret' => $paymentIntent->client_secret]);
} catch (\Stripe\Exception\ApiErrorException $e) {
   http_response_code(500); 
   echo json_encode([
      'error' => $e->getMessage()
   ]);
}
  • Creación de cargo/Intento de pago (PHP => Pasarela):
    • Tu API PHP utiliza su clave secreta y el SDK de la pasarela para crear un «cargo», «intento de pago» o «sesión de checkout«.
    • En este punto, PHP le dice a la pasarela cuánto cobrar, qué moneda, y opcionalmente, dónde redirigir al usuario después de la interacción con la pasarela.
    • La pasarela devuelve una respuesta (ej. un client_secret de Stripe o una URL de redirección).
  • Respuesta al frontend (PHP => Angular):
    • Tu API PHP envía esta respuesta (ej. el client_secret de Stripe) de vuelta a Angular.
  • Confirmación del pago (Angular => Pasarela):
    • Angular utiliza el client_secret o la URL de redirección para completar la interacción del usuario con la pasarela. Esto puede implicar:
      • Confirmar el PaymentIntent directamente con Stripe.js.
      • Redirigir al usuario a una página de pago hosteada por la pasarela.
  • Notificación de Webhook (Pasarela => PHP):
    • Una vez que el pago se completa (o falla) en la pasarela, esta envía un webhook a tu backend PHP.
    • Tu backend PHP es el único que debe actualizar el estado del pedido en tu base de datos basándose en esta notificación oficial del webhook. Angular no debe hacer esto.

Ventajas de esta Separación:

  • Seguridad Mejorada: Los datos sensibles de la tarjeta nunca pasan por tus servidores (ni Angular ni PHP), minimizando tu exposición a PCI DSS.
  • Fiabilidad: Las operaciones críticas (creación de cargos, reembolsos) se realizan en el backend, que es más estable y controlado.
  • Escalabilidad: Separar responsabilidades permite escalar tu frontend y backend de forma independiente.
  • Mantenimiento: Facilita la depuración y el mantenimiento al tener claras las responsabilidades de cada parte.

Anexo 3: Errores en servidores y el comportamiento de los webhooks

Los webhooks son fundamentales para la fiabilidad de las integraciones de pago. Sin embargo, ¿qué sucede cuando tu servidor PHP que debe recibirlos experimenta un error y no completa una llamada de webhook?

El problema: Tu servidor no responde o responde incorrectamente

Una llamada de webhook fallida puede ocurrir por varias razones:

  • Error interno del servidor (500 Internal Server Error): Tu script PHP de webhook tiene un error de código, una excepción no manejada, o un problema de conexión a la base de datos.
  • Tiempo de espera excedido (Timeout): El script de webhook tarda demasiado en procesar la solicitud (quizás porque está haciendo operaciones complejas) y la pasarela corta la conexión.
  • Respuestas HTTP incorrectas: Tu script no devuelve un código de estado HTTP 200 OK, lo que indica a la pasarela que no se recibió el webhook correctamente.
  • Problemas de red: Fallos en la conexión entre la pasarela y tu servidor.

La solución de la pasarela: Reintentos y colas

Las pasarelas de pago están diseñadas para ser resilientes ante estos fallos. No asumen que si no reciben una HTTP 200 OK la primera vez, el evento no se procesó.

En su lugar, implementan mecanismos de reintento (retries):

  1. Reintentos programados: Si tu servidor no responde con un HTTP 200 OK (o responde con un error 4xx/5xx), la pasarela de pago asumirá que el webhook no fue entregado o procesado correctamente.
  2. Intervalos de reintento: La pasarela esperará un tiempo antes de volver a intentar enviar el mismo webhook. Los intervalos suelen ser exponenciales (ej. 1 minuto, 5 minutos, 30 minutos, 1 hora, etc.) para evitar sobrecargar tu servidor.
  3. Límite de reintentos: Hay un número máximo de reintentos (ej. 3 a 20 intentos en 24-72 horas). Si después de todos los reintentos tu servidor sigue sin responder correctamente, la pasarela dejará de intentar enviar ese webhook particular.

¿Qué implica esto para ti?

  • Idempotencia es crucial: Dado que un webhook puede ser enviado varias veces, tu script PHP debe ser idempotente. Esto significa que procesar el mismo webhook dos o más veces no debe causar efectos secundarios no deseados (como duplicar un pedido, aplicar un reembolso dos veces, etc.). Usa el ID del evento del webhook para verificar si ya ha sido procesado antes de ejecutar tu lógica de negocio.
  • Monitoreo de webhooks: La mayoría de las pasarelas ofrecen un panel de gestión de webhooks donde puedes ver el historial de entrega, los códigos de estado de las respuestas de tu servidor y si hubo reintentos. Monitoriza este panel para identificar problemas recurrentes.
  • Logs detallados: Tus propios logs de servidor PHP deben registrar cada webhook recibido y el resultado de su procesamiento. Esto te ayuda a diagnosticar por qué un webhook pudo haber fallado.
  • Respuestas rápidas: Como se mencionó en el Anexo 2, tu script de webhook debe responder con HTTP 200 OK tan pronto como haya verificado la firma y haya puesto la lógica de negocio en una cola asíncrona. Esto asegura que la pasarela reciba la confirmación rápidamente y evita reintentos innecesarios.

En el ámbito de las pasarelas de pago, la idempotencia es una propiedad crucial que garantiza que una operación, como un intento de cobro, produzca el mismo resultado sin importar cuántas veces se envíe con los mismos parámetros.

Esto es vital porque en entornos de red inestables o ante fallos temporales, un comercio podría reenviar la misma solicitud de pago sin saber si la anterior se procesó, lo que sin idempotencia llevaría a cargos o pedidos duplicados.

Para evitarlo, las pasarelas modernas usan una clave de idempotencia (un ID único enviado por el comercio con la solicitud); la primera vez que se recibe esta clave, se procesa la transacción y se almacena el resultado, y si la misma clave llega de nuevo, la pasarela simplemente devuelve la respuesta original sin reejecutar el cobro, asegurando así la fiabilidad de las transacciones y una mejor experiencia para el usuario.


Ejemplo de escenario de error y recuperación:

  1. Pago exitoso: Un usuario completa un pago. La pasarela autoriza la transacción.
  2. Primer Intento de webhook: La pasarela envía el webhook payment_intent.succeeded a tu URL https://tudominio.com/webhook.php.
  3. Fallo en tu servidor: Tu script webhook.php tiene un error de base de datos y responde con HTTP 500.
  4. Reintento de la pasarela: La pasarela detecta el HTTP 500 y, después de un minuto, reintenta enviar el mismo webhook.
  5. Corrección de error: Mientras tanto, tú has notado el error en tus logs, lo has corregido y desplegado la solución.
  6. Segundo intento exitoso: El segundo intento de webhook llega, tu script PHP lo procesa correctamente, actualiza el estado del pedido y responde con HTTP 200 OK.
  7. Procesamiento único: Gracias a la idempotencia (verificando el ID del webhook o el ID del PaymentIntent), tu sistema solo procesa el pago una vez, a pesar de haber recibido dos intentos de webhook.

¡Absolutamente! Es una pregunta crucial que aborda un escenario de fallo importante. Vamos a añadir esa sección al Anexo 4: Errores en Servidores y el Comportamiento de los Webhooks.


Anexo 4: Errores en Servidores y el Comportamiento de los Webhooks

Los webhooks son fundamentales para la fiabilidad de las integraciones de pago. Sin embargo, ¿qué sucede cuando tu servidor PHP que debe recibirlos experimenta un error y no completa una llamada de webhook?

El Problema: Tu Servidor No Responde o Responde Incorrectamente

Una llamada de webhook fallida puede ocurrir por varias razones:

  • Error Interno del Servidor (500 Internal Server Error): Tu script PHP de webhook tiene un error de código, una excepción no manejada, o un problema de conexión a la base de datos.
  • Tiempo de Espera Excedido (Timeout): El script de webhook tarda demasiado en procesar la solicitud (quizás porque está haciendo operaciones complejas) y la pasarela corta la conexión.
  • Respuestas HTTP Incorrectas: Tu script no devuelve un código de estado HTTP 200 OK, lo que indica a la pasarela que no se recibió el webhook correctamente.
  • Problemas de Red: Fallos en la conexión entre la pasarela y tu servidor.

La Solución de la Pasarela: Reintentos y Colas

Las pasarelas de pago están diseñadas para ser resilientes ante estos fallos. No asumen que si no reciben una HTTP 200 OK la primera vez, el evento no se procesó. En su lugar, implementan mecanismos de reintento (retries):

  1. Reintentos Programados: Si tu servidor no responde con un HTTP 200 OK (o responde con un error 4xx/5xx), la pasarela de pago asumirá que el webhook no fue entregado o procesado correctamente.
  2. Intervalos de Reintento: La pasarela esperará un tiempo antes de volver a intentar enviar el mismo webhook. Los intervalos suelen ser exponenciales (ej. 1 minuto, 5 minutos, 30 minutos, 1 hora, etc.) para evitar sobrecargar tu servidor.
  3. Límite de Reintentos: Hay un número máximo de reintentos (ej. 3 a 20 intentos en 24-72 horas). Si después de todos los reintentos tu servidor sigue sin responder correctamente, la pasarela dejará de intentar enviar ese webhook particular.

¿Qué Implica Esto para Ti?

  • Idempotencia es Crucial: Dado que un webhook puede ser enviado varias veces, tu script PHP debe ser idempotente. Esto significa que procesar el mismo webhook dos o más veces no debe causar efectos secundarios no deseados (como duplicar un pedido, aplicar un reembolso dos veces, etc.). Usa el ID del evento del webhook para verificar si ya ha sido procesado antes de ejecutar tu lógica de negocio.
  • Monitoreo de Webhooks: La mayoría de las pasarelas ofrecen un panel de gestión de webhooks donde puedes ver el historial de entrega, los códigos de estado de las respuestas de tu servidor y si hubo reintentos. Monitoriza este panel para identificar problemas recurrentes.
  • Logs Detallados: Tus propios logs de servidor PHP deben registrar cada webhook recibido y el resultado de su procesamiento. Esto te ayuda a diagnosticar por qué un webhook pudo haber fallado.
  • Respuestas Rápidas: Como se mencionó en el Anexo 2, tu script de webhook debe responder con HTTP 200 OK tan pronto como haya verificado la firma y haya puesto la lógica de negocio en una cola asíncrona. Esto asegura que la pasarela reciba la confirmación rápidamente y evita reintentos innecesarios.

Cuando el webhook falló definitivamente: intervención manual necesaria

A pesar de los reintentos automáticos de la pasarela, puede haber escenarios en los que tu servidor estuvo inactivo o con errores durante todo el período de reintentos.

Si la pasarela agota sus intentos de envío de un webhook sin recibir una respuesta HTTP 200 OK, dejará de intentar notificar a tu sistema sobre ese evento particular.

En estos casos, la intervención manual es, de hecho, el camino habitual. Tu panel de control de la pasarela de pago se convierte en tu herramienta principal para la reconciliación y la resolución de incidencias.

Cómo Actuar en Estos Casos:

  1. Identificación del Problema:
    • Monitorización activa: Revisa regularmente el panel de webhooks de tu pasarela. Muchas pasarelas tienen secciones dedicadas a «Eventos Fallidos» o «Historial de Webhooks» donde se listan los eventos que no pudieron ser entregados.
    • Alertas: Configura alertas (por correo electrónico, Slack, etc.) en tu pasarela para ser notificado si un webhook falla persistentemente o agota sus reintentos.
    • Discrepancias en tu sistema: Si un cliente se queja de que su pedido no se ha actualizado después de un pago que él considera exitoso, o si encuentras un pago registrado en la pasarela que no tiene un estado de pedido correspondiente en tu base de datos.
  2. Investigación en el panel de la pasarela:
    • Accede al panel de gestión de la pasarela.
    • Localiza la transacción específica que te interesa (por ID de transacción, ID de pago, etc.).
    • Verifica su estado oficial en la pasarela (por ejemplo, «pagado», «reembolsado», «fallido»).
    • Revisa el historial de webhooks asociado a esa transacción para ver los intentos de envío y las respuestas obtenidas de tu servidor. Esto te dará pistas sobre por qué falló la entrega.
  3. Acción manual (conciliación):
    • Una vez que confirmes el estado real de la transacción en la pasarela, deberás actualizar manualmente el estado de tu pedido o registro correspondiente en tu propia base de datos.
    • Por ejemplo, si un pago aparece como «succeeded» en Stripe, pero tu pedido sigue en «pendiente» porque el webhook nunca llegó, deberás cambiar el estado de tu pedido a «pagado» y activar manualmente cualquier proceso de negocio asociado (envío de confirmación, preparación del producto, etc.).
    • Regenerar un webhook: Algunas pasarelas permiten reenviar manualmente un webhook desde su panel. Si es posible, inténtalo. Esto ejecutaría tu lógica de procesamiento y te permitiría depurar el error en tu servidor. Si funciona, la automatización se encargará, si no, la actualización manual de la base de datos es el último recurso.

Consideraciones Finales:

  • Minimiza la necesidad de intervención manual: El objetivo siempre es diseñar un sistema lo suficientemente robusto como para que las intervenciones manuales sean raras. Esto se logra con:
    • Lógica de webhooks idempotente.
    • Procesamiento asíncrono para evitar timeouts.
    • Monitorización proactiva.
    • Manejo de errores sólido en tu código PHP.
  • Auditoría y registros: Mantener logs detallados en ambos lados (tu servidor y el panel de la pasarela) es fundamental para auditar y resolver rápidamente estos escenarios poco frecuentes pero críticos.

Comprender el comportamiento de los webhooks ante fallos es crucial para diseñar un sistema de pago fiable que pueda recuperarse de problemas temporales en el servidor sin perder datos ni generar inconsistencias.