Full SDK (iOS)


👍

SDK recomendado

Recomendamos utilizar el Seamless SDK iOS para una experiencia de integración sin problemas. Esta opción ofrece una solución de pago flexible con componentes de interfaz de usuario predefinidos y opciones de personalización.

Esta página proporciona todos los pasos para añadir, configurar y utilizar el SDK completo de iOS en tu proyecto.

Requisitos

Para implementar el SDK de Yuno iOS, necesitas cumplir los siguientes requisitos:

Paso 1: Incluya la biblioteca en tu proyecto

Puede agregar la biblioteca usando CocoaPods o Swift Package Manager.

CocoaPods

Para añadir el SDK de Yuno a tu proyecto iOS, necesitas instalar el SDK de Yuno. Si no tienes un Podfile, sigue la guía de CocoaPods para crear uno. Después de crear el Podfile, integrarás el SDK de Yuno con Cocoapods añadiendo la siguiente línea a tu Podfile.

pod 'YunoSDK', '~> 1.1.22'

Después, necesita ejecutar la instalación:

instalar pod

Administrador de Paquetes Swift

Para añadir el SDK de Yuno a tu proyecto iOS, necesitas instalar el archivo Administrador de Paquetes Swift. Con el paquete Swift configurado, añade YunoSDK como dependencia, tal y como se presenta en el siguiente bloque de código:

dependencias: [
    .package(url: "https://github.com/yuno-payments/yuno-sdk-ios.git", .upToNextMajor(from: "1.1.17"))
]

Paso 2: Initialize el SDK con la clave pública

Para empezar a ejecutar la comprobación completa de Yuno para iOS, primero obtén el ID de tu aplicación Yuno y la Clave Pública de la API. Después, importa e initialize Yuno como se muestra a continuación:

import YunoSDK

Yuno.initialize(
    apiKey: "PUBLIC_API_KEY",
    config: YunoConfig(),
    callback: { (value: Bool) in }
)
📘

Credenciales

Para más información, consulte la página de credenciales: https://docs.y.uno/reference/authentication

🚧

Uso de UISceneDelegate

Si su aplicación utiliza un UISceneDelegate, asegúrese de colocar el código de inicialización de Yuno dentro de su SceneDelegate.

La comprobación completa le permite configurar la apariencia y el proceso. Se trata de un paso opcional que se configura a través de la clase YunoConfig. Si desea establecer las configuraciones, el siguiente bloque de código muestra los elementos que pueden configurarse:

final class YunoConfig {
    let cardFormType: CardFormType,
    let appearance: Yuno.Appearance,
    let saveCardEnabled: Bool,
    let keepLoader: Bool
}

Configura el SDK con las siguientes opciones:

ParámetroDescripción
cardFormTypeEste campo se puede utilizar para elegir el flujo de pago y Tarjeta de Inscripción. Es una propiedad opcional y considera .oneStep por defecto.
appearanceEste campo opcional define la apariencia de la caja. De forma predeterminada, utiliza los estilos de Yuno.
saveCardEnabledEste campo opcional se puede utilizar para elegir si la casilla de verificación Guardar tarjeta se muestra en los flujos de tarjetas. Por defecto es falso.
keepLoaderEste campo opcional proporciona control sobre cuándo ocultar el cargador. Si se establece en true, la hideLoader() se debe llamar a la función para ocultar el cargador. De forma predeterminada, está configurado en false.
hideCardholderNameEste campo opcional te permite ocultar el campo del nombre del titular de la tarjeta en el formulario de la tarjeta. Cuando se establece en true, el campo del nombre del titular de la tarjeta no se muestra. Cuando no se especifica o se establece en false, se muestra el campo del nombre del titular de la tarjeta (comportamiento predeterminado). Ocultar el campo no afecta al PAN, la caducidad, la recopilación del CVV, la lógica BIN ni las validaciones 3DS/proveedor. El comerciante es responsable de garantizar que se proporcione el nombre del titular de la tarjeta cuando lo requiera tu pago .
📘

Acceda a su clave API

Recupera tu Clave API de la sección de Desarrolladores en el Panel de Control de Yuno.

Paso 3: Iniciar el proceso de pago

La clase ViewController se define como una subclase de UIViewController y también adopta el protocolo YunoPaymentDelegate protocolo.

❗️

