EPaySe
Guide

Accept Payments

Learn how to integrate EPaySe payment processing into your application using the Redirect, Iframe, or Server-to-Server (S2S) integration methods.

Integration Methods

Redirect

Redirect customers to EPaySe's hosted checkout page. Simplest integration with no PCI scope.

Iframe

Embed the checkout form within your page using an iframe. Customers never leave your site.

Server-to-Server

Full control over the checkout UX. Requires PCI DSS SAQ D compliance for handling card data.

Payment Flow

1

Create Transaction

Your backend calls POST /api/v1/transaction/create with order details

2

Customer Checkout

Redirect to checkoutUrl or embed the iframe

3

Payment Processing

EPaySe processes payment through the selected PSP with fraud checks

4

Result Notification

Customer redirected to your redirectUrl + webhook sent asynchronously

1. Redirect Integration

The simplest way to accept payments. Create a transaction via API, then redirect your customer to the EPaySe hosted checkout page.

API Request

Bash
Create Transaction (cURL)
curl -X POST https://staging-gateway.epayse.com/api/v1/transaction/create \
  -H "Content-Type: application/json" \
  -H "X-Api-Key-Id: your_api_key" \
  -H "X-Signature: generated_hmac_signature" \
  -H "X-Timestamp: 1700000000" \
  -H "X-Nonce: unique_nonce_value" \
  -H "X-Signature-Version: 3" \
  -d '{
    "ref": "ORDER-2024-001",
    "amount": 1000,
    "currency": "USD",
    "websiteUrl": "https://yoursite.com",
    "redirectUrl": "https://yoursite.com/payment/success",
    "cancelUrl": "https://yoursite.com/payment/cancel",
    "description": "Payment for Order #001",
    "customerDetails": {
      "firstName": "John",
      "lastName": "Doe",
      "email": "[email protected]",
      "country": "US",
      "ip": "203.0.113.50",
      "phoneCode": "US",
      "phoneNumber": "5551234567"
    }
  }'

Response

JSON
Success Response (200)
{
  "status": "SUCCESS",
  "message": "Transaction created successfully",
  "data": {
    "transactionId": "01kd096yg112e40pcyfwsahyev",
    "checkoutUrl": "/checkout/01kd096yg112e40pcyfwsahyev?expires=1766325765&signature=c0108b47..."
  }
}

PHP Integration Example

PHP
Create Payment (PHP)
<?php

$apiKey = 'your_api_key';
$secretKey = 'your_secret_key';

$timestamp = time();
$nonce = bin2hex(random_bytes(16));

$payload = json_encode([
    'ref' => 'ORDER-' . uniqid(),
    'amount' => 10.00,           // Amount in dollars (major units)
    'currency' => 'USD',
    'websiteUrl' => 'https://yoursite.com',
    'redirectUrl' => 'https://yoursite.com/payment/success',
    'cancelUrl' => 'https://yoursite.com/payment/cancel',
    'description' => 'Payment for Order #1234',
    'customerDetails' => [
        'firstName' => 'John',
        'lastName' => 'Doe',
        'email' => '[email protected]',
        'country' => 'US',
        'ip' => $_SERVER['REMOTE_ADDR'],  // Always use real customer IP
        'phoneCode' => 'US',
        'phoneNumber' => '5551234567',
    ],
]);

// Generate the HMAC-SHA256 signature (version 3): METHOD|PATH|TIMESTAMP|NONCE|BODY
$path = 'api/v1/transaction/create';   // no leading slash
$signatureString = implode('|', ['POST', $path, $timestamp, $nonce, $payload]);
$signature = hash_hmac('sha256', $signatureString, $secretKey);

$ch = curl_init('https://staging-gateway.epayse.com/api/v1/transaction/create');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $payload,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'X-Api-Key-Id: ' . $apiKey,
        'X-Signature: ' . $signature,
        'X-Timestamp: ' . $timestamp,
        'X-Nonce: ' . $nonce,
        'X-Signature-Version: 3',
    ],
    CURLOPT_RETURNTRANSFER => true,
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);

if ($response['status'] === 'SUCCESS') {
    // Redirect customer to EPaySe checkout
    header('Location: ' . $response['data']['checkoutUrl']);
    exit;
}

// Handle error
echo 'Error: ' . ($response['message'] ?? 'Unknown error');

Amount Format: The amount field is in dollars (major units) with up to two decimal places, for both the standard and S2S APIs. For example, 10.00 = $10.00 USD.

2. Required Parameters

Every transaction requires the following fields:

ParameterTypeDescription
refstring Unique merchant reference (max 250 chars). Acts as idempotency key.
amountnumber Amount in dollars, up to 2 decimals (min: 1.00, max: 1500.00)
currencystring ISO 4217 currency code (e.g., USD)
websiteUrlstringYour website URL (must be registered)
redirectUrlstringURL to redirect customer after payment
cancelUrlstringURL to redirect customer if they cancel
descriptionstringPayment description shown to customer
customerDetailsobject Customer information (firstName, lastName, email, country, ip, phoneCode, phoneNumber)

3. Iframe Integration

Embed the EPaySe checkout directly within your page. Customers complete payment without leaving your site.

Iframe Response

Use the create-with-iframe endpoint to get embeddable URLs:

JSON
Iframe Response (200)
{
  "status": "SUCCESS",
  "message": "Transaction created successfully",
  "data": {
    "transactionId": "01kd096yg112e40pcyfwsahyev",
    "checkoutUrl": "/checkout/01kd096yg112e40pcyfwsahyev?expires=...",
    "iframe": {
      "fullCheckoutUrl": "https://gateway.epayse.com/checkout/01kd...?expires=...&signature=...",
      "paymentMethods": [
        {
          "key": "credit_card",
          "name": "Credit/Debit Card",
          "url": "https://gateway.epayse.com/checkout-field/...",
          "embedCode": "<iframe src=\"...\" />"
        }
      ],
      "expiresAt": "2024-01-15T15:00:00+00:00",
      "configuration": { "width": "100%", "height": "900px" },
      "postMessageEvents": [
        "epayse:payment:success",
        "epayse:payment:failed",
        "epayse:payment:cancel",
        "epayse:height:change"
      ]
    }
  }
}

Listen for Iframe Events

Handle payment events from the embedded iframe using postMessage:

JavaScript
Iframe PostMessage Events
// Listen for EPaySe iframe events
window.addEventListener('message', function(event) {
  // IMPORTANT: Verify origin for security
  const ALLOWED_ORIGINS = [
    'https://gateway.epayse.com',    // Production
    'https://sandbox-gateway.epayse.com'  // Sandbox
  ];

  if (!ALLOWED_ORIGINS.includes(event.origin)) {
    return; // Ignore untrusted origins
  }

  const { type, data } = event.data;

  switch(type) {
    case 'epayse:payment:success':
      console.log('Payment successful:', data.transactionId);
      // Verify payment via webhook or API before fulfilling order
      break;

    case 'epayse:payment:failed':
      console.error('Payment failed:', data.message);
      // Show error message to customer
      break;

    case 'epayse:payment:cancel':
      console.log('Payment cancelled:', data.transactionId);
      // Redirect to cart or retry
      break;

    case 'epayse:height:change':
      // Dynamically resize iframe
      document.getElementById('epayse-checkout')
        .style.height = data.height + 'px';
      break;
  }
});

Security: Always verify the event.origin before processing iframe messages. Only trust messages from gateway.epayse.com (production) or sandbox-gateway.epayse.com (testing).

4. Payment Status Lifecycle

A transaction progresses through the following statuses:

StatusDescription
INCOMPLETE
Transaction created, awaiting customer action
PENDING
Payment submitted, processing at PSP
AUTHENTICATING
3D Secure authentication in progress
SUCCESS
Payment completed successfully
FAIL
Payment failed (max retries reached)
CANCEL
Customer cancelled the payment
EXPIRE
Checkout session expired

5. Redirect URL Parameters

After payment, the customer is redirected to your redirectUrl with query parameters:

JavaScript
Redirect URL Parameters
// Redirect back to your site after payment (redirectUrl when paid, cancelUrl otherwise):
// https://yoursite.com/payment/success?
//   base64_encode_data=<base64 JSON: status, ref, message, transactionId, amount,
//                        paidAmount, currency, paymentMethod>
//   &timestamp=<unix seconds>
//   &signature=<hex HMAC-SHA256(secretKey, timestamp + base64_encode_data)>

// 1. Verify signature + timestamp (max 600 s old) with your API secret key
// 2. Only then decode base64_encode_data
// 3. IMPORTANT: still confirm via webhook or API call before fulfilling the order.
//    See "Transaction API > Redirect URL" for verifier code in PHP and Node.js

6. Verify Payment via Webhook

Always verify payment results using webhooks rather than relying on redirect parameters. Webhooks are sent asynchronously after the payment is processed.

PHP
Webhook Handler (PHP)
<?php

// Receive and verify a webhook notification (endpoint configured in Settings → Webhooks)
$payload   = file_get_contents('php://input');          // the raw body, exactly as received
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$timestamp = $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? '';
$secret    = getenv('EPAYSE_WEBHOOK_SECRET');           // the whsec_... secret of this endpoint

// Verify timestamp (reject if older than 5 minutes)
if (abs(time() - (int) $timestamp) > 300) {
    http_response_code(401);
    exit('Timestamp expired');
}

// Verify HMAC signature: timestamp immediately followed by the raw body (no separator)
$expected = hash_hmac('sha256', $timestamp . $payload, $secret);
if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    exit('Invalid signature');
}

$event = json_decode($payload, true);

switch ($event['type']) {
    case 'payment.paid':
        // Payment confirmed - fulfill the order
        $transaction = $event['data']['object'];
        updateOrderStatus($transaction['ref'], 'paid');
        break;

    case 'payment_attempt.failed':
        // A payment attempt failed (the customer may retry)
        $transaction = $event['data']['object'];
        updateOrderStatus($transaction['ref'], 'failed');
        break;
}

// Always return 200 to acknowledge receipt
http_response_code(200);
echo json_encode(['received' => true]);

7. Testing

Use sandbox test cards to test your integration:

Card NumberResultUse Case
4111 1111 1111 1111
Success
Successful payment
4000 0000 0000 0002
Decline
Card declined
4000 0000 0000 0119
3DS
3D Secure required

Use any future expiry date and any 3-digit CVV for testing.

8. Common Mistakes

DON'T

Use your server IP instead of the customer's real IP address

DON'T

Trust redirect URL parameters as proof of payment

DON'T

Send amount in cents (e.g. 1000) — always use dollars with up to 2 decimals (10.00)

DO

Always verify payment via webhooks before fulfilling orders

DO

Use unique ref values for each transaction (idempotency key)

DO

Verify iframe event.origin before processing PostMessage events

Next Steps

Explore related documentation to complete your integration.