Přeskočit na hlavní obsah

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:

  1. Ověří parametry (ID objednávky + kontrolní kód), aby případný útočník nemohl iterovat čísla objednávek.
  2. Zkontroluje, zda objednávka existuje a není již zaplacena.
  3. Vytvoří novou platbu přes Comgate API.
  4. Uloží vazbu mezi objednávkou a vytvořenou platbou.
  5. 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.

  1. 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>"
);
  1. 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

Sekvenční diagram
  1. E-shop odešle e-mail
  • Nezakládá platbu.
  • Obsahuje pouze bezpečný odkaz na vlastní skript.
  1. Zákazník klikne na odkaz
  • Ověří se objednávka.
  • Vytvoří se platba přes API.
  • API vrátí URL platby.
  1. Expirace platby v tuto chvíli běží
  2. 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

Sekvenční diagram

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.