Payment Vault - React Native

Los widgets de nuestra bóveda de pagos es la manera de integrar funcionalidades como wallets, tokenización, etc. sin procesar el pago.

La bóveda de pagos de DEUNA son distintos tipos de widgets que permiten a nuestros comercios realizar tareas como:

  • Guardar tarjetas de crédito y débito de forma segura por medio de nuestro VAULT Widget.

  • Realizar pagos con Click To Pay por medio de nuestro Click To Pay Widget.

    • Ejemplo:


Paso 1: Completar los Primeros Pasos

Antes de integrar los widgets, es necesario que completes la sección de primeros pasos. En esta sección, te explicamos los requisitos necesarios y cómo inicializar el SDK. Puedes encontrar más información en Primeros Pasos con el SDK de Android.

Una vez que hayas completado estos pasos, podrás continuar con el paso 2.

Paso 2: Mostrar un Widget

2.1 Mostrar el Widget en un Modal

Sigue los siguientes pasos para mostrar el Vault Widget de DEUNA en un Modal:

  1. Crea una instancia de la clase DeunaSDK.
  2. Agrega el componente DeunaWidget a tu vista.
  3. Llama a la función initElements.
import { DeunaSDK, DeunaWidget } from "@deuna/react-native-sdk";

const YourScreen = () => {
  const onShowWidget = () => {
    deunaSDK.initElements({
      userToken: "<DEUNA user token>", // optional
      userInfo: {
        firstName: "Esteban",
        lastName: "Posada",
        email: "[email protected]",
      }, // optional
      callbacks: {
        onSuccess: async (data) => {
          await deunaSDK.close(); // Close the widget
          console.log("Success", data);
          // Handle success
        },
        onError: async (error) => {
          console.error("Error:", error);
          await deunaSDK.close(); // Close the widget
          // Handle error
        },
        onClosed: (action) => {
          console.log("Widget closed with action:", action);
          // Handle close action
        },
        onEventDispatch: (type, response) => {
          console.log("Event:", type, response);
          // Handle specific events
        },
      },
      widgetExperience: {
        userExperience: {
          showSavedCardFlow: false, // optional
          defaultCardFlow: false, // optional
        },
      },
    });

    return (
      <View>
        <DeunaWidget instance={deunaSDK} />
        <Button
          onPress={onShowPaymentWidget}
          title="Show Widget"
        ></Button>
      </View>
    );
  };
};

2.1. 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 initElements.

IMPORTANTE: Para visualizar correctamente el widget de DEUNA de forma embebida, el componente DeunaWidget debe estar dentro de un componente que delimite sus dimensiones.

import {
  DeunaSDK,
  DeunaWidget,
  Mode, // AGREGAR ESTA LINEA
} from "@deuna/react-native-sdk";

const YourScreen = () => {
  const onShowWidget = () => {
    deunaSDK.initElements({
      userToken: "<DEUNA user token>", // optional
      mode: Mode.EMBEDDED,
      userInfo: {
        firstName: "Esteban",
        lastName: "Posada",
        email: "[email protected]",
      }, // optional
      callbacks: {
        onSuccess: async (data) => {
          await deunaSDK.close(); // Close the widget
          console.log("Success", data);
          // Handle success
        },
        onError: async (error) => {
          console.error("Error:", error);
          await deunaSDK.close(); // Close the widget
          // Handle error
        },
        onClosed: (action) => {
          console.log("Widget closed with action:", action);
          // Handle close action
        },
        onEventDispatch: (type, response) => {
          console.log("Event:", type, response);
          // Handle specific events
        },
      },
    });

    return (
      <View>
        {/* Delimita las dimensiones del Widget */}
        <View style={{ flex: 1, width: "100%" }}>
          <DeunaWidget instance={deunaSDK} />
        </View>
        <Button onPress={onShowWidget} title="Show Payment Widget"></Button>
      </View>
    );
  };
};

Parámetros

ParámetroDescripción
callbacksCallbacks que serán llamados en caso de éxito, error, o cuando el widget se cierre.
userToken (Opcional)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.

Importante: para que este userToken sea usado y se le muestren las tarjetas guardadas al cliente, el correo asociado a ese userToken debe ser el mismo que se envía al crear la orden en billing_address.email en caso que se le pase un orderToken. En caso que ambos correos no coincidan, se usará el flujo sin mostrar las tarjetas por seguridad.

https://docs.deuna.com/reference/users-register
https://docs.deuna.com/reference/request-otp
https://docs.deuna.com/reference/login-with-otp
orderToken(Opcional)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.

IMPORTANTE: Se puede extraer la información de usuario que esta disponible en billing_address para usar dentro del widget.
userInfo(Opcional)Información de usuario que se pasara al widget, información posible disponible a pasar son: email, firstName, lastName. Estos campos NO son necesarios en caso que se use un userToken.
styleFile (Opcional)UUID proporcionado por DEUNA. Esto aplica si quieres configurar un archivo custom styles personalizado (Cambiar colores, textos, logo, etc). Si se proporciona un valor válido para styleFile el vault widget utilizará la configuración de la UI proporcionada por la configuración del tema que coincida con el UUID proporcionado.
types(Opcional)Un listado de los tipos de widgets que debe renderizar la función initElements.

