SDK de Android

Instalar

build.gradle (nivel de proyecto):

repositories {
    maven { url = uri("https://yunopayments.jfrog.io/artifactory/snapshots-libs-release") }
}

build.gradle (nivel de la aplicación):

dependencies {
    implementation("com.yuno.sdk:yuno-sdk-android:2.8.1")
}
📘

Requisitos

Android 5.0 (API 21)+, Kotlin 1.9.24+, Java 17, Jetpack Compose (para la integración de Compose)

Initialize

En la clase Application:

import com.yuno.sdk.Yuno
import android.app.Application

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        Yuno.initialize(
            this,
            publicApiKey = "your-public-api-key",
            config = YunoConfig()
        )
    }
}

AndroidManifest.xml:

<application
    android:name=".MyApplication"
    ...>
</application>

pago básico de pago

Jetpack Compose

import androidx.compose.runtime.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.yuno.sdk.Yuno
import com.yuno.sdk.payments.OneTimeToken

@Composable
fun PaymentScreen() {
    var checkoutSession by remember { mutableStateOf<String?>(null) }
    var paymentMethodSelected by remember { mutableStateOf(false) }
    val scope = rememberCoroutineScope()
    
    LaunchedEffect(Unit) {
        // 1. Initialize checkout with callback
        startCheckout(
            callbackPaymentState = { state ->
                when (state) {
                    "SUCCEEDED" -> navigateToSuccess()
                    "FAIL" -> showError()
                    else -> {}
                }
            }
        )
        
        // 2. Create session on backend
        val session = createCheckoutSession()
        checkoutSession = session.checkoutSession
        
        // 3. Update SDK with session and country
        updateCheckoutSession(
            checkoutSession = session.checkoutSession,
            countryCode = "US"
        )
    }
    
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp)
    ) {
        Text("Total: $25.00", style = MaterialTheme.typography.headlineMedium)
        
        Spacer(modifier = Modifier.height(16.dp))
        
        // Payment methods list
        Column(
            modifier = Modifier
                .weight(1f)
                .verticalScroll(rememberScrollState())
        ) {
            PaymentMethodListViewComponent(
                activity = LocalContext.current as ComponentActivity,
                onPaymentSelected = { isSelected ->
                    paymentMethodSelected = isSelected
                }
            )
        }
        
        // Pay button
        Button(
            onClick = {
                scope.launch {
                    startPayment(
                        showStatusYuno = true,
                        callbackOTT = { token ->
                            token?.let { createPayment(it, checkoutSession!!) }
                        }
                    )
                }
            },
            enabled = paymentMethodSelected,
            modifier = Modifier.fillMaxWidth()
        ) {
            Text("Pay Now")
        }
    }
}

suspend fun createCheckoutSession(): CheckoutSession {
    return apiClient.post("/checkout", mapOf(
        "amount" to mapOf("currency" to "USD", "value" to 2500),
        "customer_id" to "cus_123",
        "country" to "US"
    ))
}

suspend fun createPayment(token: String, checkoutSession: String) {
    apiClient.post("/payment/create", mapOf(
        "one_time_token" to token,
        "checkout_session" to checkoutSession
    ))
}

Vistas XML (tradicionales)

import com.yuno.sdk.Yuno
import com.yuno.sdk.payments.OneTimeToken

