Skip to main content

Overview

The Yuno Android SDK provides a pre-built payment UI that handles payment method rendering, card tokenization, and 3DS authentication. It supports both View-based (Activity/Fragment) and Jetpack Compose integrations.
The Android SDK maintains SAQ-A PCI compliance (the simplest compliance level. Card data never touches your servers).

Prerequisites

  • Android Studio Hedgehog (2023.1) or later
  • Minimum SDK: API 21 (Android 5.0)
  • Target SDK: API 34+
  • Kotlin 1.9+
  • Gradle 8.0+
  • Yuno API keys (Authentication)
  • At least one payment method enabled in your Dashboard

Installation

1

Add the Yuno Maven repository

In your project-level settings.gradle.kts:
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url = uri("https://yunopayments.jfrog.io/artifactory/snapshots") }
    }
}
2

Add the SDK dependency

In your app-level build.gradle.kts:
dependencies {
    implementation("com.yuno.payments:android-sdk:1.5.0")
}
3

Sync Gradle

Click Sync Now in Android Studio or run:
./gradlew build

SDK Initialization

Initialize the SDK in your Application class:
import android.app.Application
import com.yuno.payments.core.Yuno
import com.yuno.payments.core.YunoConfig

class YourApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        Yuno.initialize(
            application = this,
            config = YunoConfig(
                publicApiKey = "your-public-api-key",
                environment = YunoConfig.Environment.SANDBOX // Use PRODUCTION for live
            )
        )
    }
}
Register the Application class in AndroidManifest.xml:
<application
    android:name=".YourApplication"
    ...>
</application>

Configuration options

ParameterTypeRequiredDescription
publicApiKeyStringYesYour Yuno public API key
environmentEnvironmentYesSANDBOX or PRODUCTION
languageYunoLanguageNoUI language. Defaults to device locale
cardFlowCardFlowNoONE_STEP (default) or MULTI_STEP

Full Checkout

Full Checkout renders all enabled payment methods with a single call.

Activity / Fragment

1

Create a checkout session (server-side)

Create a session from your backend:
// POST https://api-sandbox.y.uno/v1/checkout/sessions
{
  "amount": { "currency": "USD", "value": 50.00 },
  "country": "CO",
  "merchant_order_id": "order-123",
  "workflow": "SDK_CHECKOUT"
}
Pass the checkout_session token to your Android app.
2

Register the checkout launcher

import com.yuno.payments.features.checkout.FullCheckoutLauncher
import com.yuno.payments.features.checkout.FullCheckoutResult

class CheckoutActivity : AppCompatActivity() {

    private val checkoutLauncher = registerForActivityResult(
        FullCheckoutLauncher()
    ) { result: FullCheckoutResult ->
        handleResult(result)
    }

    private fun handleResult(result: FullCheckoutResult) {
        when (result.status) {
            PaymentStatus.SUCCEEDED -> navigateToConfirmation(result.paymentId)
            PaymentStatus.FAILED -> showError(result.errorMessage)
            PaymentStatus.PROCESSING -> showProcessingState()
            PaymentStatus.CANCELLED -> showCancelledState()
        }
    }
}
3

Launch Full Checkout

fun startCheckout(sessionToken: String) {
    checkoutLauncher.launch(
        FullCheckoutParams(
            checkoutSession = sessionToken,
            countryCode = "CO"
        )
    )
}
4

Verify payment (server-side)

Always confirm the payment status from your backend:
// Server-side verification
// GET https://api-sandbox.y.uno/v1/payments/{payment_id}

Jetpack Compose

import com.yuno.payments.features.checkout.YunoFullCheckout
import com.yuno.payments.features.checkout.rememberCheckoutState

@Composable
fun CheckoutScreen(checkoutSession: String) {
    val checkoutState = rememberCheckoutState()

    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Button(
            onClick = {
                checkoutState.startFullCheckout(
                    checkoutSession = checkoutSession,
                    countryCode = "CO"
                )
            }
        ) {
            Text("Pay Now")
        }
    }

    YunoFullCheckout(
        state = checkoutState,
        onResult = { result ->
            when (result.status) {
                PaymentStatus.SUCCEEDED -> { /* Navigate to confirmation */ }
                PaymentStatus.FAILED -> { /* Show error */ }
                PaymentStatus.PROCESSING -> { /* Show processing */ }
                PaymentStatus.CANCELLED -> { /* Handle cancellation */ }
            }
        }
    )
}

Seamless Checkout

Seamless Checkout gives you control over payment method selection while Yuno handles the payment form.
1

Retrieve available payment methods

Yuno.getPaymentMethods(
    checkoutSession = sessionToken,
    countryCode = "CO"
) { methods ->
    // Display methods in your custom UI
    updatePaymentMethodList(methods)
}
2

Register the seamless checkout launcher

private val seamlessLauncher = registerForActivityResult(
    SeamlessCheckoutLauncher()
) { result: SeamlessCheckoutResult ->
    handleResult(result)
}
3

Launch for selected method

