WayForPay integráció PHP-ben: fizetési űrlap, aláírás és visszahívás
WayForPay a praktikus módja annak, hogy UAH, USD és EUR kártyás fizetéseket fogadjon el egy ukrán vállalkozástól. Ez az útmutató végigvezeti a PHP-ben való teljes integrációt: a fizetési űrlap aláírását, a szerver visszahívását, a helyes válaszadást és a megrendelés állapotának megerősítését.
Röviden
- A folyamat három részből áll: egy aláírt fizetési űrlap, amely elküldi az ügyfelet WayForPay hez, egy szerverek közötti visszahívás (
serviceUrl), valamint a saját rendelési állapotoldal. - Minden kérést és választ aláírnak HMAC_MD5 tel a kereskedői titkos kulcs használatával; tereprend számít.
- Egy rendelést csak ellenőrzött visszahívás vagy
CHECK_STATUSválasz esetén jelöljön ki fizetettként, soha nem a webhelyére visszatérő ügyféltől. - A visszahívásra egy aláírt JSON „elfogadás” választ kell adnia, ellenkező esetben WayForPay tovább próbálkozik.
- Tartsa az összegeket, a pénznemet és a rendelési hivatkozást az adatbázisában, és hasonlítsa össze a visszahívással.
A PHP-ben a WayForPay integráció kis mennyiségű kód, de több helyen van, ahol a néma hiba vagy fizetettként megjelölt, kifizetetlen vagy soha nem teljesített kifizetett megrendeléseket jelent. Saját oldalainkon futtatjuk WayForPay fizetést, beleértve az ezen a webhelyen található fizetős szolgáltatásokat is, és számos ügyfélboltba bekötöttük. Alább látható az általunk használt szerkezet, a dokumentációban felsorolt részletekkel, de az emberek hajlamosak átfutni.
Hogyan működik a fizetési folyamat
- Az ügyfél a „Fizetés” gombra kattint. A szerver létrehoz egy megbízást az adatbázisban egyedi
orderReference, fix összeg és pénznem megadásával. - A kiszolgáló elkészíti a fizetési űrlap mezőit, aláírja azokat, és automatikusan beküldő HTML űrlapot jelenít meg, amely a WayForPay fizetési oldalán jelenik meg.
- Az ügyfél a WayForPay oldalon fizet (kártya, Apple Pay, Google Pay és egyéb módok engedélyezettek a kereskedői fiókjában).
- WayForPay felhívja
serviceUrlt a tranzakció eredményével. Ebben a kiszolgálók közötti hívásban megbízik. - Az ügyfelet a
returnUrlre irányítja át, ahol megjeleníti a megrendelés aktuális állapotát.
Az 5. lépés megtörténhet a 4. lépés befejezése előtt, ezért a visszahívási oldalon a „befizetés megerősítése” feliratnak kell szerepelnie a visszahívás feldolgozásáig.
Amire szüksége van a kereskedői fiókból
merchantAccount– az Ön kereskedői bejelentkezési adatai.merchantSecretKey– az aláírásokhoz használt titok. Tartsa egy környezeti változóban vagy egy nyomon nem követett konfigurációs fájlban, soha ne gitben vagy előtér-kódban.merchantDomainName– webhelyének a fiókban regisztrált domainje.- A fiókjában engedélyezett pénznemek és fizetési módok.
1. lépés: Készítse el és írja alá a fizetési űrlapot
Az aláírás egy HMAC, a kiválasztott mezők felett MD5, pontosvesszővel összekötve. Vásárlás esetén a rendelés a következő: kereskedői számla, kereskedői domain név, rendelési hivatkozás, rendelés dátuma (Unix időbélyeg), összeg, pénznem, majd az összes terméknév, az összes termékszám és az összes termék ára.
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);
Ezután jelenítse meg az űrlapot. A termékmezők tömbök, ezért a [] utótagot használják:
<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>
A leggyakoribb aláírási hibák: eltérő számformátum az aláírásban és az űrlapon (50 vs 50.00), az aláírás után megváltozott (kivágott, HTML-kihagyott) terméknév, valamint a mezők sorrendjének rögzítéséről való megfeledkezés.
2. lépés. Fogadja a visszahívást a serviceUrl címen
Amikor a fizetés eléri a végső állapotot, WayForPay elküldi az eredményt serviceUrl oldalon. Olvassa el a nyers törzset (ez JSON; egyes beállítások űrlapmezőket is szállítanak, ezért mindkettőt kezelje), és ellenőrizze az aláírást. A visszahíváshoz a következőképpen kerül kiszámításra: kereskedői számla, rendelési hivatkozás, összeg, pénznem, engedélyezési kód, kártyamaszk, tranzakció állapota és okkódja.
$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;
}
Használja hash_equals az összehasonlításhoz, hogy elkerülje az időzítési szivárgást. Csak az aláírás érvényessége után nézze meg a rendelést, és hasonlítsa össze amount és currency a tárolttal. Ha eltérnek, naplózza, és ne jelölje kifizetettnek a megrendelést.
3. lépés: Frissítse a rendelést, és válaszoljon helyesen
A transactionStatus mezőben megtudhatja, mi történt: Approved azt jelenti, hogy a pénzt lefoglalták; Declined, Expired és hasonló értékek meghibásodást jelentenek; Pending vagy InProcessing várakozást jelent; Refunded és Voided azt jelenti, hogy a pénz visszakerült. Frissítse megrendelését ennek megfelelően egy tranzakció során, és tegye idempotenssé: ha a rendelés már ki van fizetve, ne tegyen semmit, és továbbra is sikeresen válaszoljon.
WayForPay aláírt választ igényel, hogy tudja, hogy megkapta az üzenetet. Az aláírás a rendelési hivatkozás felett van, az accept szó és a pontos idő:
$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);
Ha a szervere nem válaszol így, WayForPay sikertelenként kezeli a kézbesítést és újra próbálkozik, ami azt jelenti, hogy többször is ugyanazt a visszahívást kapja. Ez egy másik oka az idempotencia ellenőrzésének.
4. lépés: Erősítse meg az állapotot CHECK_STATUS gombbal
A visszahívások elmaradhatnak: a szerver leállt, a tűzfal blokkolta a kérést, a telepítés megszakította az útvonalat. WayForPay egy CHECK_STATUS API-hívást kínál, amely hivatkozása alapján visszaadja a rendelés aktuális állapotát. Használja két helyen: a visszatérő oldalon, ha néhány másodperc után nem érkezett meg a visszahívás, és egy kis cron feladatban, amely újraellenőrzi a mondjuk tizenöt percnél tovább "függőben" elakadt rendeléseket. A kérelmet HMAC_MD5 kóddal írják alá a kereskedői fiókon és a rendelési hivatkozáson keresztül.
$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);
Alkalmazza ugyanazokat az ellenőrzéseket, mint a visszahívásnál: ellenőrizze a válasz aláírását, ha jelen van, hasonlítsa össze az összeget és a pénznemet, és azonnal frissítse a megbízást.
Tesztelés az élő adás előtt
- Használja a WayForPay dokumentációjában szereplő tesztmódot és tesztkártyákat, amíg a teljes fizetés, az elutasítás és a visszatérítés meg nem jelenik a naplókban.
serviceUrlnek elérhetőnek kell lennie az internetről HTTPS-en keresztül. Localhost-on használjon alagutat, vagy telepítse egy átmeneti tartományra.- Minden visszahívást naplózzon a nyers törzsével, az ellenőrzési eredménnyel és az eredménnyel. Soha ne naplózza a titkos kulcsot.
- Győződjön meg arról, hogy a WAF- vagy botvédelem (például Cloudflare ben) nem támadja meg vagy blokkolja WayForPay visszahívási kérelmeit.
Gyakori hibák
- Bízva a visszatérési URL-ben. Az ügyfél fizetés nélkül kinyithatja.
- Rendelési hivatkozás újrafelhasználása. Minden kísérlethez egyedi hivatkozásra van szükség, különben összekevered a kísérleteket.
- Az összeg módosítása aláírás után, vagy az egyik ár megjelenítése és a másik aláírása.
- Nem válaszol a visszahívásra az aláírt elfogadó válasszal.
- Fizetésként jelölés az összeg és a pénznem ellenőrzése előtt.
- Több pénznem, egy megosztott titok és nincs hozzárendelés: tartsa a pénznemet a sorrendben, és ellenőrizze visszahíváskor.
Hogyan segíthetünk
A fizetési integrációkat végpontokig építjük ki: WayForPay, Stripe, PayPal, ismétlődő számlázás, visszatérítés és egyeztetési jelentések. Ha már rendelkezik működő pénztárral, de nem biztos a hibamódjaiban, foglaljon egy architektúra elemzést, és áttekintjük a visszahíváskezelést, az idempotenciát és a naplózást. Egy másik szolgáltatóról szóló hasonló útmutatóért lásd Stripe webhooks-t PHP-ben, az átfogó megközelítéshez pedig olvassa el az indítási integrációs útmutatónkat.
Gyakori kérdések
Melyik aláírást használja WayForPay ?
HMAC_MD5 a kiválasztott mezők felett pontosvesszővel összekapcsolva, a kereskedő titkos kulcsával. A helyszíni sorrend rögzített, és különbözik a fizetési űrlap, a visszahívás és a visszahívási válasz tekintetében.
Mit kell visszaadnia a serviceUrl végpontnak?
JSON-válasz orderReference-vel, az „accept” állapottal, az aktuális Unix-idővel és az „orderReference;accept;time” HMAC_MD5-ként kiszámított aláírásával. Enélkül WayForPay újra megpróbálja a visszahívást.
Megbízhatom a returnUrl oldalon, hogy kifizetettként jelölje meg a rendelést?
Nem. Az ügyfél böngészője fizetés nélkül is megnyithatja az URL-t. A rendeléseket csak egy ellenőrzött serviceUrl visszahívás vagy egy CHECK_STATUS válasz után jelölje meg kifizetettként, a Jóváhagyva állapottal, valamint a megfelelő összeggel és pénznemgel.
Hogyan ellenőrizhetem a WayForPay rendelés állapotát?
Küldjön aláírt CHECK_STATUS kérelmet a WayForPay API-nak a kereskedői fiókjával és a megrendelés hivatkozásával. Használja a visszatérési oldalon és egy cron feladatban, amely újraellenőrzi a függőben lévő rendeléseket.
Miért mondja WayForPay, hogy az aláírás érvénytelen?
Általában az aláírás és a nyomtatvány összegének formátuma eltér (50 vs 50,00), az aláírás után megváltozott a terméknév, rossz a mezők sorrendje vagy rossz titkos kulcsot használtak.
Ingyenes felfedező hívás
Hozzon kaotikus stacket vagy elakadt integrációt - az Integrono feltérképezi a legokosabb első lépést.
Senior rálátást kap a költségvetési csapdákra, a függőségekre és arra, hogy vásároljon, ragasszon vagy építsen - mielőtt a fizetett munka elindul. A CEO a körben marad.