SecureNexPay Developer Documentation

Secure payment integration for custom websites, apps, and WooCommerce stores.

Overview

SecureNexPay lets merchants create secure payment links, redirect customers to checkout, receive signed payment webhooks, and mark orders as paid safely.

Create PaymentSecure CheckoutAllowed DomainHMAC SignatureTimestampNonce Replay ProtectionWebhook VerificationWebhook RetryWooCommerce Ready

Quick Start

1. Get Public Key and Secret Key from SecureNexPay Merchant Panel
2. Create payment from your backend/server
3. Generate HMAC signature using Secret Key
4. Redirect customer to checkout_url
5. Receive signed webhook
6. Verify webhook signature
7. Mark order as paid
Never call Create Payment API directly from frontend JavaScript. Always call it from your backend/server because Secret Key must stay private.

Base URL

https://merchant.securenexpay.com

Minimum Files Required for Custom PHP Website

FileRequiredPurpose
config.phpYesStore Public Key, Secret Key, API URLs. This file must not be public.
create-payment.phpYesCreate payment request, sign request, call SecureNexPay API, redirect customer.
webhook.phpYesReceive payment notification, verify signature, update order status.
success.phpOptionalShow customer a success/thank-you page after payment.
cancel.phpOptionalShow customer a failed/cancelled payment page.

Merchant Credentials

Public Key
Used to identify the merchant.
Secret Key
Used to generate request signature and verify webhook signature.
Allowed Domain
Only approved merchant domain can create payment.
Provider Brand Key
Optional admin-assigned brand key for merchant-specific branded checkout.
Important: Never expose your Secret Key in frontend JavaScript, public mobile app code, browser console, GitHub, or client-side HTML.

Payment Flow

Customer clicks Pay Now
   ↓
Merchant backend creates signed request
   ↓
POST https://merchant.securenexpay.com/api/create-payment.php
   ↓
SecureNexPay validates:
Public Key + Merchant Status + HMAC Signature + Timestamp + Nonce + Allowed Domain
   ↓
Payment Link Created
   ↓
Customer redirects to checkout_url
   ↓
Customer completes payment
   ↓
SecureNexPay sends signed webhook to merchant webhook_url
   ↓
Merchant verifies webhook signature
   ↓
Order marked as paid

Create Payment API

Endpoint

POST https://merchant.securenexpay.com/api/create-payment.php

Required Headers

HeaderRequiredDescription
Content-TypeYesUse application/json.
AcceptRecommendedUse application/json.
X-SecureNexPay-TimestampYesCurrent Unix timestamp. Request must be fresh.
X-SecureNexPay-NonceYesRandom unique string for every request. Prevents replay attack.
X-SecureNexPay-SignatureYesHMAC SHA256 signature generated using Secret Key.

Request Body

{
  "public_key": "pk_live_xxxxxxxxxxxxxxxxx",
  "order_id": "ORDER1001",
  "amount": "190.00",
  "customer_name": "John Doe",
  "customer_email": "john@example.com",
  "customer_phone": "01700000000",
  "success_url": "https://yourdomain.com/payment-success",
  "cancel_url": "https://yourdomain.com/payment-cancel",
  "webhook_url": "https://yourdomain.com/api/securenexpay-webhook"
}

Signature Formula

signature = HMAC_SHA256(raw_json_body + timestamp + nonce, secret_key)
Important: Generate the signature using the exact raw JSON body that you send to the API. Do not change body data after generating the signature.

Required Fields

FieldRequiredDescription
public_keyYesMerchant public key.
order_idYesYour website/app order ID.
amountYesPayment amount. Example: 190.00
customer_nameNoCustomer name.
customer_emailNoCustomer email.
customer_phoneNoCustomer phone number.
success_urlYes if allowed domain is setCustomer redirect URL after success. Domain must match allowed domain.
cancel_urlYes if allowed domain is setCustomer redirect URL after cancel/fail. Domain must match allowed domain.
webhook_urlYes if allowed domain is setServer webhook endpoint. Domain must match allowed domain.

Custom PHP Integration Example

1. config.php

<?php

define('SNP_PUBLIC_KEY', 'pk_live_xxxxxxxxxxxxxxxxx');
define('SNP_SECRET_KEY', 'sk_live_xxxxxxxxxxxxxxxxx');
define('SNP_CREATE_URL', 'https://merchant.securenexpay.com/api/create-payment.php');

