Skip to main content

Payment Gateway via Link

E-shops often need to send customers a payment link via email. However, customers may read the email after a longer delay. If the e-shop creates the payment in the Comgate system at the moment the email is sent, the payment expiration would already be running. This could result in a situation where the customer opens the email too late and is no longer able to complete the payment. Therefore, the e-shop should send an email containing a link that creates the payment only when the customer clicks it.

Typical examples of sending a payment link include:

  • sending an invoice
  • reminding the customer about an unpaid order
  • manual order creation by an operator
  • restoring a cancelled or unsuccessful payment

Instead of a direct link to the payment gateway, the email should contain a link to your e-shop script, for example:

<a href="www.eshop.cz/generuj-platbu.php?objednavka=112233&token=we498xvrgh4b9we">Pay for the order</a>

This script:

If the e-shop creates the payment immediately when sending the email:

  1. Verifies the parameters (order ID + verification code) so a potential attacker cannot iterate through order numbers.
  2. Checks that the order exists and hasn’t already been paid.
  3. Creates a new payment via the Comgate API.
  4. Stores the link between the order and the created payment.
  5. Redirects the customer to the payment gateway.

The payment is therefore created at the exact moment when the customer clicks the link in the email.

  1. Send a link to your endpoint in the email.
<?php
// Create an order ID and a secure token
$order_id = 112233;
$secure_token = bin2hex(random_bytes(16)); // Minimum token, in practice longer and stored in the DB

// Build the link
$link = "https://eshop.cz/pay?order={$order_id}&token={$secure_token}";

// Send the email (use a better library than mail() in production)
mail(
"customer@example.com",
"Payment for order 112233",
"Pay here: " . $link,
"From: Store <sender@eshop.cz>"
);
  1. When the customer arrives at the endpoint https://eshop.cz/pay?order=<id>&token=<secureToken>
<?php

// Get parameters from the URL
$order_id = intval($_GET['order']) ?? null;
$secure_token = $_GET['token'] ?? null;

// Load the order from the 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]
);

// e.g. using the 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 ...");

// Redirect the customer to the payment gateway
Helpers::redirect($createPaymentResponse->getRedirect()); // header("Location: " . $redirect_url)

} else {
var_dump($createPaymentResponse->getMessage());
}
} catch (ApiException $e) {
var_dump($e->getMessage());
}

Further information about the method create.

Sequence diagram of the process

Sequence diagram
  1. The e-shop sends an email
  • It does not create a payment.
  • It contains only a secure link to the e-shop’s own script.
  1. The customer clicks the link
  • The order is verified.
  • A payment is created via the API.
  • The API returns the payment URL.
  1. The payment expiration starts at this moment

  2. The customer pays

  • The order is marked as paid.

Security Measures

To prevent a situation where an attacker could browse all your orders simply by changing the order ID in the URL, add a verification token.

  • Do not use only the order ID.
  • Always use a verification code, token, or a signed link.
  • The token should be:
    • random,
    • sufficiently long,
    • time-unlimited or have a clearly defined validity period.

Problem: Payment Created Too Early

Sequence diagram

If the e-shop creates the payment immediately when sending the email:

  • the payment has a limited validity period (e.g. several days),
  • the customer may read the email later,
  • the payment may already be invalid,
  • the payment expiration period starts running immediately from the moment it is created.