Files
fotospiel-app/app/Services/PayPal/PayPalWebhookVerifier.php
2026-02-04 14:23:07 +01:00

63 lines
2.0 KiB
PHP

<?php
namespace App\Services\PayPal;
use App\Services\PayPal\Exceptions\PayPalException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class PayPalWebhookVerifier
{
public function __construct(private readonly PayPalClient $client) {}
/**
* @param array<string, mixed> $payload
*/
public function verify(Request $request, array $payload): bool
{
$webhookId = config('services.paypal.webhook_id');
if (! is_string($webhookId) || $webhookId === '') {
if (app()->environment('production')) {
Log::warning('PayPal webhook verification skipped: webhook id missing.');
}
return true;
}
$signature = (string) $request->headers->get('PAYPAL-TRANSMISSION-SIG', '');
if ($signature === '') {
Log::warning('PayPal webhook missing signature header.', [
'header' => 'PAYPAL-TRANSMISSION-SIG',
]);
return false;
}
$payload = array_filter([
'auth_algo' => $request->headers->get('PAYPAL-AUTH-ALGO'),
'cert_url' => $request->headers->get('PAYPAL-CERT-URL'),
'transmission_id' => $request->headers->get('PAYPAL-TRANSMISSION-ID'),
'transmission_sig' => $signature,
'transmission_time' => $request->headers->get('PAYPAL-TRANSMISSION-TIME'),
'webhook_id' => $webhookId,
'webhook_event' => $payload,
], static fn ($value) => $value !== null && $value !== '');
try {
$response = $this->client->post('/v1/notifications/verify-webhook-signature', $payload);
} catch (PayPalException $exception) {
Log::warning('PayPal webhook verification failed', [
'message' => $exception->getMessage(),
'status' => $exception->status(),
'context' => $exception->context(),
]);
return false;
}
return strtoupper((string) ($response['verification_status'] ?? '')) === 'SUCCESS';
}
}