Payment Widget for Web
Integrate DEUNA Payment Widget on the web with responsive presentation, controlled submission, callbacks, payment filtering, and recovery.
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#
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#
Parameters#
| Parameter | Required | Purpose |
|---|---|---|
orderToken | Yes | Token returned when your backend created the order. |
callbacks | No, recommended | Success, error, close, resize, payment, BIN, installment, and event handlers. |
language | No | en, es, or pt; otherwise merchant defaults apply. |
userToken | No | Authenticated DEUNA user context for eligible saved payment methods. |
paymentMethods | No | Restricts or directly opens configured methods. Do not hardcode processors used by routing unless required. |
mode + target | No | Render inside a matching element instead of the default modal. Both are required for target mode. |
hidePayButton | No | Hides the widget action when your page owns submission. |
styleFile | No | DEUNA-managed theme/style identifier or approved style resource. |
widgetExperience | No | Supported theme and user-experience overrides. |
behavior | No | Supported flow behavior such as split cards or parent popup redirects. |
fraudCredentials | No | Approved fraud-provider configuration only. |
sessionId, idempotencyKey | No | Correlation and duplicate-attempt controls for supported flows. |
domain | No | Controlled environment override; omit in normal production use. |
Modal or embedded#
Modal is the default. For embedded mode:
<div id="deuna-payment" aria-label="Payment details"></div>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.
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#
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:
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#
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.