Recursos avançados do SDK para iOS

Configuração avançada e integrações personalizadas para iOS.

Opções alternativas de montagem

O fluxo básico utiliza Yuno.startPayment() que lida com todo o fluxo de pagamento automaticamente. Para obter mais controle, use estas alternativas:

Seleção de método de pagamento personalizado (startPaymentLite)

Selecione qual método de pagamento exibir. Seu delegado deve implementar YunoPaymentFullDelegate com as propriedades necessárias:

class PaymentViewController: UIViewController, YunoPaymentFullDelegate {
    var checkoutSession: String { return _checkoutSession }
    var countryCode: String { "US" }
    var language: String? { "en" }
    var viewController: UIViewController? { self }
    
    private var _checkoutSession: String = ""
    
    func setupPayment() async {
        // 1. Create session
        let session = await createCheckoutSession()
        _checkoutSession = session.checkoutSession
        
        // 2. Fetch available methods
        let methods = await fetchPaymentMethods(sessionId: checkoutSession)
        
        // 3. Display in your UI, then start payment with selected method
        Yuno.startPaymentLite(
            paymentMethodType: selectedMethod, // "CARD", "PIX", etc.
            vaultedToken: nil, // or saved token
            delegate: self
        )
    }
}

Fluxo simplificado (startPaymentSeamlessLite)

Semelhante ao Lite, mas com criação automática de pagamentos:

Yuno.startPaymentSeamlessLite(
 paymentMethodType: "CARTÃO",
 vaultedToken: nil,
    delegado: self
)

Inscrição (Salvar cartões)

Salvar durante o pagamento

Seu delegado fornece as informações da sessão por meio de propriedades:

class PaymentViewController: UIViewController, YunoPaymentFullDelegate {
    var checkoutSession: String { _checkoutSession }
    var countryCode: String { "US" }
    var language: String? { "en" }
    var viewController: UIViewController? { self }
    
    private var _checkoutSession: String = ""
    
    func setupPayment() async {
        let session = await createCheckoutSession()
        _checkoutSession = session.checkoutSession
        
        // Start payment - SDK will show save card checkbox automatically
        Yuno.startPayment()
    }
    
    // In delegate:
    func yunoCreatePayment(with token: String, information: [String: Any]) {
        Task {
            await createPayment(
                token: token,
                vaultOnSuccess: true // Save after successful payment
            )
            Yuno.continuePayment(showPaymentStatus: true)
        }
    }
}

Inscrição separada

class EnrollmentViewController: UIViewController, YunoEnrollmentDelegate {
    var customerSession: String { _customerSession }
    var countryCode: String { "US" }
    var language: String? { "en" }
    var viewController: UIViewController? { self }
    
    private var _customerSession: String = ""
    
    func setupEnrollment() async {
        // Create customer session on backend
        let session = await createCustomerSession(customerId: "cus_123")
        _customerSession = session.id
        
        // Start enrollment - SDK reads session from delegate
        Yuno.enrollPayment(delegate: self)
    }
    
    func yunoEnrollmentStatus(status: Yuno.EnrollmentStatus, vaultedToken: String?) {
        if status == .successful, let token = vaultedToken {
            print("Card saved:", token)
        }
    }
    
    func yunoDidSelect(enrollmentMethod: EnrollmentMethodSelected) {
        print("Selected enrollment method:", enrollmentMethod)
    }
}

Token armazenados

Use os cartões salvos fornecendo o token armazenado no cofre token startPaymentLite:

class PaymentViewController: UIViewController, YunoPaymentFullDelegate {
    var checkoutSession: String { _checkoutSession }
    var countryCode: String { "US" }
    var language: String? { "en" }
    var viewController: UIViewController? { self }
    
    private var _checkoutSession: String = ""
    
    func payWithSavedCard(vaultedToken: String) {
        Yuno.startPaymentLite(
            paymentMethodType: "CARD",
            vaultedToken: vaultedToken,
            delegate: self
        )
    }
}

