Platební brána pomocí odkazu
Jak generovat odkaz na platbu v e-mailu (bez rizika expirace platby)?
E-shopy často potřebují zákazníkovi poslat odkaz na zaplacení v emailu. Zákazník si ale e-mail může přečíst po delší časové prodlevě. Kdyby e-shop rovnou vytvořil při posílání emailu i platbu v systému Comgate, tak by už platba měla nastavenou expiraci. Mohlo by dojít k situaci, že zákazník e-mail otevře pozdě a platbu nestihne zaplatit. Proto by měl e-shop posílat e-mailem odkaz, který teprve platbu založí, až když na odkaz zákazník klikne.
Typickými příklady zaslání odkazu na úhradu jsou:
- zaslání faktury
- připomenutí nezaplacené objednávky
- ruční vytvoření objednávky operátorem
- obnova zrušené nebo neúspěšné platby
Správné řešení: Generování platby až při kliknutí zákazníka v e-mailu
Místo přímého odkazu na platební bránu se do e-mailu vloží odkaz na skript vašeho e-shopu, například:
<a href="www.eshop.cz/generuj-platbu.php?objednavka=112233&token=we498xvrgh4b9we">Zaplatit objednávku</a>
Tento skript: Pokud e-shop založí platbu okamžitě při odeslání e-mailu:
- Ověří parametry (ID objednávky + kontrolní kód), aby případný útočník nemohl iterovat čísla objednávek.
- Zkontroluje, zda objednávka existuje a není již zaplacena.
- Vytvoří novou platbu přes Comgate API.
- Uloží vazbu mezi objednávkou a vytvořenou platbou.
- Přesměruje zákazníka na platební bránu.
Platba tak vzniká v přesný moment, když zákazník kliká na odkaz v e-mailu.
- V emailu pošlete odkaz na váš endpoint
<?php
// Vytvořte ID objednávky a bezpečný token
$order_id = 112233;
$secure_token = bin2hex(random_bytes(16)); // Minimální token, v reálu delší a uložený v DB
// Sestavení odkazu
$link = "https://eshop.cz/pay?order={$order_id}&token={$secure_token}";
// Odeslání emailu (použijte lepší knihovnu než mail() pro produkci)
mail(
"zakaznik@priklad.cz",
"Platba za objednávku 112233",
"Zaplaťte zde: " . $link,
"From: Obchod <odesilatel@eshop.cz>"
);
- Po příchodu zákazníka na endpoint
https://eshop.cz/pay?order=<id>&token=<secureToken>
<?php
// Získání parametrů z URL
$order_id = intval($_GET['order']) ?? null;
$secure_token = $_GET['token'] ?? null;
// Načtení objednávky z DB
$orderData = $this->db->query("SELECT amount, currency, email, secure_token, status FROM objednavka WHERE id = :order_id AND token = :token", ['order_id' => $order_id, 'token' => $secure_token]);
// např. použití PHP SDK https://github.com/comgate-payments/sdk-php
$comgateSDKclient = Comgate::defaults()
->setMerchant('123456')
->setSecret('foobarbaz')
->createClient();
$payment = new Payment();
$payment
->setPrice(Money::ofInt($orderData['amount']))
->setCurrency($orderData['currency'])
->setEmail($orderData['email'])
->setFullName(...)
...
try {
$createPaymentResponse = $comgateSDKclient->createPayment($payment);
if ($createPaymentResponse->getCode() === RequestCode::OK) {
$this->db->query("INSERT INTO platba_objednavky (objednavka_id, kod_platby, ...) VALUES ...")
// Přesměrování zákazníka na platební bránu
Helpers::redirect($createPaymentResponse->getRedirect()); // header("Location: " . $redirect_url)
} else {
var_dump($createPaymentResponse->getMessage());
}
} catch (ApiException $e) {
var_dump($e->getMessage());
}
Další informace u metody create.
Sekvenční diagram procesu
- E-shop odešle e-mail
- Nezakládá platbu.
- Obsahuje pouze bezpečný odkaz na vlastní skript.
- Zákazník klikne na odkaz
- Ověří se objednávka.
- Vytvoří se platba přes API.
- API vrátí URL platby.
- Expirace platby v tuto chvíli běží
- Zákazník zaplatí
- Objednávka se označí jako zaplacená.
Bezpečnostní opatření
Abyste zabránili situaci, kdy by si útočník chtěl prohlížet všechny vaše objednávky pouze změnou id objednávky v URL, přidejte kontrolní token.
- Nepoužívejte pouze samotné ID objednávky.
- Vždy používejte kontrolní kód, token nebo podepsaný odkaz.
- Token by měl být:
- náhodný,
- dostatečně dlouhý,
- časově neomezený nebo s jasně definovanou platností.
Problém: Platba vytvořená příliš brzy
Pokud e-shop založí platbu okamžitě při odeslání e-mailu:
- platba má omezenou dobu platnosti (např. několik dní),
- zákazník si může e-mail přečíst pozdě,
- platba už může být neplatná,
- doba expirace platby běží okamžitě od jejího vzniku.