El Payment Widget es una herramienta integrada que permite a los comercios ofrecer múltiples métodos de pago a sus clientes de manera sencilla y eficiente. Este widget es compatible tanto con Métodos de Pago Alternativos (APMs) como con tarjetas de crédito y débito, proporcionando flexibilidad en las opciones de pago para los usuarios.
El Payment Widget soporta:
- Métodos de Pago Alternativos (APMs): como OXXO, KueskiPay, entre otros.
- Tarjetas de Crédito y Débito: MasterCard, Visa, American Express, etc.
Inicializa el Widget
Antes de integrar el Payment Widget, completa los Primeros Pasos.
1. Muestra el Widget
Mostrar en un Modal
Sigue los siguientes pasos para mostrar el Payment Widget de DEUNA en un Modal:
- Crea una instancia de la clase
DeunaSDK
. - Agrega el componente
DeunaWidget
a tu vista. - Llama a la función
initPaymentWidget
.

import {
DeunaSDK,
DeunaWidget
} from '@deuna/react-native-sdk';
const deunaSDK = DeunaSDK.initialize({
publicApiKey: "YOUR_PUBLIC_API_KEY",
environment: "sandbox",
});
const YourScreen = () => {
const onShowPaymentWidget = () => {
deunaSDK.initPaymentWidget({
orderToken: "YOUR_ORDER_TOKEN",
callbacks: {
onSuccess: async (order) => {
await deunaSDK.close(); // Cierra el Modal y libera los recursos del widget de pago.
// TU CÓDIGO AQUÍ
},
onError: (error) => {
// Manejo de errores
},
onClosed: (action) => {
// Widget cerrado
},
},
});
};
return (
<View>
<DeunaWidget instance={deunaSDK} />
<Button
onPress={onShowPaymentWidget}
title="Show Payment Widget"
></Button>
</View>
);
};
Mostrar el Widget de forma embebida.
Para mostrar el widget de DEUNA de forma embebida necesitaras pasar el parámetro mode: Mode.EMBEDDED
cuando llames a la función initPaymentWidget
.
Para visualizar correctamente el widget de DEUNA de forma embebida, el componenteDeunaWidget
debe estar dentro de un componente que delimite sus dimensiones.