IU personalizada (integração sem interface gráfica)

Crie formulários de pagamento totalmente personalizados com controle total da interface do usuário quando precisar de controle total sobre todos os elementos da interface, experiências de checkout altamente personalizadas ou tiver recursos de desenvolvimento para uma interface personalizada.

import YunoSDK

class CustomPaymentVC: UIViewController {
    
    func processWithCustomUI() async {
        // 1. Initialize headless client
        let apiClient = Yuno.apiClientPayment(
            countryCode: "US",
            checkoutSession: "session_id"
        )
        
        // 2. Collect card data in your custom UI
        let cardData = CardData(
            number: "4111111111111111",
            expirationMonth: 12,
            expirationYear: 25,
            securityCode: "123",
            holderName: "John Doe",
            type: .credit
        )
        
        // 3. Generate token
        do {
            let result = try await apiClient.generateToken(data: TokenCollectedData(
                checkoutSession: "session_id",
                paymentMethod: CollectedData(
                    type: "CARD",
                    card: cardData
                )
            ))
            
            // 4. Create payment with token
            await createPayment(token: result.token)
            
            // 5. Handle continuation if needed
            if apiClient.shouldContinue {
                try await apiClient.continuePayment()
            }
        } catch {
            print("Error: \(error)")
        }
    }
}

Com Token Vaulted Token

let resultado = tente aguarde apiClient.generateToken(dados: TokenCollectedData(
 checkoutSession: "session_id",
    paymentMethod: CollectedData(
        tipo: "CARD",
 vaultedToken: "saved_token_id",
        cartão: CardData(código de segurança: "123")
    )
))

Integração do modo de renderização

Exiba o formulário de pagamento em sua visualização personalizada.

class PaymentViewController: UIViewController, YunoPaymentRenderFlowProtocol {
    
    func startRenderMode() async {
        let session = try await createCheckoutSession()
        
        let config = YunoConfig(
            checkoutSession: session.id,
            countryCode: "US"
        )
        
        Yuno.startPaymentRenderFlow(with: config, delegate: self)
    }
    
    // SDK provides view to embed
    func formView() -> UIView? {
        let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 350, height: 500))
        containerView.backgroundColor = .systemBackground
        return containerView
    }
    
    // Handle form submission
    func submitForm() async {
        // Customer submitted payment form
    }
    
    // Handle result
    func yunoPaymentResult(_ result: PaymentResult) {
        if result.status == .succeeded {
            navigateToSuccess()
        }
    }
}

SwiftUI:

struct RenderModeView: View, YunoPaymentRenderFlowProtocol {
    @State private var paymentView: UIView?
    
    var body: some View {
        if let view = paymentView {
            PaymentViewWrapper(view: view)
                .frame(height: 500)
        }
    }
    
    func startPayment() async {
        let config = YunoConfig(checkoutSession: "session_id", countryCode: "US")
        await Yuno.startPaymentRenderFlow(with: config, delegate: self)
    }
    
    func formView() -> UIView? {
        let view = UIView()
        DispatchQueue.main.async {
            paymentView = view
        }
        return view
    }
}

struct PaymentViewWrapper: UIViewRepresentable {
    let view: UIView
    
    func makeUIView(context: Context) -> UIView { view }
    func updateUIView(_ uiView: UIView, context: Context) {}
}

Estilo e aparência

Personalize a aparência do SDK com Yuno.Appearance:

import YunoSDK

func configureAppearance() {
    var appearance = Yuno.Appearance()
    
    // Cores
    appearance.primaryColor = UIColor.systemBlue
    appearance.backgroundColor = UIColor.systemBackground
    appearance.textColor = UIColor.label
    appearance.errorColor = UIColor.systemRed
    
    // Tipografia
    aparência.fontFamily = "SF Pro Display"
    aparência.fontSize = 16
    
    // Raio do canto
    aparência.cornerRadius = 12
    
    // Aplicar
    Yuno.setAppearance(aparência)
}

