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:

Prerequisites:

  • Create session_id from your backend: Call POST /request-payment-page to get payment URL and get session ID

  • A valid DOKU payment session ID from your backend

  • Basic HTML/JavaScript knowledge

  • Web server or local development environment

DOKU JS Transaction Flow

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>

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>

ID must be the same as stated in this documentation

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):

Field
Type
Description
Example

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

1. SDK Not Loaded

Error: PG is not defined

Solution: Make sure the SDK script is loaded before your code:

<script src="https://sandbox.doku.com/card-session/card-session-1.0.0.js"></script>
<script>
    // Your code here
    PG.init();
</script>
2. Invalid Session ID

Error: Invalid session ID

Solution: Ensure you're getting a valid payment session ID from your backend API.

3. Card Validation Errors

Error: Invalid card number

Solution:

  • Remove all spaces from card number

  • Verify the card number is valid

  • Use test cards in sandbox environment

4. Network Errors

Error: Network request failed

Solution:

  • Check your internet connection

  • Verify the SDK URL is correct for your environment

  • Check browser console for CORS errors

5. Form Not Submitting

Issue: Clicking submit button does nothing

Solution:

  • Ensure e.preventDefault() is called in the submit handler

  • Check browser console for JavaScript errors

  • Verify all required fields have values

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

  1. Test the integration in sandbox environment

  2. Implement proper error handling

  3. Add form validation

  4. Style your payment form

  5. Set up production environment

  6. Implement server-side payment verification

Last updated

Was this helpful?