import {
DeunaSDK,
DeunaWidget,
Mode, // AGREGAR ESTA LINEA
} from "@deuna/react-native-sdk";
const deunaSDK = DeunaSDK.initialize({
publicApiKey: "YOUR_PUBLIC_API_KEY",
environment: "sandbox",
});
const YourScreen = () => {
const onShowPaymentWidget = () => {
deunaSDK.initPaymentWidget({
orderToken: "YOUR_ORDER_TOKEN",
mode: Mode.EMBEDDED, // AGREGAR ESTA LINEA
callbacks: {
onSuccess: async (order) => {
await deunaSDK.close(); // Libera los recursos del widget de pago.
// TU CÓDIGO AQUÍ
},
onError: (error) => {
// Manejo de errores
},
onClosed: (action) => {
// Widget cerrado
},
},
});
};
return (
<View>
{/* Delimita las dimensiones del Widget */}
<View style={{ flex: 1, width: "100%" }}>
<DeunaWidget instance={deunaSDK} />
</View>
<Button
onPress={onShowPaymentWidget}
title="Show Payment Widget"
></Button>
</View>
);
};
Parámetros
Atributos | Tipo | Modal | Embebido | Descripción |
---|---|---|---|---|
| string | ✅ | ✅ | El orderToken es un token único generado para la orden de pago. Este token es generado a través del API de DEUNA y debes implementar el endpoint correspondiente en tu backend para obtener esta información.
|
| Json (Callbacks) | ✅ | ✅ | Los callbacks son funciones de retorno que se encargan de escuchar y manejar los eventos del widget de pago. Estos eventos permiten gestionar acciones específicas basadas en el estado del pago. Los principales callbacks incluyen: |
| string | ✅ | ✅ | El bearer token del usuario de DEUNA. Cuando este es enviado, todas las acciones dentro del widget van a hacer sobre este usuario de DEUNA.
|
| string | ✅ | ✅ | UUID proporcionado por DEUNA. Esto aplica si quieres configurar un archivo |
| Json[] | ✅ | ✅ | Una lista métodos de pago permitidos. Este parámetro determina qué tipo de widget se debe renderizar. |
| string | ✅ | ✅ | Este parámetro permite especificar el idioma en el que se mostrará la interfaz del widget. Debe proporcionarse como un código de idioma válido (por ejemplo, "es" para español, "en" para inglés, "pt" para portugués). Comportamiento:
|
| Json | ✅ | ✅ | Utiliza este parámetro para configurar el comportamiento del widget. |
2. Configura métodos de pago
Parámetro callbacks > onDownloadFile
(Opcional)
callbacks > onDownloadFile
(Opcional)Utiliza el callback onDownloadFile
para escuchar cuando una solicitud para descargar un archivo ha sido recibida (Descarga de un Voucher, una imagen, etc.).
deunaSDK.initPaymentWidget({
orderToken: "YOUR_ORDER_TOKEN",
mode: Mode.EMBEDDED, // AGREGAR ESTA LINEA
callbacks: {
onDownloadFile: (file) => {
const { type, data } = file;
const mapper = {
[DownloadType.URL]: () => {
// TODO: Implement download from url
},
[DownloadType.BASE64]: () => {
// TODO: Implement download from image base64
},
};
mapper[type]();
},
},
});
Parámetro behavior
(Opcional)
behavior
(Opcional)El método initPaymentWidget
acepta un parámetro opcional llamado behavior
, el cual permite personalizar el comportamiento del widget de pago según las necesidades del comercio o del flujo deseado.
Esto incluye configuraciones como:
- Mostrar un flujo de pago en uno o dos pasos.
- Habilitar pagos con múltiples tarjetas.
- Activar comportamientos específicos para ciertos métodos de pago
Estas configuraciones aplican a todos los métodos de pago habilitados en el widget.
Comportamiento de los métodos de pago paymentMethods
paymentMethods
Dentro de behavior
, puedes especificar configuraciones globales o específicas por método de pago a través del parámetro paymentMethods
. A continuación, explicamos dos casos comunes:
flowType
: Control del tipo de flujo (ej. PayPal)
Este parámetro controla cómo se presenta el flujo de pago para métodos como PayPal.
Es útil para mejorar la experiencia del usuario mostrando primero un resumen y luego la confirmación de pago, o todo en un solo paso.
Valores disponibles:
twoStep
→ Muestra primero un resumen del pedido, luego el formulario de pago.singleStep
→ Muestra directamente el formulario de pago.
Compatibilidad actual: Solo aplica a PayPal por ahora.
deunaSDK.initPaymentWidget({
orderToken: "TOKEN",
.
.
.
behavior: {
paymentMethods: {
flowType: "twoStep",
},
},
});
💡 Ejemplo de uso: Si quieres que el usuario vea primero un resumen del pedido antes de autorizar PayPal, usa "twoStep".
splitPayments
: Pago dividido en múltiples tarjetas
Permite al cliente dividir el monto total del pedido entre dos tarjetas. Ideal para compras de alto valor o si el usuario quiere usar más de un método de pago.
Requisitos Previos:
- La opción debe estar habilitada en la configuración del comercio.
- Actualmente solo se admite división entre 2 tarjetas como máximo.
deunaSDK.initPaymentWidget({
orderToken: "TOKEN",
.
.
.
behavior: {
paymentMethods: {
creditCard: {
splitPayments: {
maxCards: 2, // Número máximo de tarjetas permitidas
},
},
},
},
});
💡 Ejemplo de uso: Un cliente puede pagar $500 usando dos tarjetas diferentes, dividiendo el monto entre ambas.
Configuración de Auto Purchase para PayPal
La función Auto Purchase (compra automática) para PayPal permite procesar pagos instantáneamente cuando:
- El cliente tiene previamente vinculada su cuenta de PayPal.
- Ha autorizado pagos rápidos en su cuenta.
deunaSDK.initPaymentWidget({
orderToken: "<DEUNA order token>",
paymentMethods: [
{
paymentMethod: "wallet",
processors: ["paypal_wallet"],
configuration: {
express: true,
},
},
],
});
Parámetros de Configuración
Parámetro | Tipo | Valor por Defecto | Descripción |
---|---|---|---|
express | boolean | true | Cuando es true , procesa el pago automáticamente si el cliente tiene PayPal vinculado. Cuando es false , permite seleccionar/confirmar la cuenta. |
IMPORTANTE: la configuración de express solo funcionará si en el parámetro paymentMethods
se le pasa únicamente la configuración para PayPal.
3. Mostrar u ocultar métodos de pago
El Payment Widget puede desplegar varios métodos de pago disponibles para una orden, sin que el comercio tenga que agregar individualmente cada botón de APM en su Frontend.
Al invocar la función initPaymentWidget, el parámetro paymentMethods define los métodos de pago que el widget mostrará:
- Si se pasa 1 solo método en paymentMethods el widget abre automáticamente el formulario del método de pago sin mostrar botones de otros AMPs.

