Blog

Integrationen 8 Min. Lesezeit

WayForPay Integration in PHP: Zahlungsformular, Signatur und Rückruf

WayForPay ist die praktische Möglichkeit, Kartenzahlungen in UAH, USD und EUR von einem ukrainischen Unternehmen zu akzeptieren. Dieser Leitfaden führt Sie durch die vollständige Integration in PHP: Signieren des Zahlungsformulars, Empfangen des Serverrückrufs, korrekte Beantwortung und Bestätigen des Bestellstatus.

Titelbild: WayForPay Integration in PHP: Zahlungsformular, Signatur und Rückruf

Kurz gesagt

  • Der Ablauf besteht aus drei Teilen: einem signierten Zahlungsformular, das den Kunden an WayForPay weiterleitet, einem Server-zu-Server-Rückruf (serviceUrl) und Ihrer eigenen Bestellstatusseite.
  • Jede Anfrage und Antwort wird mit HMAC_MD5 unter Verwendung Ihres geheimen Händlerschlüssels signiert. Die Feldreihenfolge ist wichtig.
  • Markieren Sie eine Bestellung nur aufgrund eines verifizierten Rückrufs oder einer CHECK_STATUS Antwort als bezahlt, niemals, wenn der Kunde auf Ihre Website zurückkehrt.
  • Sie müssen den Rückruf mit einer signierten JSON-Antwort „Akzeptieren“ beantworten, andernfalls versucht WayForPay es immer wieder.
  • Behalten Sie Beträge, Währung und Bestellreferenz in Ihrer Datenbank und vergleichen Sie diese mit den Angaben im Rückruf.

Eine WayForPay Integration in PHP ist eine kleine Codemenge, aber es gibt mehrere Stellen, an denen ein stiller Fehler bedeutet, dass entweder unbezahlte Bestellungen als bezahlt markiert werden oder bezahlte Bestellungen, die nie ausgeführt werden. Wir betreiben WayForPay Checkout auf unseren eigenen Websites, einschließlich der kostenpflichtigen Dienste auf dieser Website, und haben ihn in mehrere Kundenshops integriert. Nachfolgend finden Sie die Struktur, die wir verwenden, mit den Details, die in der Dokumentation aufgeführt sind, aber die Leute neigen dazu, sie zu überfliegen.

So funktioniert der Zahlungsfluss

  1. Der Kunde klickt auf „Bezahlen“. Ihr Server erstellt in der Datenbank eine Bestellung mit einer eindeutigen orderReference, einem festen Betrag und einer Währung.
  2. Ihr Server erstellt die Zahlungsformularfelder, signiert sie und rendert ein automatisch sendendes HTML-Formular, das auf der WayForPay -Zahlungsseite veröffentlicht wird.
  3. Der Kunde bezahlt auf der WayForPay Seite (Karte, Apple Pay, Google Pay und andere in Ihrem Händlerkonto aktivierte Methoden).
  4. WayForPay ruft Ihre serviceUrl mit dem Transaktionsergebnis auf. Diesem Server-zu-Server-Aufruf vertrauen Sie.
  5. Der Kunde wird zu Ihrer returnUrl weitergeleitet, wo Ihnen der aktuelle Bestellstatus angezeigt wird.

Schritt 5 kann ausgeführt werden, bevor Schritt 4 abgeschlossen ist. Daher muss auf der Rückgabeseite „Bestätigung Ihrer Zahlung“ stehen, bis der Rückruf bearbeitet wurde.

Was Sie vom Händlerkonto benötigen

  • merchantAccount – Ihr Händler-Login.
  • merchantSecretKey – das für Signaturen verwendete Geheimnis. Behalten Sie es in einer Umgebungsvariablen oder einer nicht verfolgten Konfigurationsdatei, niemals in Git oder im Front-End-Code.
  • merchantDomainName – die Domain Ihrer Website, wie im Konto registriert.
  • Die für Ihr Konto aktivierten Währungen und Zahlungsmethoden.