Deprecación

El objeto startCheckout ha quedado obsoleto en las últimas versiones del SDK de iOS.

protocol YunoPaymentDelegate: AnyObject {

    var checkoutSession: String { get }
    var countryCode: String { get }
    var language: String? { get }
    var viewController: UIViewController? { get }

    func yunoCreatePayment(with token: String)
    func yunoCreatePayment(with token: String, information: [String: Any])
    func yunoPaymentResult(_ result: Yuno.Result)
}


class ViewController: YunoPaymentDelegate {

    func viewDidLoad() {
        super.viewDidLoad()
    }
}

Parámetros

ParámetroDescripción
checkoutSessionSe refiere a la sesión de checkout del pago actual.
countryCodeEste parámetro determina el país para el que se está configurando el proceso de pago. La lista completa de países admitidos y su código de país está disponible en la página Cobertura de países.
languageDefine el idioma que se utilizará en los formularios de pago. Puede establecerlo en una de las opciones de idioma disponibles:
  • es (español)
  • en (Inglés)
  • pt (portugués)
  • fil (filipino)
  • id (indonesio)
  • ms (malayo)
  • th (tailandés)
  • zh-TW (chino (tradicional, Taiwán))
  • zh-CN (chino simplificado, China)
  • vi (vietnamita)
  • fr (francés)
  • pl (polaco)
  • eso (italiano)
  • de (alemán)
  • ru (ruso)
  • tr (turco)
  • nl (holandés)
  • sv (sueco)
  • ko (coreano)
  • ja (japonés)
viewControllerEsta propiedad representa la UIViewController utilizado para presentar el flujo de pago . Aunque la propiedad sigue siendo opcional por compatibilidad con versiones anteriores, debes proporcionar un controlador visible para que el SDK pueda presentar su interfaz de usuario correctamente.
yunoCreatePayment(with token: String)Este método es responsable de crear un pago con el token proporcionado. Toma un parámetro String llamado token, que representa el token de pago.
yunoCreatePayment(with token: String, information: [String: Any])Este método es responsable de crear un pago con el token proporcionado. Toma un parámetro String llamado token, que representa el token de pago. Además, devuelve toda la información de respuesta del token en un diccionario.
yunoPaymentResult(_ result: Yuno.Result)Este método se llama cuando se completa el proceso de pago, proporcionando el resultado del pago como parámetro de tipo Yuno.Result.
❗️

Nota importante sobre yunoCreatePayment

Puedes llamar yunoCreatePayment con o sin el information Parámetro según sus necesidades. Sin embargo, utiliza solo una versión en tu código, ya que llamar a ambas no es obligatorio y podría causar problemas.

🚧

Requisitos de concurrencia de Swift 6

Si está utilizando Swift 6, deberá implementar el YunoPaymentDelegate Protocolo con consideraciones específicas de concurrencia. Swift 6 introduce requisitos de seguridad de subprocesos más estrictos que afectan la implementación de delegados. Consulte Implementando YunoPaymentDelegate con concurrencia Swift 6 Sección para opciones de implementación detalladas y mejores prácticas.

Paso 4: Añadir la vista SDK a la caja

Su punto de vista debe adoptar la YunoPaymentFullDelegate protocolo. Esto permite que su aplicación responda a acciones pago, como cuando el usuario selecciona un método de pago.

He aquí cómo definir el delegado:

protocol YunoPaymentFullDelegate: YunoPaymentDelegate {
    func yunoDidSelect(paymentMethod: YunoSDK.PaymentMethodSelected)
    func yunoDidUnenrollSuccessfully(_ success: Bool)
    func yunoUpdatePaymentMethodsViewHeight(_ height: CGFloat)
}

Parámetros

FunciónDescripción
yunoDidSelect(paymentMethod: YunoSDK.PaymentMethodSelected)Llamada cuando el usuario selecciona un método de pago.
- paymentMethod: El método elegido por el usuario.
yunoDidUnenrollSuccessfully(_ success: Bool)Llamada cuando finaliza una acción de desinscripción.
- success: true si funcionara, false si no lo hiciera.
yunoUpdatePaymentMethodsViewHeight(_ height: CGFloat)Llamado cuando getPaymentMethodViewAsync() Se invoca siempre que cambia la altura de la vista.

