Fonctionnalités avancées SDK iOS

Configuration avancée et intégrations personnalisées pour iOS.

Options de montage alternatives

Le flux de base utilise Yuno.startPayment() qui gère automatiquement l'intégralité du flux de paiement. Pour plus de contrôle, utilisez ces alternatives :

Sélection d'un mode de paiement personnalisé (startPaymentLite)

Sélectionnez le mode de paiement à afficher. Votre délégué doit mettre en œuvre YunoPaymentFullDelegate avec les propriétés requises :

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

Flux simplifié (startPaymentSeamlessLite)

Similaire à Lite, mais avec création automatique des paiements :

Yuno.startPaymentSeamlessLite(
 paymentMethodType: "CARD",
 vaultedToken: nil,
    delegate: self
)

Inscription (enregistrer les cartes)

Enregistrer pendant le paiement

Votre délégué fournit les informations de session via les propriétés :

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

Inscription séparée

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 voûtés

Utilisez les cartes enregistrées en fournissant le token stocké dans le coffre-fort 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
        )
    }
}

Interface utilisateur personnalisée (intégration sans interface graphique)

Créez des formulaires de paiement entièrement personnalisés avec un contrôle total de l'interface utilisateur lorsque vous avez besoin d'un contrôle complet sur chaque élément de l'interface utilisateur, d'expériences de paiement hautement personnalisées ou que vous disposez de ressources de développement pour une interface utilisateur personnalisée.

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

Avec Token voûté

let result = try await apiClient.generateToken(data: TokenCollectedData(
 checkoutSession: "session_id",
    paymentMethod: CollectedData(
        type: "CARD",
 vaultedToken: "saved_token_id",
        card: CardData(securityCode: "123")
    )
))

Intégration du mode de rendu

Affichez le formulaire de paiement dans votre vue personnalisée.

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

Style et apparence

Personnalisez l'apparence du SDK avec Yuno.Appearance:

import YunoSDK

func configureAppearance() {
    var appearance = Yuno.Appearance()
    
    // Couleurs
    appearance.primaryColor = UIColor.systemBlue
    appearance.backgroundColor = UIColor.systemBackground
    appearance.textColor = UIColor.label
    appearance.errorColor = UIColor.systemRed
    
    // Typographie
    apparence.fontFamily = "SF Pro Display"
    apparence.fontSize = 16
    
    // Rayon des coins
    apparence.cornerRadius = 12
    
    // Appliquer
    Yuno.setAppearance(apparence)
}

Concurrence Swift 6

Traitez les avertissements de concurrence avec des annotations appropriées :

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

Délégué non isolé :

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

Intégration ClearSale

Activer la prévention contre la fraude :

Installer le 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
}

Les données ClearSale sont automatiquement collectées et envoyées avec les paiements.

Configuration personnalisée

Types de flux de cartes

Configurer le flux d'entrée de la carte lors de l'initialisation de Yuno :

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

Masquer le nom du titulaire de la carte

Configurer la visibilité du nom du titulaire de la carte :

// Set globally
Yuno.hideCardholderName = true

Afficher/Masquer l'écran d'état

Contrôler l'état des paiements dans continuePayment():

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

Gestion des erreurs

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

Point d’ancrage Web

Vérifier le statut du paiement dans le backend :

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

Test

Mode test

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

Journalisation de débogage

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

Performance

Précharger le SDK

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

Chargement différé

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