fun onPaymentMethodSelected(method: YunoPaymentMethod) {
    seamlessLauncher.launch(
        SeamlessCheckoutParams(
            checkoutSession = sessionToken,
            paymentMethodType = method.type,
            countryCode = "CO"
        )
    )
}
4

Handle payment creation callback

class CheckoutActivity : AppCompatActivity(), YunoSeamlessListener {

    override fun yunoCreatePayment(
        oneTimeToken: String,
        tokenWithInformation: YunoTokenData
    ) {
        // Create payment on your server
        PaymentApi.createPayment(oneTimeToken) { success ->
            if (success) {
                Yuno.continuePayment()
            }
        }
    }

    override fun yunoPaymentResult(result: PaymentResult) {
        handleResult(result)
    }
}

3DS Handling

The SDK handles 3D Secure authentication automatically. When a payment requires 3DS, the SDK presents the authentication challenge within the checkout flow. No additional code is required. The payment result callback receives the final outcome after 3DS completes.
Test 3DS flows in sandbox using Yuno’s test card numbers. Check the Testing guide for available test credentials.

Google Pay

To enable Google Pay in the Yuno Android SDK:
1

Enable Google Pay in Yuno Dashboard

Navigate to Dashboard > Settings > Payment Methods and enable Google Pay.
2

Add Google Pay metadata to manifest

<application>
    <meta-data
        android:name="com.google.android.gms.wallet.api.enabled"
        android:value="true" />
</application>
3

Pass Google Pay configuration

checkoutLauncher.launch(
    FullCheckoutParams(
        checkoutSession = sessionToken,
        countryCode = "US",
        googlePay = YunoGooglePayConfig(
            merchantName = "Your Store Name",
            countryCode = "US"
        )
    )
)

ProGuard Rules

If you use code shrinking (R8/ProGuard), add these rules to your proguard-rules.pro:
# Yuno SDK
-keep class com.yuno.payments.** { *; }
-keepclassmembers class com.yuno.payments.** { *; }
-dontwarn com.yuno.payments.**

# Required for payment processing
-keep class com.google.android.gms.wallet.** { *; }
The SDK ships with consumer ProGuard rules. These additional rules are only needed if you encounter obfuscation issues.

Customization

Customize the checkout appearance to match your app’s design:
val appearance = YunoAppearance(
    primaryColor = Color.parseColor("#6200EE"),
    backgroundColor = Color.WHITE,
    textColor = Color.BLACK,
    cornerRadiusDp = 12,
    fontFamily = "sans-serif-medium",
    buttonStyle = ButtonStyle.ROUNDED
)

Yuno.initialize(
    application = this,
    config = YunoConfig(
        publicApiKey = "your-public-api-key",
        environment = YunoConfig.Environment.SANDBOX,
        appearance = appearance
    )
)
PropertyTypeDescription
primaryColorInt (Color)Primary accent color for buttons and highlights
backgroundColorInt (Color)Background color of the checkout sheet
textColorInt (Color)Primary text color
cornerRadiusDpIntCorner radius in dp for cards and buttons
fontFamilyStringFont family name
buttonStyleButtonStyleROUNDED or RECTANGULAR

Localization

The SDK supports automatic localization based on the device locale. Override with:
Yuno.initialize(
    application = this,
    config = YunoConfig(
        publicApiKey = "your-public-api-key",
        environment = YunoConfig.Environment.SANDBOX,
        language = YunoLanguage.SPANISH
    )
)
Supported languages: English, Spanish, Portuguese, Indonesian, Malay, Thai.

Dark mode

The SDK respects the system dark mode setting by default. Colors adapt automatically unless you provide explicit appearance overrides.

Error Handling

Handle SDK errors through the result callback:
private fun handleResult(result: FullCheckoutResult) {
    result.error?.let { error ->
        when (error.code) {
            YunoErrorCode.NETWORK_ERROR ->
                showRetryAlert("Check your internet connection")
            YunoErrorCode.AUTHENTICATION_FAILED ->
                showError("Invalid API key. Verify your configuration.")
            YunoErrorCode.SESSION_EXPIRED ->
                refreshSessionAndRetry()
            YunoErrorCode.CANCELLED ->
                { /* User cancelled — no action needed */ }
            else ->
                showError(error.message ?: "An unexpected error occurred")
        }
    }
}

Common error codes

Testing in Sandbox

1

Use sandbox environment

Set environment = YunoConfig.Environment.SANDBOX during initialization.
2

Use test credentials

Use sandbox API keys from Dashboard > API Keys > Sandbox.
3

Test with Yuno test cards

Use Yuno-provided test card numbers to simulate different outcomes. See Testing.
Sandbox transactions use simulated providers. Some payment methods may have limited availability in sandbox compared to production.

Troubleshooting

SDK not initializing

  • Verify Yuno.initialize() is called in Application.onCreate() before any Activity launches
  • Confirm the public API key is correct and matches your environment
  • Check that minSdk is set to 21 or higher in build.gradle.kts

