Integrácia WayForPay v PHP: platobný formulár, podpis a spätné volanie
WayForPay je praktický spôsob, ako prijímať platby kartou v UAH, USD a EUR od ukrajinského podniku. Táto príručka vás prevedie úplnou integráciou v PHP: podpísanie platobného formulára, prijatie spätného volania zo servera, správne zodpovedanie a potvrdenie stavu objednávky.
V skratke
- Tok má tri časti: podpísaný platobný formulár, ktorý pošle zákazníka na WayForPay, spätné volanie medzi servermi (
serviceUrl) a vašu vlastnú stránku stavu objednávky. - Každá požiadavka a odpoveď je podpísaná pomocou HMAC_MD5 pomocou vášho tajného kľúča obchodníka; na poľnom poriadku záleží.
- Označte objednávku ako zaplatenú iba na základe overeného spätného volania alebo odpovede
CHECK_STATUS, nikdy nie od zákazníka, ktorý sa vracia na vašu stránku. - Na spätné volanie musíte odpovedať podpísanou odpoveďou „prijať“ JSON, inak sa WayForPay neustále pokúša.
- Uchovajte si sumy, menu a referenciu objednávky vo svojej databáze a porovnajte ich s tým, čo hovorí spätné volanie.
Integrácia WayForPay v PHP je malé množstvo kódu, ale má niekoľko miest, kde tichá chyba znamená buď nezaplatené objednávky označené ako platené, alebo platené objednávky, ktoré sa nikdy nesplnia. Pokladňu WayForPay prevádzkujeme na našich vlastných stránkach, vrátane platených služieb na tejto webovej lokalite, a zaviedli sme ju do niekoľkých klientskych obchodov. Nižšie je uvedená štruktúra, ktorú používame, s podrobnosťami, ktoré dokumentácia uvádza, ale ľudia majú tendenciu prehliadať.
Ako funguje tok platieb
- Zákazník klikne na „Zaplatiť“. Váš server vytvorí objednávku v databáze s jedinečnou
orderReference, pevnou sumou a menou. - Váš server vytvorí polia platobného formulára, podpíše ich a vykreslí formulár HTML s automatickým odoslaním, ktorý sa uverejní na platobnej stránke WayForPay.
- Zákazník platí na stránke WayForPay (karta, Apple Pay, Google Pay a ďalšie spôsoby povolené vo vašom účte obchodníka).
- WayForPay zavolá vašu
serviceUrls výsledkom transakcie. Tento hovor server-to-server je to, čomu dôverujete. - Zákazník je presmerovaný na vašu
returnUrl, kde zobrazíte aktuálny stav objednávky.
Krok 5 sa môže uskutočniť pred dokončením kroku 4, takže na návratovej stránke musí byť uvedené „potvrdzujem vašu platbu“, kým sa spätné volanie nespracuje.
Čo potrebujete od obchodného účtu
merchantAccount– vaše prihlasovacie údaje obchodníka.merchantSecretKey– tajomstvo používané na podpisy. Uchovávajte ho v premennej prostredia alebo nesledovanom konfiguračnom súbore, nikdy nie v git alebo v kóde front-end.merchantDomainName– doména vašej stránky, ako je zaregistrovaná v účte.- Meny a spôsoby platby povolené pre váš účet.
Krok 1. Vytvorte a podpíšte platobný formulár
Podpis je HMAC s MD5 nad vybranými poľami spojenými bodkočiarkou. Pre nákup je objednávka: obchodný účet, názov domény obchodníka, referencia objednávky, dátum objednávky (časová pečiatka Unix), suma, mena, potom všetky názvy produktov, všetky počty produktov a všetky ceny produktov.
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);
Potom vykreslite formulár. Polia produktu sú polia, takže používajú príponu []:
<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>
Najčastejšie chyby podpisu sú: iný formát čísla v podpise a formulári (50 vs 50.00), názov produktu, ktorý sa po podpise zmení (orezaný, s kódom HTML) a zabudne sa, že poradie polí je pevné.
Krok 2. Prijmite spätné volanie na serviceUrl
Keď platba dosiahne konečný stav, WayForPay odošle výsledok na serviceUrl. Prečítajte si nespracované telo (je to JSON; niektoré nastavenia doručujú aj polia formulára, takže spracujte obe) a overte podpis. Pre spätné volanie sa počíta podľa: obchodného účtu, referencie objednávky, sumy, meny, autorizačného kódu, masky karty, stavu transakcie a kódu dôvodu.
$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;
}
Na porovnanie použite hash_equals, aby ste sa vyhli únikom načasovania. Až keď je podpis platný, mali by ste vyhľadať objednávku a porovnať amount a currency s tým, čo ste uložili. Ak sa líšia, prihláste sa a neoznačte objednávku ako zaplatenú.
Krok 3. Aktualizujte objednávku a odpovedzte správne
transactionStatus vám povie, čo sa stalo: Approved znamená, že peniaze sú zachytené; Declined, Expired a podobné hodnoty znamenajú zlyhanie; Pending alebo InProcessing znamená čakať; Refunded a Voided znamená, že peniaze boli vrátené. Podľa toho aktualizujte svoju objednávku v transakcii a urobte ju idempotentnou: ak je objednávka už zaplatená, nerobte nič a stále odpovedajte úspešne.
WayForPay vyžaduje podpísanú odpoveď, aby vedel, že ste správu dostali. Podpis je nad referenciou objednávky, slovom accept a aktuálnym časom:
$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);
Ak váš server neodpovedá takto, WayForPay považuje doručenie za neúspešné a zopakuje to, čo znamená, že dostanete rovnaké spätné volanie niekoľkokrát. To je ďalší dôvod kontroly idempotencie.
Krok 4. Potvrďte stav pomocou CHECK_STATUS
Spätné volania môžu chýbať: váš server bol mimo prevádzky, firewall zablokoval požiadavku, nasadenie prerušilo trasu. WayForPay ponúka volanie API CHECK_STATUS, ktoré vracia aktuálny stav objednávky podľa jej referencie. Použite ho na dvoch miestach: na návratovej stránke, ak spätné volanie neprišlo po niekoľkých sekundách, a v malej úlohe cron, ktorá prekontroluje objednávky uviaznuté v „čakacej“ na viac ako, povedzme, pätnásť minút. Žiadosť je podpísaná pomocou HMAC_MD5 cez obchodný účet a referenciu objednávky.
$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);
Použite rovnaké kontroly ako pri spätnom volaní: overte podpis odpovede, ak je prítomný, porovnajte sumu a menu a aktualizujte objednávku idempotentne.
Testovanie pred spustením naživo
- Použite testovací režim a testovacie karty z dokumentácie WayForPay, kým sa vo vašich denníkoch nezobrazí úplná platba, odmietnutie a vrátenie peňazí.
- Vaša
serviceUrlmusí byť dostupná z internetu cez HTTPS. Na localhost použite tunel alebo nasaďte na fázovú doménu. - Zaznamenajte každé spätné volanie s jeho nespracovaným telom, výsledkom overenia a výsledkom. Nikdy neprihlasujte tajný kľúč.
- Uistite sa, že ochrana WAF alebo bota (napríklad v Cloudflare) nenapáda ani neblokuje žiadosti WayForPay o spätné volanie.
Časté chyby
- Dôverovať návratovej adrese URL. Zákazník si ho môže otvoriť bez platenia.
- Opätovné použitie referencie objednávky. Každý pokus potrebuje jedinečnú referenciu, v opačnom prípade budete pokusy zamieňať.
- Zmena sumy po podpise alebo zobrazenie jednej ceny a podpísanie inej.
- Neodpovedanie na spätné volanie s podpísanou odpoveďou na prijatie.
- Označte ako zaplatené pred kontrolou sumy a meny.
- Niekoľko mien, jedno zdieľané tajomstvo a žiadne mapovanie: ponechajte menu v objednávke a overte si ju spätným volaním.
Ako môžeme pomôcť
Vytvárame platobné integrácie od začiatku do konca: WayForPay, Stripe, PayPal, opakovaná fakturácia, refundácie a správy o vyrovnaní. Ak už máte funkčnú pokladňu, ale nie ste si istí spôsobmi jej zlyhania, rezervujte si analýzu architektúry a my skontrolujeme spracovanie spätných volaní, idempotenciu a protokolovanie. Podobnú príručku pre iného poskytovateľa nájdete v časti Stripe webhooky v PHP a celkový prístup nájdete v našej príručke pre integráciu pri spustení.
Časté otázky
Aký podpis používa WayForPay ?
HMAC_MD5 cez vybrané polia spojené bodkočiarkou pomocou tajného kľúča obchodníka. Poradie polí je pevné a líši sa pre platobný formulár, spätné volanie a spätné volanie.
Čo musí vrátiť koncový bod serviceUrl?
Odpoveď JSON s príkazom orderReference, stavom „accept“, aktuálnym časom Unixu a podpisom vypočítaným ako HMAC_MD5 z „orderReference;accept;time“. Bez toho WayForPay zopakuje spätné volanie.
Môžem dôverovať stránke returnUrl, že označí objednávku ako zaplatenú?
Nie. Prehliadač zákazníka môže túto adresu URL otvoriť bez platenia. Označte objednávky ako zaplatené až po overenom spätnom volaní serviceUrl alebo odpovedi CHECK_STATUS so stavom Schválené a zodpovedajúcou sumou a menou.
Ako skontrolujem stav objednávky WayForPay ?
Odošlite podpísanú požiadavku CHECK_STATUS do API WayForPay s vaším účtom obchodníka a referenciou objednávky. Použite ho na návratovej stránke a v úlohe cron, ktorá prekontroluje neuzavreté objednávky.
Prečo WayForPay hovorí, že podpis je neplatný?
Zvyčajne sa formát sumy medzi podpisom a formulárom líši (50 vs 50,00), názov produktu bol po podpise zmenený, poradie polí je nesprávne alebo je použitý nesprávny tajný kľúč.
Bezplatný objavovací hovor
Prineste chaotický stack alebo zaseknutú integráciu - Integrono namapuje najmúdrejší prvý krok.
Dostanete seniorský pohľad na rozpočtové pasce, závislosti a na to, či kúpiť, zlepiť alebo postaviť - kým nezačne platená práca. CEO ostáva v okruhu.