Para mostrar los métodos de pago, llame al siguiente método y pase su modelo de vista o controlador como delegado.

await Yuno.getPaymentMethodViewAsync(delegate:)

Este método devolverá automáticamente el tipo correcto de vista dependiendo del framework de interfaz de usuario que esté utilizando:

  • Si utiliza UIKit, devuelve un UIView.
  • Si utiliza SwiftUI, devuelve un some View.

Esto facilita la integración del SDK en cualquier proyecto iOS, independientemente del framework de interfaz de usuario que se utilice.

Paso 5: Iniciar el proceso de pago

Para iniciar un pago después de mostrar los métodos de pago, llame a la función startPayment :

Yuno.startPaymentshowPaymentStatus:Bool)

Paso 6: Obtener el OTT ( token de un solo uso)

Puedes obtener el token único para realizar el pago consecutivo al final de este proceso. Recibirás el token único en la función. yunoCreatePayment() que implementa al adoptar el YunoPaymentDelegate. A continuación se muestra un ejemplo de recuperación del token de un solo uso:

func yunoCreatePayment(with token: String) { ... }

Paso 7: Crear el pago

Una vez completados los pasos descritos anteriormente, puede crear un pago. La creación de pagos consecutivos debe realizarse utilizando el endpoint Create Payment . El comerciante debe llamar a su backend para crear el pago dentro de Yuno, utilizando el token de un solo uso y la sesión de pago.

📘

Continuar con el método de pago

Para garantizar una experiencia de pago fluida, es fundamental integrar el método continuePayment después de crear un pago. Este paso es especialmente importante para los métodos de pago asíncronos que requieren acciones adicionales del cliente. Esto es lo que necesita saber:

  • Manejo de pagos asincrónicos:La API indicará la necesidad de tomar medidas adicionales con el sdk_action_required campo establecido en verdadero.
  • Funcionalidad: El yuno.continuePayment() Esta función está diseñada para administrar y mostrar cualquier pantalla adicional necesaria para que el cliente complete el pago.
  • Simplificación del proceso: Al utilizar este método, puede agilizar el proceso de pago, ya que maneja automáticamente varios escenarios para usted.
YunocontinuePayment()

Paso 8: Gestionar pago (opcional)

🚧

Enlaces profundos y Mercado Pago Checkout Pro

Este paso solo es necesario si utilizas un método de pago que utiliza enlaces profundos o Mercado Pago Checkout Pro. Si tus métodos de pago no utilizan enlaces profundos, puedes omitir este paso.

Algunos métodos de pago sacan a los usuarios de la app para completar la transacción. Una vez finalizado el pago, se redirige al usuario a la app mediante un enlace profundo. El SDK utiliza este enlace profundo para comprobar qué ha sucedido, verificando si el pago se realizó correctamente, falló o se canceló, y puede mostrar una pantalla de estado al usuario.

Para solucionar esto, necesita actualizar su AppDelegate Para devolver la URL entrante al SDK de Yuno. Esto permite que el SDK lea el resultado y, opcionalmente, muestre el estado del pago. El siguiente fragmento de código muestra cómo añadirlo a la aplicación:

func application(_ app: UIApplication,
                 open url: URL,
                 options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {

  guard url.scheme == "yunoexample" else { return false }

  return Yuno.receiveDeeplink(url)
}

Este código detecta enlaces profundos que abren tu aplicación. Al recibir una URL, comprueba si el esquema coincide con el que usaste en el callback_url durante la configuración de la sesión de pago. Si coincide, la URL se pasa al SDK de Yuno mediante Yuno.receiveDeeplink(...)Luego, el SDK lee el resultado del pago y muestra la pantalla de estado correspondiente al usuario.

Asegúrese de que url.scheme En este código coincide con el callback_url que usted proporcionó al crear el checkout_session.

Llamar de vuelta

Una vez que se completa el pago, el SDK puede devolver diferentes estados de transacción: success, fail, processing, reject, internalErrory userCancell. Las descripciones de cada estado de transacción se presentan en la siguiente tabla.

Estado de la transacciónDescripción
succeededIndica que el proceso de transacción o pago se ha completado con éxito.
failEste estado indica que la transacción o el proceso de pago ha fallado. Significa que hubo un error o problema durante el proceso de pago, impidiendo que se completara exitosamente.
processingIndica que el proceso de transacción o pago se está procesando actualmente. Por lo general, se usa cuando hay un retraso en el procesamiento del pago, como esperar la aprobación de un servicio de terceros o una institución financiera.
rejectEste estado indica que la transacción ha sido rechazada. El rechazo puede ocurrir por varios motivos, como fondos insuficientes, actividad fraudulenta o solicitudes que violen reglas o políticas específicas.
internalErrorSignifica que ocurrió un error inesperado dentro del sistema o la infraestructura que maneja el proceso de pago. Este estado sugiere un problema en el servidor o en el backend en lugar de un problema con la entrada o solicitud del usuario.
userCancellEste estado indica que el usuario ha cancelado o abortado voluntariamente la transacción o proceso de pago. Este estado generalmente se usa cuando existe una opción para que el usuario cancele o abandone el proceso de pago.

Validación pago

En esta sección se explica cómo gestiona el SDK pago cuando los usuarios cancelan o abandonan pago , y cómo se relaciona el estado del SDK con pago del backend en estos casos.

Sincronizar pago (Apple Pay)

En el caso de pago sincrónicos, como Apple Pay, cuando tú cancelas o cierras la interfaz de usuario de la cartera antes de recibir la respuesta del proveedor pago (PSP):

  • Estado del SDK: Devoluciones userCancell (CANCELLED)
  • pago en el backend: Restos PENDING hasta el tiempo de espera de PSP o la cancelación por parte del comerciante
  • ImportanteEl SDK no devolverá reject o processing en este escenario

Esto garantiza que el pago backend pago en estado pendiente y pueda ser gestionado correctamente por el sistema del comerciante.

pago asíncronos (métodos basados en PIX y QR)

Para pago asíncronos como PIX, cuando tú cierras la ventana del código QR (haces clic en X) antes de completar el pago:

  • Estado del SDK: Devoluciones PENDING, opcionalmente con un subestado como CLOSED_BY_USER
  • pago en el backend: Restos PENDING y el código QR sigue siendo válido hasta su fecha de caducidad.
  • Reutilización de la sesión de pago: al volver a abrir la misma sesión de pago, se puede mostrar el mismo código QR válido.
  • Sin cancelación automática: El pago PIX no pago cancela automáticamente cuando tú cierras la ventana QR.

Este comportamiento permite a los usuarios volver al pago y completar la transacción utilizando el mismo código QR antes de que caduque.

Pagos asíncronos caducados

Si un código QR PIX caduca de forma natural:

  • Estado del backendActualizado a EXPIRED
  • Estado del SDK: Las devoluciones de llamada del SDK y endpoints de sondeo endpoints EXPIRED de manera constante

Esto garantiza que los comerciantes reciban información precisa sobre el estado cuando un pago ha caducado.

Para obtener el estado de la transacción, tienes que implementar el delegado que se presenta en el siguiente fragmento de código:

enum Result {
    case reject, success, fail, processing, internalError, userCancell
}

func yunoPaymentResult(_ result: Yuno.Result) { ... }
func yunoEnrollmentResult(_ result: Yuno.Result) { ... }

Características complementarias

Yuno iOS SDK proporciona servicios y configuraciones adicionales que puedes utilizar para mejorar la experiencia de los clientes. Utiliza las personalizaciones del SDK para cambiar la apariencia del SDK para que coincida con tu marca o para configurar el cargador.

  • Cargador: Controla el uso del cargador mediante las opciones de configuración del SDK.
  • Guardar tarjeta para futuros pagos: Además, puede mostrar una casilla de verificación para guardar o inscribir tarjetas usando cardSaveEnable: true. A continuación encontrará ejemplos de la casilla de verificación para ambos renders de formulario de tarjeta.
  • También puede elegir una de las opciones de renderizado para la forma de la tarjeta. A continuación encontrará capturas de pantalla que presentan la diferencia entre las opciones cardFormType ONE_STEP y STEP_BY_STEP.

Integración del modo de renderizado

El modo de renderizado del SDK de Yuno ofrece mayor flexibilidad en la interfaz de usuario, lo que permite a los desarrolladores integrar flujos de pago con control total sobre la interfaz de usuario, conservando al mismo tiempo toda la funcionalidad del SDK. Este modo proporciona vistas SwiftUI que se integran perfectamente en la interfaz de usuario existente.

Función principal: startPaymentRenderFlow

El objeto startPaymentRender Esta función es una característica del SDK de Yuno que permite a los comerciantes integrar el proceso de pago de forma más detallada y personalizable. Esta función ofrece control total sobre cuándo y cómo se muestran los formularios de pago, lo que facilita una integración más fluida con la interfaz de usuario de la aplicación del comerciante.

Esta función está diseñada para ofrecer un mayor control sobre el flujo de pago, permitiendo a los comerciantes:

  • Integre formularios de pago de forma personalizada dentro de su propia interfaz de usuario.
  • Controle con precisión cuándo se muestran los formularios de datos de pago.
  • Obtenga un control detallado sobre el proceso de confirmación de pago.
  • Proporcionar una experiencia de usuario más fluida y consistente dentro de la aplicación del comerciante.

Sintaxis

La sección de sintaxis proporciona la firma del método startPaymentRender Función. Esta función es fundamental para integrar el proceso de pago en tu aplicación, ofreciendo un enfoque personalizable y detallado para gestionar los formularios y flujos de pago.

@MainActor static func startPaymentRenderFlow(
    pagoMétodoSeleccionado: PaymentMethodSelected,
    con delegado: YunoPaymentDelegate
) async -> algún YunoPaymentRenderFlowProtocolo

Parámetros

El objeto startPaymentRender requiere parámetros específicos para operar con eficacia. Estos parámetros son esenciales para definir el método de pago y manejar las respuestas del proceso de pago.

ParámetroTipoDescripción
paymentMethodSelectedPaymentMethodSelectedEl método de pago seleccionado por el usuario. Debe incluir el vaultedToken (si existe) y el paymentMethodType
delegateYunoPaymentDelegateEl delegado que gestionará las respuestas del proceso de pago, incluida la creación del token y el resultado final.

Valor de retorno

Devuelve una instancia que cumple con YunoPaymentRenderFlowProtocol, que proporciona métodos para gestionar el flujo de procesamiento de pagos.

Protocolo YunoPaymentRenderFlowProtocol

La instancia devuelta por startPaymentRender se ajusta a este protocolo que incluye los siguientes métodos:

formView(método de pago seleccionado:con:)

func formularioVer(
    métodoPagoSeleccionado: PaymentMethodSelected,
    con delegado: YunoPaymentDelegate
) async -> ¿CualquierVista?
  • Finalidad: Obtiene la vista del formulario para capturar los datos de pago
  • Comportamiento:
    • Si el método de pago requiere mostrar un formulario, devuelve un AnyView con el formulario correspondiente
    • Si el método de pago no necesita mostrar ningún formulario (por ejemplo, métodos ya configurados), devuelve nil
  • Cuándo utilizarlo: Llamar inmediatamente después de crear la instancia de flujo de pago

enviarFormulario()

func submitForm()
  • Finalidad: Enviar los datos del formulario para su validación
  • Comportamiento: Ejecuta todas las validaciones necesarias y, si tiene éxito, procede a generar un nuevo token de un solo uso.
  • Cuándo utilizar: Cuando el usuario ejecuta la acción "pagar" en la aplicación del comerciante.

continuePayment()

func continuePayment() async -> ¿CualquierVista?
  • Finalidad: Continúa el proceso de pago después de que se haya generado el token de un solo uso.
  • Comportamiento:
    • Si es necesario mostrar alguna vista adicional (por ejemplo, autenticación 3DS), devuelve un icono AnyView
    • Si no se requiere ninguna vista adicional, devuelve nil
  • Cuándo utilizarlo: Tras recibir el token de un solo uso a través del delegado y crear el pago.

Flujo de implementación

Esta sección describe la secuencia de pasos necesarios para implementar el proceso de procesamiento de pagos utilizando el SDK de Yuno.

Paso 1: Configuración inicial

Para comenzar a utilizar startPaymentRenderAsegúrese de que el SDK esté inicializado correctamente y que tenga un archivo válido. checkoutSessionSiga los pasos a continuación para configurar su entorno:

await Yunoinitialize(apiKey: "tu_clave_api")

Paso 2: Crear una instancia de flujo de pago

Cree una instancia de flujo de pago para administrar y representar el proceso de pago utilizando el método seleccionado.

let paymentFlow = await Yuno.startPaymentRenderFlow(
    métodoPagoSeleccionado: métodoPagoSeleccionado,
    con: yo
)

Paso 3: Obtener y mostrar el formulario

Recupere y presente el formulario de pago para recopilar la información de pago del usuario de manera eficiente.

let formView = await paymentFlow.formView(
    paymentMethodSelected: selectedPaymentMethod,
    with: self
)

if let formView = formView {
    VStack {
        Text("Payment Information")

        formView

        Button("Pay") {
            paymentFlow.submitForm()
        }
    }
} else {
    paymentFlow.submitForm()
}

Paso 4: Gestionar el token de un solo uso

Implemente el método delegado para recibir el token:

extension MyViewController: YunoPaymentDelegate {
    var checkoutSession: String {
        return "your_checkout_session"
    }

    var countryCode: String {
        return "CO"
    }

    var viewController: UIViewController? {
        return self
    }

    func yunoCreatePayment(with token: String, information: [String: Any]) {
        createPaymentInBackend(token: token) { [weak self] success in
            if success {
                Task {
                    let additionalView = await self?.paymentFlow?.continuePayment()
                    if let additionalView = additionalView {
                        self?.showAdditionalView(additionalView)
                    }
                }
            }
        }
    }

    func yunoPaymentResult(_ result: Yuno.Result) {
        switch result {
        case .succeeded:
            showSuccessMessage()
        case .reject:
            showRejectionMessage()
        case .fail:
            showErrorMessage()
        case .processing:
            showProcessingMessage()
        case .userCancell:
            handleCancellation()
        case .internalError:
            showInternalErrorMessage()
        }
    }
}

Ejemplo completo

import SwiftUI
import YunoSDK

struct PaymentRenderView: View {
    @State private var paymentFlow: YunoPaymentRenderFlowProtocol?
    @State private var formView: AnyView?
    @State private var additionalView: AnyView?

    let selectedPaymentMethod: PaymentMethodSelected
    let delegate: YunoPaymentDelegate

    var body: some View {
        VStack(spacing: 20) {
            Text("Complete Purchase")
                .font(.title2)
                .fontWeight(.bold)

            OrderSummaryView()

            if let formView = formView {
                VStack(alignment: .leading) {
                    Text("Payment Information")
                        .font(.headline)

                    formView
                }
            }

            if let additionalView = additionalView {
                additionalView
            }

            Spacer()

            Button(action: {
                paymentFlow?.submitForm()
            }) {
                Text("Confirm Payment")
                    .font(.headline)
                    .foregroundColor(.white)
                    .frame(maxWidth: .infinity)
                    .padding()
                    .background(Color.blue)
                    .cornerRadius(10)
            }
        }
        .padding()
        .onAppear {
            setupPaymentFlow()
        }
    }

    private func setupPaymentFlow() {
paymentFlow = await Yuno.startPaymentRenderFlow(
    paymentMethodSelected: selectedPaymentMethod,
    with: delegate
)

        Task {
            formView = await paymentFlow?.formView(
                paymentMethodSelected: selectedPaymentMethod,
                with: delegate
            )
        }
    }
}

class PaymentDelegate: YunoPaymentDelegate {
    let checkoutSession: String
    let countryCode: String
    weak var viewController: UIViewController?

    init(checkoutSession: String, countryCode: String, viewController: UIViewController?) {
        self.checkoutSession = checkoutSession
        self.countryCode = countryCode
        self.viewController = viewController
    }

    func yunoCreatePayment(with token: String, information: [String: Any]) {
        PaymentService.createPayment(token: token) { [weak self] result in
            switch result {
            case .success:
                Task {
                    await self?.continuePaymentProcess()
                }
            case .failure(let error):
                print("Error creating payment: \(error)")
            }
        }
    }

    func yunoPaymentResult(_ result: Yuno.Result) {
        DispatchQueue.main.async {
            switch result {
            case .succeeded:
                NotificationCenter.default.post(name: .paymentSucceeded, object: nil)
            case .reject:
                NotificationCenter.default.post(name: .paymentRejected, object: nil)
            }
        }
    }

    private func continuePaymentProcess() async {
    }
}

Casos de uso comunes

Esta sección describe escenarios típicos en los que se puede utilizar el SDK de Yuno para gestionar diversos métodos de pago, proporcionando flexibilidad y facilidad de integración.

1. Pago con tarjeta de crédito

En este caso de uso, demostramos cómo procesar pagos utilizando nueva información de tarjeta de crédito, requiriendo que el usuario complete un formulario para capturar los detalles necesarios de la tarjeta.

let pagoTarjeta = MétodoPagoTarjetapaymentMethodType: "TARJETA")
let flujo = Yuno.startPaymentRender(metodoPagoSeleccionado: pagoTarjeta, con: delegado)

