Browser Details SDK
A lightweight, zero-dependency JavaScript SDK that collects browser environment data required for S2S payment processing with the EPaySe API.
Lightweight
Under 1KB minified. No bloat — just the browser data fields required by the EPaySe S2S API.
Zero Dependencies
Pure ES5 IIFE — no build tools, no npm install required. Drop a single script tag and you're ready.
Cross-Browser
Works in all modern browsers and IE11+. Collects all 12 browser fields required by the EPaySe S2S API.
Installation
Add the SDK to your checkout page via a script tag:
<!-- Production -->
<script src="https://staging-gateway.epayse.com/js/epayse-browser.js"></script>
<!-- Sandbox (for testing) -->
<script src="https://staging-sandbox-gateway.epayse.com/js/epayse-browser.js"></script>Or copy and self-host the full source if you prefer to serve it from your own infrastructure:
/*!
* EPaySe Browser Details SDK v1.0.0
* Collects browser environment data for the EPaySe S2S Payment API.
* License: MIT
*/
(function(root) {
'use strict';
var VERSION = '1.0.0';
function getBrowserDetails() {
return {
userAgent: navigator.userAgent,
language: navigator.language || navigator.userLanguage || '',
screenWidth: screen.width,
screenHeight: screen.height,
timeZone: new Date().getTimezoneOffset(),
acceptHeader: '',
colorDepth: screen.colorDepth || 24,
windowWidth: window.innerWidth || 0,
windowHeight: window.innerHeight || 0,
timeZoneName: (typeof Intl !== 'undefined' && Intl.DateTimeFormat)
? Intl.DateTimeFormat().resolvedOptions().timeZone
: '',
javaEnabled: false,
javascriptEnabled: true
};
}
function injectHiddenFields(formSelector) {
var form = typeof formSelector === 'string'
? document.querySelector(formSelector)
: formSelector;
if (!form || form.tagName !== 'FORM') {
console.warn('[EPaySe] injectHiddenFields: form not found or invalid');
return null;
}
var details = getBrowserDetails();
var keys = Object.keys(details);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var fieldName = 'browserDetails[' + key + ']';
var existing = form.querySelector('input[name="' + fieldName + '"]');
var input = existing || document.createElement('input');
input.type = 'hidden';
input.name = fieldName;
input.value = details[key] === null ? '' : String(details[key]);
if (!existing) form.appendChild(input);
}
return details;
}
root.EPaySe = root.EPaySe || {};
root.EPaySe.browser = {
version: VERSION,
getBrowserDetails: getBrowserDetails,
injectHiddenFields: injectHiddenFields
};
}(typeof self !== 'undefined' ? self : this));Quick Usage
Call getBrowserDetails() to collect all browser fields at any point after the page loads:
const details = EPaySe.browser.getBrowserDetails();
console.log(details);
// Example output:
// {
// userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...",
// language: "en-US",
// screenWidth: 1920,
// screenHeight: 1080,
// timeZone: -420,
// acceptHeader: "", // ← must be set server-side
// colorDepth: 24,
// windowWidth: 1440,
// windowHeight: 900,
// timeZoneName: "Asia/Bangkok",
// javaEnabled: false,
// javascriptEnabled: true
// }Form Integration
Use injectHiddenFields() to automatically append all browser data as hidden inputs to your payment form before it is submitted. This is the simplest integration path for server-rendered checkout pages.
<!-- Your payment form -->
<form id="payment-form" method="POST" action="/checkout">
<input type="text" name="card_number" placeholder="Card Number" />
<input type="text" name="expiry" placeholder="MM/YY" />
<input type="text" name="cvv" placeholder="CVV" />
<button type="submit">Pay Now</button>
</form>
<script src="https://staging-gateway.epayse.com/js/epayse-browser.js"></script>
<script>
document.getElementById('payment-form').addEventListener('submit', function() {
// Inject all browser fields as hidden inputs before submission
EPaySe.browser.injectHiddenFields('#payment-form');
});
</script>Fetch API Pattern
For single-page applications or JavaScript-driven checkouts, collect the data and include it in your JSON payload:
const details = EPaySe.browser.getBrowserDetails();
fetch('/your-backend/create-payment', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
amount: 10000,
currency: 'USD',
browserDetails: details
})
})
.then(res => res.json())
.then(data => {
if (data.checkout_url) {
window.location.href = data.checkout_url;
}
});Server-Side Integration
Your backend receives the browser details and forwards them to the EPaySe S2S API. The server must set acceptHeader from the customer's HTTP request before forwarding — the SDK always returns an empty string for this field.
<?php
// In your payment controller endpoint
public function createPayment(Request $request): JsonResponse
{
// Merge browser details with server-supplied acceptHeader
$browserDetails = $request->input('browserDetails', []);
$browserDetails['acceptHeader'] = $request->header('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8');
$timestamp = time();
$nonce = bin2hex(random_bytes(16));
$payload = json_encode([
'amount' => $request->input('amount'),
'currency' => $request->input('currency'),
'orderId' => $request->input('order_id'),
'returnUrl' => route('payment.callback'),
'cancelUrl' => route('payment.cancel'),
'browserDetails' => $browserDetails,
]);
$signature = hash_hmac('sha256', $timestamp . $nonce . $payload, config('services.epayse.secret_key'));
$response = Http::withHeaders([
'X-Api-Key-Id' => config('services.epayse.api_key'),
'X-Signature' => $signature,
'X-Timestamp' => $timestamp,
'X-Nonce' => $nonce,
])->withBody($payload, 'application/json')
->post('https://api.epayse.com/api/v1/transaction/s2s');
return response()->json($response->json());
}// Express.js example
const crypto = require('crypto');
app.post('/create-payment', async (req, res) => {
const { amount, currency, browserDetails } = req.body;
// Add server-side Accept header
browserDetails.acceptHeader = req.headers['accept'] || 'text/html,application/xhtml+xml,*/*';
const timestamp = Math.floor(Date.now() / 1000);
const nonce = crypto.randomBytes(16).toString('hex');
const payload = JSON.stringify({
amount,
currency,
orderId: `ORD-${Date.now()}`,
returnUrl: 'https://yoursite.com/payment/callback',
cancelUrl: 'https://yoursite.com/payment/cancel',
browserDetails,
});
const signature = crypto
.createHmac('sha256', process.env.EPAYSE_SECRET_KEY)
.update(timestamp + nonce + payload)
.digest('hex');
const response = await fetch('https://api.epayse.com/api/v1/transaction/s2s', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key-Id': process.env.EPAYSE_API_KEY,
'X-Signature': signature,
'X-Timestamp': timestamp,
'X-Nonce': nonce,
},
body: payload,
});
res.json(await response.json());
});Important: acceptHeader must be set server-side
Accept header to JavaScript. The SDK returns an empty string for acceptHeader — your server must populate it from $request->header('Accept') (PHP) or req.headers['accept'] (Node.js) before forwarding to the EPaySe API. Field Reference
All 12 fields are required by the EPaySe S2S API.
| Field | Type | Source | Description |
|---|---|---|---|
userAgent | string | Browser | Full browser user agent string |
language | string | Browser | Browser language (e.g. en-US) |
screenWidth | number | Browser | Total screen width in pixels |
screenHeight | number | Browser | Total screen height in pixels |
timeZone | number | Browser | UTC offset in minutes (e.g. -420 for UTC+7) |
acceptHeader | string | Server-side | HTTP Accept header — must be set by your server from the customer's request |
colorDepth | number | Browser | Screen color depth in bits (default 24) |
windowWidth | number | Browser | Browser viewport width in pixels |
windowHeight | number | Browser | Browser viewport height in pixels |
timeZoneName | string | Browser | IANA timezone name (e.g. Asia/Bangkok) |
javaEnabled | boolean | Browser | Always false — Java applets are universally disabled |
javascriptEnabled | boolean | Browser | Always true — SDK is running, so JS is enabled |
Related Resources
Learn more about the S2S API, JavaScript SDK, and authentication.