deunaSDK.initPaymentWidget({
orderToken: "<DEUNA order token>",
userToken: "...", // optional
styleFile: "...", // optional
callbacks: { ... }, // replace with actual callbacks object
paymentMethods: [
{
paymentMethod: "voucher",
processors: ["payu_oxxo_cash"]
}
]
});

deunaSDK.initPaymentWidget({
orderToken: "<DEUNA order token>",
userToken: "...", // optional
styleFile: "...", // optional
callbacks: { /* your callbacks object */ },
paymentMethods: [
{
paymentMethod: "voucher",
processors: ["daviplata"]
}
]
});

deunaSDK.initPaymentWidget({
orderToken: "<DEUNA order token>",
userToken: "user_token_here", // optional
styleFile: "style-file-id", // optional
callbacks: {
onSuccess: (data) => console.log("Payment success", data),
onError: (error) => console.error("Payment error", error),
onClose: () => console.log("Widget closed"),
},
paymentMethods: [
{
paymentMethod: "voucher",
processors: ["nequi_push_voucher"],
},
],
});
- Si se especifica más de 1 método de pago en el parámetro paymentMethods, el widget solo mostrará esos métodos habilitados los cuales deben estar configurados a nivel comercio.
For credit card processing there is no need to pass the processors's array since the merchant can have multiple configured for the use of routing.

deunaSDK.initPaymentWidget({
orderToken: "<DEUNA order token>",
userToken: "user_token_here", // optional
styleFile: "style-file-ids", // optional
callbacks: {
onSuccess: (data) => console.log("Payment success", data),
onError: (error) => console.error("Payment error", error),
onClose: () => console.log("Widget closed"),
},
paymentMethods: [
{
paymentMethod: "credit_card",
},
{
paymentMethod: "bnpl",
processors: ["kueski"],
},
{
paymentMethod: "voucher",
processors: ["payu_oxxo_cash"],
},
],
});
- Si no se especifica una lista de métodos en paymentMethods y no se utilizó el parámetro include_payment_options al crear la orden, el widget mostrará todos los métodos de pago configurados para el comercio.

