Full SDK (iOS)


👍

SDK recomendado

Recomendamos o uso do iOS Seamless SDK para uma experiência de integração tranquila. Essa opção oferece uma solução de pagamento flexível com componentes de IU pré-criados e opções de personalização.

Esta página fornece todas as etapas para adicionar, configurar e usar o SDK completo do iOS em seu projeto.

Requisitos

Para implementar o SDK do Yuno para iOS, você precisa atender aos seguintes requisitos:

Etapa 1: Inclua a biblioteca em seu projeto

Você pode adicionar a biblioteca usando o CocoaPods ou o Swift Package Manager.

CocoaPods

Para adicionar o Yuno SDK ao seu projeto iOS, você precisa instalar o Yuno SDK. Se você não tiver um Podfile, siga o guia CocoaPods para criar um. Depois de criar o Podfile, você integrará o Yuno SDK ao Cocoapods adicionando a linha abaixo ao seu Podfile.

pod 'YunoSDK', '~> 1.1.22'

Depois, você precisa executar a instalação:

instalação do pod

Gerenciador de pacotes Swift

Para adicionar o Yuno SDK ao seu projeto iOS, você precisa instalar o pacote Gerenciador de pacotes Swift. Com o pacote Swift configurado, adicione YunoSDK como uma dependência, conforme apresentado no bloco de código a seguir:

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

Etapa 2: Initialize o SDK com a chave pública

Para começar a executar o checkout completo do Yuno para iOS, primeiro obtenha o ID do aplicativo Yuno e a chave de API pública. Em seguida, importe e initialize o Yuno conforme mostrado abaixo:

import YunoSDK

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

Credenciais

Consulte a página de credenciais para obter mais informações: https://docs.y.uno/reference/authentication

🚧

Uso do UISceneDelegate

Se o seu aplicativo estiver usando um UISceneDelegate, certifique-se de colocar o código de inicialização do Yuno dentro do SceneDelegate.

O checkout completo permite que você configure a aparência e o processo. Essa é uma etapa opcional que você configura por meio da classe YunoConfig. Se você quiser definir as configurações, o bloco de código a seguir mostra os elementos que podem ser configurados:

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

Configure o SDK com as seguintes opções:

ParâmetroDescrição
cardFormTypeEsse campo pode ser usado para escolher o fluxo do cartão de pagamento e de inscrição. É uma propriedade opcional e considera .oneStep por padrão.
appearanceEsse campo opcional define a aparência do checkout. Por padrão, ele usa os estilos Yuno.
saveCardEnabledEsse campo opcional pode ser usado para escolher se a caixa de seleção Salvar cartão é exibida nos fluxos de cartões. Por padrão, ela é falsa.
keepLoaderEsse campo opcional fornece controle sobre quando ocultar o carregador. Se definido como true, o hideLoader() deve ser chamada para ocultar o carregador. Por padrão, ela é definida como false.
hideCardholderNameEste campo opcional permite ocultar o campo do nome do titular do cartão no formulário do cartão. Quando definido como true, o campo do nome do titular do cartão não é exibido. Quando não especificado ou definido como false, o campo do nome do titular do cartão é exibido (comportamento padrão). Ocultar o campo não afeta o PAN, a validade, a coleta do CVV, a lógica do BIN ou as validações 3DS/provedor. O comerciante é responsável por garantir que o nome do titular do cartão seja fornecido quando exigido pelo seu provedor de pagamentos.
📘

Acesse sua chave de API

Recupere sua chave de API na seção Desenvolvedores no Painel de Controle do Yuno.

Etapa 3: Inicie o processo de checkout

A classe ViewController é definida como uma subclasse de UIViewController e também adota o YunoPaymentDelegate protocolo.

❗️

Depreciação

O startCheckout foi preterido nas versões recentes do SDK do 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âmetroDescrição
checkoutSessionRefere-se à sessão de checkout do pagamento atual.
countryCodeEsse parâmetro determina o país para o qual o processo de pagamento está sendo configurado. A lista completa de países compatíveis e seu código de país está disponível na página Cobertura do país.
languageDefine o idioma a ser usado nos formulários de pagamento. Você pode defini-lo como uma das opções de idioma disponíveis:
  • es (espanhol)
  • en (inglês)
  • pt (português)
  • fil (filipino)
  • id (indonésio)
  • ms (malaio)
  • th (tailandês)
  • zh-TW (chinês (tradicional, Taiwan))
  • zh-CN (chinês (simplificado, China))
  • vi (vietnamita)
  • fr (francês)
  • pl (polonês)
  • it (italiano)
  • de (alemão)
  • ru (russo)
  • tr (turco)
  • nl (holandês)
  • sv (sueco)
  • ko (coreano)
  • ja (japonês)