2. create-payment.php

<?php
require_once __DIR__ . '/config.php';

$orderId = 'ORDER1001';
$amount = '190.00';

$payload = [
    'public_key' => SNP_PUBLIC_KEY,
    'order_id' => $orderId,
    'amount' => $amount,
    'customer_name' => 'John Doe',
    'customer_email' => 'john@example.com',
    'customer_phone' => '01700000000',
    'success_url' => 'https://yourdomain.com/success.php?order_id=' . urlencode($orderId),
    'cancel_url' => 'https://yourdomain.com/cancel.php?order_id=' . urlencode($orderId),
    'webhook_url' => 'https://yourdomain.com/webhook.php'
];

$rawBody = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$timestamp = time();
$nonce = bin2hex(random_bytes(16));
$signature = hash_hmac('sha256', $rawBody . $timestamp . $nonce, SNP_SECRET_KEY);

$ch = curl_init(SNP_CREATE_URL);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $rawBody,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Accept: application/json',
        'X-SecureNexPay-Timestamp: ' . $timestamp,
        'X-SecureNexPay-Nonce: ' . $nonce,
        'X-SecureNexPay-Signature: ' . $signature
    ],
    CURLOPT_TIMEOUT => 30
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$result = json_decode($response, true);
if ($httpCode >= 200 && $httpCode < 300 && !empty($result['checkout_url'])) {
    header('Location: ' . $result['checkout_url']);
    exit;
}

echo 'Payment creation failed.';
echo '<pre>' . htmlspecialchars($response) . '</pre>';

3. webhook.php

<?php
require_once __DIR__ . '/config.php';
header('Content-Type: application/json');

$rawPayload = file_get_contents('php://input');
$receivedSignature = $_SERVER['HTTP_X_SECURENEXPAY_SIGNATURE'] ?? '';
$expectedSignature = hash_hmac('sha256', $rawPayload, SNP_SECRET_KEY);

if (!$receivedSignature || !hash_equals($expectedSignature, $receivedSignature)) {
    http_response_code(401);
    echo json_encode(['success' => false, 'message' => 'Invalid webhook signature.']);
    exit;
}

$data = json_decode($rawPayload, true);
if (!is_array($data)) {
    http_response_code(400);
    echo json_encode(['success' => false, 'message' => 'Invalid JSON payload.']);
    exit;
}

if (($data['status'] ?? '') === 'COMPLETED') {
    $orderId = $data['order_id'];
    $paymentUid = $data['payment_uid'];
    $transactionId = $data['transaction_id'];
    $amount = $data['amount'];

    // TODO:
    // 1. Find order by $orderId
    // 2. Verify amount matches your order amount
    // 3. Store $paymentUid and $transactionId
    // 4. Mark order as paid/completed
}

http_response_code(200);
echo json_encode(['success' => true, 'message' => 'Webhook processed.']);

4. success.php

<?php
echo 'Payment successful. Your order is being processed.';

5. cancel.php

<?php
echo 'Payment cancelled or failed. Please try again.';

Create Payment Success Response

{
  "success": true,
  "message": "Payment created successfully.",
  "payment_uid": "PAY20260614123456xxxx",
  "provider_payment_uid": null,
  "order_id": "ORDER1001",
  "amount": "190.00",
  "checkout_url": "https://merchant.securenexpay.com/checkout/pay.php?payment_uid=PAY...",
  "provider_checkout_url": "https://secure.securenexpay.com/api/execute/xxxx"
}
Redirect customer to checkout_url. SecureNexPay will handle provider checkout and payment completion.

Create Payment Error Responses

Missing Signature

{
  "success": false,
  "message": "Missing request signature."
}

Invalid Signature

{
  "success": false,
  "message": "Invalid request signature."
}

Unauthorized Domain

{
  "success": false,
  "message": "Unauthorized domain.",
  "allowed_domain": "shop.example.com",
  "request_domain": "otherdomain.com",
  "field": "webhook_url"
}

Provider Brand/API Key Error

{
  "success": false,
  "message": "Provider payment creation failed.",
  "provider_response": {
    "status": 0,
    "message": "Invalid API Request."
  }
}

Allowed Domain Rule

If a merchant has an allowed domain, then success_url, cancel_url, and webhook_url must use the same domain.

Allowed domain: shop.example.com

