JavaScript SDK
Introduction
The JavaScript SDK provides an easy way to integrate EasyProcess + IDEM payment processing directly into your web application. With just a few lines of code, you can create secure payment forms that handle card processing, 3D Secure authentication, and real-time status updates.
Payment requests, refunds and webhooks are described in the API documentation.
Prerequisites
Contact your sales representative to enable the SDK for your account.
Configuration
Step 1: Enable SDK in Settings
Go to your merchant settings and configure the SDK:
- Secret key (
sk_…): generated by the platform, shown masked in your settings. It stays on your server and is the only key that can create a payment session. Never put it in a page. - Publishable key (
pk_…): generated by the platform, shown in your settings. It goes in your page and can only submit a card on a session your server created. - Allowed Origins: the exact origins of the pages that host the form, scheme and host, port if any (e.g.,
https://yoursite.com,https://www.yoursite.com). Mandatory: without it every card submission is refused (origin_not_configured).
Both keys are generated together by your account manager; ask them to regenerate the pair if the secret key ever reaches a page or a repository. Make sure to note your Merchant ID (an 8-digit number), as you will need it in the server call and in the page.
Quick Start
Step 1: Create the payment session on your server
Your server opens the payment session with your secret key. The amount, the currency, your order reference and the customer are set here, once, and the browser cannot change them. The response carries a session_id that you hand to your page.
Please take a look at the example, on the right or below if you're on mobile.
Create the payment session (server side, with the secret key)
curl -X POST https://gateway.idem-club.com/api/sdk/payment/session \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"merchant_id": "12345678",
"amount": 49.99,
"currency": "USD",
"order_ref": "1234",
"customer": {
"email": "[email protected]",
"firstname": "John",
"lastname": "Doe",
"address": "1 Main Street",
"city": "New York",
"state": "NY",
"zipcode": "10001",
"country": "US",
"phone": "+13055550123"
}
}'
<?php
// Same call from PHP. $secretKey comes from your configuration, never from a page.
$ch = curl_init('https://gateway.idem-club.com/api/sdk/payment/session');
curl_setopt_array($ch, array(
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array(
'Authorization: Bearer ' . $secretKey,
'Content-Type: application/json'
),
CURLOPT_POSTFIELDS => json_encode(array(
'merchant_id' => '12345678',
'amount' => 49.99,
'currency' => 'USD',
'order_ref' => '1234',
'customer' => array(
'email' => '[email protected]', 'firstname' => 'John', 'lastname' => 'Doe',
'address' => '1 Main Street', 'city' => 'New York', 'state' => 'NY',
'zipcode' => '10001', 'country' => 'US', 'phone' => '+13055550123'
)
))
));
$session = json_decode(curl_exec($ch), true);
curl_close($ch);
if (empty($session['success'])) {
// $session['code'] and $session['message'] say why (see Error Codes): stop here
throw new RuntimeException('Payment session refused: ' . (isset($session['code']) ? $session['code'] : 'no response'));
}
$sessionId = $session['session_id']; // hand it to your page (Step 3)
The response: {"success": true, "session_id": "…", "expires_at": "…", "status": "active", "attempts": 0, "reused": false}. The session lives 30 minutes and is tied to order_ref (25 characters maximum): calling again for the same order returns the same session ("reused": true) with its current status; the same order with another amount or currency is refused (order_ref_conflict). The customer fields are the ones of the card payment. Email, first name, last name, city and country are mandatory, and the state is mandatory for a US customer. A session without them is refused at payment time (invalid_customer). Send the address and the zip code too: the platform does not test them, but they go to the anti-fraud checks. An IDEM Club merchant also needs a mobile number, for a customer that IDEM Club does not know yet. A customer sent from the page is ignored.
All the dates that the platform sends you are in the Eastern time of the United States (America/New_York), and expires_at is one of them. This zone is EST in winter and EDT in summer, and the dates carry no timezone suffix. Read them with that zone, never with a fixed offset: a fixed offset is wrong for half of the year.
The session_id is a secret. Whoever holds it, together with your publishable key, can submit a card on that session and read its outcome. Do not log it, do not put it in a URL, do not show it to your support staff. Pass it to your page in the HTML you render, or through your own authenticated endpoint.
Step 2: Basic HTML Setup
Please take a look at the HTML example, on the right or below if you're on mobile.
Basic HTML Setup for the SDK
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Payment Page</title>
<!-- SDK Files (use the correct domain for your environment) -->
<!-- Prod: https://gateway.idem-club.com | Sandbox: https://gateway.idem-club.info -->
<script src="https://gateway.idem-club.com/sdk/v1/sdk.min.js"></script>
<!-- Minimal styling for the SDK -->
<link rel="stylesheet" href="https://gateway.idem-club.com/sdk/v1/sdk.min.css">
<!-- Optional: Your custom styles -->
<style>
#payment-container {
max-width: 400px;
margin: 50px auto;
padding: 20px;
border: 1px solid #ddd;
border-radius: 8px;
}
</style>
</head>
<body>
<div id="payment-container">
<h2>Complete Payment</h2>
<div id="payment-form"></div>
</div>
<script>
// Your JavaScript goes here (see next section)
</script>
</body>
</html>
JavaScript Implementation
Please take a look at the JavaScript example, on the right or below if you're on mobile.
JavaScript SDK Implementation
// Initialize the SDK with the PUBLISHABLE key (environment is inferred from the domain serving the SDK)
var sdk = PaymentSDK.init({
merchantId: '12345678', // Replace with your merchant ID
publishableKey: 'pk_YOUR_PUBLISHABLE_KEY' // The pk_ key. Never the sk_ key.
});
// Create the payment form on the session your server created in Step 1
var paymentForm = sdk.createPaymentForm({
container: '#payment-form',
sessionId: 'SESSION_ID_FROM_YOUR_SERVER', // the session_id of Step 1
// Success handler
onSuccess: function(result) {
console.log('Payment successful, transaction', result.transaction_id);
alert('Payment completed! Transaction ID: ' + result.transaction_id);
// Redirect to success page
window.location.href = '/payment-success';
},
// Error handler
onError: function(error) {
console.error('Payment failed:', error.code, error.message);
alert('Payment failed: ' + error.message);
},
// Pending handler (for async processors)
onPending: function(context) {
console.log('Processing payment...');
// SDK automatically handles status updates via SSE
// The form will update when payment completes
}
});
When the customer clicks Pay, the SDK reads the state of the session first and sends the card only when the session is still open: a page reloaded on a paid order shows the outcome and calls onSuccess without sending a card again.
Testing
Sandbox Environment
- Load SDK from the sandbox domain:
https://gateway.idem-club.info/sdk/v1/sdk.min.js - Create the session with the secret key of your sandbox account, on
https://gateway.idem-club.info/api/sdk/payment/session: sandbox and production have their own pair of keys - Test cards for synchronous processors:
- Success:
4444333322221111 - Decline: Any other valid card number
- Success:
- Test cards for async processors:
- Success:
4242424242424242, or any other valid card number - Decline: An async processor decides on the amount, not on the card. Ask your account manager for the amounts of your sandbox processor.
- Success:
- CAUTION: the SDK does a Luhn test in the browser, before it sends the card. A card that fails this test never reaches the processor, whatever your sandbox accepts.
Browser Console
- Open Developer Tools (F12)
- Check Console for any errors
- Verify SDK initialization message
Common Test Scenarios
- Successful payment
- Declined card
- Invalid card number
- Expired card
- Missing required fields
Production Checklist
- Load SDK from production domain (
https://gateway.idem-club.com) - Verify CORS origins are correctly configured
- Keep the secret key on your server: the page holds the publishable key only
- Test with real payment amounts
- Implement proper error handling
- Add logging for troubleshooting
- Set up webhook endpoints for backend processing
Advanced Features
Debug Logging
Use the optional onLog function to surface SDK internal logs to your console.
Please take a look at the JavaScript example, on the right or below if you're on mobile.
Debug Logging
var sdk = PaymentSDK.init({
merchantId: '12345678',
publishableKey: 'pk_YOUR_PUBLISHABLE_KEY',
onLog: function() {
// Prefix logs for easy filtering in the console
try {
console.log('[PaymentSDK]', Array.prototype.slice.call(arguments));
} catch (e) {}
}
});
What gets logged:
- SDK initialization details (version, merchant id, domain-inferred environment)
- SSE connection events (open, message, error)
- Status updates received from the stream
- Non-fatal parse or network errors
Handle Async Payments
Please take a look at the JavaScript example, on the right or below if you're on mobile.
Handle Async Payments
onPending: function(context) {
// Show custom loading UI
document.getElementById('loading-message').style.display = 'block';
// context.session_id names the session: keep it for your own logic, never log it
// SSE automatically handles updates
// onSuccess or onError will be called when complete
}
IDEM Club Integration
For merchants with IDEM Club integration enabled (m_idem = 1), the SDK automatically handles:
- IDEM user validation
- Automatic token purchase and transfer upon payment completion
- Push notifications to IDEM App users
- One-click payment confirmation for IDEM members
The mr_idem_user_id field will be automatically set when processing payments for IDEM Club members.
Webhook Integration
Do not rely on JavaScript callbacks alone for fulfillment or accounting. Always implement a backend Webhook listener to receive authoritative status updates even if the browser closes or the network drops.
- What it is: Server-to-server notification on status changes (completed, rejected, refunded, etc.)
- Why it matters: More reliable than browser redirects; ensures consistent backend updates
- What to do: Expose a secure endpoint that validates the message and finalizes your order on terminal status
- Learn more: See the Webhooks section of the API documentation
Error Codes
| Code | Description | User Action |
|---|---|---|
declined |
Payment was declined by the card processor (counts one of the 3 requests the session may send to the processor) | Try different payment method |
invalid_request |
Request refused before the processor (missing or invalid parameter). No attempt consumed | Check the parameters and submit again |
invalid_customer |
A mandatory customer field is empty: first name, last name, city, country, or the state for a US customer. No attempt consumed | Complete the customer object |
invalid_email |
Customer email address rejected (invalid, or not accepted by the platform). No attempt consumed | Correct the email address |
amount_out_of_range |
Amount below the minimum or above the maximum of your account. No attempt consumed | Check the amount limits of your account |
currency_mismatch |
Currency differs from your account currency. No attempt consumed | Use your account currency |
duplicate_reference |
A payment with this order reference was already received (HTTP 409). No attempt consumed | Check the status of that order and payment before retrying; use a new reference only for a genuinely new purchase |
order_ref_conflict |
An open session exists for this order reference with another amount or currency (HTTP 409) | Reconcile with the open session (same amount and currency) or let it expire; a new reference is only for a different order |
payment_refused |
Request refused after its creation but before the processor (customer account or card locked, processor unavailable on this channel). No attempt consumed | Follow the message |
payment_in_progress |
Another submission of this order is being processed right now (HTTP 409); the SDK reads the order's outcome and follows it | Do not resubmit |
session_busy |
Another request is opening the session of this order (HTTP 409) | Retry in a moment |
session_inactive |
The session's payment is in flight or already completed (HTTP 409); the SDK reads the outcome and follows it | Do not resubmit |
payments_unavailable |
Payments are suspended on this merchant account (HTTP 403) | Contact support |
forbidden_new_users |
Your account accepts known customers only, and this email has no account yet (HTTP 403). No attempt consumed | Contact support |
idem_signup_not_allowed |
Your account is an IDEM Club account, but it does not allow automatic login or signup (HTTP 422). No attempt consumed | Contact support |
merchant_not_found |
The merchant of the server call does not exist (HTTP 404). No attempt consumed | Check the merchant_id of your server call |
processing_error |
The platform did not complete the payment (HTTP 500). This response does not say what happened to the card | Read the status of the session before you submit again |
attempts_exceeded |
Three requests already reached the processor on this session (the session counts declined, pending and completed requests; it restarts from zero when the platform switches the order to the fallback processor) | Wait and try again later |
unauthorized |
No Authorization header (HTTP 401) |
Pass the publishable key to PaymentSDK.init(); send the secret key on payment/session |
secret_key_invalid |
The key sent to POST /api/sdk/payment/session is not the secret key of this merchant (HTTP 401). A publishable key is refused here too |
Check the secret key and the merchant_id of your server call |
public_key_invalid |
The key in the page is not the publishable key of the merchant that owns the session (HTTP 401) | Check the publishable key passed to PaymentSDK.init(), and that the session was created for the same merchant |
secret_key_in_browser |
A secret key (sk_) was sent from the page (HTTP 403). The platform logs it as a leak |
Remove the secret key from the page, use the publishable key, and ask for both keys to be regenerated |
origin_required |
A browser endpoint was called without an Origin header (HTTP 403). Browsers send it on cross-origin requests only: the page must be served from one of your allowed origins, not from the platform host |
Call payment/process, payment/status and payment/stream from the page only; your server calls payment/session |
origin_not_configured |
No allowed origin is configured on your account (HTTP 403) | Set the allowed origins in your settings |
origin_not_allowed |
The origin of the page is not in your allowed origins (HTTP 403) | Add the exact origin (scheme and host, port if any) to the allowed origins |
not_found / method_not_allowed |
Unknown endpoint, or wrong HTTP method (HTTP 404 / 405) | Check the SDK version and the URL |
session_expired |
Payment session expired | Refresh page and start over |
idem_user_invalid |
IDEM Club validation failed | Check customer information |
Troubleshooting
| Issue | Solution |
|---|---|
| "Missing Authorization header" | Pass the publishable key to PaymentSDK.init(); on payment/session, send Authorization: Bearer sk_… |
| "Invalid secret key" on payment/session | Check the secret key and the merchant_id; sandbox and production keys differ |
| "A secret key was presented on a browser endpoint" | The page holds the secret key: remove it, use the publishable key, ask for both keys to be regenerated |
| "Origin not allowed" / "No allowed origin is configured" | Add the exact origin of your page to the allowed origins in your settings |
| "Session expired" | Payment took too long, refresh page |
| "SDK disabled" | Contact support to enable SDK |
| Form doesn't appear | Check container selector exists |
| SSE connection fails | Ensure CloudFlare or similar is not blocking SSE |
Debugging a refused session or payment
If POST /api/sdk/payment/session answers 401 or 403, or if the form shows an error before any card is sent:
- Enable logging - Initialize with
onLogto capture SDK messages - Verify domain/environment - Ensure correct domain (sandbox:
.info, prod:.com); the keys of one environment do not work on the other - Inspect Network tab - Every response carries
code,messageandcorrelation_id - Common causes:
secret_key_invalid: wrong secret key, or wrongmerchant_idin the server callpublic_key_invalid: wrong publishable key in the page, or a session of another merchantsecret_key_in_browser: the secret key ended up in the pagesdk_disabled_merchant: the SDK is not enabled on your accountorigin_not_allowed/origin_not_configured: the exact origin of the page is not in your allowed originssession_not_found/session_expired: the page holds a stalesession_id; create a new session
- Provide
correlation_idto support for faster tracing