viewControllerEssa propriedade representa o UIViewController usado para apresentar o fluxo de pagamento. Embora a propriedade permaneça opcional para compatibilidade com versões anteriores, você deve fornecer um controlador visível para que o SDK possa apresentar sua IU corretamente.
yunoCreatePayment(with token: String)Esse método é responsável por criar um pagamento com o token fornecido. Ele recebe um parâmetro String chamado tokenque representa o token de pagamento.
yunoCreatePayment(with token: String, information: [String: Any])Esse método é responsável por criar um pagamento com o token fornecido. Ele recebe um parâmetro String chamado tokenrepresentando o token de pagamento. Além disso, ele retorna todas as informações de resposta token em um dicionário.
yunoPaymentResult(_ result: Yuno.Result)Esse método é chamado quando o processo de pagamento é concluído, fornecendo o resultado do pagamento como um parâmetro do tipo Yuno.Result.
❗️

Observação importante sobre o yunoCreatePayment

Você pode ligar para yunoCreatePayment com ou sem o information de acordo com suas necessidades. No entanto, use apenas uma versão em seu código, pois chamar ambas não é necessário e pode causar problemas.

🚧

Requisitos de simultaneidade do Swift 6

Se estiver usando o Swift 6, você precisará implementar o YunoPaymentDelegate com considerações específicas de simultaneidade. O Swift 6 apresenta requisitos mais rigorosos de segurança de thread que afetam a forma como você implementa os delegados. Consulte a seção Implementação YunoPaymentDelegate com Swift 6 Concurrency para obter opções de implementação detalhadas e práticas recomendadas.

Etapa 4: Adicionar a visualização do SDK ao checkout

Sua visualização precisa adotar o YunoPaymentFullDelegate protocolo. Isso permite que seu aplicativo responda a ações relacionadas a pagamentos, como quando o usuário seleciona um método de pagamento.

Veja a seguir como definir o delegado:

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

Parâmetros

FunçãoDescrição
yunoDidSelect(paymentMethod: YunoSDK.PaymentMethodSelected)Chamado quando o usuário seleciona um método de pagamento.
- paymentMethod: O método que o usuário escolheu.
yunoDidUnenrollSuccessfully(_ success: Bool)Chamada quando uma ação de cancelamento de registro é concluída.
- success: true se funcionasse, false se não o fizesse.
yunoUpdatePaymentMethodsViewHeight(_ height: CGFloat)Chamado quando getPaymentMethodViewAsync() é chamado e sempre que a altura da exibição é alterada.

Para exibir os métodos de pagamento, chame o método a seguir e passe seu modelo de visualização ou controlador como delegado.

await Yuno.getPaymentMethodViewAsync(delegate:)

Esse método retornará automaticamente o tipo correto de exibição, dependendo da estrutura da interface do usuário que você estiver usando:

  • Se você estiver usando UIKit, ele retorna um UIView.
  • Se você estiver usando SwiftUI, ele retorna um some View.

Isso facilita a integração do SDK em qualquer projeto iOS, independentemente da estrutura de interface do usuário que você usa.

Etapa 5: Iniciar o processo de payment

Para iniciar um pagamento após a exibição dos métodos de pagamento, chame a função startPayment método:

Yuno.startPaymentshowPaymentStatus:Bool)

Etapa 6: obtenha o OTT ( token de uso único)

Você pode obter o token de uso único para criar o pagamento back-to-back no final desse processo. Você obterá o token de uso único na função yunoCreatePayment() que você implementa ao adotar o YunoPaymentDelegate. Um exemplo de recuperação do token de uso único é mostrado abaixo:

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

Etapa 7: Criar o pagamento

Depois de concluir as etapas descritas acima, você poderá criar um pagamento. A criação do pagamento back-to-back deve ser realizada usando o endpoint Create Payment. O comerciante deve chamar seu backend para criar o pagamento dentro do Yuno, usando o token de uso único e a sessão de checkout.

📘

Continuar com o método Payment