Checkout not appearing

  • Ensure the checkout session token is valid and not expired
  • Verify the Activity is not finishing when launching checkout
  • Check that at least one payment method is enabled in Dashboard for the specified country
  • Confirm the FullCheckoutLauncher is registered before onCreate() completes

Build errors

  • Duplicate classes: Add exclude rules for conflicting dependencies
  • Desugaring issues: Enable core library desugaring in build.gradle.kts:
android {
    compileOptions {
        isCoreLibraryDesugaringEnabled = true
    }
}

dependencies {
    coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4")
}

Payment failing silently

  • Implement the result callback to capture all outcomes
  • Enable verbose logging for debugging:
Yuno.initialize(
    application = this,
    config = YunoConfig(
        publicApiKey = "your-public-api-key",
        environment = YunoConfig.Environment.SANDBOX,
        enableLogging = true
    )
)
  • Check Logcat with tag filter YunoSDK for SDK output

Fragment lifecycle conflicts

If using Fragments, register the launcher in onCreate() (not onViewCreated()):
class CheckoutFragment : Fragment() {
    // Register in class body or onCreate — NOT in onViewCreated
    private val checkoutLauncher = registerForActivityResult(
        FullCheckoutLauncher()
    ) { result -> handleResult(result) }
}

API Reference

YunoConfig Parameters

ParameterTypeRequiredDefaultDescription
publicApiKeyStringYes.Your Yuno public API key
environmentYunoConfig.EnvironmentYes.SANDBOX or PRODUCTION
languageYunoLanguageNoDevice localeUI language (ENGLISH, SPANISH, PORTUGUESE, INDONESIAN, MALAY, THAI)
cardFlowCardFlowNoONE_STEPONE_STEP (single form) or MULTI_STEP (step-by-step card entry)
enableLoggingBooleanNofalseEnable verbose SDK logging to Logcat (tag: YunoSDK)
appearanceYunoAppearanceNoDefault themeVisual customization

FullCheckoutParams

ParameterTypeRequiredDescription
checkoutSessionStringYesCheckout session ID from your server
countryCodeStringYesISO 3166-1 alpha-2 country code
googlePayYunoGooglePayConfigNoGoogle Pay configuration

SeamlessCheckoutParams

ParameterTypeRequiredDescription
checkoutSessionStringYesCheckout session ID
paymentMethodTypeStringYesPayment method type (e.g., "CARD", "PIX", "PSE")
countryCodeStringYesISO 3166-1 alpha-2 country code
vaultedTokenStringNoVaulted token for saved payment methods

Callback Interfaces

OnPaymentListener:
MethodParametersDescription
onPaymentStateChange(state)PaymentStateCalled when the payment lifecycle state changes
onTokenGenerated(token)StringCalled when a one-time token is generated for payment creation
YunoSeamlessListener:
MethodParametersDescription
yunoCreatePayment(oneTimeToken, tokenWithInformation)String, YunoTokenDataCalled when a token is generated. Create payment server-side, then call Yuno.continuePayment()
yunoPaymentResult(result)PaymentResultCalled with the final payment outcome

Enrollment

Register the enrollment launcher and start enrollment for returning customers:
private val enrollmentLauncher = registerForActivityResult(
    EnrollmentLauncher()
) { result: EnrollmentResult ->
    handleEnrollmentResult(result)
}

fun startEnrollment(sessionId: String) {
    enrollmentLauncher.launch(
        EnrollmentParams(
            enrollmentSession = sessionId,
            countryCode = "CO",
            customerId = "customer-001"
        )
    )
}
Enrollment Statuses: CREATED, READY_TO_ENROLL, ENROLLED, ENROLL_FAILED, EXPIRED, REJECTED, DECLINED, UNENROLLED

Activity Result Handling

Register launchers at class level or in onCreate(). Never in onViewCreated():
class CheckoutActivity : AppCompatActivity() {
    private val fullCheckoutLauncher = registerForActivityResult(
        FullCheckoutLauncher()
    ) { result -> handlePaymentResult(result) }

    private val seamlessLauncher = registerForActivityResult(
        SeamlessCheckoutLauncher()
    ) { result -> handlePaymentResult(result) }
}

Extended Customization

Additional appearance properties beyond the basics:
PropertyTypeDescription
errorColorInt (Color)Color for error messages and invalid field states
borderColorInt (Color)Border color for input fields
elevationFloatElevation in dp for the checkout sheet
fontSizeSpIntBase font size in sp
Dark Mode: The SDK respects the system dark mode setting by default. Use forceDarkMode = true in YunoAppearance to override.

Payment Method Types

ConstantDescription
"CARD"Credit and debit cards
"PIX"PIX instant payments (Brazil)
"PSE"PSE bank transfers (Colombia)
"OXXO"OXXO cash vouchers (Mexico)
"NEQUI"Nequi mobile wallet (Colombia)
"APPLE_PAY"Apple Pay
"GOOGLE_PAY"Google Pay

Next steps

Mobile SDK Overview

Compare all mobile SDK options.

iOS SDK

Building for iOS? Start here.

Customization

Theme and style your checkout.

Testing

Test card numbers and sandbox setup.