Recursos avançados do Android SDK

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

Opções alternativas de montagem

O fluxo básico utiliza a exibição automática do método de pagamento. Para maior controle, utilize estas alternativas:

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

Controle qual método de pagamento exibir:

// 1. Fetch available methods
val methods = fetchPaymentMethods(sessionId)

// 2. Display in your UI
// 3. Start payment with selected method

startPaymentLite(
    paymentMethodType = selectedMethod, // "CARD", "PIX", etc.
    vaultedToken = null,
    showPaymentStatus = true,
    callbackOTT = { token ->
        token?.let { createPayment(it, checkoutSession) }
    }
)

Fluxo simplificado (startPaymentSeamlessLite)

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

startPaymentSeamlessLite(
 paymentMethodType "CARD",
 vaultedToken  null,
 showPaymentStatus  true
)

Inscrição (Salvar cartões)

Salvar durante o pagamento

// When creating payment on backend, include vault_on_success flag
suspend fun createPayment(token: String, checkoutSession: String) {
    apiClient.post("/payment/create", mapOf(
        "one_time_token" to token,
        "checkout_session" to checkoutSession,
        "vault_on_success" to true // Save after successful payment
    ))
}

// Configure SDK to show save checkbox
startCheckout(
    callbackPaymentState = { state -> handlePaymentState(state) }
)

// Update with session - SDK will show "Save card" checkbox automatically
updateCheckoutSession(
    checkoutSession = session.checkoutSession,
    countryCode = "US"
)

Inscrição separada

// Create customer session on backend
val customerSession = createCustomerSession("cus_123")

// Start enrollment
initEnrollment(
    customerSession = customerSession.id,
    countryCode = "US"
)

// Start enrollment flow
startEnrollment(
    showEnrollmentStatus = true,
    callback = { vaultedToken ->
        vaultedToken?.let {
            println("Card saved: $it")
        }
    }
)

Token armazenados

startPaymentLite(
 paymentMethodType "CARD",
 vaultedToken "vtok_saved_card_123",
 showPaymentStatus  true,
 callbackOTT { token >
 token?.let { createPayment(it, checkoutSession) }
    }
)

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 com.yuno.sdk.Yuno
import com.yuno.sdk.api.ApiClientPayment

lifecycleScope.launch {
    // 1. Initialize 
    val apiClient = Yuno.apiClientPayment(
 countryCode "US",
 checkoutSession "session_id"
    )
    
    // 2. Colete os dados do cartão em sua interface de usuário personalizada
    val token  apiClient.generateToken(
 checkoutSession "session_id",
        paymentMethod = PaymentMethod(
            type = "CARD",
            card = CardData(
                number = "4111111111111111",
                expirationMonth = 12,
                expirationYear = 25,
                securityCode = "123",
                holderName = "John Doe",
                type = "CREDIT"
            )
        )
    )
    
    // 3. Crie o pagamento com token
 
    createPayment(token.oneTimeToken)
    
    // 4. Lidar com a continuação, se necessário
    apiClient.continuePayment(
        activity = this@PaymentActivity,
        onPaymentResult = { result ->
            handlePaymentResult(result)
        }
    )
}

Com Token Vaulted Token

val token  apiClient.generateToken(
 checkoutSession "session_id",
    paymentMethod = PaymentMethod(
        type = "CARD",
 vaultedToken "saved_token_id",
        card = CardData(securityCode = "123")
    )
)

Integração do modo de renderização

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

class PaymentActivity : ComponentActivity(), YunoPaymentRenderListener {
    
    private lateinit var paymentController: YunoPaymentFragmentController
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        setContent {
            var paymentView by remember { mutableStateOf<View?>(null) }
            
            Column {
                Button(onClick = { startRenderMode() }) {
                    Text("Pay Now")
                }
                
                paymentView?.let {
                    AndroidView(factory = { it })
                }
            }
        }
    }
    
    private fun startRenderMode() {
        lifecycleScope.launch {
            val session = createCheckoutSession()
            
            paymentController = Yuno.startPaymentRender(
                activity = this@PaymentActivity,
                checkoutSession = session.id,
                countryCode = "US",
                listener = this@PaymentActivity
            )
        }
    }
    
    override fun onFormView(view: View) {
        // Add view to your layout
        findViewById<FrameLayout>(R.id.payment_container).addView(view)
    }
    
    override fun onSubmitForm() {
        // Customer submitted form
    }
    
    override fun onPaymentResult(result: PaymentResult) {
        if (result.status == PaymentStatus.SUCCEEDED) {
            navigateToSuccess()
        }
    }
}

Estilo

Personalize a aparência do SDK com temas.

cores.xml:

<color name="yuno_primary">#007bff</color>
<color name="yuno_background">#ffffff</color>
<color name="yuno_text">#333333</color>
<color name="yuno_error">#dc3545</color>

temas.xml:

<style name="YunoSDKTheme" parent="Theme.MaterialComponents">
    <item name="colorPrimary">@color/yuno_primary</item>
    <item name="colorOnPrimary">@android:color/white</item>
    <item name="android:textColor">@color/yuno_text</item>
</style>

Aplicar tema:

Yuno.definirTema(R.estilo.TemaYunoSDK)

Digitalização de cartões (OCR)

Ative a leitura de cartões com a câmera.

Adicionar dependência:

dependencies {
    implementation("com.yuno.sdk:card-scan:2.8.1")
}

Habilite na configuração:

Yuno.initialize(
    isto,
    chavePúblicaAPI = "sua-chave",
    config = YunoConfig(
        digitalizaçãoDeCartãoAtivada = verdadeiro
    )
)