Para garantir uma experiência de pagamento perfeita, é fundamental integrar o continuePayment depois de criar um pagamento. Essa etapa é particularmente importante para métodos de pagamento assíncronos que exigem ações adicionais do cliente. Aqui está o que você precisa saber:

  • Tratamento assíncrono de pagamentos: A API sinalizará a necessidade de ação adicional com o sdk_action_required definido como verdadeiro.
  • Funcionalidade: O yuno.continuePayment() foi criada para gerenciar e exibir todas as telas adicionais necessárias para que o cliente conclua o pagamento.
  • Simplificação do processo: Ao usar esse método, você pode simplificar o processo de pagamento, pois ele lida automaticamente com vários cenários para você.
YunocontinuePayment()

Etapa 8: Lidar com o status do pagamento (opcional)

🚧

Deep Links e Mercado Pago Checkout Pro

Essa etapa só é necessária se você estiver usando um método de pagamento que dependa de links diretos ou do Mercado Pago Checkout Pro. Se seus métodos de pagamento não usarem deep links, você pode pular esta etapa.

Alguns métodos de pagamento levam os usuários para fora do seu aplicativo para concluir a transação. Depois que o pagamento é concluído, o usuário é redirecionado de volta ao seu aplicativo usando um deep link. O SDK usa esse link direto para verificar o que aconteceu, verificando se o pagamento foi bem-sucedido, falhou ou foi cancelado, e pode mostrar uma tela de status para o usuário.

Para lidar com isso, você precisa atualizar seu AppDelegate para passar a URL de entrada de volta para o Yuno SDK. Isso permite que o SDK leia o resultado e, opcionalmente, exiba o status do pagamento. O trecho de código a seguir mostra como você pode adicioná-lo ao seu aplicativo:

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

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

  return Yuno.receiveDeeplink(url)
}

Esse código escuta os links diretos que abrem seu aplicativo. Quando uma URL é recebida, ele verifica se o esquema corresponde ao que você usou na função callback_url durante a configuração da sessão de checkout. Se corresponder, a URL é passada para o Yuno SDK usando Yuno.receiveDeeplink(...). Em seguida, o SDK lê o resultado do pagamento e mostra a tela de status apropriada ao usuário.

Certifique-se de que o url.scheme nesse código corresponde ao callback_url que você forneceu ao criar o checkout_session.

Retorno de chamada

Depois que o pagamento é concluído, o SDK pode retornar diferentes estados de transação: success, fail, processing, reject, internalErrore userCancell. As descrições de cada estado de transação são apresentadas na tabela abaixo.

Estado da transaçãoDescrição
succeededIndica que a transação ou o processo de payment foi concluído com êxito.
failEsse estado indica que a transação ou o processo de pagamento falhou. Isso significa que houve um erro ou problema durante o processo de pagamento, impedindo que ele fosse concluído com êxito.
processingIndica que a transação ou o processo de pagamento está sendo processado no momento. Normalmente, é usado quando há um atraso no processamento do pagamento, como a espera de aprovação de um serviço de terceiros ou de uma instituição financeira.
rejectEsse estado indica que a transação foi rejeitada. A rejeição pode ocorrer por vários motivos, como fundos insuficientes, atividade fraudulenta ou solicitações que violam regras ou políticas específicas.
internalErrorIsso significa que ocorreu um erro inesperado no sistema ou na infraestrutura que está lidando com o processo de pagamento. Esse estado sugere um problema no servidor ou no backend, e não um problema com a entrada ou a solicitação do usuário.
userCancellEsse estado indica que o usuário cancelou ou abortou voluntariamente a transação ou o processo de pagamento. Esse estado é normalmente usado quando há uma opção para o usuário cancelar ou abandonar o processo de pagamento.

Validação do status do pagamento

Esta seção explica como o SDK lida com o status do pagamento quando os usuários cancelam ou abandonam os fluxos de pagamento e como o status do SDK se relaciona com o status do pagamento no back-end nesses cenários.

Sincronizar métodos de pagamento (Apple Pay)

Para métodos de pagamento síncronos, como o Apple Pay, quando um usuário cancela ou fecha a interface do usuário da carteira antes de receber a resposta do provedor de serviços de pagamento (PSP):

  • Status do SDK: Devoluções userCancell (CANCELLED)
  • Status do pagamento no backend: Restos mortais PENDING até ao tempo limite do PSP ou ao cancelamento pelo comerciante
  • Importante: O SDK não retornará reject ou processing nesse cenário

Isso garante que o pagamento no backend permaneça em estado pendente e possa ser tratado adequadamente pelo sistema do comerciante.

Formas de pagamento assíncronas (PIX e métodos baseados em QR)