let form = await flow.formView(paymentMethodSelected: cardPayment, with: delegate)

2. Pago con método guardado

Este escenario demuestra el uso de un método de pago guardado, lo que permite a los usuarios pagar sin tener que volver a ingresar los detalles mediante el uso de un token almacenado.

let tarjetaguardada = TarjetaPagoGuardada(
   paymentMethodType"TARJETA",
   vaultedToken: "saved_token_123"
)
let flow = Yuno.startPaymentRender(paymentMethodSelected: savedCard, with: delegate)

let form = await flow.formView(paymentMethodSelected: savedCard, with: delegate)

3. Pago con autenticación 3DS

3D Secure (3DS) añade un paso de verificación adicional para mayor seguridad. El SDK de Yuno integra este proceso en tu flujo de pago a la perfección.

func yunoCreatePayment(with token: String, information: [String: Any]) {
    createPayment(token: token) { [weak self] success in
        if success {
            Task {
                let authView = await self?.paymentFlow?.continuePayment()
                if let authView = authView {
                    self?.show3DSView(authView)
                }
            }
        }
    }
}

Consideraciones importantes

Esta sección destaca los puntos clave para integrar el SDK de Yuno de manera efectiva, garantizando un proceso de pago seguro y sin problemas.

Prerrequisitos

  • Asegúrese de que el SDK esté inicializado antes de usarlo startPaymentRender
  • El delegado debe implementar todos los métodos requeridos de YunoPaymentDelegate
  • El objeto checkoutSession debe ser válido y activo

