HMAC implementation for signature validation
This commit is contained in:
@ -45,7 +45,8 @@ return [
|
|||||||
'/api/external' => [
|
'/api/external' => [
|
||||||
'/toku/success' => [
|
'/toku/success' => [
|
||||||
'validator' => Incoviba\Service\Venta\MediosPago\Toku::class,
|
'validator' => Incoviba\Service\Venta\MediosPago\Toku::class,
|
||||||
'token' => $container->get('TOKU_TOKEN')
|
'token' => $container->get('TOKU_TOKEN'),
|
||||||
|
'secret' => $container->get('TOKU_WEBHOOK_SECRET'),
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
]
|
]
|
||||||
|
17
app/src/Service/HMAC.php
Normal file
17
app/src/Service/HMAC.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Service;
|
||||||
|
|
||||||
|
use Incoviba\Common\Ideal;
|
||||||
|
|
||||||
|
class HMAC extends Ideal\Service
|
||||||
|
{
|
||||||
|
public static function validate(string $timestamp, string $requestSignature, string $requestId, string $secret): bool
|
||||||
|
{
|
||||||
|
$message = "{$timestamp}.{$requestId}";
|
||||||
|
$encodedSecret = mb_convert_encoding($secret, 'UTF-8');
|
||||||
|
$encodedMessage = mb_convert_encoding($message, 'UTF-8');
|
||||||
|
$hmacObject = hash_hmac('sha256', $encodedMessage, $encodedSecret);
|
||||||
|
$computedSignature = base64_encode($hmacObject);
|
||||||
|
return hash_equals($computedSignature, $requestSignature);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Incoviba\Service\Venta\MediosPago;
|
namespace Incoviba\Service\Venta\MediosPago;
|
||||||
|
|
||||||
|
use Incoviba\Service\HMAC;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Incoviba\Service\Venta\MediosPago\Toku\{Customer,Subscription,Invoice};
|
use Incoviba\Service\Venta\MediosPago\Toku\{Customer,Subscription,Invoice};
|
||||||
@ -11,6 +12,7 @@ use Incoviba\Exception\ServiceAction\Read;
|
|||||||
use Incoviba\Model;
|
use Incoviba\Model;
|
||||||
use Incoviba\Model\Persona;
|
use Incoviba\Model\Persona;
|
||||||
use Incoviba\Model\Venta\Propietario;
|
use Incoviba\Model\Venta\Propietario;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
class Toku extends Ideal\Service
|
class Toku extends Ideal\Service
|
||||||
{
|
{
|
||||||
@ -407,12 +409,23 @@ class Toku extends Ideal\Service
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$tracestate = explode(';', substr($request->getHeaderLine('Tracestate'), strlen('dd=')));
|
$tokuSignature = $request->getHeaderLine('Toku-Signature');
|
||||||
$ptid = substr(array_find($tracestate, fn($item) => str_starts_with($item, 't.tid:')), strlen('t.tid:'));
|
try {
|
||||||
$datadogTags = explode(',', $request->getHeaderLine('X-Datadog-Tags'));
|
list($timestamp, $signature) = array_map(function($elem) {
|
||||||
$tid = array_find($datadogTags, fn($item) => str_contains($item, 'p.tid='));
|
return explode('=', $elem)[1];
|
||||||
$tid = substr($tid, strpos($tid, 'p.tid=') + strlen('p.tid='));
|
}, explode(',', $tokuSignature));
|
||||||
|
$body = $request->getBody()->getContents();
|
||||||
return $tid === $ptid;
|
$json = json_decode($body, true);
|
||||||
|
if (!is_array($json)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!array_key_exists('id', $json)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$eventId = $json['id'];
|
||||||
|
return HMAC::validate($timestamp, $signature, $eventId, $tokenConfig['secret']);
|
||||||
|
} catch (Throwable $throwable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user