Para métodos de pagamento assíncronos como o PIX, quando um usuário fecha a janela do código QR (clica em X) antes de concluir o pagamento:

  • Status do SDK: Devoluções PENDING, opcionalmente com um subestatuto, como CLOSED_BY_USER
  • Status do pagamento no backend: Restos mortais PENDING e o código QR permanece válido até ao seu prazo de validade.
  • Reutilização da sessão de checkout: reabrir a mesma sessão de checkout pode exibir o mesmo código QR válido.
  • Sem cancelamento automático: O pagamento PIX não é cancelado automaticamente quando o usuário fecha a janela do QR.

Esse comportamento permite que os usuários retornem ao fluxo de pagamento e concluam a transação usando o mesmo código QR antes que ele expire.

Pagamentos assíncronos expirados

Se um código QR PIX expirar naturalmente:

  • Status do backendAtualizado para EXPIRED
  • Status do SDK: endpoints de chamadas de retorno do SDK e endpoints de pesquisa EXPIRED de forma consistente

Isso garante que os comerciantes recebam informações precisas sobre o status quando um método de pagamento expirar.

Para obter o estado da transação, você precisa implementar o delegado apresentado no seguinte trecho de código:

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

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

Recursos complementares

O SDK do Yuno iOS oferece serviços e configurações adicionais que você pode usar para melhorar a experiência dos clientes. Use as personalizações do SDK para alterar a aparência do SDK de acordo com sua marca ou para configurar o carregador.

  • Carregador: Controle o uso do carregador por meio das opções de configuração do SDK.
  • Salvar o cartão para pagamentos futuros: Além disso, você pode exibir uma caixa de seleção para salvar ou registrar cartões usando cardSaveEnable: true. Abaixo você encontra exemplos da caixa de seleção para ambas as renderizações do formulário de cartão.
  • Você também pode escolher uma das opções de renderização para o formulário do cartão. Abaixo você encontra capturas de tela que apresentam a diferença entre as opções de renderização cardFormType ONE_STEP e STEP_BY_STEP.

Integração do modo de renderização

O modo de renderização no Yuno SDK oferece maior flexibilidade de interface do usuário, permitindo que os desenvolvedores integrem fluxos de pagamento com controle total sobre a interface do usuário, mantendo a funcionalidade full SDK . Esse modo fornece visualizações SwiftUI que podem ser incorporadas perfeitamente à sua interface de usuário existente.

Função principal: startPaymentRenderFlow

O startPaymentRender é um recurso do Yuno SDK que permite que os comerciantes integrem o processo de pagamento de forma mais detalhada e personalizável. Essa função concede controle total sobre quando e como os formulários de pagamento são exibidos, facilitando uma integração mais suave com a UI do aplicativo existente do comerciante.

Essa função foi projetada para oferecer maior controle sobre o fluxo de pagamento, permitindo que os comerciantes:

  • Integrar formulários de pagamento de forma personalizada em sua própria interface de usuário.
  • Controle com precisão quando os formulários de dados de pagamento são exibidos.
  • Obtenha controle detalhado sobre o processo de confirmação de pagamento.
  • Proporcionar uma experiência de usuário mais fluida e consistente no aplicativo do comerciante.

Sintaxe

A seção de sintaxe fornece a assinatura do método para o startPaymentRender função. Essa função é fundamental para integrar o processo de pagamento em seu aplicativo, oferecendo uma abordagem personalizável e detalhada para lidar com formulários e fluxos de pagamento.

@MainActor static func startPaymentRenderFlow(
    paymentMethodSelected: PaymentMethodSelected,
    with delegate: YunoPaymentDelegate
) async -> some YunoPaymentRenderFlowProtocol

Parâmetros

O startPaymentRender requer parâmetros específicos para operar com eficácia. Esses parâmetros são essenciais para definir o método de pagamento e lidar com as respostas do processo de pagamento.

ParâmetroTipoDescrição
paymentMethodSelectedPaymentMethodSelectedO método de pagamento selecionado pelo usuário. Deve incluir o vaultedToken (se houver) e o paymentMethodType
delegateYunoPaymentDelegateO delegado que tratará das respostas do processo de pagamento, incluindo a criação token e o resultado final

Valor de retorno

Retorna uma instância que está em conformidade com YunoPaymentRenderFlowProtocolque fornece métodos para lidar com o fluxo de renderização de pagamentos.

Protocolo YunoPaymentRenderFlowProtocol

A instância retornada por startPaymentRender está em conformidade com esse protocolo, que inclui os seguintes métodos:

formView(paymentMethodSelected:with:)

