Proyecto de demostración en PHP 8.2 con arquitectura hexatonial, sin frameworks, utilizando puertos y adaptadores. Envía notificaciones de pagos firmadas con JWT a través de HTTP.
- Crea un objeto
Paymentcon datos de prueba. - Firma el contenido con JWT usando una clave secreta.
- Envia el
Paymentcomo JSON vía HTTP POST. - El receptor valida la firma y guarda el resultado en un log.
- Todo orquestado a través de clases desacopladas por capas.
payment-notifier/
├── src/
│ ├── Domain/
│ │ ├── Entity/ # Entidades puras (Payment)
│ │ └── Port/ # Interfaces (puertos)
│ ├── Application/ # Casos de uso
│ └── Infrastructure/
│ ├── Http/ # Adaptadores de salida HTTP
│ └── Jwt/ # Firma y validación JWT
├── public/
│ └── receive.php # Receptor de notificaciones
├── run.php # Cliente CLI para enviar una notificación
├── config.php # Configuración de endpoint y secreto
├── notificacion.log # Log generado por receive.php
└── composer.json
- Docker instalado
(No necesitas instalar PHP ni Composer en tu sistema)
docker run --rm -v $(pwd):/app -w /app composer installEsto inicia el servidor en http://localhost:8009:
docker run --rm -v $(pwd):/app -w /app -p 8009:8000 php:8.2-cli php -S 0.0.0.0:8000 -t public
Dejá esta terminal abierta para que el receptor escuche.
Desde otra terminal, ejecutá:
docker run --rm -v $(pwd):/app -w /app php:8.2-cli php run.php✅ Notificación enviada correctamente.
✅ Recibido:
{
"amount": 120.75,
...
}
- Abre
http://localhost:8009/receive.phpen el navegador para ver el log acumulado.
La cabecera Signature contiene el JWT firmado.
El receptor valida que el cuerpo del POST coincida exactamente con lo firmado.
docker run --rm -v $(pwd):/app -w /app php:8.2-cli ./vendor/bin/phpunit🔍 Esto es lo que ocurre:
run.php se ejecuta
Se hace require config.php para obtener la secret y el endpoint.
Se crea un objeto Payment (entidad del dominio) con los datos de prueba.
Se firma el contenido
Se instancia FirebaseJwtSigner, que usa firebase/php-jwt para firmar el array del Payment.
Se construye un GuzzlePaymentNotifier, que es un adaptador que implementa la interfaz del puerto para enviar la notificación vía HTTP.
Se ejecuta el caso de uso SendPaymentNotification
Este recibe el Payment y lo pasa al Notifier.
GuzzlePaymentNotifier firma el JSON del Payment y envía la petición HTTP POST al endpoint configurado con:
Cuerpo JSON
Cabecera Signature con el JWT firmado
📥 En el receptor (public/receive.php):
Se recibe el POST /receive.php y se recoge el cuerpo (php://input) y los headers.
Se valida:
Primera verificación: El JWT es válido (FirebaseJwtValidator)
Segunda verificación: Se recalcula el JWT desde los datos del cuerpo y se compara con la cabecera Signature.
Si todo es correcto:
Se guarda un log bonito con ✅ y los datos del pago
Se imprime en el navegador en GET /receive.php