Gestión estatal

  • Compruebe siempre si formView() devoluciones nil antes de mostrar la vista
  • Manejar adecuadamente el caso donde continuePayment() devoluciones nil
  • Implementar estados de carga durante operaciones asincrónicas

Seguridad

  • Nunca guarde tokens de un solo uso: úselos inmediatamente
  • Valide siempre los resultados de pago en su backend
  • Implementar tiempos de espera adecuados para las operaciones de red

Actuación

  • Llamadas a formView() y continuePayment() son asincrónicos
  • Considere mostrar indicadores de carga durante estas operaciones
  • Reutiliza la instancia del flujo de pago cuando sea posible

Solución de problemas

Esta sección ofrece soluciones rápidas a problemas comunes surgidos durante la integración del SDK de Yuno, garantizando un proceso de pago más fluido.

Problemas comunes

  1. formView()siempre regresanil

    • Verificar que el método de pago seleccionado requiera un formulario
    • Asegúrese de que el SDK se inicialice correctamente
  2. El delegado no recibeyunoCreatePayment

    • Verificar que submitForm() se está llamando correctamente
    • Confirmar que el formulario tiene datos válidos
  3. continuePayment()No devuelve la vista cuando se espera

    • Algunos métodos de pago no requieren vistas adicionales
    • Comprueba la configuración del método de pago en tu panel de Yuno