Concorrência no Swift 6

Lide com avisos de simultaneidade com anotações adequadas:

@MainActor
class PaymentViewController: UIViewController, YunoPaymentFullDelegate {
    var checkoutSession: String { _checkoutSession }
    var countryCode: String { "US" }
    var language: String? { "en" }
    var viewController: UIViewController? { self }
    
    private var _checkoutSession: String = ""
    
    // Safe to call from any thread
    nonisolated func startPayment() {
        Task { @MainActor in
            Yuno.startPayment()
        }
    }
    
    // UI updates on main thread
    @MainActor
    func yunoPaymentResult(_ result: PaymentResult) {
        updateUI(result)
    }
}

Delegado não isolado:

extension PaymentViewController {
    nonisolated func yunoPaymentResult(_ result: PaymentResult) {
        MainActor.assumeIsolated {
            // UI updates here
            self.showResult(result)
        }
    }
}

Integração ClearSale

Habilite a prevenção contra fraudes:

Instale o SDK ClearSale:

pod 'ClearSaleSDK'

Initialize:

import ClearSale

func application(_ application: UIApplication, 
                didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    
    // Initialize ClearSale
    ClearSale.setup(apiKey: "your-clearsale-key")
    
    // Initialize Yuno
    Yuno.initialize(apiKey: "your-public-key")
    
    return true
}

Os dados da ClearSale são coletados automaticamente e enviados junto com os pagamentos.

Configuração personalizada

Tipos de fluxo de cartões

Configure o fluxo de entrada do cartão durante a inicialização do Yuno:

// In AppDelegate or App struct
Yuno.initialize(
    apiKey: "your-public-key",
    cardFlow: .oneStep // or .stepByStep
)

Ocultar nome do titular do cartão

Configurar a visibilidade do nome do titular do cartão:

// Set globally
Yuno.hideCardholderName = true

Mostrar/ocultar tela de status

Controle a tela de status de pagamento em continuePayment():

func yunoCreatePayment(with token: String, information: [String: Any]) {
    Task {
        await createPayment(token: token)
        Yuno.continuePayment(showPaymentStatus: false) // Handle result yourself
    }
}

Tratamento de erros

func yunoPaymentResult(_ result: PaymentResult) {
    switch result.status {
    case .succeeded:
        handleSuccess(result)
    case .failed:
        handleFailure(result.error)
    case .pending:
        handlePending(result)
    case .rejected:
        handleRejection(result)
    }
}

func handleFailure(_ error: YunoError?) {
    guard let error = error else { return }
    
    switch error.code {
    case "SESSION_EXPIRED":
        // Recreate session
        Task { await createNewSession() }
    case "INVALID_CARD":
        showAlert("Please check your card details")
    case "INSUFFICIENT_FUNDS":
        showAlert("Insufficient funds")
    case "NETWORK_ERROR":
        showAlert("Connection error. Please try again.")
    default:
        showAlert("Payment failed: \(error.message)")
    }
}

Webhooks

Verifique o status do pagamento no backend:

// Backend receives webhook
POST /webhooks/yuno
{
  "type": "payment.succeeded",
  "data": {
    "payment_id": "pay_123",
    "status": "SUCCEEDED",
    "amount": 2500
  }
}

Testes

Modo de teste

// Use test key
Yuno.initialize(apiKey: "pk_test_your_key")

Registro de depuração

// Enable logs in development
#if DEBUG
Yuno.setLogLevel(.verbose)
#endif

Desempenho

Pré-carregar SDK

// Preload in background
Task(priority: .background) {
    _ = Yuno.self
}

Carregamento lento

// Load only when needed
lazy var yuno: Yuno = {
    Yuno.initialize(apiKey: "pk_test_key")
    return Yuno.shared
}()