Skip to main content
On this page

The DEUNA Web SDK is a browser script that renders payment experiences in a modal or a responsive target element. Your backend creates orders and protects private credentials; the browser receives a public API key and short-lived order token.

Integration architecture#

Sequence diagram
1Browser2Merchant backend3DEUNA API4DEUNA Web SDKStart checkoutCreate order with privateAPI keyorder_tokenPublic key context + ordertokeninitialize + initPaymentWidgetCallbacks and lifecycle eventsRetrieve final order state
Merchant or customerDEUNA
01 · backend
Create the order
Keep private API keys, totals, and business rules on the server.
02 · browser
Initialize once
Load the pinned CDN script and set the explicit environment.
03 · customer
Open one experience
Payment Widget, Elements, Voucher, or Next Action.
04 · backend
Verify final state
Reconcile before fulfillment.

1. Load a pinned version#

HTML
<script
  crossorigin
  src="https://cdn.deuna.io/web-sdk/v1.7/index.js">
</script>

The script exposes window.DeunaSDK. Pin the version in production and test upgrades in sandbox first. Do not silently rewrite the CDN URL at runtime from untrusted input.

For a single-page application, load the script once at the document level. If you load it dynamically, resolve a shared promise so concurrent routes do not add duplicate tags.

JavaScript
function loadDeunaSdk() {
  if (window.DeunaSDK) return Promise.resolve(window.DeunaSDK);
  if (window.__deunaSdkPromise) return window.__deunaSdkPromise;

  window.__deunaSdkPromise = new Promise((resolve, reject) => {
    const script = document.createElement('script');
    script.src = 'https://cdn.deuna.io/web-sdk/v1.7/index.js';
    script.crossOrigin = 'anonymous';
    script.onload = () => resolve(window.DeunaSDK);
    script.onerror = () => reject(new Error('DEUNA Web SDK failed to load'));
    document.head.append(script);
  });

  return window.__deunaSdkPromise;
}

2. Initialize the environment#

JavaScript
await DeunaSDK.initialize({
  publicApiKey: 'YOUR_PUBLIC_API_KEY',
  env: 'sandbox',
});

Use sandbox for integration tests and production for live traffic. Production is the SDK default, but setting env explicitly prevents accidental cross-environment tokens and credentials.

3. Choose loading strategy#

StrategyUse whenTradeoff
Preload one likely widgetThe checkout page can initialize before the final click.Fast opening; consumes network and browser resources earlier.
Initialize, then open on demandThe experience is rarely used or the page must minimize early work.Simpler lifecycle; customer sees the widget loading state.
Preload Payment WidgetJavaScript
await DeunaSDK.initialize({
  publicApiKey: 'YOUR_PUBLIC_API_KEY',
  env: 'sandbox',
  preloadWidgets: [
    {
      widget: 'payment',
      params: {
        language: 'en',
        callbacks,
      },
    },
  ],
});

// Once your backend returns the token, reveal the prepared widget.
await DeunaSDK.initPaymentWidget({orderToken});

Preload only the experience the customer is likely to open. The current source supports payment, elements, voucher, and nextAction preload entries.

4. Open an experience#

Content Security Policy#

Start from your application’s existing policy and allow only the DEUNA origins used by the selected environment and features. The production SDK itself loads from https://cdn.deuna.io; widget frames use the production Checkout or Elements hosts, while API and storage connections use DEUNA production endpoints. Sandbox uses the corresponding *.sandbox.deuna.io hosts.

Production-oriented baseline; merge with your existing policyHTTP
Content-Security-Policy:
  script-src 'self' https://cdn.deuna.io;
  frame-src https://checkout-ux.deuna.com https://elements.deuna.com https://cdn.getduna.com;
  connect-src 'self' https://api.deuna.io https://apigw.getduna.com https://elements.deuna.com;

Wallets, fraud providers, APMs, fonts, images, and custom style files can require additional provider-specific origins. Add only the origins exercised by your configured integration; verify the browser console in sandbox and keep the policy under source control. Do not add broad wildcards to silence violations.

Responsive host and accessibility#

Modal mode uses the viewport on screens up to 600 px wide. For embedded mode, provide a fluid host and update its height from onResize.

CSS
#deuna-payment {
  width: 100%;
  min-width: 0;
  min-height: 32rem;
}

@media (max-width: 600px) {
  #deuna-payment { min-height: 100dvh; }
}

Keep zoom enabled, do not trap focus outside the widget, restore focus after closure, and test keyboard navigation plus 200% text zoom.

Sandbox acceptance checklist#

  • The script loads once and failure produces a recoverable UI.
  • Sandbox keys and order tokens never reach production, or vice versa.
  • Modal and target modes work at 320 px width and with a keyboard only.
  • Success, decline, close, timeout, refresh, and network interruption are handled.
  • 3DS and APM popups or redirects are not blocked by CSP or iframe sandboxing.
  • Logs exclude tokens, customer details, and payment data.
  • Your backend—not the callback—decides whether fulfillment is allowed.

Next steps#