O botão para digitalização do cartão aparece automaticamente no formulário do cartão.

Integração ClearSale

Habilite a prevenção contra fraudes.

Adicionar SDK ClearSale:

dependencies {
    implementation("br.com.clearsale:cs-android-sdk:4.0.0")
}

Initialize:

import br.com.clearsale.androidsdk.ClearSale

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        
        // Initialize ClearSale
        ClearSale.init(this, "your-clearsale-app-key")
        
        // Initialize Yuno
        Yuno.initialize(this, "your-public-key", YunoConfig())
    }
}

fingerprint ClearSale fingerprint coletada e enviada automaticamente.

Tratamento de erros

Lidar com erros na chamada de retorno do estado do pagamento e no processamento do pagamento:

// Set up error handling in payment state callback
startCheckout(
    callbackPaymentState = { state ->
        when (state) {
            "SUCCEEDED" -> handleSuccess()
            "FAIL" -> {
                // Handle payment failure
                showError("Payment failed")
            }
            "REJECT" -> {
                // Handle payment rejection
                showRejectedMessage()
            }
            "PROCESSING" -> showPendingMessage()
            else -> {}
        }
    }
)

// Update session with error handling
try {
    val session = createCheckoutSession()
    updateCheckoutSession(
        checkoutSession = session.checkoutSession,
        countryCode = "US"
    )
} catch (e: Exception) {
    Log.e("Payment", "Session error: ${e.message}")
    showError("Failed to initialize payment")
}

// Handle errors during payment creation
startPayment(
    showStatusYuno = true,
    callbackOTT = { token ->
        lifecycleScope.launch {
            try {
                createPayment(token, checkoutSession)
            } catch (e: Exception) {
                Log.e("Payment", "Payment creation error: ${e.message}")
                showError("Payment failed: ${e.message}")
            }
        }
    }
)

Testes e depuração

Ativar registro

Yuno.setLogLevel(LogLevel.VERBOSE)

Modo de teste

Yuno.initialize(
    isto,
    chavePúblicaDaAPI = "pk_test_sua_chave",
    config = YunoConfig(modoDeTeste = verdadeiro)
)

Desempenho

Inicialização preguiçosa

val yuno por lazy {
    Yuno.initialize(this, "pk_test_key", YunoConfig())
    Yuno.getInstance()
}

Pré-carregar SDK

lifecycleScope.launch(Dispatchers.IO) {
    Yuno.preload(this@MainActivity)
}

Retorno do navegador externo (links diretos)

Lide com usuários que retornam ao seu aplicativo após fluxos de pagamento externos, como desafios de autenticação 3DS, redirecionamentos de transferência bancária, pagamentos PIX e métodos de pagamento alternativos com redirecionamentos externos.

1. Defina callback_url na sessão de checkout

Incluir callback_url ao criar a sessão de checkout no seu backend:

{
  "callback_url": "myapp://return"
}
❗️

Importante

Sem callback_url, os usuários podem ficar presos no navegador externo, sem ter como retornar ao seu aplicativo.

2. Configurar o tratamento de links diretos

Adicionar um intent-filter à sua atividade em AndroidManifest.xml:

<activity android:name=".YourMainActivity">
    <intent-filter android:autoVerify="true">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data
            android:scheme="myapp"
            android:host="return" />
    </intent-filter>
</activity>

O esquema (myapp) e host (return) deve corresponder ao seu callback_url.

3. Lidar com a intenção de devolução

Lidar com o link direto quando o usuário retornar:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    
    // Check if app was opened via deep link
    intent.data?.let { uri ->
        val url = uri.toString()
        if (url.contains("myapp://return")) {
            handlePaymentReturn(uri)
        }
    }
}

private fun handlePaymentReturn(uri: Uri) {
    val sessionId = uri.getQueryParameter("checkoutSession")
    
    sessionId?.let {
        continuePayment(
            showPaymentStatus = true,
            checkoutSession = it,
            countryCode = "US"
        ) { result ->
            result?.let { status ->
                Toast.makeText(this, "Payment status: $status", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

4. Exemplo de integração completa

class PaymentActivity : ComponentActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // Initialize checkout
        startCheckout(
            callbackPaymentState = { state ->
                handlePaymentState(state)
            }
        )
        
        // Handle deep link return
        if (intent?.data != null) {
            handleDeepLinkReturn(intent)
        } else {
            // Normal payment flow
            initializePaymentUI()
        }
    }
    
    private fun handleDeepLinkReturn(intent: Intent) {
        intent.data?.let { uri ->
            if (uri.toString().contains("myapp://return")) {
                val sessionId = extractCheckoutSession(uri)
                
                sessionId?.let {
                    continuePayment(
                        showPaymentStatus = true,
                        checkoutSession = it,
                        countryCode = "US"
                    ) { result ->
                        when (result) {
                            "SUCCEEDED" -> navigateToSuccess()
                            "FAILED" -> showError("Payment failed")
                            else -> showPendingMessage()
                        }
                    }
                }
            }
        }
    }
    
    private fun extractCheckoutSession(uri: Uri): String? {
        return uri.getQueryParameter("checkoutSession")
    }
}

Melhores práticas

  • Inclua sempre callback_url em fluxos de pagamento que podem redirecionar
  • Teste o tratamento de links diretos em vários dispositivos e versões do Android
  • Lidar com dados de links diretos ausentes ou malformados de maneira elegante
  • Atualize o status do pagamento na sua interface do usuário após retornar do navegador externo.