Was ist ein Webhook?
Ein Webhook ist eine Methode zur Übertragung von Daten zwischen zwei Systemen in Echtzeit. Im Gegensatz zu traditionellen Abrufmethoden (z. B. APIs, bei denen das empfangende System aktiv Daten anfordert), sendet ein Webhook automatisch eine Nachricht, sobald ein definiertes Ereignis eintritt. Diese „Push“-Technologie ermöglicht es, sofortige Aktionen auszulösen, wodurch Zeit, Serverlast und Ressourcen gespart werden.
Webhooks werden häufig in der Systemintegration eingesetzt, z. B. um automatisierte Prozesse zwischen verschiedenen Plattformen, Anwendungen oder Diensten zu ermöglichen. Typische Anwendungsfälle sind Benachrichtigungen über neue Bestellungen, Änderungen von Tickets oder Statusaktualisierungen in Projektmanagement-Tools.
Technische Funktionsweise eines Webhooks
- Trigger-Ereignis: Ein Ereignis tritt auf (z. B. eine neue Bestellung in einem Shop oder eine Statusänderung in einer Anwendung).
- Webhook-Aufruf (Request): Das System, das das Ereignis auslöst (z. B. ein Onlineshop), sendet eine HTTP-POST-Anfrage an eine zuvor definierte URL.
- Empfänger (Listener/Endpoint): Das Zielsystem (z. B. eine externe Anwendung) empfängt die Nachricht an einer URL (oft auch „Endpoint“ genannt) und verarbeitet die übermittelten Daten.
- Rückmeldung (optional): Das Zielsystem gibt eine Antwort (z. B. einen Statuscode
200 OK), um zu signalisieren, dass die Nachricht erfolgreich empfangen wurde.
Technische Komponenten eines Webhooks
- Trigger: Das Ereignis, das den Webhook auslöst (z. B. „Neuer Kunde erstellt“, „Bestellung abgeschlossen“, „Ticket geschlossen“).
- URL/Endpoint: Die URL, an die die Daten gesendet werden. Dies ist der Listener, der auf die eingehenden Daten wartet.
- HTTP-Request: Der POST-Request enthält die Nutzdaten (Payload) in einem JSON– oder XML-Format.
- Header: Die Anfrage enthält Header-Informationen, die oft eine Signatur (z. B. HMAC) enthalten, um die Authentizität zu überprüfen.
- Response: Der Empfänger des Webhooks gibt eine Antwort (meist Status 200) zurück, um den Absender zu informieren, dass die Nachricht erfolgreich verarbeitet wurde.
Beispiel-Payload eines Webhook-Requests json Code kopieren
{
"event": "order.completed",
"order_id": "123456",
"customer": {
"name": "Max Mustermann",
"email": "max@example.com"
},
"items": [
{
"product_id": "ABC123",
"quantity": 2,
"price": 29.99
}
],
"total_price": 59.98
}
Erläuterung der Felder:
- event: Art des Ereignisses (z. B. Bestellung abgeschlossen).
- order_id: Eindeutige ID der Bestellung.
- customer: Details zum Kunden (Name, E-Mail usw.).
- items: Liste der gekauften Artikel (mit ID, Anzahl und Preis).
- total_price: Gesamtsumme der Bestellung.
Zwei Praxis-Cases für Webhooks
Case 1: Webhook in einem E-Commerce-Shop
Use Case:
Automatische Aktualisierung des CRM-Systems bei einer neuen Bestellung.
Beschreibung:
Ein E-Commerce-Shop verkauft Produkte. Sobald ein Kunde eine Bestellung abschließt, soll diese Bestellung automatisch in das CRM-System des Unternehmens übertragen werden, damit der Kundendienst auf die Bestellung zugreifen kann.
- Trigger: Abschluss einer Bestellung im Onlineshop.
- Webhook-Aufruf: Der Shop sendet die Bestelldaten an den Webhook-Endpoint des CRM-Systems.
- Payload: Der Payload enthält Informationen zur Bestellung (z. B. Artikel, Kunde, Preis).
- Empfänger (Listener): Das CRM-System empfängt die Daten, validiert die Signatur und erstellt eine neue Kundenakte oder aktualisiert die bestehende.
- Antwort: Das CRM sendet
200 OK, um zu bestätigen, dass die Daten erfolgreich empfangen wurden.
Vorteile:
- Echtzeit-Synchronisation der Kundendaten ohne manuelles Importieren.
- Vermeidung von Datenverlust durch garantierte Rückmeldungen (
200 OK). - Spart Ressourcen, da keine periodischen API-Abfragen (Polling) benötigt werden.
Technische Herausforderungen:
- Sicherheit: Überprüfung der Signatur im HTTP-Header, um sicherzustellen, dass die Nachricht wirklich vom Shop stammt.
- Fehlerbehandlung: Wenn das CRM nicht antwortet, muss der Webhook-Dienst eine Warteschlange (Queue) verwenden, um die Nachricht später erneut zuzustellen (Retry-Mechanismus).
Case 2: Webhook für Zahlungsdienstleister
Use Case:
Benachrichtigung über den Zahlungsstatus durch einen Zahlungsdienstleister (z. B. PayPal oder Stripe).
Beschreibung:
Ein Onlineshop bietet Zahlungen über einen Zahlungsdienstleister wie Stripe an. Sobald eine Zahlung bestätigt wird, soll der Shop darüber informiert werden, damit die Bestellung zur Bearbeitung freigegeben werden kann.
- Trigger: Kunde schließt die Zahlung erfolgreich ab (Zahlungsstatus: „erfolgreich“).
- Webhook-Aufruf: Stripe sendet eine Nachricht an den Webhook-Endpoint des Shops.
- Payload: Der Payload enthält Details zur Zahlung, einschließlich Transaktions-ID, Zahlungsbetrag und Zahlungsstatus.
- Empfänger (Listener): Der Webserver des Shops empfängt die Daten, validiert die HMAC-Signatur und aktualisiert den Status der Bestellung.
- Antwort: Der Shop antwortet mit
200 OK, um den Empfang zu bestätigen.
Vorteile:
- Echtzeit-Benachrichtigung: Der Zahlungsstatus wird sofort im Shop aktualisiert, wodurch die Bearbeitung der Bestellung automatisiert wird.
- Fehlerminimierung: Vermeidung von manueller Kontrolle von Zahlungseingängen.
- Flexibilität: Verschiedene Zahlungsdienstleister (Stripe, PayPal, Klarna) verwenden Webhooks.
Technische Herausforderungen:
- Sicherheit: Verifizierung der Webhook-Signatur, um sicherzustellen, dass die Nachricht von Stripe stammt.
- Zuverlässigkeit: Verwendung von Warteschlangen, um sicherzustellen, dass keine Zahlungen verloren gehen (Retry-Logik, wenn das Shopsystem nicht erreichbar ist).
- Idempotenz: Das Shopsystem muss sicherstellen, dass die gleiche Transaktion nicht mehrmals verarbeitet wird (z. B. durch Speichern der Transaktions-ID).
Vorteile von Webhooks
- Echtzeit-Benachrichtigung: Keine Verzögerung, im Gegensatz zu Polling.
- Effizienz: Geringere Serverlast, da die Verbindung nur bei Bedarf hergestellt wird.
- Flexibilität: Kann mit vielen Plattformen integriert werden (CRM, Zahlungsanbieter, ERP).
- Einfachheit: Leicht zu implementieren, da es sich oft nur um einen HTTP-Endpoint handelt.
Sicherheitsmaßnahmen bei Webhooks
- Verifizierung der Signatur: Viele Plattformen (z. B. Stripe) senden einen HMAC-Signatur-Hash, der verifiziert werden muss, um sicherzustellen, dass die Nachricht echt ist.
- HTTPS verwenden: Webhooks sollten nur über HTTPS gesendet werden, um die Daten zu verschlüsseln.
- Ratenbegrenzung: Begrenzen der Anzahl der Anfragen, um DDoS-Angriffe zu vermeiden.
- IP-Whitelisting: Nur bestimmte IPs dürfen den Webhook-Endpoint ansprechen.
- Idempotenz: Duplikate verhindern, z. B. durch Speichern der „Webhook-IDs“, die von der Plattform gesendet werden.
Webhook Listener (PHP)
<?php
// Konfiguration - Ersetze die Werte durch deine Daten
define('SECRET_KEY', 'dein_geheimer_schlüssel'); // HMAC Secret-Key, den der Absender (z. B. Stripe) verwendet
define('LOG_FILE', '/var/log/webhook.log'); // Pfad zur Log-Datei (für Fehlerprotokolle)
// 1. Empfange die Roh-Daten des Requests
$requestBody = file_get_contents('php://input');
// 2. Überprüfe die Signatur (optional, aber dringend empfohlen)
$signatureHeader = $_SERVER['HTTP_X_SIGNATURE'] ?? ''; // Beispiel-Header (von Stripe oder einem anderen Dienst)
if (!verifySignature($requestBody, $signatureHeader, SECRET_KEY)) {
http_response_code(400); // Ungültige Anfrage
logMessage('Ungültige Signatur: ' . $signatureHeader);
exit('Ungültige Signatur');
}
// 3. Wandelt die empfangenen JSON-Daten in ein PHP-Array um
$data = json_decode($requestBody, true);
if (json_last_error() !== JSON_ERROR_NONE) {
http_response_code(400); // Fehlerhafte Anfrage
logMessage('JSON-Parsing-Fehler: ' . json_last_error_msg());
exit('Ungültige JSON-Daten');
}
// 4. Verarbeite die empfangenen Daten
if (!empty($data)) {
// Beispiel: Unterschiedliche Events verarbeiten
if ($data['event'] === 'order.completed') {
handleOrderCompleted($data);
} elseif ($data['event'] === 'payment.succeeded') {
handlePaymentSucceeded($data);
} else {
logMessage('Unbekanntes Event: ' . $data['event']);
}
}
// 5. Sende eine Bestätigung zurück, dass alles erfolgreich war
http_response_code(200);
echo json_encode(['status' => 'success']);
// --- FUNKTIONEN ---
/**
* Verifiziert die Signatur des Webhook-Requests.
*
* @param string $payload Der Payload des Requests.
* @param string $signature Die Signatur aus dem Header (z. B. 'X-Signature').
* @param string $secretKey Der geheime Schlüssel, der für die HMAC-Generierung verwendet wurde.
* @return bool True, wenn die Signatur gültig ist, false andernfalls.
*/
function verifySignature($payload, $signature, $secretKey)
{
$computedSignature = hash_hmac('sha256', $payload, $secretKey);
return hash_equals($computedSignature, $signature);
}
/**
* Verarbeitet das 'order.completed'-Event.
*
* @param array $data Die empfangenen Daten (Bestelldaten).
*/
function handleOrderCompleted($data)
{
logMessage('Bestellung abgeschlossen: ' . json_encode($data));
// Beispiel: Bestellung in die Datenbank einfügen
$orderId = $data['order_id'] ?? 'unbekannt';
$customerName = $data['customer']['name'] ?? 'unbekannt';
$totalPrice = $data['total_price'] ?? 0;
// Hier kannst du die Bestellung in die Datenbank speichern (Beispielcode, bitte anpassen)
$db = new PDO('mysql:host=localhost;dbname=deinedatenbank;charset=utf8', 'username', 'password');
$stmt = $db->prepare("INSERT INTO orders (order_id, customer_name, total_price, created_at) VALUES (?, ?, ?, NOW())");
$stmt->execute([$orderId, $customerName, $totalPrice]);
logMessage("Bestellung $orderId erfolgreich verarbeitet.");
}
/**
* Verarbeitet das 'payment.succeeded'-Event.
*
* @param array $data Die empfangenen Daten (Zahlungsdaten).
*/
function handlePaymentSucceeded($data)
{
logMessage('Zahlung erfolgreich: ' . json_encode($data));
$paymentId = $data['payment_id'] ?? 'unbekannt';
$orderId = $data['order_id'] ?? 'unbekannt';
$amount = $data['amount'] ?? 0;
// Beispiel: Zahlung als erfolgreich markieren
$db = new PDO('mysql:host=localhost;dbname=deinedatenbank;charset=utf8', 'username', 'password');
$stmt = $db->prepare("UPDATE orders SET payment_status = 'paid', payment_id = ? WHERE order_id = ?");
$stmt->execute([$paymentId, $orderId]);
logMessage("Zahlung für Bestellung $orderId erfolgreich registriert.");
}
/**
* Protokolliert Nachrichten in einer Log-Datei.
*
* @param string $message Die Nachricht, die geloggt werden soll.
*/
function logMessage($message)
{
$timestamp = date('[Y-m-d H:i:s]');
file_put_contents(LOG_FILE, $timestamp . ' ' . $message . PHP_EOL, FILE_APPEND);
}
Erläuterungen zum Code
- Sicherheit
- Signaturprüfung: Der Webhook überprüft, ob die Signatur im Header mit der HMAC-Signatur übereinstimmt, die mit dem geheimen Schlüssel generiert wurde.
- HTTPS verwenden: Der Listener sollte nur über HTTPS zugänglich sein, um die Übertragung zu verschlüsseln.
- IP-Whitelisting: Wenn möglich, die IP-Adresse des Absenders überprüfen und sicherstellen, dass sie in einer Whitelist enthalten ist.
- Rate Limiting: Schutz gegen Überlastungsangriffe durch Ratenbegrenzung.
- Sicherheit (HMAC)
- Die Signatur (z. B.
X-Signature) wird durch HMAC-SHA256 generiert. Dies stellt sicher, dass der Absender authentisch ist. - Mit
hash_equals()wird eine Timing-Attacke verhindert, indem die Vergleichszeit unabhängig von der Länge der Signatur ist.
- Die Signatur (z. B.
- Zuverlässigkeit
- Logs: Der Listener protokolliert jeden eingehenden Request und Fehler.
- Datenbank: Neue Bestellungen und erfolgreiche Zahlungen werden in einer MySQL-Datenbank gespeichert.
- Retry-Logik: Falls der Dienst, der den Webhook sendet (z. B. Stripe), keine
200 OK-Antwort erhält, wird der Request in der Regel automatisch erneut gesendet.
- Payload-Validierung
- Der Listener überprüft, ob die empfangenen Daten JSON-konform sind (
json_decode). - Wenn die JSON-Daten fehlerhaft sind, wird eine
400 Bad Request-Antwort zurückgegeben.
- Der Listener überprüft, ob die empfangenen Daten JSON-konform sind (
- Fehlerbehandlung
- Wenn ein Fehler auftritt (ungültige Signatur, fehlerhafter JSON-Payload), wird eine HTTP 400-Antwort gesendet.
- Logging: Fehler (z. B. fehlgeschlagene Signaturprüfung) werden in eine Log-Datei geschrieben (
/var/log/webhook.log).
Wie testet man den Listener?
Lokaler Server: Starte einen lokalen PHP-Server.
php -S localhost:8000
Test mit cURL:
curl -X POST http://localhost:8000/webhook.php \
-H 'X-Signature: 1234567890abcdef' \
-H 'Content-Type: application/json' \
-d '{
"event": "order.completed",
"order_id": "ORD123",
"customer": { "name": "Max Mustermann" },
"total_price": 49.99
}'
Simuliere eine ungültige Signatur: Ändere den Header X-Signature, um zu testen, ob der Listener korrekt auf eine falsche Signatur reagiert
Erweiterungen
- Queue: Lege fehlgeschlagene Webhooks in eine Queue (z. B. RabbitMQ oder Redis) und verarbeite sie später.
- E-Mail-Benachrichtigung: Sende eine E-Mail, wenn ein Fehler auftritt.
- REST-API: Kombiniere den Listener mit einer REST-API, um eine Bestellübersicht anzuzeigen.
Fazit
Webhooks sind eine essenzielle Methode, um Systeme in Echtzeit zu integrieren. Sie sind unverzichtbar in modernen Anwendungen, insbesondere im E-Commerce, bei Zahlungsdienstleistern oder CRM-Integrationen. Im Gegensatz zu klassischen API-Abfragen (Pull-Modell) ermöglichen sie den Echtzeit-Datenfluss ohne unnötigen Serveraufwand. Die wichtigsten technischen Aspekte sind die Sicherheit (HMAC-Signaturen, HTTPS) und die Zuverlässigkeit (Warteschlangen, Retry-Logik).
Mit den Praxis-Cases wird klar, wie einfach Webhooks Prozesse automatisieren können, von Zahlungsstatus-Updates bis zur CRM-Datenaktualisierung.
Wenn du zu einem der Cases tiefer eintauchen möchtest oder den Code für den Listener benötigst, lass es mich wissen.