54 lines
1.7 KiB
PHP
54 lines
1.7 KiB
PHP
<?php
|
||
declare(strict_types=1);
|
||
|
||
namespace PaypalV2;
|
||
|
||
/**
|
||
* Verifiziert PayPal-Webhook-Signaturen serverseitig gegen die PayPal-API.
|
||
* Nur so ist ein eingehendes Event vertrauenswuerdig.
|
||
*/
|
||
final class Webhook
|
||
{
|
||
/**
|
||
* @param array<string,string> $headers Request-Header (Schluessel lowercase)
|
||
* @param string $rawBody Roher Request-Body (unveraendert!)
|
||
*/
|
||
public function verify(array $headers, string $rawBody): bool
|
||
{
|
||
$webhookId = Config::webhookId();
|
||
if ($webhookId === '') {
|
||
\error_log('PayPal v2 Webhook: keine webhook_id konfiguriert – Event abgelehnt.');
|
||
return false;
|
||
}
|
||
|
||
$event = \json_decode($rawBody, true);
|
||
if (!\is_array($event)) {
|
||
return false;
|
||
}
|
||
|
||
$payload = [
|
||
'transmission_id' => $headers['paypal-transmission-id'] ?? '',
|
||
'transmission_time' => $headers['paypal-transmission-time'] ?? '',
|
||
'cert_url' => $headers['paypal-cert-url'] ?? '',
|
||
'auth_algo' => $headers['paypal-auth-algo'] ?? '',
|
||
'transmission_sig' => $headers['paypal-transmission-sig'] ?? '',
|
||
'webhook_id' => $webhookId,
|
||
'webhook_event' => $event,
|
||
];
|
||
|
||
foreach (['transmission_id', 'transmission_time', 'cert_url', 'auth_algo', 'transmission_sig'] as $k) {
|
||
if ($payload[$k] === '') {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
[$status, $body] = (new PayPalClient())->request(
|
||
'POST',
|
||
'/v1/notifications/verify-webhook-signature',
|
||
$payload
|
||
);
|
||
|
||
return $status === 200 && (($body['verification_status'] ?? '') === 'SUCCESS');
|
||
}
|
||
}
|