EPaySe
Coming Soon

JavaScript SDK

The official EPaySe JavaScript SDK is under development. Use the REST API directly with fetch or axios in the meantime.

JavaScript Integration

Native Fetch

Use the built-in Fetch API for server-side calls. No external HTTP libraries required.

Crypto Module

Node.js crypto module handles HMAC-SHA256 signatures and timing-safe comparison natively.

Full Stack

Server-side for API calls and HMAC signing, client-side for checkout redirects.

Create a Transaction (Node.js)

Create a payment transaction using Node.js with the native crypto and fetch APIs:

JavaScript
Create Transaction (Node.js)
const crypto = require('crypto');

const API_KEY = 'your_api_key';
const SECRET_KEY = 'your_secret_key';
const BASE_URL = 'https://api.epayse.com/api/v1';

async function createTransaction(amount, currency, orderId) {
    const timestamp = Math.floor(Date.now() / 1000).toString();
    const nonce = crypto.randomBytes(16).toString('hex');

    const payload = JSON.stringify({
        amount,
        currency,
        orderId,
        description: `Payment for ${orderId}`,
        returnUrl: 'https://yoursite.com/payment/callback',
        cancelUrl: 'https://yoursite.com/payment/cancel',
    });

    // Generate HMAC-SHA256 signature
    const signatureString = timestamp + nonce + payload;
    const signature = crypto
        .createHmac('sha256', SECRET_KEY)
        .update(signatureString)
        .digest('hex');

    const response = await fetch(`${BASE_URL}/transaction/create`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-Api-Key-Id': API_KEY,
            'X-Signature': signature,
            'X-Timestamp': timestamp,
            'X-Nonce': nonce,
        },
        body: payload,
    });

    const data = await response.json();

    if (data.status === 'SUCCESS') {
        return data.data.checkout_url;
    }

    throw new Error(data.message || 'Transaction creation failed');
}

// Usage
const checkoutUrl = await createTransaction(100.00, 'USD', 'ORD-001');
console.log('Redirect to:', checkoutUrl);

Create a Refund

Issue full or partial refunds using the same HMAC authentication pattern:

JavaScript
Create Refund
async function createRefund(transactionId, amount, reason = '') {
    const timestamp = Math.floor(Date.now() / 1000).toString();
    const nonce = crypto.randomBytes(16).toString('hex');

    const payload = JSON.stringify({
        transactionId,
        refundAmount: amount,
        reason,
    });

    const signature = crypto
        .createHmac('sha256', SECRET_KEY)
        .update(timestamp + nonce + payload)
        .digest('hex');

    const response = await fetch(`${BASE_URL}/refund/create`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-Api-Key-Id': API_KEY,
            'X-Signature': signature,
            'X-Timestamp': timestamp,
            'X-Nonce': nonce,
        },
        body: payload,
    });

    return response.json();
}

// Full refund
await createRefund('01kbkzs3pdcdkjvsq2xb2j0ej3', 100.00, 'Customer request');

// Partial refund
await createRefund('01kbkzs3pdcdkjvsq2xb2j0ej3', 25.00, 'Partial refund');

Verify Webhook Signature (Express.js)

Validate incoming webhook signatures using timing-safe comparison to prevent replay attacks:

JavaScript
Express.js Webhook Handler
const crypto = require('crypto');

function verifyWebhookSignature(payload, headers, secretKey) {
    const signature = headers['x-signature'] || '';
    const timestamp = headers['x-timestamp'] || '';
    const nonce = headers['x-nonce'] || '';

    // Reject if timestamp is older than 5 minutes
    const age = Math.abs(Math.floor(Date.now() / 1000) - parseInt(timestamp));
    if (age > 300) {
        return false;
    }

    const expected = crypto
        .createHmac('sha256', secretKey)
        .update(timestamp + nonce + payload)
        .digest('hex');

    return crypto.timingSafeEqual(
        Buffer.from(expected),
        Buffer.from(signature)
    );
}

// Express.js webhook handler
app.post('/webhooks/epayse', express.raw({ type: 'application/json' }), (req, res) => {
    const payload = req.body.toString();

    if (!verifyWebhookSignature(payload, req.headers, SECRET_KEY)) {
        return res.status(401).json({ error: 'Invalid signature' });
    }

    const event = JSON.parse(payload);

    switch (event.event) {
        case 'transaction.success':
            // Handle successful payment
            break;
        case 'refund.completed':
            // Handle completed refund
            break;
    }

    res.json({ received: true });
});

Browser Checkout Flow

On the client side, initiate payment by calling your backend API and redirecting to the EPaySe checkout page:

HTML
Browser Checkout Button
<!-- Include in your checkout page -->
<script>
async function initiatePayment(amount, orderId) {
    try {
        const response = await fetch('/api/create-payment', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ amount, orderId }),
        });

        const { checkoutUrl } = await response.json();

        // Redirect to EPaySe hosted checkout
        window.location.href = checkoutUrl;
    } catch (error) {
        console.error('Payment failed:', error);
        alert('Unable to process payment. Please try again.');
    }
}
</script>

<button onclick="initiatePayment(99.99, 'ORD-001')">
    Pay $99.99
</button>

Security Note: Never expose your API secret key in browser-side code. All HMAC signing must happen on your server. The browser should only call your own backend API endpoint.

Related Resources

Explore the full API documentation for detailed endpoint specifications.