<?php
declare(strict_types=1);
namespace App\Subscriber;
use App\Event\HttpClient\Events;
use App\Event\HttpClient\HttpClientRequestEvent;
use App\Event\HttpClient\HttpClientResponseEvent;
use App\Payment\Provider\Basys\BasysClient;
use App\Service\Graph\ContainerTraversablePathAccess;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class HttpClientSubscriber implements EventSubscriberInterface
{
const HTTP_ERROR_CODES_REGEX = '/(^5\\d{2}$)|(^4\\d{2}$)/';
private LoggerInterface $logger;
public function __construct(LoggerInterface $restLogger)
{
$this->logger = $restLogger;
}
public static function getSubscribedEvents(): array
{
return [
Events::HTTP_CALL_OUTGOING => 'onRequest',
Events::HTTP_CALL_INCOMING => 'onResponse',
];
}
public function onRequest(HttpClientRequestEvent $requestEvent)
{
$request = $requestEvent->getRequest();
$data = $this->getMaskedBody($requestEvent);
$this->logger->info(\sprintf('[HTTP: REQUEST] [%s] %s %s with query parameters %s and body %s and headers %s',
$requestEvent->getRequestIdentifier(),
$requestEvent->getMethod(),
$request->getUrl(),
\http_build_query($request->getParameters() ?? []),
\is_array($data) ? \json_encode($data) : $data,
\json_encode($request->getHeaders())
));
}
private function getMaskedBody(HttpClientRequestEvent $requestEvent)
{
if ($requestEvent->getContext() == BasysClient::PROVIDER_NAME) {
$data = $requestEvent->getRequest()->getBody();
if (empty($data)) {
return $data;
}
$containerTraversablePathAccess = new ContainerTraversablePathAccess(
is_array($data) ? $data : json_decode($data, true)
, false);
if (
$containerTraversablePathAccess->getByPath('payment_method.card.cvc', false) !== false
|| $containerTraversablePathAccess->getByPath('payment_method.card.expiration_date', false) !== false
|| $containerTraversablePathAccess->getByPath('payment_method.card.number', false) !== false
) {
$data = is_array($data) ? $data : json_decode($data, true);
$data['payment_method']['card']['number'] = '***HIDE*FOR*LOGS***';
$data['payment_method']['card']['cvc'] = '***HIDE*FOR*LOGS***';
$data['payment_method']['card']['expiration_date'] = '***HIDE*FOR*LOGS***';
}
return $data;
}
return $requestEvent->getRequest()->getBody();
}
public function onResponse(HttpClientResponseEvent $responseEvent)
{
$response = $responseEvent->getResponse();
if (preg_match(self::HTTP_ERROR_CODES_REGEX, (string)$response->getStatusCode())) {
$this->logger->error(\sprintf('[HTTP: RESPONSE] [%s] Response with status code \'%s\' and body \'%s\'',
$responseEvent->getRequestIdentifier(),
$response->getStatusCode(),
$response->getRawBody()
));
} else {
$this->logger->info(\sprintf('[HTTP: RESPONSE] [%s] Response with status code \'%s\' and body \'%s\'',
$responseEvent->getRequestIdentifier(),
$response->getStatusCode(),
$response->getRawBody()
));
}
}
}