* * Server-zu-Server, keine Session. Der Provider prueft die Signatur selbst und * entscheidet, was mit dem Ereignis passiert. Antwort 2xx = angenommen, sonst * stellt der Anbieter erneut zu. */ declare(strict_types=1); require __DIR__ . '/core/payments/bootstrap.php'; $module = isset($_GET['p']) ? (string) $_GET['p'] : ''; $provider = \Payments\Registry::get($module, $base_object); if (!$provider) { \http_response_code(404); echo 'unknown provider'; exit; } $rawBody = (string) \file_get_contents('php://input'); $headers = []; foreach ($_SERVER as $key => $value) { if (\strncmp($key, 'HTTP_', 5) === 0) { $headers[\strtolower(\str_replace('_', '-', \substr($key, 5)))] = (string) $value; } } // Letzte Zustellung roh ablegen -- nur wenn logs/webhook_debug existiert (Fehlersuche an // der Signaturpruefung, 13.09.2026). logs/ ist per .htaccess gesperrt. if (\is_file(__DIR__ . '/logs/webhook_debug')) { @\file_put_contents(__DIR__ . '/logs/webhook_last_' . \preg_replace('/[^a-z0-9_]/', '', $module) . '.json', \json_encode(['time' => \date('c'), 'headers' => $headers, 'body' => $rawBody], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); } try { $status = $provider->onWebhook($headers, $rawBody); } catch (\Throwable $e) { \error_log('payment_webhook ' . $module . ': ' . $e->getMessage()); $status = 500; } \http_response_code($status); echo $status < 300 ? 'ok' : 'rejected';