Skip to main content
On this page

Payment Widget displays the payment methods eligible for an existing order and processes the selected method through DEUNA. It supports cards and configured alternative payment methods without exposing sensitive credentials to merchant JavaScript.

Before you begin#

Complete Get started with the Web SDK, create the order on your backend, and return only its order_token to the browser.

Open Payment Widget#

JavaScript
await DeunaSDK.initPaymentWidget({
  orderToken,
  language: 'en',
  callbacks: {
    onSuccess: async () => {
      await DeunaSDK.close();
      await verifyOrderOnBackend();
    },
    onError: ({type, metadata}) => {
      showRecovery({type, code: metadata.code});
    },
    onClosed: (action, metadata) => {
      restorePaymentMethods(action, metadata);
    },
    onCardBinDetected: ({cardBin, cardBrand}) => {
      updateCardOffers(cardBin, cardBrand);
    },
    onInstallmentSelected: ({cardBin, installmentPlanOptionId}) => {
      rememberPlan(cardBin, installmentPlanOptionId);
    },
    onPaymentProcessing: () => disableDuplicateActions(),
    onEventDispatch: (event, payload) => trackSafeEvent(event, payload),
  },
});

Integration sequence#

01 · server
Create the order
Calculate totals and obtain the order token.
02 · browser
Open Payment Widget
Pass the token and supported client configuration.
03 · SDK
Process the selected method
Handle validation, challenge, provider, and lifecycle behavior.
04 · server
Verify and fulfill
Use authoritative order state.

Parameters#

ParameterRequiredPurpose
orderTokenYesToken returned when your backend created the order.
callbacksNo, recommendedSuccess, error, close, resize, payment, BIN, installment, and event handlers.
languageNoen, es, or pt; otherwise merchant defaults apply.
userTokenNoAuthenticated DEUNA user context for eligible saved payment methods.
paymentMethodsNoRestricts or directly opens configured methods. Do not hardcode processors used by routing unless required.
mode + targetNoRender inside a matching element instead of the default modal. Both are required for target mode.
hidePayButtonNoHides the widget action when your page owns submission.
styleFileNoDEUNA-managed theme/style identifier or approved style resource.
widgetExperienceNoSupported theme and user-experience overrides.
behaviorNoSupported flow behavior such as split cards or parent popup redirects.
fraudCredentialsNoApproved fraud-provider configuration only.
sessionId, idempotencyKeyNoCorrelation and duplicate-attempt controls for supported flows.
domainNoControlled environment override; omit in normal production use.

Modal or embedded#

Modal is the default. For embedded mode:

HTML
<div id="deuna-payment" aria-label="Payment details"></div>
JavaScript
await DeunaSDK.initPaymentWidget({
  orderToken,
  mode: 'target',
  target: '#deuna-payment',
  callbacks: {
    onResize: ({height}) => {
      document.querySelector('#deuna-payment').style.height = `${Math.ceil(height)}px`;
    },
    onSuccess: verifyOrderOnBackend,
    onError: showRecovery,
  },
});

The selector must match one stable element. Do not render it inside an element that is display: none during initialization or clips overflow.

Filter payment methods#

Omit paymentMethods to let the order and merchant configuration determine eligibility. Supply one method to open its form directly, or multiple methods to restrict the choice.

JavaScript
await DeunaSDK.initPaymentWidget({
  orderToken,
  paymentMethods: [
    {paymentMethod: 'credit_card'},
    {paymentMethod: 'wallet', processors: ['click_to_pay']},
  ],
  callbacks,
});

Routing can choose among configured card processors, so a credit-card entry does not normally need a processors list.

Own the submit button#

JavaScript
await DeunaSDK.initPaymentWidget({
  orderToken,
  hidePayButton: true,
  callbacks,
});

payButton.addEventListener('click', async () => {
  if (!(await DeunaSDK.isValid())) return;

  payButton.disabled = true;
  const result = await DeunaSDK.submit();
  if (result.status === 'error') showRecovery(result);
  payButton.disabled = false;
});

The active instance also exposes getWidgetState(), getSelectedPaymentMethod(), refetchOrder(), setOrderData(...), setCustomStyles(...), and close(). Use only methods relevant to the active experience and serialize updates so an old order token cannot overwrite a new checkout.

Split cards and installments#

Use the documented nested behavior for a configured two-card flow:

JavaScript
behavior: {
  paymentMethods: {
    creditCard: {
      splitPayments: {maxCards: 2},
    },
  },
}

See Split card payments for reconciliation and testing. Use onInstallmentSelected for the exact installmentPlanOptionId; never infer it from visible copy.

Error and close handling#

Flow diagram
1Widget outcome2-- No3Verify order onbackend4-- No, closed orinterrupted5Map type andmetadata code torecovery6Retrieve orderbefore retry7Render verifiedstate
Review or pending

Do not show raw provider messages. Map known types and codes to localized customer guidance, record safe diagnostics, and fall back to a generic retry message.