deunaSDK.initPaymentWidget({
orderToken: "<DEUNA order token>",
.
.
.
callbacks: {
onSuccess: (data) => console.log('Payment success', data),
onError: (error) => console.error('Payment error', error),
onClose: () => console.log('Widget closed')
},
});
Prioridades de configuración de métodos de pago
La siguiente tabla muestra como el payment widget decide que formas de pago debe mostrar cuando no se pasa el parámetro paymentMethods.
Prioridad | Fuente de Configuración | Descripción | Comportamiento en caso de un solo método de pago |
---|---|---|---|
1 | Métodos de pago pasados al ejecutar la función | Los métodos de pago se muestran según los que se pasan al iniciar el widget, siempre y cuando estén activados y configurados a nivel comercio. | Si solo se pasa un método de pago, el widget abre automáticamente el formulario del método de pago sin mostrar botones. |
2 | Orden e | Se revisa la orden para verificar si | Si solo se pasa un método de pago, el widget abre automáticamente el formulario del método de pago sin mostrar botones. |
3 | Métodos configurados a nivel comercio | Si no se pasa ningún método de pago ni en la función | Si solo se pasa un método de pago, el widget abre automáticamente el formulario del método de pago sin mostrar botones. |
4. Escucha eventos del Widget
Cuando una transacción es exitosa o falla, es importante actualizar tu interfaz para notificar a los usuarios sobre el resultado de la transacción. Esto lo puedes realizar escuchando los eventos del widget de pago mediante los callbacks.
La función initPaymentWidget
te permite escuchar los eventos del widget mediante callbacks. Define los callbacks respectivos para actualizar la interfaz de tu app.
Callbacks
Callback | Modal | Embebido | ¿Cuándo se dispara? |
---|---|---|---|
| ✅ | ✅ | Se ejecuta cuando se completó el pago. Este callback contiene un parámetro de tipo Json con la información de la orden. |
| ✅ | ✅ | Se ejecuta cuando ocurre un error. Este callback contiene un parámetro tipo PaymentsError el cual identifica el tipo de error producido. Consulta un ejemplo de la respuesta del callback aquí. |
| ✅ | ❌ | Se ejecuta cuando se cierra el dialogo que contiene el widget de pago. Este callback contiene un parámetro de tipo enum
|
| ✅ | ✅ | Se ejecuta cuando el widget de pago detecta el BIN de una tarjeta de crédito o débito ingresada o cuando el usuario borra el número de la tarjeta ingresada. Este callback contiene un parámetro de tipo **Json ** con la información del bin y la marca de la tarjeta ingresada. NOTA: El parámetro de tipo |
| ✅ | ✅ | Si la orden se puede diferir, este callback se ejecutará cuando el usuario seleccione los meses a diferir. Este callback contiene un parámetro de tipo **Json ** con la información de los meses a diferir seleccionados por el usuario. NOTA: El parámetro de tipo |
| ✅ | ✅ | Este callback se ejecutará cuando el usuario presiona en el botón pagar y se esta procesando el pago. NOTA: Si existe algún campo incorrecto en el formulario de pago este evento no se ejecutará. |
| ✅ | ✅ | Se ejecuta en todas los eventos que pueda producir el widget. |
Utiliza el callback onError para identificar si el widget no puedo ser mostrado o si ocurrió un error al procesar el pago.
onError: async (error) => {
// Assuming the error object has a 'type' property similar to PaymentsError.Type
switch (error.type) {
// The widget could not be loaded
case 'INITIALIZATION_FAILED': {
async deunaSDK.close();
break;
}
// The payment failed
case 'PAYMENT_ERROR': {
// YOUR CODE HERE
console.error('Payment failed:', error);
break;
}
// Default case for other error types
default: {
console.warn('Unhandled error type:', error.type);
break;
}
}
}
5. Cierra el Widget
La función close
libera los recursos del widget de pago y si este fue mostrado en un modal también lo cierra.
Es muy importante liberar los recursos del widget cuando ya no lo necesitas para evitar perdida de memoria.
El siguiente código de ejemplo muestra cómo cerrar el widget cuando un pago es exitoso.
deunaSDK.initPaymentWidget({
// In React/Web environment, we don't need activity context
orderToken: "<DEUNA order token>",
userToken: "<DEUNA user token>", // optional
callbacks: {
onSuccess: async(order: any) => {
await deunaSDK.close(); // Close payment widget
// Your additional success handling code
console.log('Payment successful', order);
// Example: Redirect to success page
},
}
});
Cuando el widget de DEUNA se muestra en un Modal, los recursos del mismo son liberados cuando el Modal es cerrado.
Si el widget se muestra de forma embebida y el usuario abandona tu vista es necesario liberar los recursos del widget.
import { DeunaSDK, DeunaWidget, Mode } from "@deuna/react-native-sdk";
const YourScreen = () => {
useEffect(() => {
return () => {
deunaSDK.close(); // Release the widget resources
};
}, []);
const onShowWidget = () => {
deunaSDK.initPaymentWidget({
orderToken: "TOKEN", // optional
mode: Mode.EMBEDDED,
callbacks: {...},
});
return (
<View>
<View style={{ flex: 1, width: "100%" }}>
<DeunaWidget instance={deunaSDK} />
</View>
<Button onPress={onShowWidget} title="Show Payment Widget"></Button>
</View>
);
};
};
Funcionalidades opcionales
Además de los pasos obligatorios para operar el widget, tienes las siguientes opciones de personalización:
Personalizar la apariencia del widget
Utiliza la función setCustomStyle
para personalizar la apariencia del Widget.
await DeunaSDK.setCustomStyle({...});
Para más información, ve a Personalización de estilos.
Ejemplo
deunaSDK.initPaymentWidget({
orderToken: "<DEUNA order token>",
userToken: "<DEUNA user token>", // optional
callbacks: {
onCardBinDetected: (cardBinMetadata: any) => {
deunaSDK.setCustomStyle({
theme: {
colors: {
primaryTextColor: "#023047",
backgroundSecondary: "#8ECAE6",
backgroundPrimary: "#F2F2F2",
buttonPrimaryFill: "#FFB703",
buttonPrimaryHover: "#FFB703",
buttonPrimaryText: "#000000",
buttonPrimaryActive: "#FFB703"
}
},
HeaderPattern: {
overrides: {
Logo: {
props: {
url: "https://images-staging.getduna.com/ema/fc78ef09-ffc7-4d04-aec3-4c2a2023b336/test2.png"
}
}
}
}
});
},
onSuccess: async(order: any) => {
await deunaSDK.close();
// Your success handling
}
// ... other callbacks
}
});
Refrescar el widget de pago
La función refetchOrder
actualiza el widget de pago y retorna los datos de la orden actualizada.
Esta función es útil, por ejemplo, cuando el comercio ofrece promociones. Un caso común es una "promoción del 20% al pagar con Mastercard".
En este escenario, el comercio escucha el evento onCardBinDetected para identificar la franquicia de la tarjeta. Luego, el comercio actualiza la orden en DEUNA (siendo el responsable de calcular las promociones) y, a través de esta función, notifica al widget para que se actualice, ya que el monto de la orden podría haber cambiado.
A continuación se muestra un ejemplo del uso de la función refetchOrder
.
deunaSDK.initPaymentWidget({
orderToken: "<DEUNA order token>",
userToken: "<DEUNA user token>", // optional
callbacks: {
onCardBinDetected: async (metadata) => {
if (metadata.cardBrand === "Mastercard") {
const order = await deunaSDK.refetchOrder();
console.log("Refetched order:", order);
}
},
}
});
Ocultar el botón de pago (Widget Embebido)
Cuando se muestra el widget de pago de forma embebida se puede utilizar la propiedad hidePayButton
para esconder el botón de pago del DeunaWidget.
deunaSDK.initPaymentWidget({
orderToken: "YOUR_ORDER_TOKEN",
mode: Mode.EMBEDDED, // AGREGAR ESTA LINEA
hidePayButton: true, // AGREGAR ESTA LINEA
callbacks: {
onSuccess: async (order) => {
await deunaSDK.close(); // Libera los recursos del widget de pago.
// TU CÓDIGO AQUÍ
},
onError: (error) => {
// Manejo de errores
},
onClosed: (action) => {
// Widget cerrado
},
},
});
Puedes emplear las siguientes funciones para validar y ejecutar el pago.
Método | Descripción | Respuesta |
---|---|---|
.isValid() | Valida si la información ingresada es correcta y si el pago puede ser procesado. | true si la información es válida, false en caso contrario. |
.submit() | Ejecuta el proceso de pago, equivalente a presionar el botón de pagar. Realiza las mismas validaciones internas. | { status: "success", message: "Pago procesado exitosamente" } o { status: "error", message: "The submit flow is not available" } |
Consideraciones
- Se recomienda usar
isValid()
antes de llamar asubmit()
para evitar errores en el proceso de pago. - Si el flujo de pago aún no está disponible,
submit()
siempre devolverá un error con el mensaje"The submit flow is not available"
.