sync: Zahlungsstrecke, PG-Events, Fatal-Log und PayPal-v2-Blaupause vom Live-Stand 2026-09-13
Deploy to Dev / deploy (push) Successful in 1s
Deploy to Dev / deploy (push) Successful in 1s
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
<?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');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user