Payment Widget - iOS

Con el Payment Widget de DEUNA, acepta pagos de forma ágil y rápida en tu app iOS. Sigue los siguientes pasos para capturar un pago utilizando el Payment Widget.

Paso 1: Completar los Primeros Pasos

Antes de integrar el Payment Widget, 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 iOS.

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

Paso 2: Mostrar el Widget

Para mostrar el Payment Widget, llama a la función initPaymentWidget pasando los siguientes datos:

deunaSDK.initPaymentWidget(
  orderToken: "<DEUNA order token>",
  userToken: "<DEUNA user token>", // optional
  cssFile: "<DEUNA theme ID to customize the look and feel of the widget>", // optional
  callbacks: PaymentWidgetCallbacks(
    onSuccess: { data in
      self.deunaSDK.close() // Cierra el widget de pago
    },
    onError: { type in
      // Manejo de errores
    },
    onClosed: {
      // Widget cerrado
    },
    onCanceled: {
      // El widget de pago fue cerrado por el usuario
      // No es necesario llamar a closePaymentWidget(...)
    },
    onCardBinDetected: { metadata, refetchOrder in
      guard metadata != nil else {
        // Tu código aquí
      }
    }
  )
)

Parámetros

AtributosDescripción
orderTokenEl 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.
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 ambos correos no coincidan, se usará el flujo sin mostrar las tarjetas por seguridad.
callbacksLos 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: onSuccess, onError, onClosed, onCanceled, onCardBinDetected, onInstallmentSelected
cssFile
(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 cssFile el payment widget utilizará la configuración de la UI proporcionada por la configuración del tema que coincida con el UUID proporcionado.
paymentMethods (Opcional)Una lista métodos de pago permitidos. Este parámetro determina qué tipo de widget se debe renderizar.

Ejemplo uso del parámetro paymentMethods

deunaSDK.initPaymentWidget(
  orderToken: "<DEUNA order token>",
  userToken: ..., // optional
  cssFile: ..., // optional
  callbacks: ...,
  paymentMethods: [
    [ 
  		"payment_method": "voucher",
      		"processors": ["daviplata", "nequi_push_voucher"]
   ],
    [
  		"payment_method": "paypal",
      		"processors": ["paypal"]
    ]
  ]
)

Prioridad métodos de pago

PrioridadFuente de ConfiguraciónDescripciónComportamiento en caso de un solo método de pago
1Métodos de pago pasados al ejecutar la función .initPaymentWidgetLos 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.
2Orden e include_payment_optionsSe revisa la orden para verificar si include_payment_options tiene métodos de pago que estén configurados y activados a nivel comercio. Los métodos no configurados no se muestran.Si solo se pasa un método de pago, el widget abre automáticamente el formulario del método de pago sin mostrar botones.
3Métodos configurados a nivel comercio
(API /payment-methods)
Si no se pasa ningún método de pago ni en la función .initPaymentWidget ni en include_payment_options al momento de crear la order, se toman los métodos 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.

Paso 3: Escuchar los Eventos del Widget de Pago

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 instancia de la clase PaymentWidgetCallbacks pasada a la función initPaymentWidget te permite escuchar los eventos del widget mediante callbacks. Define los callbacks respectivos para actualizar la interfaz de tu app.

3.1. Callbacks

Callback¿Cuándo se dispara?
onSuccessSe ejecuta cuando se completó el pago. Este callback contiene un parámetro de tipo [String:Any] con la información de la orden.
onCanceledSe ejecuta cuando el usuario de forma intencional cierra el widget de pago (presionando el botón X o deslizando el modal hacia abajo) sin que la operación se haya completado.
onErrorSe ejecuta cuando ocurre un error al procesar el pago. Este callback contiene un parámetro tipo enum PaymentsError el cual identifica el tipo de error producido al momento de procesar el pago.
onClosed (Opcional)Se ejecuta cuando se cierra el widget de pago, independientemente si el pago se realizó con éxito, ocurrió un error o el usuario canceló la operación.

NOTA: El orden de ejecución de onCanceled y onClosed es el siguiente:

- Si el usuario cierra manualmente el widget (presionando el botón X o deslizando el modal hacia abajo):
onCanceled > onClosed.

- Si se cierra el widget mediante código llamando a closePaymentWidget, solo se ejecuta onClosed.
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 [String:Any] con la información del bin y la marca de la tarjeta ingresada.
NOTA: El parámetro de tipo CardBinMetadata será nulo cuando el usuario elimina el texto ingresado en el campo del número de tarjeta.
onInstallmentSelected (Opcional)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 [String:Any] con la información de los meses a diferir seleccionados por el usuario.
onPaymentProcessing (Opcional)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á.
onEventDispatch (Opcional)Se ejecuta en todas los eventos que pueda producir el widget.
Este callback contiene un parámetro de tipo CheckoutEvent y la data asociada a dicho evento.

NOTA: En los callbacks onCardBinDetected y onInstallmentSelected segundo el parámetro refetchOrder es una función que se puede utilizar para refrescar los datos de la orden en el formulario de pagos. El dato retornado por la función refetchOrder es un closure con los datos de la orden o un valor nulo si ocurrió un error al momento de ejecutar la función refetchOrder.

Ejemplo:

       deunaSDK.initPaymentWidget(
            orderToken: ...,
            callbacks: PaymentWidgetCallbacks(
                onSuccess: ...,
                onError: ...,
                onClosed: ...,
                onCanceled: ...,
                onCardBinDetected: { metadata, refetchOrder in

                    guard metadata != nil else {
                        return
                    }

                    refetchOrder { order in
                        print("✋  onCardBinDetected > refetchOrder \(order?.formattedJson() ?? "nil")")
                    }

                },
                onInstallmentSelected: { metadata, refetchOrder in

                    guard metadata != nil else {
                        return
                    }

                    refetchOrder { order in
                        print("✋  onInstallmentSelected > refetchOrder: \(order?.formattedJson() ?? "nil")")
                    }
                },
                onPaymentProcessing: ...,
                onEventDispatch: ...
            ),
            userToken: ...,
            paymentMethods: ...,
            checkoutModules: ...
        )

Paso 4 (Opcional): Cerrar el Widget

Por defecto, el widget de pago solo se cierra cuando el usuario presiona el botón de cerrar del widget o cuando presiona el botón de "retroceso" en iOS. Para cerrar el modal cuando un pago es exitoso o cuando ocurre un error, debes llamar a la función close.

El siguiente código de ejemplo muestra cómo cerrar el widget cuando un pago es exitoso:

deunaSDK.initPaymentWidget(
  orderToken: "<DEUNA order token>",
  userToken: "<DEUNA user token>", // optional
  callbacks: PaymentWidgetCallbacks(
     onSuccess: { data in
         self.deunaSDK.close() // Cierra el widget de pago
         // Tu código adicional
     },
     onError: nil,
  	...
  )
)

Paso 5 (Opcional): Personalizar la apariencia del widget

Si el payment 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 payment widget.

A continuación se muestra un ejemplo de como cambiar los colores y el logo del payment widget mediante setCustomStyle

// Extension to convert a String to a Dictionary(JSON)
extension String {
    func toDictionary() -> [String: Any]? {
        guard let data = data(using: .utf8) else {
            return nil
        }
        do {
            let dictionary = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
            return dictionary
        } catch {
            print("Error: \(error.localizedDescription)")
            return nil
        }
    }
}

.
.
.


deunaSDK.initPaymentWidget(
  orderToken: "<DEUNA order token>",
  userToken: "<DEUNA user token>", // optional
  callbacks: PaymentWidgetCallbacks(
     onCardBinDetected: { metadata, refetchOrder in
       self.deunaSDK.setCustomStyle(data: """
                        {
                          "theme": {
                            "colors": {
                              "primaryTextColor": "#023047",
                              "backgroundSecondary": "#8ECAE6",
                              "backgroundPrimary": "#8ECAE6",
                              "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"
                                }
                              }
                            }
                          }
                        }
                        """.toDictionary() ?? [:]
        )     
     }
  	...
  )
)

Paso 6 (Opcional): Revisar Ejemplo Demo App

Para comprender mejor la integración del Payment Widget, revisa el proyecto de ejemplo proporcionado por DEUNA. Este ejemplo te ayudará a entender mejor cómo implementar el widget en tu aplicación iOS.

Para acceder al proyecto de ejemplo y obtener más información, Consulta la documentación del Ejemplo de Proyecto para iOS.