Blog

Integrációk 8 perc olvasás

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.

Borítókép: WayForPay integráció PHP-ben: fizetési űrlap, aláírás és visszahívás

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_STATUS vá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

  1. 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.
  2. 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.
  3. 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).
  4. WayForPay felhívja serviceUrl t a tranzakció eredményével. Ebben a kiszolgálók közötti hívásban megbízik.
  5. Az ügyfelet a returnUrl re 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.
  • serviceUrl nek 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.