SDK de Android
Instale el SDK de Android de DEUNA e integre los flujos de carrito, widget, wallet, voucher y siguiente acción.
En esta página
- Requisitos
- Instalación
- Inicialización
- Abrir widget de pago
- Experiencias disponibles
- Integrar un widget
- Filtrar y configurar métodos de pago
- Estilo dinámico y actualización del pedido
- Almacén de pagos y Pago con un clic
- Google Pay nativo
- Continúe con una acción pendiente
- Abrir un cupón
- Datos del dispositivo y huella digital para fraude
- Referencia del ciclo de vida y llamadas de retorno
- Ejemplos y código fuente oficiales
Requisitos#
Para integrar el SDK de Android de DEUNA, asegúrese de que su proyecto cumpla con los siguientes requisitos:
- Versión mínima del SDK:
minSdkVersion 24o superior (Android API 24+) - Android Gradle Plugin (AGP): Versión 8.5.1 o superior (requerido para soporte de tamaño de página de 16 KB de Android)
- Lenguaje de programación: Kotlin o Java
- Credenciales de DEUNA: Cuenta activa y credenciales válidas (contacte a support@deuna.com si experimenta demoras para obtener credenciales)
Instalación#
1. Agregue el repositorio JitPack
Agregue el repositorio JitPack dentro del dependencyResolutionManagement bloque en su settings.gradle.kts (o settings.gradle):
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven(url = "https://jitpack.io")
}
}dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
}
}Si su proyecto no utiliza dependencyResolutionManagement, agregue el repositorio en el archivo raíz build.gradle:
allprojects {
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
}
}2. Configure build.gradle y las dependencias
Asegúrese de que su minSdk sea 24 o superior, y agregue la dependencia del SDK de DEUNA:
android {
defaultConfig {
minSdk = 24
}
}
dependencies {
implementation("com.github.deuna-developers:deuna-sdk-android:2.12.7")
}android {
defaultConfig {
minSdk 24
}
}
dependencies {
implementation 'com.github.deuna-developers:deuna-sdk-android:2.12.7'
}Inicialización#
import com.deuna.maven.DeunaSDK
import com.deuna.maven.shared.EnvironmentPuede inicializar el SDK de dos maneras según la arquitectura de su aplicación:
Instancia global compartida
Inicialice una vez durante el inicio de la aplicación (por ejemplo, en su Application.onCreate):
DeunaSDK.initialize(
environment = Environment.SANDBOX, // Environment.SANDBOX or Environment.PRODUCTION
publicApiKey = "YOUR_PUBLIC_API_KEY"
)
val deunaSDK = DeunaSDK.sharedFlujo o instancia de pantalla
Cree una instancia para una pantalla de pago específica o ViewModel:
val deunaSDK = DeunaSDK(
environment = Environment.SANDBOX,
publicApiKey = "YOUR_PUBLIC_API_KEY"
)Abrir widget de pago#
El Widget de Pago ofrece múltiples métodos de pago a los clientes:
- Tarjetas de crédito y débito: Visa, Mastercard, American Express y tarjetas co-branded.
- Métodos de pago alternativos (APMs): OXXO, KueskiPay, Aplazo, Daviplata, Nequi y más.
- Carteras digitales: Google Pay y PayPal.
Mostrar en un cuadro de diálogo
Para presentar el widget de pago en un DialogFragment, llamar initPaymentWidget pasando una Activity Context:
import com.deuna.maven.initPaymentWidget
import com.deuna.maven.widgets.payment_widget.PaymentWidgetCallbacks
import com.deuna.maven.payments.PaymentsError
deunaSDK.initPaymentWidget(
context = this, // Activity context
orderToken = "YOUR_ORDER_TOKEN",
callbacks = PaymentWidgetCallbacks().apply {
onSuccess = { order ->
deunaSDK.close() // Close the DialogFragment
// YOUR CODE HERE: Handle successful payment (e.g. navigate to confirmation)
}
onError = { error ->
// Error handling
when (error.type) {
PaymentsError.Type.INITIALIZATION_FAILED -> {
deunaSDK.close()
// YOUR CODE HERE: Handle initialization failure (e.g. show alert or fallback)
}
PaymentsError.Type.PAYMENT_ERROR -> {
// YOUR CODE HERE: Handle payment processing failure (e.g. prompt retry)
}
else -> {}
}
}
onClosed = { action ->
// Widget closed: action == CloseAction.USER_ACTION or CloseAction.SYSTEM_ACTION
// YOUR CODE HERE: Handle dialog dismissal
}
onCardBinDetected = { metadata, refetchOrder ->
if (metadata != null) {
// YOUR CODE HERE: Handle card brand or BIN detection (e.g. apply discounts)
}
}
onInstallmentSelected = { metadata, refetchOrder ->
// YOUR CODE HERE: Handle installment plan selection
}
onPaymentProcessing = {
// YOUR CODE HERE: Payment processing started (e.g. disable UI buttons)
}
onEventDispatch = { event, payload ->
// YOUR CODE HERE: Track analytics event
}
},
userToken = "YOUR_USER_TOKEN", // optional
styleFile = "YOUR_STYLE_FILE_UUID", // optional
language = "en" // optional: "es", "en", "pt"
)Referencia de parámetros
| Parámetro | Tipo | Cuadro de diálogo | Integrado | Descripción |
|---|---|---|---|---|
context | Context | ✅ | ❌ | Requerido para el cuadro de diálogo. Contexto de Activity que proporciona recursos de UI y token de ventana. |
orderToken | String | ✅ | ✅ | Requerido. Token único para la orden creada a través de la API de DEUNA. importante: No defina un redirect_url en la creación del pedido si desea que onSuccess se ejecute dentro de la aplicación. |
callbacks | PaymentWidgetCallbacks | ✅ | ✅ | Requerido. Los oyentes de eventos (onSuccess, onError, onClosed, onCardBinDetected, onInstallmentSelected, onPaymentProcessing, onEventDispatch). |
userToken | String? | ✅ | ✅ | Opcional. Token de portador (bearer) de DEUNA del cliente. importante: Para que aparezcan tarjetas guardadas, el correo electrónico vinculado al userToken deben coincidir con billing_address.email de la creación del pedido. |
styleFile | String? | ✅ | ✅ | Opcional. UUID proporcionado por DEUNA para aplicar personalización de marca de tema personalizado (colores, tipografía, logo). |
paymentMethods | List<Map<String, Any>>? | ✅ | ✅ | Opcional. Lista de método de pago único para flujo de formularios directos (por ejemplo, listOf(mapOf("paymentMethod" to "bnpl", "processors" to listOf("kueski")))). |
language | String? | ✅ | ✅ | Opcional. Código de idioma ("es", "en", "pt"). Anula la configuración predeterminada del comerciante. |
behavior | WidgetBehavior? | ✅ | ✅ | Opcional. Personalización del flujo, como WidgetBehavior(paymentMethods = mapOf("flowType" to "twoStep")) para PayPal, o Pagos Divididos splitPayments. |
fraudCredentials | Map<String, Any>? | ✅ | ✅ | Opcional. Credenciales del proveedor antifraude (por ejemplo, mapOf("RISKIFIED" to mapOf("storeDomain" to "example.com"))). |
domain | String? | ✅ | ✅ | Opcional. Anula el host base predeterminado (https://pay.deuna.io). |
hidePayButton | Boolean | ❌ | ✅ | Opcional. Oculta el botón de pago integrado en modo embebido cuando su aplicación renderiza un botón nativo. |
Experiencias disponibles#
| Experiencia | Método | Tipo de configuración | Información necesaria |
|---|---|---|---|
| Widget de pago | initPaymentWidget(...) | PaymentWidgetConfiguration | context, orderToken, PaymentWidgetCallbacks |
| Caja de Pago | initElements(...) | ElementsWidgetConfiguration | context, ElementsCallbacks; types puede omitirse |
| Haga clic para pagar | initElements(...) | ElementsWidgetConfiguration | types = listOf(mapOf("name" to "click_to_pay")) |
| Siguiente Acción | initNextAction(...) | NextActionWidgetConfiguration | context, orderToken, NextActionCallbacks |
| vale | initVoucherWidget(...) | VoucherWidgetConfiguration | context, orderToken, VoucherCallbacks |
Todos los métodos modales aceptan entradas opcionales de idioma, fraude y dominio cuando están admitidas. No anules domain a menos que DEUNA te asigne un host dedicado.
Integrar un widget#
Para mostrar el widget incrustado dentro de tu aplicación con Jetpack Compose, usa AndroidView y DeunaWidget.
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import com.deuna.maven.DeunaSDK
import com.deuna.maven.web_views.deuna.DeunaWidget
import com.deuna.maven.web_views.deuna.extensions.build
import com.deuna.maven.widgets.configuration.PaymentWidgetConfiguration
import com.deuna.maven.widgets.payment_widget.PaymentWidgetCallbacks
@Composable
fun EmbeddedCheckoutScreen(
deunaSDK: DeunaSDK,
orderToken: String,
userToken: String? = null,
) {
// Retain the Deuna WebView instance across recompositions
val deunaWidget = remember { mutableStateOf<DeunaWidget?>(null) }
Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
Box(modifier = Modifier.fillMaxWidth().weight(1f)) {
AndroidView(
modifier = Modifier.fillMaxSize(),
factory = { context ->
DeunaWidget(context).apply {
this.widgetConfiguration = PaymentWidgetConfiguration(
sdkInstance = deunaSDK,
orderToken = orderToken,
userToken = userToken,
callbacks = PaymentWidgetCallbacks().apply {
onSuccess = { order ->
// YOUR CODE HERE: Handle successful payment
}
onError = { error ->
// YOUR CODE HERE: Handle payment error
}
onEventDispatch = { event, payload ->
// YOUR CODE HERE: Track analytics event
}
}
)
this.build() // Render the DEUNA widget
deunaWidget.value = this
}
}
)
}
}
// Explicitly clean up WebView resources when composable leaves composition
DisposableEffect(Unit) {
onDispose {
deunaWidget.value?.destroy()
}
}
}Redimensionamiento automático y manejo del teclado
Cuando pasas autoResizeConfig = AutoResizeConfig(initialHeightDp = 100), el widget cambia al modo de redimensionamiento automático: crece y se reduce dinámicamente para coincidir con la altura del contenido del WebView, lo que lo hace ideal para incrustar dentro de un contenedor desplazable.
- Configuración del manifiesto: Asegúrate de que tu Activity de checkout esté configurada con
adjustResizeenAndroidManifest.xml:
<activity
android:name=".CheckoutActivity"
android:windowSoftInputMode="adjustResize" />- Integración con desplazamiento en Compose: Coloca
DeunaWidgetdentro de un contenedor de desplazamiento vertical y conectasetOnScrollByCallbackal ComposeScrollState:
@Composable
fun ScrollableCheckoutScreen(
deunaSDK: DeunaSDK,
widgetConfig: PaymentWidgetConfiguration,
) {
val scrollState = rememberScrollState()
val coroutineScope = rememberCoroutineScope()
Column(
modifier = Modifier
.fillMaxSize()
.verticalScroll(scrollState)
) {
// Content above widget...
AndroidView(
modifier = Modifier.fillMaxWidth(),
factory = { context ->
DeunaWidget(context).apply {
this.widgetConfiguration = widgetConfig
this.build()
}
},
update = { widget ->
// Wire the SDK scroll request to Compose ScrollState
widget.setOnScrollByCallback { amountPx ->
coroutineScope.launch {
scrollState.animateScrollBy(amountPx)
}
}
}
)
// Content below widget...
}
}Botón de pago personalizado (hidePayButton)
Si tu aplicación renderiza su propio botón nativo fuera del widget, pasa hidePayButton = true y maneja el envío de forma programática usando isValid y submit:
PaymentWidgetConfiguration(
sdkInstance = deunaSDK,
orderToken = orderToken,
hidePayButton = true,
callbacks = callbacks
)
// When the user taps your custom native pay button:
deunaWidget.value?.isValid { isValid ->
if (isValid) {
deunaWidget.value?.submit { result ->
// result.status: "success" | "error"
// result.message: Detailed message
}
}
}| Método | Descripción | Valor de retorno |
|---|---|---|
deunaWidget.isValid { valid -> ... } | Valida la entrada del usuario en el formulario de pago activo. | Boolean |
deunaWidget.submit { result -> ... } | Envía el pago equivalente a hacer clic en el botón del widget. | SubmitResult (status: "success" o status: "error") |
Filtrar y configurar métodos de pago#
Flujo de formularios directos (paymentMethods)
Las arquitecturas de checkout de DEUNA admiten lanzarse directamente a un formulario de pago individual, un patrón conocido como flujo de formularios.
Aunque paymentMethods está tipado como una lista, los motores de checkout internos actualmente admiten solo un elemento en esta lista. Proporcionar un único método de pago abre el widget directamente en el formulario de ese método (por ejemplo, Kueski Pay BNPL), omitiendo el selector de métodos.
deunaSDK.initPaymentWidget(
context = this,
orderToken = "YOUR_ORDER_TOKEN",
callbacks = callbacks,
paymentMethods = listOf(
mapOf(
"paymentMethod" to "bnpl",
"processors" to listOf("kueski")
)
)
)Resolución de prioridad de configuración
| Prioridad | Fuente | Comportamiento |
|---|---|---|
| 1 (Mayor prioridad) | paymentMethods en .initPaymentWidget() | Flujo de formularios directos: Se abre inmediatamente en el formulario del método de pago único especificado (por ejemplo, Kueski), omitiendo el selector de métodos. |
| 2 | include_payment_options en la creación de la orden | Selección de múltiples métodos: Muestra solo los métodos de pago especificados durante la creación de la orden que estén activos en tu cuenta. |
| 3 (Respaldo) | Configuración a nivel de comerciante (/payment-methods) | Selector completo: Si se omite tanto en la llamada al SDK como en el payload de la orden, muestra todos los métodos de pago activos configurados para tu cuenta de comerciante. |
Configuraciones de PayPal
Tipo de flujo (flowType)
deunaSDK.initPaymentWidget(
context = this,
orderToken = orderToken,
behavior = WidgetBehavior(
paymentMethods = mapOf(
"flowType" to "twoStep" // "twoStep" (summary first) or "singleStep" (direct)
)
)
)Compra automática (express)
Cuando los clientes han autorizado previamente pagos rápidos con PayPal, habilita el procesamiento inmediato:
deunaSDK.initPaymentWidget(
context = this,
orderToken = orderToken,
callbacks = callbacks,
paymentMethods = listOf(
mapOf(
"paymentMethod" to "wallet",
"processors" to listOf("paypal_wallet"),
"configuration" to mapOf("express" to true)
)
)
)Pagos divididos con múltiples tarjetas
deunaSDK.initPaymentWidget(
context = this,
orderToken = orderToken,
behavior = WidgetBehavior(
paymentMethods = mapOf(
"creditCard" to mapOf(
"splitPayments" to mapOf(
"maxCards" to 2 // Maximum number of cards allowed
)
)
)
)
)Estilo dinámico y actualización del pedido#
Personaliza la apariencia de forma dinámica (setCustomStyle)
Actualiza los estilos del widget dinámicamente (por ejemplo, adaptando la marca al detectar el BIN de la tarjeta):
callbacks = PaymentWidgetCallbacks().apply {
onCardBinDetected = { metadata, _ ->
deunaSDK.setCustomStyle(
data = mapOf(
"theme" to mapOf(
"colors" to mapOf(
"primaryTextColor" to "#023047",
"buttonPrimaryFill" to "#FFB703",
"buttonPrimaryText" to "#000000"
)
)
)
)
}
}Actualiza totales del pedido (refetchOrder)
Al ofrecer promociones específicas de franquicia (por ejemplo, "20% de descuento con Mastercard"), escucha a onCardBinDetected, actualice el pedido en su backend y notifique al widget:
callbacks = PaymentWidgetCallbacks().apply {
onCardBinDetected = { metadata, _ ->
val cardBrand = metadata?.get("cardBrand") as? String
if (cardBrand == "Mastercard") {
// 1. Notify backend to apply promo
applyDiscountOnBackend(orderId, "MASTERCARD_20") {
// 2. Refresh widget totals
deunaSDK.refetchOrder { updatedOrder ->
println("Order refreshed with discount: $updatedOrder")
}
}
}
}
}Almacén de pagos y Pago con un clic#
Payment Vault es un componente de las soluciones de pago DEUNA que permite guardar tarjetas de forma segura y pagar mediante Click to Pay sin procesar pagos regulares.
Mostrar en un cuadro de diálogo
Para mostrar Card Vault en un cuadro de diálogo modal, llame a initElements (omita types para el Vault predeterminado):
import com.deuna.maven.initElements
import com.deuna.maven.shared.ElementsCallbacks
import com.deuna.maven.shared.domain.UserInfo
import com.deuna.maven.widgets.elements.ElementsWidgetExperience
deunaSDK.initElements(
context = this,
userToken = "<USER_TOKEN>", // optional if userInfo is provided
userInfo = UserInfo(
firstName = "Esteban", // optional if userToken is provided
lastName = "Posada", // optional if userToken is provided
email = "esteban@deuna.com" // required
),
callbacks = ElementsCallbacks().apply {
onSuccess = { response ->
deunaSDK.close() // Close the Vault widget
// YOUR CODE HERE: Handle card saved successfully
}
onError = { error ->
deunaSDK.close() // Close the widget on error
// YOUR CODE HERE: Handle error
}
onClosed = { action ->
// Widget closed: action == CloseAction.USER_ACTION or CloseAction.SYSTEM_ACTION
// YOUR CODE HERE: Handle widget dismissal
}
onEventDispatch = { type, response ->
// YOUR CODE HERE: Listen to widget events
}
},
orderToken = "YOUR_ORDER_TOKEN", // optional
widgetExperience = ElementsWidgetExperience( // optional
userExperience = ElementsWidgetExperience.UserExperience(
showSavedCardFlow = true, // optional: show card saving toggle
defaultCardFlow = true // optional: show toggle to save as default
)
)
)Mostrar incrustado (Jetpack Compose)
import com.deuna.maven.widgets.configuration.ElementsWidgetConfiguration
DeunaWidget(context).apply {
this.widgetConfiguration = ElementsWidgetConfiguration(
sdkInstance = deunaSDK,
orderToken = "YOUR_ORDER_TOKEN",
userInfo = UserInfo(
firstName = "Esteban",
lastName = "Posada",
email = "esteban@deuna.com"
),
callbacks = ElementsCallbacks().apply {
onSuccess = { response ->
// Explicitly release resources or update state
// YOUR CODE HERE: Handle card saved
}
onError = { error ->
// YOUR CODE HERE: Handle error
}
},
autoResizeConfig = AutoResizeConfig(initialHeightDp = 150)
)
this.build()
}Haga clic para pagar
deunaSDK.initElements(
context = this,
userInfo = UserInfo( // mandatory for Click To Pay
firstName = "Esteban",
lastName = "Posada",
email = "esteban@deuna.com"
),
callbacks = ElementsCallbacks().apply {
onSuccess = { data ->
deunaSDK.close()
// YOUR CODE HERE: Handle Click to Pay success
}
onError = { error ->
deunaSDK.close()
// YOUR CODE HERE: Handle error
}
onClosed = { action ->
// YOUR CODE HERE: Handle widget dismissal
}
},
types = listOf(
mapOf("name" to "click_to_pay")
)
)Referencia de parámetros
| Parámetro | Tipo | Cuadro de diálogo | Integrado | Descripción |
|---|---|---|---|---|
context | Context | ✅ | ❌ | Requerido para el cuadro de diálogo. Contexto de Activity. |
callbacks | ElementsCallbacks | ✅ | ✅ | Requerido. Los oyentes de eventos (onSuccess, onError, onClosed, onEventDispatch). |
userInfo | UserInfo? | ✅ | ✅ | Del cliente firstName, lastNamey email. Requerido para Click to Pay. |
userToken | String? | ✅ | ✅ | Opcional. Token de portador DEUNA. Si se proporciona, omita userInfo. |
types | List<Map<String, Any>>? | ✅ | ✅ | Opcional. Omitir para renderizar la experiencia predeterminada de Card Vault. Pasar listOf(mapOf("name" to "click_to_pay")) para renderizar Click to Pay. |
orderToken | String? | ✅ | ✅ | Opcional. Token de pedido único. Los detalles del cliente se pueden extraer de billing_address. |
styleFile | String? | ✅ | ✅ | Opcional. UUID de personalización de tema. |
widgetExperience | ElementsWidgetExperience? | ✅ | ✅ | Opcional. showSavedCardFlow (alternador de guardado de tarjeta) y defaultCardFlow (alternador de guardar como predeterminado). |
domain | String? | ✅ | ✅ | Opcional. Anula el host (https://elements.deuna.com). |
hidePayButton | Boolean | ❌ | ✅ | Opcional. Oculta el botón cuando está incrustado. Usar isValid y submit para botones personalizados. |
Google Pay nativo#
Verificar la configuración del comerciante y la capacidad del dispositivo antes de renderizar un botón de Google Pay.
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")
val params = GetWalletsAvailableParams(
orderToken = "YOUR_ORDER_TOKEN",
userInfo = userInfo
)
deunaSDK.getWalletsAvailable(
context = this,
params = params
) { wallets, error ->
if (error != null) {
// YOUR CODE HERE: Handle wallet availability check error
return@getWalletsAvailable
}
// Check if Google Pay is available on this device and merchant account
val isGooglePayAvailable = WalletProvider.GOOGLE_PAY in wallets
// YOUR CODE HERE: Update Google Pay button visibility in UI
}Después de que la verificación de disponibilidad tenga éxito, lanzar Google Pay desde la acción del botón usando initElements:
deunaSDK.initElements(
context = this,
userInfo = userInfo,
callbacks = ElementsCallbacks().apply {
onSuccess = { data ->
// YOUR CODE HERE: Handle Google Pay authorization success
}
onError = { error ->
// YOUR CODE HERE: Handle Google Pay error
}
onClosed = { action ->
// YOUR CODE HERE: Handle Google Pay sheet dismissal
}
},
types = listOf(
mapOf("name" to "GOOGLE_PAY")
),
orderToken = "YOUR_ORDER_TOKEN"
)Ver pago de google para la inscripción del comerciante y la configuración de pruebas.
Continúe con una acción pendiente#
Utilice el mismo token de pedido cuando DEUNA informe que el pago requiere un desafío o redirección 3DS compatible.
import com.deuna.maven.widgets.next_action.NextActionCallbacks
deunaSDK.initNextAction(
context = this,
orderToken = "YOUR_ORDER_TOKEN",
callbacks = NextActionCallbacks().apply {
onSuccess = { order ->
deunaSDK.close()
// YOUR CODE HERE: Handle 3DS or action completion
}
onError = { error ->
deunaSDK.close()
// YOUR CODE HERE: Handle error
}
onClosed = { action ->
// YOUR CODE HERE: Handle modal dismissal
}
}
)El SDK abre las URLs externas compatibles y regresa al widget activo. Utilice el estado de llamada de retorno para la interfaz y el estado de pago final de DEUNA para el cumplimiento.
Abrir un cupón#
import com.deuna.maven.widgets.voucher.VoucherCallbacks
deunaSDK.initVoucherWidget(
context = this,
orderToken = "YOUR_ORDER_TOKEN",
callbacks = VoucherCallbacks().apply {
onSuccess = { order ->
// YOUR CODE HERE: Handle voucher instructions display
}
onError = { error ->
// YOUR CODE HERE: Handle error
}
onClosed = { action ->
// YOUR CODE HERE: Handle widget dismissal
}
}
)Datos del dispositivo y huella digital para fraude#
El SDK de Android de DEUNA utiliza una arquitectura modular: no incluye SDKs de fraude de terceros por defecto. Solo agregue el(los) proveedor(es) específico(s) que planea usar.
Proveedores compatibles
| Proveedor | Dependencia de Gradle / Ubicación de AAR | Parámetros requeridos |
|---|---|---|
MERCADOPAGO | implementation("com.mercadolibre.android.device:sdk:4.0.1") | (Ninguna requerida - pasar emptyMap()) |
RISKIFIED | implementation("com.riskified:android-sdk:1.11.0:nogoogle@aar") | storeDomain |
CYBERSOURCE | app/libs/cybersource/*.aar | orgId, merchantId (Opcional: fpServer) |
SIGNIFYD | app/libs/signifyd/*.aar | orgId (Opcional: fpServer) |
ACCERTIFY | app/libs/accertify/*.aar + dependencias transitivas | Archivos de configuración en src/main/assets/ (Opcional: locationConsent, phoneConsent) |
Activos de Accertify y dependencias transitivas
- AAR y dependencias: Coloca
inmobile.aaryinmobile-common.aarenapp/libs/accertify/, y agregar dependencias transitivas:
dependencies {
implementation(fileTree(dir: "libs/accertify", include: ["*.aar"]))
implementation("io.insert-koin:koin-core:3.5.6")
implementation("androidx.biometric:biometric:1.1.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3")
}- Activos de configuración: Colocar dos archivos dentro de
app/src/main/assets/:server_keys_message_hosted.json: Las claves de cifrado públicas proporcionadas por Accertify.inmobile.properties: Archivo de configuración con los detalles de su comercio:PROPERTIESregisterUrl=YOUR_INMOBILE_ENDPOINT_URL logUrl=YOUR_INMOBILE_ENDPOINT_URL accountGuid=YOUR_ACCOUNT_GUID serverKeysMessage=server_keys_message_hosted.json
Configuración e inicialización temprana de Mercado Pago
- Agregar el repositorio de Mercado Libre en
settings.gradle.kts:
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven(url = "https://artifacts.mercadolibre.com/repository/android-releases/")
}
}- Agregar la dependencia en
app/build.gradle.kts:
dependencies {
implementation("com.mercadolibre.android.device:sdk:4.0.1")
}- Precalentar la huella digital temprano: Mercado Pago requiere hasta 3.5 segundos para realizar el perfilado de hardware. Llamar
initializeFraudProvidersenApplication.onCreateoMainActivity.onCreate:
DeunaSDK.initializeFraudProviders(
context = applicationContext,
params = mapOf(
"MERCADOPAGO" to emptyMap<String, Any>()
),
onSuccess = {
// Fingerprint collected and ready in background
},
onError = { error ->
// Handle initialization error
}
)Llamada directa mediante generateFraudId
deunaSDK.generateFraudId(
context = this,
params = mapOf(
"RISKIFIED" to mapOf(
"storeDomain" to "yourdomain.com"
),
"ACCERTIFY" to mapOf(
"locationConsent" to true,
"phoneConsent" to false
),
"MERCADOPAGO" to emptyMap()
)
) { fraudId ->
// fraudId is a Base64-encoded JSON string, or null if failed
if (fraudId != null) {
println("Base64 Fraud ID: $fraudId")
}
}Pasar fraudCredentials directamente a los widgets
Al usar widgets de DEUNA, pase sus credenciales directamente mediante fraudCredentials. El SDK genera el identificador internamente en el momento de la compra:
PaymentWidgetConfiguration(
sdkInstance = deunaSDK,
orderToken = "YOUR_ORDER_TOKEN",
callbacks = callbacks,
fraudCredentials = mapOf(
"RISKIFIED" to mapOf(
"storeDomain" to "yourdomain.com"
),
"MERCADOPAGO" to emptyMap()
)
)Notas de comportamiento
- Sin inflado y seguro ante fallos: Si un proveedor está incluido en los parámetros pero su dependencia nativa no fue vinculada, el SDK lo omite de forma segura sin fallar.
- Ejecución paralela: Todos los proveedores solicitados se perfilan concurrentemente en hilos en segundo plano.
- Comportamiento de respaldo: Si no hay proveedores válidos configurados o disponibles en el dispositivo,
generateFraudIdse resuelve anull.
Referencia del ciclo de vida y llamadas de retorno#
| Callback / Método | Cuadro de diálogo | Integrado | Descripción |
|---|---|---|---|
onSuccess | ✅ | ✅ | Operación de pago o bóveda de tarjetas completada exitosamente. Recibe carga útil de orden o credencial. Llamar deunaSDK.close() (diálogo) o destroy() (incrustado). |
onError | ✅ | ✅ | Error ocurrido durante la inicialización o procesamiento del pago. Recibe PaymentsError o ElementsError. |
onClosed | ✅ | ❌ | Diálogo cerrado. Recibe CloseAction.USER_ACTION (cerrado manualmente) o CloseAction.SYSTEM_ACTION (cerrado mediante close()). |
onPaymentProcessing | ✅ | ✅ | Se activa cuando el cliente toca pagar y comienza el procesamiento del pago. Usar para deshabilitar botones y mostrar indicadores de progreso. |
onCardBinDetected | ✅ | ✅ | Se activa cuando se detecta o se borra un BIN de tarjeta (null cuando el usuario borra el número). Úselo para descuentos de franquicia. |
onInstallmentSelected | ✅ | ✅ | Se activa cuando el cliente selecciona cuotas diferidas (null en el pago único completo). |
onEventDispatch | ✅ | ✅ | Emite todas las ocurrencias subyacentes de CheckoutEvent o ElementsEvent ocurrencias con cargas útiles de datos. |
close() | ✅ | ❌ | Cierra el diálogo modal activo después de que se completen las pestañas de URL externas. |
destroy() | ❌ | ✅ | Limpia los recursos de WebView cuando el componente composable contenedor se desmonta. |
Manejo de errores (onError)
Inspeccionar error.type para distinguir fallas de inicialización de rechazos de pago:
onError = { error ->
when (error.type) {
PaymentsError.Type.INITIALIZATION_FAILED -> {
// Widget failed to load; close dialog and notify user
deunaSDK.close()
}
PaymentsError.Type.PAYMENT_ERROR -> {
// Transaction declined or processor error; prompt retry
}
else -> {}
}
}Ejemplos y código fuente oficiales#
Consulta ExploreViewModel.kt para fábricas de configuración y EmbeddedScreen.kt para el manejo del ciclo de vida de WebView.