Registros de depuración

Yuno.config.environment = .staging

Migración desde otros métodos

Si estás migrando desde startPayment() o startPaymentLite():

Yuno.startPaymentshowPaymentStatus: true)

let flow = Yuno.startPaymentRender(paymentMethodSelected: method, with: delegate)
let formulario = await flujo.formularioVista(metodoPagoSeleccionado: método, con: delegado)

El principal beneficio de utilizar el nuevo método es el control detallado que proporciona tanto sobre la interfaz de usuario como sobre el proceso de pago.

📘

App Demo

Además de los ejemplos de código proporcionados, puedes acceder al repositorio de Yuno para una implementación completa de Yuno iOS SDKs.

Implementando YunoPaymentDelegate con concurrencia Swift 6

Swift 6 introduce requisitos de concurrencia más estrictos que afectan la forma en que se implementa el YunoPaymentDelegate Protocolo. Esta sección explica los desafíos y ofrece soluciones para diferentes escenarios de implementación.

📘

Comprensión de la concurrencia en Swift 6

La concurrencia es la capacidad de tu aplicación para gestionar múltiples tareas simultáneamente. Con Swift 6, las reglas de concurrencia se han vuelto más estrictas para mejorar la estabilidad de la aplicación y evitar fallos. Esto significa que tu código debe estar estructurado con mayor cuidado para garantizar la seguridad de los subprocesos y una gestión adecuada de las tareas.