func formView(
    paymentMethodSelected: PaymentMethodSelected,
    with delegate: YunoPaymentDelegate
) async -> AnyView?
  • Finalidade: Obtém a visualização do formulário para capturar dados de pagamento
  • Comportamento:
    • Se o método de pagamento exigir a exibição de um formulário, retorna um AnyView com a forma correspondente
    • Se o método de pagamento não precisar mostrar nenhum formulário (por exemplo, métodos já configurados), retorna nil
  • Quando usar: Chame imediatamente após criar a instância do fluxo de pagamento

submitForm()

func submitForm()
  • Finalidade: Enviar dados de formulário para validação
  • Comportamento: Executa todas as validações necessárias e, se for bem-sucedido, continua a gerar um novo token de uso único
  • Quando usar: Quando o usuário executa a ação "pagar" no aplicativo do comerciante

continuePayment()

func continuePayment() async -> AnyView?
  • Finalidade: Continua o processo de pagamento após a geração do token de uso único
  • Comportamento:
    • Se for necessário mostrar qualquer exibição adicional (por exemplo, autenticação 3DS), retorna um AnyView
    • Se nenhuma exibição adicional for necessária, retorna nil
  • Quando usar: Após receber o token de uso único por meio do delegado e criar o pagamento

Fluxo de implementação

Esta seção descreve a sequência de etapas necessárias para implementar o processo de renderização de pagamento usando o Yuno SDK.

Etapa 1: Configuração inicial

Para começar a usar startPaymentRenderVerifique se o SDK foi inicializado corretamente e se você possui um checkoutSession. Siga as etapas abaixo para configurar seu ambiente:

await Yunoinitialize(apiKey: "your_api_key")

Etapa 2: Criar instância de fluxo de pagamento

Crie uma instância de fluxo de pagamento para gerenciar e renderizar o processo de pagamento usando o método selecionado.

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

Etapa 3: Obter e exibir o formulário

Recupere e apresente o formulário de pagamento para coletar informações de pagamento do usuário de forma 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()
}

Etapa 4: Manipular o token de uso único

Implemente o método delegado para receber o 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()
        }
    }
}

Exemplo 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 comuns

Esta seção descreve cenários típicos em que o Yuno SDK pode ser utilizado para lidar com vários métodos de pagamento, proporcionando flexibilidade e facilidade de integração.

1. Pagamento com cartão de crédito

Neste caso de uso, demonstramos como processar pagamentos usando novas informações de cartão de crédito, exigindo que o usuário preencha um formulário para capturar os detalhes necessários do cartão.

let cardPayment = CardPaymentMethodpaymentMethodType: "CARD")
let flow = Yuno.startPaymentRender(paymentMethodSelected: cardPayment, with: delegate)

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

2. Pagamento com método salvo

Esse cenário demonstra o uso de um método de pagamento salvo, permitindo que os usuários paguem sem reinserir os detalhes, utilizando um token protegido.

let savedCard = SavedCardPayment(
   paymentMethodType: "CARD",
   vaultedToken: "saved_token_123"
)
let flow = Yuno.startPaymentRender(paymentMethodSelected: savedCard, with: delegate)

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

3. Pagamento com autenticação 3DS

O 3D Secure (3DS) adiciona uma etapa extra de verificação para aumentar a segurança. O SDK da Yuno integra esse processo em seu fluxo de pagamento sem problemas.

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)
                }
            }
        }
    }
}

Considerações importantes

Esta seção destaca os principais pontos para integrar o SDK da Yuno de forma eficaz, garantindo um processo de pagamento seguro e sem interrupções.

Pré-requisitos

  • Certifique-se de que o SDK esteja inicializado antes de usar startPaymentRender
  • O delegado deve implementar todos os métodos necessários de YunoPaymentDelegate
  • O checkoutSession deve ser válido e ativo

Gerenciamento do estado

  • Sempre verifique se formView() retornos nil antes de exibir a exibição
  • Tratar adequadamente o caso em que continuePayment() retornos nil
  • Implementar estados de carregamento durante operações assíncronas

Segurança

  • Nunca armazene tokens de uso único - use-os imediatamente
  • Sempre valide os resultados do pagamento em seu backend
  • Implementar tempos limite apropriados para operações de rede

Desempenho

  • Chamadas para formView() e continuePayment() são assíncronos
  • Considere mostrar indicadores de carga durante essas operações
  • Reutilizar a instância do fluxo de pagamento quando possível

Solução de problemas