Schritt 1. Erstellen und unterschreiben Sie das Zahlungsformular

Die Signatur ist ein HMAC mit MD5 über ausgewählten Feldern, verbunden durch ein Semikolon. Bei einem Kauf umfasst die Bestellung Folgendes: Händlerkonto, Händlerdomänenname, Bestellreferenz, Bestelldatum (Unix-Zeitstempel), Betrag, Währung, dann alle Produktnamen, alle Produktanzahlen und alle Produktpreise.

function wfpSignature(array $parts, string $secret): string
{
    return hash_hmac('md5', implode(';', $parts), $secret);
}

$orderReference = 'ORD-' . $orderId . '-' . time();
$orderDate      = time();
$amount         = '50.00';          // string with a dot, the same value everywhere
$currency       = 'EUR';
$products       = [['name' => 'Consultation, 1 hour', 'count' => 1, 'price' => '50.00']];

$parts = [$merchantAccount, $merchantDomain, $orderReference, $orderDate, $amount, $currency];
foreach ($products as $p) { $parts[] = $p['name']; }
foreach ($products as $p) { $parts[] = (string) $p['count']; }
foreach ($products as $p) { $parts[] = $p['price']; }

$signature = wfpSignature($parts, $secretKey);

Rendern Sie dann das Formular. Produktfelder sind Arrays und verwenden daher das Suffix []:

<form id="wfp" method="post" action="https://secure.wayforpay.com/pay" accept-charset="utf-8">
  <input type="hidden" name="merchantAccount" value="...">
  <input type="hidden" name="merchantAuthType" value="SimpleSignature">
  <input type="hidden" name="merchantDomainName" value="example.com">
  <input type="hidden" name="merchantSignature" value="<?= htmlspecialchars($signature) ?>">
  <input type="hidden" name="orderReference" value="<?= htmlspecialchars($orderReference) ?>">
  <input type="hidden" name="orderDate" value="<?= $orderDate ?>">
  <input type="hidden" name="amount" value="50.00">
  <input type="hidden" name="currency" value="EUR">
  <input type="hidden" name="productName[]" value="Consultation, 1 hour">
  <input type="hidden" name="productCount[]" value="1">
  <input type="hidden" name="productPrice[]" value="50.00">
  <input type="hidden" name="returnUrl" value="https://example.com/pay/return">
  <input type="hidden" name="serviceUrl" value="https://example.com/pay/callback">
</form>
<script>document.getElementById('wfp').submit();</script>

Die häufigsten Signaturfehler sind: ein unterschiedliches Zahlenformat in der Signatur und im Formular (50 vs. 50.00), ein Produktname, der nach der Signatur geändert (gekürzt, HTML-escaped) wird, und das Vergessen, dass die Reihenfolge der Felder festgelegt ist.

Schritt 2: Erhalten Sie den Rückruf auf serviceUrl

Wenn die Zahlung einen Endstatus erreicht, postet WayForPay das Ergebnis an serviceUrl. Lesen Sie den Rohtext (es ist JSON; einige Setups liefern auch Formularfelder, also behandeln Sie beide) und überprüfen Sie die Signatur. Für den Rückruf werden Folgendes berechnet: Händlerkonto, Bestellreferenz, Betrag, Währung, Autorisierungscode, Kartenmaske, Transaktionsstatus und Ursachencode.

$raw  = file_get_contents('php://input');
$data = json_decode($raw, true) ?: $_POST;

$line = implode(';', [
    $data['merchantAccount'] ?? '',
    $data['orderReference'] ?? '',
    $data['amount'] ?? '',
    $data['currency'] ?? '',
    $data['authCode'] ?? '',
    $data['cardPan'] ?? '',
    $data['transactionStatus'] ?? '',
    $data['reasonCode'] ?? '',
]);
$expected = hash_hmac('md5', $line, $secretKey);

if (!hash_equals(strtolower($expected), strtolower((string) ($data['merchantSignature'] ?? '')))) {
    http_response_code(400);
    exit;
}