class PaymentActivity : AppCompatActivity() {
    private lateinit var checkoutSession: String
    private var paymentMethodSelected = false
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_payment)
        
        initializeCheckout()
        
        findViewById<Button>(R.id.payButton).apply {
            isEnabled = false
            setOnClickListener {
                if (paymentMethodSelected) {
                    processPayment()
                }
            }
        }
    }
    
    private fun initializeCheckout() {
        lifecycleScope.launch {
            // 1. Initialize checkout with callback
            startCheckout(
                callbackPaymentState = { state ->
                    handlePaymentState(state)
                }
            )
            
            // 2. Create session on backend
            val session = createCheckoutSession()
            checkoutSession = session.checkoutSession
            
            // 3. Update SDK with session and country
            updateCheckoutSession(
                checkoutSession = session.checkoutSession,
                countryCode = "US"
            )
            
            // 4. Set up payment methods view
            setupPaymentMethodsView()
        }
    }
    
    private fun setupPaymentMethodsView() {
        // For Compose-based payment methods view:
        val composeView = findViewById<ComposeView>(R.id.paymentMethodsContainer)
        composeView.setContent {
            PaymentMethodListViewComponent(
                activity = this@PaymentActivity,
                onPaymentSelected = { isSelected ->
                    paymentMethodSelected = isSelected
                    findViewById<Button>(R.id.payButton).isEnabled = isSelected
                }
            )
        }
    }
    
    private fun processPayment() {
        lifecycleScope.launch {
            startPayment(
                showStatusYuno = true,
                callbackOTT = { token ->
                    token?.let {
                        createPayment(it, checkoutSession)
                    }
                }
            )
        }
    }
    
    private fun handlePaymentState(state: String?) {
        when (state) {
            "SUCCEEDED" -> {
                Toast.makeText(this, "Payment successful!", Toast.LENGTH_SHORT).show()
                startActivity(Intent(this, SuccessActivity::class.java))
                finish()
            }
            "FAIL" -> {
                Toast.makeText(this, "Payment failed", Toast.LENGTH_LONG).show()
            }
            "PROCESSING" -> {
                Toast.makeText(this, "Payment is being processed", Toast.LENGTH_SHORT).show()
            }
            "CANCELED" -> {
                Toast.makeText(this, "Payment canceled", Toast.LENGTH_SHORT).show()
            }
            else -> {}
        }
    }
    
    private suspend fun createCheckoutSession(): CheckoutSession = withContext(Dispatchers.IO) {
        val client = OkHttpClient()
        val json = """
            {
                "amount": {"currency": "USD", "value": 2500},
                "customer_id": "cus_123",
                "country": "US"
            }
        """.trimIndent()
        
        val request = Request.Builder()
            .url("https://api.example.com/checkout")
            .post(json.toRequestBody("application/json".toMediaType()))
            .build()
        
        val response = client.newCall(request).execute()
        Gson().fromJson(response.body?.string(), CheckoutSession::class.java)
    }
    
    private suspend fun createPayment(token: String, checkoutSession: String) = withContext(Dispatchers.IO) {
        val client = OkHttpClient()
        val json = """
            {
                "one_time_token": "$token",
                "checkout_session": "$checkoutSession"
            }
        """.trimIndent()
        
        val request = Request.Builder()
            .url("https://api.example.com/payment/create")
            .post(json.toRequestBody("application/json".toMediaType()))
            .build()
        
        client.newCall(request).execute()
    }
}

Gestión de pago

Gestiona los cambios pago a través de la callbackPaymentState devolución de llamada:

// Set up payment state callback during initialization
startCheckout(
    callbackPaymentState = { state ->
        when (state) {
            "SUCCEEDED" -> {
                // Payment successful
                navigateToSuccess()
            }
            "FAIL" -> {
                // Payment failed
                showError("Payment failed")
            }
            "PROCESSING" -> {
                // Payment is being processed
                showPendingMessage()
            }
            "REJECT" -> {
                // Payment was rejected
                showError("Payment rejected")
            }
            "CANCELED" -> {
                // User canceled
                Toast.makeText(context, "Payment canceled", Toast.LENGTH_SHORT).show()
            }
            else -> {}
        }
    }
)

// After startCheckout, update with session and country
updateCheckoutSession(
    checkoutSession = session.checkoutSession,
    countryCode = "US"
)

Autenticación 3DS

El SDK gestiona automáticamente el 3DS. Llama a continuePayment() Después de crear pago sdk_action_required es cierto:

startPayment(
    showStatusYuno = true,
 callbackOTT { token >
        lifecycleScope.launch {
            val result = createPayment(token, checkoutSession)
            
            if (result.sdkActionRequired) {
 continuePayment()
            }
        }
    }
)

Opciones de configuración

Parámetros esenciales

ParámetroTipoDescripción
checkoutSessionCadenaID de sesión del backend
countryCodeCadenaCódigo ISO del país (por ejemplo, «US»)
callbackPaymentStateFunciónllamada de retorno pago
callbackOTTFuncióntoken única token

pago

const val pago= "SUCCEEDED"
const val pago= "FAIL"
const val pago= "PROCESSING"
const val pago= "REJECT"
const val pago= "CANCELED"

Reglas de Proguard

proguard-rules.pro:

# Yuno SDK
-keep class com.yuno.sdk.** { *; }
-keep interface com.yuno.sdk.** { *; }
-dontwarn com.yuno.sdk.**

# OkHttp & Retrofit
-dontwarn okhttp3.**
-dontwarn retrofit2.**

Próximos pasos

¿Estás listo para explorar funciones más avanzadas? Consulta la guía de funciones avanzadas para:

  • Opciones de montaje alternativas - startPaymentLite() y startPaymentSeamlessLite() para la selección de pago personalizados
  • Inscripción (Guardar tarjetas): guarda pago para usarlos en el futuro.
  • Token almacenados: pagos con un solo clic con tarjetas guardadas.
  • Interfaz de usuario personalizada (integración sin interfaz gráfica): crea pago totalmente personalizados.
  • Integración del modo de renderizado: muestra pago dentro de tu vista personalizada.
  • Estilo: personaliza la apariencia del SDK con temas.
  • Escaneo de tarjetas (OCR): habilita el escaneo de tarjetas con la cámara.
  • Integración con ClearSale: prevención del fraude
  • Retorno del navegador externo (enlaces profundos): gestionar pago .

Véase también