Android SDK
Install the DEUNA Android SDK and integrate modal, embedded, wallet, voucher, and next-action flows.
On this page
Use the DEUNA Android SDK to show complete Checkout, Payment Widget, Payment Vault, Click to Pay, next-action, voucher, and native Google Pay experiences in Kotlin applications. The SDK supports Android API 22 and later.
Install#
Add JitPack to dependency resolution and pin a release of the SDK.
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven(url = "https://jitpack.io")
}
}android {
defaultConfig {
minSdk = 22
}
}
dependencies {
implementation("com.github.deuna-developers:deunasdk:<version>")
}Choose and pin <version> from the repository’s releases. Test upgrades in sandbox before promoting them to production.
Initialize#
Create one SDK instance with the public API key for the selected environment and retain it for the owning flow.
import com.deuna.maven.DeunaSDK
import com.deuna.maven.shared.Environment
val deunaSDK = DeunaSDK(
environment = Environment.SANDBOX,
publicApiKey = "YOUR_PUBLIC_API_KEY",
)For an application-wide instance, initialize the shared SDK once:
DeunaSDK.initialize(
environment = Environment.SANDBOX,
publicApiKey = "YOUR_PUBLIC_API_KEY",
)
val deunaSDK = DeunaSDK.sharedOpen Payment Widget in a modal#
Build typed callbacks and pass an Activity or another valid UI Context:
import com.deuna.maven.initPaymentWidget
import com.deuna.maven.widgets.payment_widget.PaymentWidgetCallbacks
val callbacks = PaymentWidgetCallbacks().apply {
onSuccess = { order ->
deunaSDK.close()
showConfirmation(order)
}
onError = { error -> showRetry(error) }
onClosed = { action -> showCart(action) }
onPaymentProcessing = { disablePayButton() }
onEventDispatch = { event, payload ->
analytics.track(event.name, payload)
}
}
deunaSDK.initPaymentWidget(
context = this,
orderToken = orderToken,
callbacks = callbacks,
language = "en",
)The modal host manages the widget and redirect views. Call close() when your success or error flow is complete; it waits for an active external URL to close before releasing the widget.
Available experiences#
| Experience | Method | Important input |
|---|---|---|
| Complete Checkout | initCheckout(...) | context, orderToken, CheckoutCallbacks |
| Payment Widget | initPaymentWidget(...) | context, orderToken, PaymentWidgetCallbacks |
| Payment Vault | initElements(...) | context, ElementsCallbacks; types may be omitted |
| Click to Pay | initElements(...) | types = listOf(mapOf("name" to "click_to_pay")) |
| Next Action | initNextAction(...) | Token for the order that requires another action |
| Voucher | initVoucherWidget(...) | Token for the voucher order |
All modal methods accept optional language, fraud, custom user-agent, and domain inputs where supported. Do not override domain unless DEUNA gives you a specific integration host.
Embed a widget#
Embedded mode uses a typed configuration and DeunaWidget. This Jetpack Compose example renders Payment Widget and destroys its WebView with the screen lifecycle.
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.viewinterop.AndroidView
import com.deuna.maven.web_views.deuna.DeunaWidget
import com.deuna.maven.web_views.deuna.extensions.build
import com.deuna.maven.widgets.configuration.PaymentWidgetConfiguration
val configuration = remember(orderToken) {
PaymentWidgetConfiguration(
sdkInstance = deunaSDK,
orderToken = orderToken,
callbacks = callbacks,
)
}
val widget = remember { mutableStateOf<DeunaWidget?>(null) }
AndroidView(
factory = { context ->
DeunaWidget(context).apply {
widgetConfiguration = configuration
build()
widget.value = this
}
},
)
DisposableEffect(Unit) {
onDispose { widget.value?.destroy() }
}Call resume() and pause() when the containing lifecycle starts and stops. For a widget inside a vertically scrolling screen, pass AutoResizeConfig in the configuration and connect setOnScrollByCallback to the parent scroll state.
If your application owns the pay button, set hidePayButton = true in the configuration and call the embedded DeunaWidget extension submit { result -> ... } from the button tap.
Payment Vault and Click to Pay#
Payment Vault is the default Elements experience. Pass either an authenticated userToken or enough UserInfo to identify the customer.
import com.deuna.maven.initElements
import com.deuna.maven.shared.ElementsCallbacks
import com.deuna.maven.shared.domain.UserInfo
val elementsCallbacks = ElementsCallbacks().apply {
onSuccess = { credential -> useSavedCredential(credential) }
onError = { error -> showRetry(error) }
onClosed = { action -> showPaymentMethods(action) }
}
deunaSDK.initElements(
context = this,
orderToken = orderToken,
userInfo = UserInfo(email = "ada@example.com"),
types = listOf(mapOf("name" to "vault")),
callbacks = elementsCallbacks,
)Use "click_to_pay" instead of "vault" for Click to Pay.
Native Google Pay#
Check both merchant configuration and device support before rendering your Google Pay button. The result is cached by the SDK.
import com.deuna.maven.wallets.GetWalletsAvailableParams
import com.deuna.maven.wallets.WalletProvider
import com.deuna.maven.wallets.getWalletsAvailable
val userInfo = UserInfo(email = "ada@example.com")
deunaSDK.getWalletsAvailable(
context = this,
params = GetWalletsAvailableParams(
orderToken = orderToken,
userInfo = userInfo,
),
) { wallets, error ->
if (error != null) {
showWalletError(error)
return@getWalletsAvailable
}
googlePayButton.isVisible = WalletProvider.GOOGLE_PAY in wallets
}After availability succeeds, launch the sheet from the button tap. initElements requires the availability call first.
googlePayButton.setOnClickListener {
deunaSDK.initElements(
context = this,
orderToken = orderToken,
userInfo = userInfo,
types = listOf(mapOf("name" to WalletProvider.GOOGLE_PAY.name)),
callbacks = elementsCallbacks,
)
}See Google Pay for merchant enrollment, testing, and tokenization details.
Continue a pending action#
Use the same order token when DEUNA reports that the payment requires a supported 3DS challenge or redirect.
deunaSDK.initNextAction(
context = this,
orderToken = orderToken,
callbacks = nextActionCallbacks,
)The SDK opens supported external URLs and returns to the active widget. Use callback state for the interface and a verified webhook for fulfillment.
Open a voucher#
deunaSDK.initVoucherWidget(
context = this,
orderToken = orderToken,
callbacks = voucherCallbacks,
)Voucher callbacks follow the same success, error, close, and event-dispatch lifecycle as the other payment experiences.
Fraud-device data#
Pre-initialize configured native fraud providers early, such as in Application.onCreate, to reduce latency later in the payment flow.
DeunaSDK.initializeFraudProviders(
context = applicationContext,
params = mapOf("MERCADOPAGO" to emptyMap<String, Any>()),
onError = { message -> logFraudError(message) },
)Generate the combined identifier when your order or risk flow needs it:
deunaSDK.generateFraudId(
context = this,
callback = { fraudId -> attachFraudId(fraudId) },
)Include only the fraud-provider dependencies and configuration assigned to your account. See Integrate device fingerprint.
Callback and lifecycle reference#
| Callback or method | Use it for |
|---|---|
onSuccess | Update the interface after the experience succeeds. |
onError | Handle a typed PaymentsError or ElementsError. |
onClosed | Distinguish customer and SDK-controlled closure. |
onEventDispatch | Observe supported checkout or Elements lifecycle events. |
onCardBinDetected | React to card BIN detection in Payment Widget or Elements. |
onInstallmentSelected | React to an installment-plan selection. |
onPaymentProcessing | Prevent duplicate payment actions. |
close() | Dismiss the active modal after external views have closed. |
Official examples and source#
See the example’s ExploreViewModel.kt for configuration factories and EmbeddedScreen.kt for WebView lifecycle handling.