<?php
declare(strict_types=1);
namespace App\Listener\Logger;
use App\Payment\PaymentFactory;
use App\Payment\Provider\HyperPay\HyperPayClient;
use App\Service\Payment\PaymentProviderService;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\TerminateEvent;
class PaymentWebhookRequestAndResponseLogEventListener
{
const ROUTES = [
'/webhook/payment/status'
];
const HTTP_ERROR_CODES_REGEX = '/(^5\\d{2}$)|(^4\\d{2}$)/';
/**
* @var LoggerInterface
*/
private $logger;
/**
* @var PaymentFactory
*/
private $paymentFactory;
/**
* @var PaymentProviderService
*/
private $paymentProviderService;
public function __construct(
LoggerInterface $logger,
PaymentFactory $paymentFactory,
PaymentProviderService $paymentProviderService
)
{
$this->logger = $logger;
$this->paymentFactory = $paymentFactory;
$this->paymentProviderService = $paymentProviderService;
}
public function onKernelTerminate(TerminateEvent $event)
{
$request = $event->getRequest();
$response = $event->getResponse();
if ($this->checkIfRouteMatchesConfig($request->getRequestUri())) {
if (preg_match(self::HTTP_ERROR_CODES_REGEX, (string)$response->getStatusCode())) {
$this->logger->error('data', [
'route' => $request->getMethod() . ' ' . $request->getRequestUri(),
'status' => $response->getStatusCode(),
'request_body' => $request->request->all(),
'request_body_decoded' => $this->decodeRequestBody($request),
'response' => json_decode($response->getContent(), true),
'headers' => $request->headers->all(),
'raw_request' => $request->getContent(),
'raw_response' => $response->getContent()
]);
} else {
$this->logger->info('data', [
'route' => $request->getMethod() . ' ' . $request->getRequestUri(),
'status' => $response->getStatusCode(),
'request_body' => $request->request->all(),
'request_body_decoded' => $this->decodeRequestBody($request),
'response' => json_decode($response->getContent(), true),
'headers' => $request->headers->all(),
'raw_request' => $request->getContent(),
'raw_response' => $response->getContent()
]);
}
}
}
private function checkIfRouteMatchesConfig(string $originRoute): bool
{
foreach (self::ROUTES as $route) {
if (strpos($originRoute, $route) !== false) {
return true;
}
}
return false;
}
private function decodeRequestBody(Request $request): string
{
$decodedRequestBody = '{}';
switch (true) {
case (strpos($request->getRequestUri(), 'hyperpay') !== false):
/**
* @var HyperPayClient $client
*/
$client = $this->paymentFactory->get(
$this->paymentProviderService->getPaymentProviderServiceIdentifier('hyperpay')
);
$decodedRequestBody = json_encode($client->encodeRequest($request));
break;
}
return $decodedRequestBody;
}
}