Los valores permitidos son: vault y click_to_pay .

Ejemplo: [ { "name": "click_to_pay" } ]

NOTA: Si no se pasa este parámetro por defecto se mostrará el Vault Widget de DEUNA para guardar tarjetas de crédito y débito.
language(Opcional)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:

- Si se proporciona: El widget utilizará el idioma especificado en este parámetro, independientemente de la configuración del comerciante.
- Si no se proporciona: El widget utilizará el idioma configurado por el comerciante.
widgetExperience(Opcional)Sobreescribe las configuraciones del merchant. Actualmente soportadas por el widget son las siguientes:

userExperience.showSavedCardFlow: Muestra toggle de guardado de tarjetas.
userExperience.defaultCardFlow: Muestra toggle para guardar la tarjeta como predeterminada.
hidePayButton (Opcional)Si se establece en true, el botón de pago del widget se ocultará, permitiendo que la gestión del pago sea completamente manual. Esto significa que el usuario deberá llamar explícitamente a los métodos isValid() y submit() para procesar la transacción.

Click To Pay Widget

Usando el parámetro types de la función initElements puedes realizar un pago con Click To Pay. El siguiente fragmento de código muestra como mostrar el ClickToPay widget:

NOTA: El parámetro userInfo es obligatorio para poder mostrar el ClickToPay widget.

deunaSDK.initElements({
  // In web context, we don't need the 'context' parameter
  userInfo: {
    firstName: "Esteban",
    lastName: "Posada",
    email: "[email protected]"
  }, // Required for Click to Pay
  types: [
    {
      name: "click_to_pay" // Shows Click to Pay widget
    }
  ],
  callbacks: {
    onSuccess: async (data) => {
      await deunaSDK.close();
      console.log('Success', data);
      // Handle successful payment
    },
    onEventDispatch: (eventType, data) => {
      console.log('Event:', eventType, data);
      // Handle specific events
    },
    onError: (error) => {
      console.error('Error:', error);
      // Handle payment error
    },
    onClosed: (action) => {
      console.log('Widget closed:', action);
      // Handle widget close
    }
  }
}); 

Paso 3: Escuchar los Eventos de un Widget

Es crucial manejar adecuadamente los eventos del Widget para ofrecer una experiencia fluida a los usuarios. Define los callbacks necesarios para actualizar la interfaz de tu aplicación.

3.1 Callbacks

CallbackModalEmbedded¿Cuándo se dispara?
onSuccessSe ejecuta cuando una tarjeta se guarda exitosamente o cuando el pago con Click to Pay fue exitoso. Este callback contiene un parámetro de tipo Json .
onErrorSe ejecuta cuando ocurre un error al guardar la tarjeta. Este callback contiene un parámetro tipo JSON el cual identifica el tipo de error producido.
onClosed
(Opcional)
Se ejecuta cuando se cierra el widget de pago.

Este callback contiene un parámetro de tipo string cuyos valores pueden ser uno de los siguientes:

- userAction: Cuando el widget fue cerrado manualmente por el usuario (presionando en el botón cerrar X) sin que la operación se haya completado.

- systemAction: Cuando el widget se cierra debido a la ejecución de la función close.
onCardBinDetected (Opcional)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 JSON será nulo cuando el usuario elimina el texto ingresado en el campo del número de tarjeta.
onEventDispatch (Opcional)Se ejecuta en todas los eventos que pueda producir el widget.
Este callback contiene un parámetro de tipo string y la data (JSON) asociada a dicho evento

Paso 4: Cerrar 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 se tokeniza una tarjeta de forma exitosa.

deunaSDK.initPaymentWidget({
  .
  .
  .
  callbacks: {
    onSuccess: async(data) => {
      await deunaSDK.close(); // Close payment widget
      // 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. Sin embargo 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.initElements({
      userToken: "<DEUNA user token>", // optional
      mode: Mode.EMBEDDED,
      userInfo: {...}, // optional
      callbacks: {...},
    });

    return (
      <View>
        {/* Delimita las dimensiones del Widget */}
        <View style={{ flex: 1, width: "100%" }}>
          <DeunaWidget instance={deunaSDK} />
        </View>
        <Button onPress={onShowWidget} title="Show Widget"></Button>
      </View>
    );
  };
};



Paso 5 (Opcional): Personalizar la apariencia del widget

Si el vault widget esta visible y quieres personalizar la apariencia del mismo utiliza la función setCustomStyle.

Consulta la siguiente documentación para conocer más a detalle todas las opciones de personalización del vault widget.

A continuación se muestra como cambiar los colores y el logo del vault widget mediante setCustomStyle

deunaSDK.initElements({
  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
  }
});

Ocultar el botón de pago (Widget Embebido)

Cuando se muestra el widget de forma embebida se puede utilizar la propiedad hidePayButton para esconder el botón de pago del DeunaWidget.

deunaSDK.initElements({
  ...
  mode: Mode.EMBEDDED, // AGREGAR ESTA LINEA
  hidePayButton: true, // AGREGAR ESTA LINEA
  callbacks: {...},
});

Puedes emplear las siguientes funciones para validar y ejecutar el pago.

MétodoDescripciónRespuesta
.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 a submit() 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"