Allowed:
https://shop.example.com/payment-success
https://shop.example.com/checkout/cancel
https://shop.example.com/api/webhook

Not allowed:
https://example.com/payment-success
https://sub.shop.example.com/payment-success
https://otherdomain.com/payment-success
Important: Domain matching is exact. If allowed domain is shop.example.com, only shop.example.com works. Main domain and other subdomains do not work unless configured separately.

Payment Status API

Endpoint

GET https://merchant.securenexpay.com/api/payment-status.php?public_key=pk_live_xxxxx&payment_uid=PAY20260614123456xxxx

Required Query Parameters

Parameter Required Description
public_key Yes Merchant public key.
payment_uid Yes SecureNexPay payment UID.

Example

https://merchant.securenexpay.com/api/payment-status.php?public_key=pk_live_xxxxx&payment_uid=PAY20260614123456xxxx

Success Response

{
  "success": true,
  "payment_uid": "PAY20260614123456xxxx",
  "order_id": "ORDER1001",
  "amount": "190.00",
  "net_amount": "190.00",
  "payment_method": "bkash",
  "transaction_id": "ABC123456",
  "status": "COMPLETED",
  "created_at": "2026-06-14 12:20:00",
  "paid_at": "2026-06-14 12:30:00"
}

Error Response

{
  "success": false,
  "message": "Public key is required."
}
Payment Status API is useful for backend checking, but final order completion should depend on signed webhook.

Webhook

When payment is completed, SecureNexPay sends a POST request to the merchant webhook URL.

Webhook Payload

{
  "payment_uid": "PAY20260614123456xxxx",
  "order_id": "ORDER1001",
  "amount": "190.00",
  "net_amount": "190.00",
  "status": "COMPLETED",
  "payment_method": "bkash",
  "transaction_id": "ABC123456",
  "paid_at": "2026-06-14 12:30:00"
}

Webhook Header

X-SecureNexPay-Signature: generated_hmac_signature

Webhook Signature Formula

webhook_signature = HMAC_SHA256(raw_webhook_body, secret_key)

Webhook Response Requirement

Your webhook endpoint must return HTTP 200-299 after successful processing.

Success Response

{
  "success": true,
  "message": "Webhook processed."
}

Invalid Signature Response

{
  "success": false,
  "message": "Invalid webhook signature."
}
If your endpoint returns 401, 403, 404, 500, timeout, or any non-2xx response, SecureNexPay will retry the webhook.

Webhook Retry System

If merchant webhook fails, SecureNexPay retries delivery automatically.

Retry Interval
Every 5 minutes
Maximum Attempts
5 attempts
Success Condition
HTTP 200-299 response
Failure Example
401, 403, 404, 500, timeout

Payment Status Values

StatusMeaning
PENDINGPayment created but not paid yet.
COMPLETEDPayment successfully completed.
FAILEDPayment failed.
CANCELLEDCustomer cancelled payment.

WooCommerce Integration

For WooCommerce stores, install the official SecureNexPay WooCommerce Gateway plugin and configure:

Public Key
Secret Key
Create Payment API URL
Payment Status API URL

The plugin automatically generates:

Webhook URL
Return URL
Cancel URL
Request Signature
Timestamp
Nonce
WooCommerce order should be completed only after signed webhook verification.

Integration Diagram

Customer
   ↓
Merchant Website
   ↓
create-payment.php
   ↓
SecureNexPay Create Payment API
   ↓
checkout_url
   ↓
Customer Payment Page
   ↓
Payment Completed
   ↓
Signed Webhook
   ↓
Merchant webhook.php
   ↓
Verify Signature + Update Order
   ↓
Order Completed

Security Checklist

Testing Guide

Valid Test

Correct Public Key
Correct Secret Signature
Correct Timestamp
Unique Nonce
Correct Allowed Domain
Expected: Payment created successfully

Missing Signature Test

Remove X-SecureNexPay-Signature header
Expected: 401 Missing request signature

Wrong Signature Test

X-SecureNexPay-Signature: wrong123
Expected: 401 Invalid request signature

Wrong Domain Test

Allowed domain: shop.example.com
webhook_url: https://otherdomain.com/webhook
Expected: 403 Unauthorized domain

Replay Attack Test

Send same timestamp + nonce + signature twice
Expected:
First request may pass
Second request should fail

Production Notes

Support

Email: support@securenexpay.com

Merchant Panel: merchant.securenexpay.com