El problema

Con Swift 6, los protocolos que heredan de Sendable Requieren que todas sus implementaciones sean seguras para subprocesos. Esto genera advertencias al implementar el delegado en clases marcadas como @MainActor.

Seguro para subprocesos significa que tu código puede llamarse de forma segura desde múltiples subprocesos sin provocar fallas o comportamientos inesperados. @MainActor garantiza que el código se ejecute en el hilo principal (hilo de UI).

Nuestra decisión de diseño

No marcamos los protocolos como @MainActor porque:

  • Obligaría a todas las implementaciones a ser MainActor-compatible
  • Reduciría la flexibilidad para los comerciantes que no utilizan MainActor
  • Cada implementación tiene diferentes necesidades de concurrencia

Responsabilidad del comerciante

Es responsabilidad del comerciante gestionar la concurrencia según su implementación. A continuación, se presentan tres enfoques diferentes que puede utilizar según sus necesidades específicas.

Opción 1: Propiedades inmutables

Este enfoque utiliza propiedades inmutables que son automáticamente seguras para subprocesos, lo que las hace ideales para configuraciones simples. Es ideal para aplicaciones sencillas con valores de configuración fijos que no cambian durante la ejecución.

@MainActor
class MyViewController: UIViewController, YunoPaymentDelegate {

    private let _countryCode = "CO"
    private let _language = "EN"

    nonisolated var countryCode: String { _countryCode }
    nonisolated var language: String? { _language }
    nonisolated var checkoutSession: String { _checkoutSession }

    nonisolated func yunoPaymentResult(_ result: Yuno.Result) {
        Task { @MainActor in
        }
    }
}

Opción 2: Propiedades mutables con MainActor.assumeIsolated

Este enfoque, ideal para aplicaciones en las que los valores de configuración pueden cambiar durante el tiempo de ejecución (como las preferencias del usuario), permite propiedades mutables y al mismo tiempo mantiene la seguridad de los subprocesos mediante el uso de MainActor.assumeIsolated.

@MainActor
class MyViewController: UIViewController, YunoPaymentDelegate {

    @Published var configLanguage: String = "EN"
    @Published var configCountryCode: String = "CO"

    nonisolated var language: String? {
        MainActor.assumeIsolated { configLanguage }
    }

    nonisolated var countryCode: String {
        MainActor.assumeIsolated { configCountryCode }
    }
}

Opción 3: Para noMainActor clases

Este enfoque es adecuado para clases de servicio que no requieren MainActor por lo que es ideal para servicios en segundo plano o clases utilitarias que no interactúan con la interfaz de usuario.

class MyService: YunoPaymentDelegate {

    let countryCode: String
    let language: String?
    let checkoutSession: String
    let viewController: UIViewController?

    init(countryCode: String, language: String?, checkoutSession: String, viewController: UIViewController?) {
        self.countryCode = countryCode
        self.language = language
        self.checkoutSession = checkoutSession
        self.viewController = viewController
    }

    func yunoPaymentResult(_ result: Yuno.Result) {
    }
}

⚠️ Consideraciones importantes

Al implementar la concurrencia en su delegado, tenga en cuenta estos puntos clave:

  • MainActor.assumeIsolated: Utilízalo sólo cuando garantices que se llama desde MainActor. Se trata de un mecanismo de seguridad que le dice a Swift "confía en mí, sé que esto se está ejecutando en el hilo principal".
  • nonisolated: Significa que se puede acceder a él desde cualquier subproceso, por lo que debe ser seguro para subprocesos. Utilízalo cuando tus propiedades o métodos no dependan del estado de la interfaz de usuario.
  • viewController: Permanece como @MainActor porque siempre se debe acceder desde el hilo principal. Los componentes de la interfaz de usuario siempre deben ejecutarse en el hilo principal para evitar fallos.