Esta seção oferece soluções rápidas para problemas comuns encontrados durante a integração do Yuno SDK, garantindo um processo de pagamento mais tranquilo.

Problemas comuns

  1. formView()sempre retornanil

    • Verifique se o método de pagamento selecionado requer um formulário
    • Verifique se o SDK foi inicializado corretamente
  2. O delegado não recebeyunoCreatePayment

    • Verifique se submitForm() está sendo chamado corretamente
    • Confirmar que o formulário tem dados válidos
  3. continuePayment()não retorna a exibição quando esperado

    • Alguns métodos de pagamento não exigem visualizações adicionais
    • Verifique a configuração do método de pagamento em seu painel do Yuno

Logs de depuração

Yuno.config.environment = .staging

Migração de outros métodos

Se você estiver migrando de startPayment() ou startPaymentLite():

Yuno.startPaymentshowPaymentStatus: true)

let flow = Yuno.startPaymentRender(paymentMethodSelected: method, with: delegate)
let form = await flow.formView(paymentMethodSelected: method, with: delegate)

A principal vantagem de usar o novo método é o controle detalhado que ele oferece sobre a interface do usuário e o processo de pagamento.

📘

Aplicativo de demonstração

Além dos exemplos de código fornecidos, você pode acessar o repositório Yuno para obter uma implementação completa dos SDKs do Yuno para iOS.

Implementação YunoPaymentDelegate com Swift 6 Concurrency

O Swift 6 apresenta requisitos de simultaneidade mais rígidos que afetam a forma como você implementa o YunoPaymentDelegate protocolo. Esta seção explica os desafios e oferece soluções para diferentes cenários de implementação.

📘

Entendendo a simultaneidade no Swift 6

A simultaneidade é a capacidade do seu aplicativo de gerenciar várias tarefas simultaneamente. Com o Swift 6, as regras de simultaneidade se tornaram mais rigorosas para aumentar a estabilidade do aplicativo e evitar falhas. Isso significa que seu código deve ser estruturado com mais cuidado para garantir a segurança dos threads e o gerenciamento adequado das tarefas.

O problema

Com o Swift 6, os protocolos que herdam do Sendable exigem que todas as suas implementações sejam thread-safe. Isso gera avisos ao implementar o delegado em classes marcadas como @MainActor.

Thread-safe significa que seu código pode ser chamado com segurança de vários threads sem causar falhas ou comportamento inesperado. @MainActor garante que o código seja executado no thread principal (thread da interface do usuário).

Nossa decisão de design

Não marcamos protocolos como @MainActor porque:

  • Isso forçaria todas as implementações a serem MainActor-compatível
  • Isso reduziria a flexibilidade para os comerciantes que não usam MainActor
  • Cada implementação tem necessidades de simultaneidade diferentes

Responsabilidade do comerciante

É responsabilidade do comerciante lidar com a simultaneidade de acordo com sua implementação. Abaixo estão três abordagens diferentes que você pode usar, dependendo de suas necessidades específicas.

Opção 1: Propriedades imutáveis

Essa abordagem usa propriedades imutáveis que são automaticamente thread-safe, o que as torna ideais para configurações simples. Ela é mais adequada para aplicativos simples com valores de configuração fixos que não mudam durante o tempo de execução.

@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
        }
    }
}

Opção 2: Propriedades mutáveis com MainActor.assumeIsolated

Essa abordagem, melhor para aplicativos em que os valores de configuração podem ser alterados durante o tempo de execução (como as preferências do usuário), permite propriedades mutáveis e, ao mesmo tempo, mantém a segurança do thread usando 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 }
    }
}

Opção 3: Para nãoMainActor aulas

Essa abordagem é adequada para classes de serviço que não requerem MainActor o que o torna melhor para serviços em segundo plano ou classes utilitárias que não interagem com a interface do usuário.

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) {
    }
}

⚠️ Considerações importantes

Ao implementar a simultaneidade em seu delegado, tenha em mente estes pontos-chave:

  • MainActor.assumeIsolated: Use apenas quando você garantir que ele seja chamado de MainActor. Esse é um mecanismo de segurança que diz ao Swift "confie em mim, eu sei que isso está sendo executado no thread principal".
  • nonisolated: Significa que pode ser acessado de qualquer thread, portanto, deve ser thread-safe. Use-o quando suas propriedades ou métodos não dependerem do estado da interface do usuário.
  • viewController: Permanece como @MainActor porque ele deve ser sempre acessado pelo thread principal. Os componentes da interface do usuário devem sempre ser executados no thread principal para evitar falhas.