Was von Payora signierte Webhooks sind
Von Payora signierte Webhooks sind HTTP-Anfragen mit einer digitalen Signatur, damit Ihr PHP-Endpunkt prüfen kann, ob das Ereignis wirklich von Payora stammt und unterwegs nicht verändert wurde. Wenn Sie lernen, wie man von Payora signierte Webhooks in PHP überprüft, ist der Ablauf grundsätzlich einfach: Payora sendet ein Ereignis, Ihr Server liest die Rohdaten und Ihr Code verifiziert die Signatur, bevor er irgendetwas im Inhalt vertraut. Wer also lernen möchte, wie man Payora Webhook in PHP verifizieren sauber umsetzt, sollte immer mit dem unveränderten Payload beginnen.
Diese Prüfung ist wichtig, weil ein Webhook von jedem Client kommen kann, der Ihre URL kennt. Ein Angreifer kann den Endpunkt aus Protokollen kopieren und dann ein gefälschtes Zahlungsereignis mit einem sauberen JSON-Body per POST senden. Eine Signatur vereitelt diesen Trick, und genau deshalb sollten Sie Payora signierte Webhooks prüfen, bevor Sie irgendeine Geschäftslogik ausführen.
Das Ereignis selbst ist erst nach der Verifikation nützlich. Vorher ist es nur Text.
Stellen Sie sich das wie ein nummeriertes Ticket an einer Tür vor. Der Body ist die Nachricht, die Signatur ist der Stempel, und Ihr PHP-Code entscheidet, ob beide zusammenpassen. Wenn ja, verarbeiten Sie das Ereignis. Wenn nicht, lehnen Sie es sofort ab. Auf diese Weise lässt sich die PHP Webhook Signatur überprüfen, ohne die Integrität der Daten zu gefährden.
Wenn Sie bereits einen Zahlungsablauf auf Ihrer Website betreiben, begegnet Ihnen dieselbe Disziplin auch an anderen Stellen des Stacks. Wer einen Leitfaden zu einem Krypto-Zahlungsgateway für E-Commerce liest, sieht dasselbe Muster: weniger blind annehmen, mehr prüfen und erst dann die Bestellung aktualisieren.
Voraussetzungen für einen PHP-Webhook-Endpunkt
Sie brauchen dafür kein riesiges Framework. Ein PHP-8.x-Endpunkt reicht aus, und PHP 7.4 kann für manche Projekte ebenfalls funktionieren, aber der Code muss Zugriff auf den rohen Request-Body und auf die Header haben, die Payora sendet. Das bedeutet, Ihr Server-Setup muss normalen HTTP-Zugriff erlauben und darf keine benutzerdefinierte Schicht haben, die Header umschreibt oder entfernt.
Verwenden Sie HTTPS. Ohne TLS läuft der Webhook offen über das Netz, und eine Signatur allein behebt keine schwache Transport-Sicherheit. Ein Zertifikat, eine korrekte Virtual-Host-Konfiguration und eine erreichbare öffentliche URL sind die Grundvoraussetzung.
In der Praxis sind zwei PHP-Erweiterungen relevant: hash für HMAC-Arbeiten und, wenn Sie die JSON-Verarbeitung damit aufbauen, die nativen JSON-Funktionen, die PHP mitliefert. Für Tests von Ihrer Seite aus kann auch cURL hilfreich sein, der Webhook-Endpunkt selbst braucht es jedoch nicht.
Sie benötigen außerdem das Payora-Secret oder den Signaturschlüssel, der zur Webhook-Konfiguration in Ihrem Payora-Konto passt. Bewahren Sie diesen Wert außerhalb des Webroots auf. Legen Sie ihn nicht in Git ab. Ein Secret in einem öffentlichen Repository macht aus Verifikation schnell nur noch Theater.
Noch etwas: Ihr Endpunkt sollte nur POST-Anfragen akzeptieren. GET-Anfragen können mit 405 beantwortet werden, und diese kleine Einschränkung spart bei der Fehlersuche Zeit, weil sie den tatsächlich zu prüfenden Traffic eingrenzt.
Den rohen Webhook-Body und die Header erfassen
Signaturprüfungen hängen von den exakten Bytes ab, die Payora gesendet hat. Lesen Sie in PHP den rohen Request-Body mit file_get_contents('php://input'). Erstellen Sie den Payload nicht aus $_POST oder aus dekodiertem JSON neu, weil dabei Leerzeichen, Reihenfolge der Schlüssel oder Kodierung verändert werden können.
Dasselbe gilt für Header. Sie brauchen den Signatur-Header. Verwenden Sie getallheaders(), wo verfügbar, oder lesen Sie Server-Variablen wie $_SERVER['HTTP_X_...'], wenn Ihre Umgebung den Header-Helfer herausfiltert. Kleine Unterschiede beim Hosting sind hier wichtig.
Stellen Sie sich einen Webhook-Body mit 412 Bytes vor. Wenn Ihr Code ihn dekodiert und dann erneut kodiert, sehen Sie vielleicht immer noch dieselben Felder, aber die Bytes sind nicht mehr identisch. Diese eine Abweichung reicht aus, um die Verifikation zu brechen.
Die Grundregel lautet: zuerst erfassen, dann parsen. Speichern Sie zuerst die Rohzeichenfolge. Prüfen Sie dann die Header. Erst danach sollten Sie die Struktur des Payloads anfassen.
Wenn Sie Zahlungsabläufe vor dem Start testen, spart dieselbe Gewohnheit auch anderswo Zeit. Der Artikel zum Testen eines Krypto-Zahlungsgateways wendet dieselbe Logik auf Sandbox-Ereignisse an, bei denen die Treue des Payloads darüber entscheidet, ob Ihr Test wirklich aussagekräftig ist.
Die erwartete Signatur in PHP nachbilden
Das übliche Muster ist ein HMAC, berechnet aus dem rohen Payload und einem gemeinsamen Secret. Beginnen Sie mit dem Algorithmus, der in Payoras Webhook-Dokumentation genannt wird. Wenn dort SHA-256 steht, verwenden Sie SHA-256. Wenn ein Präfix, ein Versions-Tag oder ein Zeitstempelformat genannt wird, übernehmen Sie genau diese Struktur.
Eine typische Form sieht so aus: Sie bauen die signierte Nachricht aus Zeitstempel und Roh-Body zusammen und führen dann hash_hmac() mit dem gemeinsamen Secret und dem angegebenen Hash-Algorithmus aus. Das Ergebnis muss je nach Spezifikation eventuell hex- oder base64-kodiert werden. Raten Sie nicht beim Format. Lesen Sie es aus den Webhook-Einstellungen ab.
Hier ist ein minimales Beispiel im PHP-Stil, mit Platzhaltern dort, wo Payoras Format abweichen kann:
$rawBody = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_PAYORA_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_PAYORA_SIGNATURE'] ?? '';
$secret = getenv('PAYORA_WEBHOOK_SECRET');
$signedPayload = $timestamp . '.' . $rawBody;
$expected = hash_hmac('sha256', $signedPayload, $secret);Dieses Beispiel zeigt nur die Form, keine verbindliche Vorgabe. Wenn Payora nur den Payload signiert, lassen Sie den Zeitstempel aus der Zeichenfolge weg. Wenn Payora eine kanonische JSON-Form signiert, folgen Sie genau dieser Methode und nicht Ihrer bevorzugten. Ein einziges falsches Trennzeichen lässt jede Anfrage scheitern.
Für Händler, die sich auch um Abrechnungsregeln und Sonderfälle kümmern, ist der Beitrag über Grenzen bei Krypto-Zahlungsrechnungen eine nützliche Ergänzung, weil Webhook-Verarbeitung und Rechnungsrichtlinien im selben Bestelllebenszyklus oft zusammenkommen.
Die berechnete Signatur mit der Signatur von Payora vergleichen
Sobald Sie die erwartete Signatur haben, vergleichen Sie sie mit der eingehenden Signatur mit einer zeitkonstanten Prüfung. In PHP ist das meist hash_equals(). Ein einfacher Vergleich mit == oder === ist hier nicht das richtige Werkzeug, weil er zeitliche Hinweise preisgeben kann und bei subtilen Abweichungen weniger defensiv ist.
Normalisieren Sie vor dem Vergleich das Format genau so, wie Payora es erwartet. Wenn der Header hexadezimal ist, vergleichen Sie Hex. Wenn der Header base64 ist, vergleichen Sie base64. Wenn die eingehende Signatur ein Präfix wie sha256= hat, entfernen oder behalten Sie es genau so, wie es die Dokumentation vorgibt.
Beispielablauf:
- Den rohen Body lesen.
- Den Signatur-Header lesen.
- Die erwartete Signatur nach der dokumentierten Formel erzeugen.
- Beide Zeichenfolgen mit
hash_equals()vergleichen. - Die Anfrage mit 401 oder 400 ablehnen, wenn sie nicht übereinstimmen.
Ein 401 ist sinnvoll, wenn die Signatur falsch ist. Ein 400 passt, wenn erforderliche Header fehlen. In jedem Fall sollte die Antwort kurz sein. Keine zusätzlichen Hinweise.
Ein Satz reicht hier: Geben Sie das Secret nicht aus. Dieser Fehler ist selten und katastrophal.
Zeitstempel, Replay-Schutz und Toleranzregeln behandeln
Wenn Payora einen Zeitstempel oder Nonce enthält, prüfen Sie ihn, bevor Sie das Ereignis akzeptieren. Das blockiert Replay-Angriffe, bei denen ein Angreifer einen gültigen Webhook später erneut sendet und Ihre Anwendung dazu bringen will, zweimal zu zahlen oder zweimal zu versenden. Das Zeitfenster sollte sich nach Payoras Regel richten, nicht nach Ihrer Vermutung.
Das übliche Muster ist, den Webhook-Zeitstempel mit Ihrer Serverzeit zu vergleichen und zu alte Anfragen außerhalb des Toleranzfensters abzulehnen. Wenn die Doku 5 Minuten sagt, nehmen Sie 5 Minuten. Wenn dort 300 Sekunden steht, speichern Sie 300 Sekunden als benannte Einstellung und vermeiden Sie eine rätselhafte Zahl, die in drei Dateien fest verdrahtet ist.
Uhrdrift kann legitimen Traffic kaputtmachen. Ein Server, der 7 Minuten danebenliegt, kann eine gültige Anfrage ablehnen. Synchronisieren Sie Ihre Server mit NTP und halten Sie die Zeitzone konsistent. Die Zeitzone ändert Unix-Zeitstempel zwar nicht, aber falsche lokale Einstellungen können Logs trotzdem schwer lesbar machen.
Nonces sind noch einfacher, wenn es sie gibt. Speichern Sie jeden Nonce nur einmal, markieren Sie ihn als verwendet und lehnen Sie Duplikate ab. Ein kleiner Cache oder eine Datenbanktabelle reicht dafür aus. Ein Nonce, eine Annahme.
Wenn Sie auf Zahlungsseiten auch feste Preise akzeptieren, ist hier die Richtlinie wichtig. Ein separater Beitrag über ob ich einen Festpreis verwenden sollte hilft dabei, Wechselkursregeln und Webhook-Zeitpunkte aufeinander abzustimmen, damit Sie nach einem verspäteten Ereignis nicht den falschen Betrag bestätigen.
Gültige Ereignisse verarbeiten und die richtige HTTP-Antwort zurückgeben
Nachdem die Verifikation bestanden ist, parsen Sie den Payload und verzweigen nach dem Ereignistyp. Ein payment.succeeded-Ereignis sollte nicht denselben Codepfad nehmen wie ein refund.updated-Ereignis. Trennen Sie das sauber. So erledigt jeder Handler nur eine Aufgabe und Ihre Logs bleiben lesbar.
Die Geschäftslogik sollte laufen, bevor Sie die 2xx-Antwort senden. Wenn Sie eine Bestellung als bezahlt markieren, schreiben Sie zuerst die Datenbankzeile. Wenn Sie eine E-Mail in die Warteschlange stellen, fügen Sie sie zuerst ein. Wenn einer dieser Schritte fehlschlägt, geben Sie 500 zurück und lassen Sie Payora später erneut versuchen.
Diese Reihenfolge ist wichtig, weil eine 2xx-Antwort Payora normalerweise signalisiert, dass das Ereignis angenommen wurde. Wenn Sie 200 zu früh zurückgeben und dann bei einem Datenbank-Schreibzugriff abstürzen, kann es zu einer Abweichung zwischen Payora und Ihrer Anwendung kommen. Solche Fehler sind um 2 Uhr morgens teuer.
Ein kleiner Antwort-Body reicht aus. „OK“ funktioniert. Noch besser: Geben Sie gar keinen Body zurück und halten Sie den Statuscode klar. Echoen Sie den Payload nicht zurück.
Für Teams, die Kunden auch direkt aus Zahlungsereignissen heraus abrechnen, zeigt der Artikel über das Krypto-Zahlungsgateway für Freelancer, wie ein Webhook von einem technischen Ereignis zu einer echten Abrechnungsaktion werden kann, ohne unnötige Zwischenschritte.
Fehlgeschlagene Signaturprüfungen beheben
Die meisten Fehler haben fünf Ursachen: Der rohe Body wurde verändert, der Header-Name ist falsch, das Secret ist falsch, die Kodierung unterscheidet sich oder die Zeitstempelprüfung liegt außerhalb der Toleranz. Beginnen Sie mit dem Body. Wenn Sie den rohen Payload und die berechnete Signatur protokolliert haben, vergleichen Sie diese, bevor Sie die Datenbank anfassen.
Eine Veränderung des Bodys kommt häufig vor. Framework-Middleware kann Leerzeichen trimmen, JSON dekodieren oder Zeilenenden normalisieren. Schon ein zusätzliches Newline-Zeichen reicht. Wenn Payora {"a":1} signiert hat und Ihre Anwendung {"a":1}\n liest, stimmt der HMAC nicht mehr.
Der nächste Punkt sind Header-Abweichungen. Manche Server wandeln Bindestriche in Unterstriche um. Manche Proxy-Schichten entfernen benutzerdefinierte Header, wenn sie nicht ausdrücklich erlaubt sind. Wenn Ihr Signatur-Header in PHP fehlt, prüfen Sie die Webserver-Konfiguration und die Proxy-Einstellungen, nicht nur den Code.
Kodierungsprobleme sind tückisch. UTF-8 und maskierte Unicode-Zeichen können in Logs korrekt aussehen und trotzdem unterschiedliche Bytes erzeugen. Wenn Ihre Anwendung JSON neu schreibt, kann die Signatur brechen, obwohl der Payload im Browser identisch wirkt.
Das falsche Secret ist der einfachste Fehler und der, den Menschen zuletzt prüfen. Verifizieren Sie die Umgebungsvariable, das Staging-Secret und das Produktions-Secret getrennt. Ein kopiertes Secret aus dem falschen Konto kann einen Nachmittag kosten.
Uhrdrift erzeugt ein anderes Symptom: Die Signatur passt, aber die Anfrage wird trotzdem abgelehnt, weil der Zeitstempel zu alt ist. Prüfen Sie in diesem Fall NTP, Container-Uhren und jeden Reverse Proxy, der seine eigene Zeit stempelt. Kleine Infrastrukturabweichungen können wie eine falsche Signatur aussehen.
Wenn Ihre Installation auch mit WordPress oder Mitgliedschaftsabrechnung verbunden ist, ist der Artikel über wie man USDT-Zahlungen annimmt nützlich, weil er zeigt, wie Webhook-Verarbeitung, Zugriffskontrolle und Zahlungsbestätigung in einem einzigen Ablauf zusammenpassen.
Ein letzter Test hilft sehr: Senden Sie denselben Payload zweimal. Die erste Anfrage sollte bestehen. Die zweite sollte fehlschlagen, wenn Sie einen wiederverwendeten Nonce speichern und ablehnen, oder sie sollte nur bestehen, wenn Ihr Webhook-Design keinen nonce-basierten Replay-Schutz verwendet. Dieses eine Duplikat zeigt Ihnen, ob Ihr Schutz wirklich funktioniert.




Kommentare