DOKU JS Integration Guide
What is DOKU JS ?
The DOKU JS Integration feature enables non-PCI DSS certified merchants to securely collect customer card details for online transactions by embedding a Javascript into their HTML files while still having the freedom to manages how their checkoutpage will looks like. PCI DSS compliance is needed before activating this feature please contact DOKU team first.
Integration steps
Understanding the complete payment flow from merchant perspective:
Example HTML Files
<!DOCTYPE html>
<html>
<head>
<title>DOKU Payment Integration</title>
<!-- Step 1: Include the SDK -->
<script src="https://sandbox.doku.com/card-session/card-session-1.0.0.js"></script>
</head>
<body>
<form id="payment-form">
<input type="text" id="sessionId" placeholder="Payment Session ID" required />
<input type="text" id="cardNumber" placeholder="Card Number" required />
<input type="text" id="expiryMonth" placeholder="MM" required />
<input type="text" id="expiryYear" placeholder="YY" required />
<input type="text" id="cvv" placeholder="CVV" required />
<input type="text" id="firstName" placeholder="First Name" required />
<input type="text" id="lastName" placeholder="Last Name" required />
<button type="submit">Pay Now</button>
</form>
<script>
// Step 2: Initialize SDK
PG.init();
// Step 3: Handle form submission
document.getElementById('payment-form').addEventListener('submit', function(e) {
e.preventDefault();
const cardData = {
session_id: document.getElementById('sessionId').value.trim(),
card_number: document.getElementById('cardNumber').value.replace(/\s/g, ''),
expiry_month: document.getElementById('expiryMonth').value.trim(),
expiry_year: document.getElementById('expiryYear').value.trim(),
cvv: document.getElementById('cvv').value.trim(),
card_holder_first_name: document.getElementById('firstName').value.trim(),
card_holder_last_name: document.getElementById('lastName').value.trim()
};
// Step 4: Submit payment
PG.payment.collectCardData(cardData, function(error, response) {
if (error) {
alert('Payment failed: ' + error.message);
} else {
alert('Payment successful!');
console.log('Payment response:', response);
}
});
});
</script>
</body>
</html>Step 1: Include the SDK
Add the SDK script to your HTML page according to your environment:
<!-- For sandbox/testing environment -->
<script src="https://sandbox.doku.com/card-session/card-session-1.0.4.js"></script>
<!-- For production environment -->
<script src="https://app.doku.com/card-session/card-session-1.0.4.js"></script>⚠️ Important:
Each SDK URL is environment-specific. Always use sandbox URL for testing and production URL for live payments. Never use sandbox SDK in production!
HTML ID must be the same as stated in this documentation
Note: Place this in your <head> section or before the closing </body> tag.
Step 2: Create Your Payment Form
Create a form with the required input fields:
<form id="credit-card-form">
<!-- Session ID (obtained from your backend) -->
<div class="form-group">
<label for="paymentSessionId">Session ID</label>
<input type="text" id="paymentSessionId" name="payment-session-id" required />
</div>
<!-- Card Information -->
<div class="form-group">
<label for="cardNumber">Card Number</label>
<input type="text" id="cardNumber" name="card-number" required />
</div>
<div class="form-group">
<label for="expiryMonth">Expiry Month (MM)</label>
<input type="text" id="expiryMonth" name="expiry-month" placeholder="12" required />
</div>
<div class="form-group">
<label for="expiryYear">Expiry Year (YY)</label>
<input type="text" id="expiryYear" name="expiry-year" placeholder="27" required />
</div>
<div class="form-group">
<label for="cvv">CVV</label>
<input type="text" id="cvv" name="cvv" required />
</div>
<!-- Cardholder Information -->
<div class="form-group">
<label for="firstName">First Name</label>
<input type="text" id="firstName" name="first-name" required />
</div>
<div class="form-group">
<label for="lastName">Last Name</label>
<input type="text" id="lastName" name="last-name" required />
</div>
</form>Step 3: Initialize the SDK
Add this script to initialize the SDK:
// Initialize the Payment Gateway SDK
PG.init();
Place this after the SDK script is loaded, preferably in a tag at the bottom of your page.
Step 4: Handle Form Submission
Capture the form submission and send the payment data to DOKU:
const form = document.getElementById('credit-card-form');
form.addEventListener('submit', function(e) {
e.preventDefault();
submitPayment();
});
function submitPayment() {
// Collect card data from form
const cardData = {
session_id: document.getElementById('paymentSessionId').value.trim(),
card_number: document.getElementById('cardNumber').value.replace(/\s/g, ''),
expiry_month: document.getElementById('expiryMonth').value.trim(),
expiry_year: document.getElementById('expiryYear').value.trim(),
cvv: document.getElementById('cvv').value.trim(),
card_holder_first_name: document.getElementById('firstName').value.trim(),
card_holder_last_name: document.getElementById('lastName').value.trim(),
};
// Submit to DOKU
PG.payment.collectCardData(cardData, function(error, response) {
console.log('Payment response:', response);
console.log('Payment error:', error);
if (error) {
// Handle error
alert('Payment failed: ' + error.message);
// You can show error message to user or redirect to error page
} else {
// Handle success
alert('Payment successful!');
// You can redirect to success page or show confirmation
// window.location.href = '/payment-success';
}
});
}API References
PG.init()
Initialize the Payment Gateway SDK. Call this once when the page loads.
PG.init();Parameters: None
Returns: void
PG.payment.collectCardData(cardData, callback)
Submit card data for payment processing.
PG.payment.collectCardData(cardData, callback);Required Parameters (cardData object):
session_id REQUIRED
string
Payment session ID from backend
"ps_sandbox_1762256259630_lRDnbpJT3c"
card_number REQUIRED
string
Card number (no spaces)
"4512490000000907"
expiry_month REQUIRED
string
Card expiry month (MM)
"12"
expiry_year REQUIRED
string
Card expiry year (YY or YYYY)
"27" or "2027"
cvv REQUIRED
string
Card CVV/CVV2 code
"123"
card_holder_first_name REQUIRED
string
Cardholder first name
"John"
card_holder_last_name REQUIRED
string
Cardholder last name
"Doe"
Callback Function:
function callback(error, response) {
if (error) {
// Error handling
console.error(error.message);
} else {
// Success handling
console.log(response);
}
}Callback Parameters:
error: Error object if payment fails (null on success)
error.message: Error message string
response: Response object if payment succeeds (null on error)
Contains payment result data
Troubleshooting
Common Issues
Debug Mode
Enable console logging to debug issues:
PG.payment.collectCardData(cardData, function(error, response) {
console.log('Card Data:', cardData);
console.log('Error:', error);
console.log('Response:', response);
// Your handling code
});Security Best Practices
1. Never Store Card Data
Never save card numbers, CVV, or sensitive data in your database or logs. The SDK handles secure transmission of card data to DOKU's servers.
2. Use HTTPS
Always serve your payment page over HTTPS to ensure encrypted communication between the user's browser and your server.
3. Validate Input
Validate user input on both client and server side to prevent malicious data submission and improve user experience.
4. Session Management
Generate payment session IDs server-side with proper authentication. Never expose your API credentials on the client side.
5. Anti-Clickjacking Protection
What is Clickjacking? Clickjacking is an attack where a malicious actor tricks users into clicking on hidden elements by overlaying transparent layers on your payment page.
Protect your payment integration by implementing these defense mechanisms:
JavaScript Frame-Breaker
Add this script to prevent your payment page from being loaded in unauthorized iframes:
<script type="text/javascript">
// Anti-clickjacking frame-breaker
if (self === top) {
// Page is not in an iframe - safe to proceed
var antiClickjack = document.getElementById("antiClickjack");
if (antiClickjack) {
antiClickjack.parentNode.removeChild(antiClickjack);
}
} else {
// Page is in an iframe - redirect to legitimate location
top.location = self.location;
}
</script>Add this style in your page <head> to hide content until the frame-breaker runs:
<style id="antiClickjack">
body { display: none !important; }
</style>X-Frame-Options HTTP Header
Configure your web server to send the X-Frame-Options header to prevent framing:
Apache (.htaccess or httpd.conf):
Header always set X-Frame-Options "DENY"
# Or to allow same-origin framing only:
# Header always set X-Frame-Options "SAMEORIGIN"Nginx:
add_header X-Frame-Options "DENY" always;
# Or to allow same-origin framing only:
# add_header X-Frame-Options "SAMEORIGIN" always;Node.js/Express:
app.use((req, res, next) => {
res.setHeader('X-Frame-Options', 'DENY');
next();
});Content-Security-Policy Header
Implement CSP with frame-ancestors directive for more granular control:
Apache:
Header always set Content-Security-Policy "frame-ancestors 'none'"
# Or to allow specific domains:
# Header always set Content-Security-Policy "frame-ancestors 'self' https://trusted-domain.com"Nginx:
add_header Content-Security-Policy "frame-ancestors 'none'" always;
# Or to allow specific domains:
# add_header Content-Security-Policy "frame-ancestors 'self' https://trusted-domain.com" always;Node.js/Express:
app.use((req, res, next) => {
res.setHeader('Content-Security-Policy', "frame-ancestors 'none'");
next();
});Best Practice: Defense in Depth
Implement multiple layers of clickjacking protection for maximum security:
JavaScript frame-breaker (client-side)
X-Frame-Options header (HTTP-level)
Content-Security-Policy header (modern standard)
Reference: OWASP Clickjacking Defense Cheat Sheet
6. PCI Compliance
The SDK handles card data securely, but ensure your implementation follows PCI DSS guidelines. This includes:
Never logging sensitive card data
Implementing proper access controls
Regular security assessments
Secure coding practices
Next Steps
Test the integration in sandbox environment
Implement proper error handling
Add form validation
Style your payment form
Set up production environment
Implement server-side payment verification
Last updated
Was this helpful?