Verwenden Sie hash_equals für den Vergleich, um Zeitverluste zu vermeiden. Erst wenn die Unterschrift gültig ist, sollten Sie die Bestellung nachschlagen und amount und currency mit Ihren hinterlegten Angaben vergleichen. Sollten sie abweichen, protokollieren Sie dies und kennzeichnen Sie die Bestellung nicht als bezahlt.

Schritt 3. Aktualisieren Sie die Bestellung und antworten Sie richtig

Das Feld transactionStatus informiert Sie darüber, was passiert ist: Approved bedeutet, dass das Geld erfasst wurde; Declined, Expired und ähnliche Werte bedeuten einen Fehler; Pending oder InProcessing bedeuten Warten; Refunded und Voided bedeuten, dass das Geld zurückerstattet wurde. Aktualisieren Sie Ihre Bestellung in einer Transaktion entsprechend und machen Sie sie idempotent: Wenn die Bestellung bereits bezahlt ist, tun Sie nichts und antworten Sie trotzdem erfolgreich.

WayForPay benötigt eine signierte Antwort, damit es weiß, dass Sie die Nachricht erhalten haben. Die Signatur steht über der Bestellreferenz, dem Wort „ accept und der aktuellen Uhrzeit:

$time   = time();
$status = 'accept';
$reply  = [
    'orderReference' => $data['orderReference'],
    'status'         => $status,
    'time'           => $time,
    'signature'      => hash_hmac('md5', "{$data['orderReference']};{$status};{$time}", $secretKey),
];

header('Content-Type: application/json');
echo json_encode($reply);

Wenn Ihr Server nicht auf diese Weise antwortet, behandelt WayForPay die Zustellung als fehlgeschlagen und versucht es erneut, was bedeutet, dass Sie denselben Rückruf mehrmals erhalten. Das ist ein weiterer Grund für die Idempotenzprüfung.

Schritt 4: Bestätigen Sie den Status mit CHECK_STATUS

Rückrufe können übersehen werden: Ihr Server war ausgefallen, eine Firewall hat die Anfrage blockiert, ein Deploy hat die Route unterbrochen. WayForPay bietet einen CHECK_STATUS-API-Aufruf an, der den aktuellen Status einer Bestellung anhand ihrer Referenz zurückgibt. Verwenden Sie es an zwei Stellen: auf der Rückgabeseite, wenn der Rückruf nach ein paar Sekunden nicht eintrifft, und in einem kleinen Cronjob, der Bestellungen, die länger als beispielsweise fünfzehn Minuten im Status „Ausstehend“ stecken, erneut überprüft. Die Anfrage wird mit HMAC_MD5 über das Händlerkonto und die Bestellreferenz signiert.

$payload = [
    'transactionType'   => 'CHECK_STATUS',
    'merchantAccount'   => $merchantAccount,
    'orderReference'    => $orderReference,
    'merchantSignature' => hash_hmac('md5', "{$merchantAccount};{$orderReference}", $secretKey),
    'apiVersion'        => 1,
];

$ch = curl_init('https://api.wayforpay.com/api');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => json_encode($payload),
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 15,
]);
$result = json_decode((string) curl_exec($ch), true);

Führen Sie die gleichen Prüfungen wie bei einem Rückruf durch: Überprüfen Sie die Antwortsignatur, sofern vorhanden, vergleichen Sie den Betrag und die Währung und aktualisieren Sie die Bestellung idempotent.

Testen Sie, bevor Sie live gehen

  • Verwenden Sie den Testmodus und die Testkarten aus der WayForPay -Dokumentation, bis in Ihren Protokollen eine vollständige Zahlung, eine Ablehnung und eine Rückerstattung angezeigt werden.
  • Ihre serviceUrl muss über HTTPS aus dem Internet erreichbar sein. Verwenden Sie auf localhost einen Tunnel oder stellen Sie es in einer Staging-Domäne bereit.
  • Protokollieren Sie jeden Rückruf mit seinem Rohtext, dem Überprüfungsergebnis und dem Ergebnis. Protokollieren Sie niemals den geheimen Schlüssel.
  • Stellen Sie sicher, dass die WAF oder der Bot-Schutz (z. B. in Cloudflare) die Rückrufanfragen von WayForPay nicht anfechten oder blockieren.

