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. This process ensures compliance with PCI DSS standards and provides flexibility for various integration models—either through by using the merchant’s own front-end integrated or with tokenization

Integration steps

Understanding the complete payment flow from merchant perspective:

Integration Steps Summary:

  1. Create Payment Session: Call POST /request-payment-page to get payment URL and session ID

  2. Customer Completes Payment: Customer enters card on payment page, SDK handles encryption & 3DS

  3. Receive Notification: Webhook POST to your callback URL with payment status

  4. Fallback (if needed): GET check status API to poll for status updates

DOKU JS Transaction Flow

1. Generate session_id

Generate a session id to be used for the transaction in this guide

2. Include the SDK

Add the SDK script to your HTML page:

<!-- For sandbox/testing environment -->
<script src="https://api-sandbox.doku.com/card-session/sandbox/v2.0.0/card-session.js"></script>

<!-- For production environment -->
<script src="https://api.doku.com/card-session/production/v2.0.0/card-session.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!

3. Initialize the SDK

Configure the SDK with your environment and client ID:

// Initialize SDK (environment is pre-configured in the SDK file)
PG.init().then((sdkInstance) => {
  // Verify environment
  console.log('Environment:', PG.getEnvironment());
  console.log('API URL:', PG.getApiBaseUrl());

  // Important: Chain the Device Data API status check
  return sdkInstance.isDeviceDataApiSuccessful();
})
.then(() => {
  // This block runs ONLY if both initialization AND the Device Data API check succeeded.

  // Proceed with secure payment flow (e.g., enabling the Pay button)
  document.getElementById('payButton').disabled = false;
})
.catch((error) => {
  // This block catches all failures (critical init error OR Device Data API error).
  
  // Proceed with secure payment flow (e.g., disable payment and alert the user/system)
  document.getElementById('payButton').disabled = true;
});

4. Card Validation

Cards Number(PAN) has several rules to validate is validity, Use built-in validation utilities before submitting:

// Validate card number
if (!PG.card.validateCardNumber(cardNumber)) {
  alert('Invalid card number');  //can be replaced with your own alert
  return;
}

// Detect card brand
const brand = PG.card.detectBrand(cardNumber); // 'visa', 'mastercard', 'amex', 'discover', 'jcb', 'dinersclub', 'unionpay'

// Validate expiry
if (!PG.card.validateExpiry(month, year)) {
  alert('Invalid or expired card'); //can be replaced with your own alert
  return;
}

// Validate CVV
if (!PG.card.validateCvv(cvv, brand)) {
  alert('Invalid CVV');  //can be replaced with your own alert
  return;
}

5. Submit the payment

Submit the card data with the session ID from step 1:

 const cardData = {
          session_id: document.getElementById('paymentSessionId'),
          card_number: document.getElementById('cardNumber'),
          expiry_month: document.getElementById('expiryMonth'),
          expiry_year: document.getElementById('expiryYear'),
          cvv: document.getElementById('cvv'),
          card_holder_first_name: document.getElementById('firstName').value,
          card_holder_last_name: document.getElementById('lastName').value,
          card_holder_email: document.getElementById('email').value,
          card_holder_phone_number: document.getElementById('phone')?.value,
          billing_information: {
            address: document.getElementById('billingAddress').value,
            city: document.getElementById('billingCity').value,
            postal_code: document.getElementById('billingPostalCode').value,
            country: document.getElementById('billingCountry').value,
          },
        };


          // Submit to DOKU
          PG.payment.collectCardData(cardData, function(error, response) {
            if (error) {
              alert('Payment failed: ' + error.message);
            } else {
              alert('Payment successful!');
            }
          });

7. Handle 3D Secure

When 3DS authentication(OTP) is required, the SDK automatically redirects the user to issuer's OTP page after 1.5 seconds:

PG.payment.collectCardData(cardData, function(error, response) {
    if (response.requires_action) {
        // SDK will automatically redirect to response.action_url after 1.5s
        // You can show a loading message during this time
        showMessage('Redirecting to authentication page...');

        // The redirect happens automatically - no need to call window.location.href
    }
});

When user completes authentication, they'll be redirected back to your callback URL:

// Check for 3DS callback in URL (on your callback page)
const urlParams = new URLSearchParams(window.location.search);
const paymentRequestId = urlParams.get('payment_request_id');
const status = urlParams.get('status');

if (paymentRequestId && status) {
    // User returned from 3DS
    if (status === 'success') {
        showSuccessMessage('Payment authenticated successfully!');
    } else {
        showErrorMessage('Payment authentication failed');
    }
}

⚠️ Important:

  • The SDK automatically redirects to the 3DS page after 1.5 seconds

  • No need to manually call window.location.href

  • Always handle both success and failure cases when user returns

  • Users may cancel the authentication or encounter errors

  • Make sure to redirect merchant to Pending page and regularly refresh while waiting for notification status SUCCESS/FAILED

  • Mitigation options for clickjacking prevention. Clickjacking, also known as a "UI redress attack", is when an attacker uses multiple transparent or opaque layers to trick a user into clicking on a button or link on another page when they were intending to click on the top-level page. To use the Hosted Session, you must implement one or more of the following defenses against clickjacking attacks and specify which defenses are implemented using the frameEmbeddingMitigation field:

    • Javascript: Include "frame-breaker" JavaScript on your payment page.

    • x-frame-options: Your server returns an X-Frame Options HTTP response header.

    • csp: Your server returns a Content-Security-Policy HTTP response header containing a frame-ancestors directive.

    • For information on defending against clickjacking attacks, see Clickjacking Defense Cheat Sheet on the OWASP external website.

8.Receives Notification

Follow this Notification Guides to receives notification

Handling Response Code

Follow this Response Code documentation for handling each cases

Last updated

Was this helpful?