Häufige Fehler

  • Der Rückgabe-URL vertrauen. Der Kunde kann es öffnen, ohne zu bezahlen.
  • Wiederverwendung einer Bestellreferenz. Für jeden Versuch ist eine eindeutige Referenz erforderlich, sonst verwechseln Sie die Versuche.
  • Den Betrag nach der Unterzeichnung ändern oder einen Preis anzeigen und einen anderen unterzeichnen.
  • Der Rückruf wird nicht mit der unterzeichneten Annahmeantwort beantwortet.
  • Markieren Sie die Zahlung als bezahlt, bevor Sie den Betrag und die Währung überprüfen.
  • Mehrere Währungen, ein gemeinsames Geheimnis und keine Zuordnung: Behalten Sie die Währung in der Reihenfolge bei und überprüfen Sie sie beim Rückruf.

Wie wir helfen können

Wir erstellen End-to-End -Zahlungsintegrationen: WayForPay, Stripe, PayPal, wiederkehrende Abrechnungen, Rückerstattungen und Abgleichsberichte. Wenn Sie bereits über einen funktionierenden Checkout verfügen, sich aber über die Fehlermodi nicht sicher sind, buchen Sie eine Architekturanalyse und wir überprüfen die Rückrufverarbeitung, Idempotenz und Protokollierung. Eine ähnliche Anleitung zu einem anderen Anbieter finden Sie unter Stripe -Webhooks in PHP. Den Gesamtansatz finden Sie in unserem Startup-Integrations-Playbook.

Häufige Fragen

Welche Signatur verwendet WayForPay ?

HMAC_MD5 über ausgewählte Felder, verbunden mit einem Semikolon, unter Verwendung des geheimen Händlerschlüssels. Die Reihenfolge der Felder ist festgelegt und unterscheidet sich für das Zahlungsformular, den Rückruf und die Rückrufantwort.

Was muss der serviceUrl-Endpunkt zurückgeben?

Eine JSON-Antwort mit orderReference, dem Status „accept“, der aktuellen Unix-Zeit und einer als HMAC_MD5 berechneten Signatur von „orderReference;accept;time“. Ohne sie versucht WayForPay den Rückruf erneut.

Kann ich darauf vertrauen, dass die returnUrl-Seite eine Bestellung als bezahlt markiert?

Nein. Der Browser des Kunden kann diese URL öffnen, ohne dafür zu bezahlen. Markieren Sie Bestellungen erst dann als bezahlt, wenn ein verifizierter serviceUrl-Rückruf oder eine CHECK_STATUS Antwort mit dem Status „Genehmigt“ sowie dem entsprechenden Betrag und der entsprechenden Währung erfolgt ist.

Wie überprüfe ich den Status einer WayForPay -Bestellung?

Senden Sie eine signierte CHECK_STATUS Anfrage mit Ihrem Händlerkonto und der Bestellreferenz an die WayForPay -API. Verwenden Sie es auf der Rückgabeseite und in einem Cron-Job, der in der Schwebe befindliche Bestellungen erneut überprüft.

Warum sagt WayForPay, dass die Signatur ungültig ist?

Normalerweise unterscheidet sich das Betragsformat zwischen der Signatur und dem Formular (50 vs. 50,00), ein Produktname wurde nach der Signatur geändert, die Reihenfolge der Felder ist falsch oder es wird der falsche geheime Schlüssel verwendet.

Kostenloses Kennenlerngespräch

Unordentlicher Stack oder festgefahrene Integration - Integrono plant den klügsten ersten Schritt.

Sie bekommen eine Senior-Einschätzung zu Budgetfallen, Abhängigkeiten und ob kaufen, kleben oder bauen der richtige Weg ist - bevor die bezahlte Arbeit beginnt. Der CEO bleibt eingebunden.