SDK Android
Installa l'SDK Android di DEUNA e integra i flussi di pagamento modal, embedded, wallet, voucher e "prossimo passo".
In questa pagina
- Requisiti
- Installazione
- Inizializzazione
- Widget di pagamento aperto
- Esperienze disponibili
- Integrare un widget
- Filtra e configura i metodi di pagamento
- Stile dinamico e aggiornamento dell'ordine
- Archiviazione dei pagamenti e Click to Pay
- Google Pay nativo
- Continuare un'azione in sospeso
- Aprire un buono
- Dati del dispositivo antifrode e fingerprinting
- Riferimento a callback e ciclo di vita
- Esempi e codice sorgente ufficiali
Requisiti#
Per integrare l'SDK Android di DEUNA, assicurati che il tuo progetto soddisfi i seguenti requisiti:
- Versione SDK minima:
minSdkVersion 24o superiore (Android API 24+) - Android Gradle Plugin (AGP): Versione 8.5.1 o superiore (richiesta per il supporto della dimensione di pagina Android 16 KB)
- Linguaggio di programmazione: Kotlin o Java
- Credenziali DEUNA: Account attivo e credenziali valide (contatta support@deuna.com se riscontri ritardi nell'ottenimento delle credenziali)
Installazione#
1. Aggiungi il repository JitPack
Aggiungi il repository JitPack all'interno del dependencyResolutionManagement blocco nel tuo 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' }
}
}Se il tuo progetto non utilizza dependencyResolutionManagement, aggiungi il repository nel file build.gradle:
allprojects {
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
}
}2. Configura build.gradle e le dipendenze
Assicurati che il tuo minSdk sia 24 o superiore, e aggiungi la dipendenza dell'SDK 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'
}Inizializzazione#
import com.deuna.maven.DeunaSDK
import com.deuna.maven.shared.EnvironmentPuoi inizializzare l'SDK in due modi a seconda dell'architettura della tua app:
Istanza condivisa globale
Inizializza una volta durante l'avvio dell'applicazione (ad esempio, nel tuo Application.onCreate):
DeunaSDK.initialize(
environment = Environment.SANDBOX, // Environment.SANDBOX or Environment.PRODUCTION
publicApiKey = "YOUR_PUBLIC_API_KEY"
)
val deunaSDK = DeunaSDK.sharedIstanza di flusso o schermata
Crea un'istanza per una specifica schermata di checkout o ViewModel:
val deunaSDK = DeunaSDK(
environment = Environment.SANDBOX,
publicApiKey = "YOUR_PUBLIC_API_KEY"
)Widget di pagamento aperto#
Il Payment Widget offre ai clienti più metodi di pagamento:
- Carte di credito e di debito: Visa, Mastercard, American Express e carte co-branded.
- Metodi di pagamento alternativi (APM): OXXO, KueskiPay, Aplazo, Daviplata, Nequi e altri.
- Portafogli digitali: Google Pay e PayPal.
Visualizza in una finestra di dialogo
Per presentare il payment widget in una DialogFragment, chiamare initPaymentWidget passando un'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"
)Riferimento parametri
| Parametro | Tipo | Dialog | Incorporato | Descrizione |
|---|---|---|---|---|
context | Context | ✅ | ❌ | Obbligatorio per il dialog. Contesto dell'attività che fornisce risorse UI e token di finestra. |
orderToken | String | ✅ | ✅ | Obbligatorio. Token univoco per l'ordine creato tramite API DEUNA. Importante: Non definire un redirect_url nella creazione dell'ordine se vuoi che onSuccess venga eseguito in-app. |
callbacks | PaymentWidgetCallbacks | ✅ | ✅ | Obbligatorio. I listener di eventi (onSuccess, onError, onClosed, onCardBinDetected, onInstallmentSelected, onPaymentProcessing, onEventDispatch). |
userToken | String? | ✅ | ✅ | Facoltativo. Token bearer DEUNA del cliente. Importante: Affinché le carte salvate appaiano, l'email collegata a userToken devono corrispondere al billing_address.email della creazione dell'ordine. |
styleFile | String? | ✅ | ✅ | Facoltativo. UUID fornito da DEUNA per applicare il branding del tema personalizzato (colori, tipografia, logo). |
paymentMethods | List<Map<String, Any>>? | ✅ | ✅ | Facoltativo. Elenco di metodi di pagamento singolo per il flusso di moduli diretti (ad es. listOf(mapOf("paymentMethod" to "bnpl", "processors" to listOf("kueski")))). |
language | String? | ✅ | ✅ | Facoltativo. Codice lingua ("es", "en", "pt"). Sostituisce la configurazione predefinita del merchant. |
behavior | WidgetBehavior? | ✅ | ✅ | Facoltativo. Personalizzazione del flusso, come WidgetBehavior(paymentMethods = mapOf("flowType" to "twoStep")) per PayPal, o Split Payments splitPayments. |
fraudCredentials | Map<String, Any>? | ✅ | ✅ | Facoltativo. Credenziali del provider antifrode (ad es. mapOf("RISKIFIED" to mapOf("storeDomain" to "example.com"))). |
domain | String? | ✅ | ✅ | Facoltativo. Sostituisce l'host base predefinito (https://pay.deuna.io). |
hidePayButton | Boolean | ❌ | ✅ | Facoltativo. Nasconde il pulsante di pagamento integrato in modalità embedded quando la tua applicazione renderizza un pulsante nativo. |
Esperienze disponibili#
| Esperienza | Metodo | Tipo di configurazione | Informazioni di input essenziali |
|---|---|---|---|
| Widget di pagamento | initPaymentWidget(...) | PaymentWidgetConfiguration | context, orderToken, PaymentWidgetCallbacks |
| Vault di pagamento | initElements(...) | ElementsWidgetConfiguration | context, ElementsCallbacks; types Può essere omesso |
| Clicca per pagare | initElements(...) | ElementsWidgetConfiguration | types = listOf(mapOf("name" to "click_to_pay")) |
| Prossimo passo | initNextAction(...) | NextActionWidgetConfiguration | context, orderToken, NextActionCallbacks |
| Voucher | initVoucherWidget(...) | VoucherWidgetConfiguration | context, orderToken, VoucherCallbacks |
Tutti i metodi modali accettano input opzionali per lingua, antifrode e dominio, dove supportati. Non sovrascrivere domain a meno che DEUNA non ti assegni un host dedicato.
Integrare un widget#
Per visualizzare il widget incorporato all'interno della tua applicazione con Jetpack Compose, usa AndroidView e 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()
}
}
}Ridimensionamento automatico e gestione della tastiera
Quando passi autoResizeConfig = AutoResizeConfig(initialHeightDp = 100), il widget passa in modalità di ridimensionamento automatico: cresce e si riduce dinamicamente per adattarsi all'altezza del contenuto WebView, rendendolo ideale per l'incorporamento all'interno di un contenitore scorrevole.
- Configurazione del manifest: Assicurati che la tua Activity di checkout sia configurata con
adjustResizeinAndroidManifest.xml:
<activity
android:name=".CheckoutActivity"
android:windowSoftInputMode="adjustResize" />- Integrazione con lo scorrimento in Compose: Posiziona
DeunaWidgetall'interno di un contenitore di scorrimento verticale e collegasetOnScrollByCallbackalScrollState:
@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...
}
}Pulsante di pagamento personalizzato (hidePayButton)
Se la tua app renderizza il proprio pulsante nativo al di fuori del widget, passa hidePayButton = true e gestisci l'invio in modo programmatico utilizzando isValid e 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
}
}
}| Metodo | Descrizione | Valore di ritorno |
|---|---|---|
deunaWidget.isValid { valid -> ... } | Convalida l'input dell'utente nel modulo di pagamento attivo. | Boolean |
deunaWidget.submit { result -> ... } | Invia il pagamento equivalente al clic sul pulsante del widget. | SubmitResult (status: "success" o status: "error") |
Filtra e configura i metodi di pagamento#
Flusso dei moduli diretti (paymentMethods)
Le architetture di checkout DEUNA supportano l'avvio diretto in un singolo modulo di pagamento, uno schema noto come flusso dei moduli.
Sebbene paymentMethods sia tipizzato come una lista, i motori di checkout interni attualmente supportano solo un elemento in questa lista. Fornire un singolo metodo di pagamento apre il widget direttamente nel modulo di quel metodo (ad esempio Kueski Pay BNPL), bypassando il selettore dei metodi.
deunaSDK.initPaymentWidget(
context = this,
orderToken = "YOUR_ORDER_TOKEN",
callbacks = callbacks,
paymentMethods = listOf(
mapOf(
"paymentMethod" to "bnpl",
"processors" to listOf("kueski")
)
)
)Risoluzione della priorità di configurazione
| Priorità | Fonte | Comportamento |
|---|---|---|
| 1 (Più alta) | paymentMethods in .initPaymentWidget() | Flusso dei moduli diretti: Si apre immediatamente nel modulo del singolo metodo di pagamento specificato (ad esempio, Kueski), saltando il selettore dei metodi. |
| 2 | include_payment_options nella creazione dell'ordine | Selezione multi-metodo: Visualizza solo i metodi di pagamento specificati durante la creazione dell'ordine che sono attivi sul tuo account. |
| 3 (Fallback) | Configurazione a livello merchant (/payment-methods) | Selettore completo: Se omesso sia nella chiamata SDK che nel payload dell'ordine, visualizza tutti i metodi di pagamento attivi configurati per il tuo account merchant. |
Configurazioni PayPal
Tipo di flusso (flowType)
deunaSDK.initPaymentWidget(
context = this,
orderToken = orderToken,
behavior = WidgetBehavior(
paymentMethods = mapOf(
"flowType" to "twoStep" // "twoStep" (summary first) or "singleStep" (direct)
)
)
)Acquisto automatico (express)
Quando i clienti hanno precedentemente autorizzato pagamenti rapidi con PayPal, abilita l'elaborazione immediata:
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)
)
)
)Pagamenti divisi con più carte
deunaSDK.initPaymentWidget(
context = this,
orderToken = orderToken,
behavior = WidgetBehavior(
paymentMethods = mapOf(
"creditCard" to mapOf(
"splitPayments" to mapOf(
"maxCards" to 2 // Maximum number of cards allowed
)
)
)
)
)Stile dinamico e aggiornamento dell'ordine#
Personalizza dinamicamente l'aspetto (setCustomStyle)
Aggiorna gli stili del widget dinamicamente (ad esempio adattando il branding al rilevamento del BIN della carta):
callbacks = PaymentWidgetCallbacks().apply {
onCardBinDetected = { metadata, _ ->
deunaSDK.setCustomStyle(
data = mapOf(
"theme" to mapOf(
"colors" to mapOf(
"primaryTextColor" to "#023047",
"buttonPrimaryFill" to "#FFB703",
"buttonPrimaryText" to "#000000"
)
)
)
)
}
}Aggiorna i totali dell'ordine (refetchOrder)
Quando offri promozioni specifiche per franchising (ad esempio, "20% di sconto con Mastercard"), ascolta onCardBinDetected, aggiorna l'ordine sul tuo backend e notifica il 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")
}
}
}
}
}Archiviazione dei pagamenti e Click to Pay#
Payment Vault è un componente delle soluzioni di pagamento DEUNA che consente di salvare le carte in modo sicuro e di pagare tramite Click to Pay senza elaborare checkout regolari.
Visualizza in una finestra di dialogo
Per visualizzare Card Vault in una finestra di dialogo modale, chiama initElements (ometti types per il Vault predefinito):
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
)
)
)Visualizza incorporato (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()
}Clicca per pagare
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")
)
)Riferimento parametri
| Parametro | Tipo | Dialog | Incorporato | Descrizione |
|---|---|---|---|---|
context | Context | ✅ | ❌ | Obbligatorio per il dialog. Contesto dell'Activity. |
callbacks | ElementsCallbacks | ✅ | ✅ | Obbligatorio. I listener di eventi (onSuccess, onError, onClosed, onEventDispatch). |
userInfo | UserInfo? | ✅ | ✅ | Cliente firstName, lastNamee email. Obbligatorio per Click to Pay. |
userToken | String? | ✅ | ✅ | Facoltativo. Token bearer DEUNA. Se fornito, ometti userInfo. |
types | List<Map<String, Any>>? | ✅ | ✅ | Facoltativo. Ometti per visualizzare l'esperienza Card Vault predefinita. Fornisci listOf(mapOf("name" to "click_to_pay")) per visualizzare Click to Pay. |
orderToken | String? | ✅ | ✅ | Facoltativo. Token ordine univoco. I dettagli del cliente possono essere estratti da billing_address. |
styleFile | String? | ✅ | ✅ | Facoltativo. UUID per la personalizzazione del tema. |
widgetExperience | ElementsWidgetExperience? | ✅ | ✅ | Facoltativo. showSavedCardFlow (interruttore per il salvataggio della carta) e defaultCardFlow (interruttore per salvare come predefinito). |
domain | String? | ✅ | ✅ | Facoltativo. Sostituisce l'host (https://elements.deuna.com). |
hidePayButton | Boolean | ❌ | ✅ | Facoltativo. Nasconde il pulsante quando incorporato. Usa isValid e submit per pulsanti personalizzati. |
Google Pay nativo#
Controlla la configurazione del merchant e le capacità del dispositivo prima di visualizzare un pulsante 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
}Dopo che la verifica della disponibilità ha esito positivo, avvia Google Pay dall'azione del pulsante utilizzando 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"
)Vedi Google Pay per l'iscrizione del merchant e la configurazione dei test.
Continuare un'azione in sospeso#
Utilizzare lo stesso token d'ordine quando DEUNA segnala che il pagamento richiede una sfida o reindirizzamento 3DS supportato.
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
}
}
)L'SDK apre gli URL esterni supportati e ritorna al widget attivo. Utilizzare lo stato del callback per l'interfaccia e lo stato finale del pagamento DEUNA per l'evasione.
Aprire un buono#
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
}
}
)Dati del dispositivo antifrode e fingerprinting#
L'SDK Android di DEUNA utilizza un'architettura modulare: non include gli SDK antifrode di terze parti per impostazione predefinita. Aggiungere solo il/i provider specifico/i che si intende utilizzare.
Provider supportati
| Fornitore | Dipendenza Gradle / Posizionamento AAR | Parametri obbligatori |
|---|---|---|
MERCADOPAGO | implementation("com.mercadolibre.android.device:sdk:4.0.1") | (Nessuna richiesta - passa emptyMap()) |
RISKIFIED | implementation("com.riskified:android-sdk:1.11.0:nogoogle@aar") | storeDomain |
CYBERSOURCE | app/libs/cybersource/*.aar | orgId, merchantId (Opzionale: fpServer) |
SIGNIFYD | app/libs/signifyd/*.aar | orgId (Opzionale: fpServer) |
ACCERTIFY | app/libs/accertify/*.aar + dipendenze transitive | File di configurazione in src/main/assets/ (Opzionale: locationConsent, phoneConsent) |
Asset di Accertify e dipendenze transitive
- AAR e dipendenze: Posiziona
inmobile.aareinmobile-common.aarinapp/libs/accertify/, e aggiungi dipendenze transitive:
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")
}- Asset di configurazione: Posiziona due file all'interno di
app/src/main/assets/:server_keys_message_hosted.json: Le chiavi di crittografia pubbliche fornite da Accertify.inmobile.properties: File di configurazione con i dettagli del merchant:PROPERTIESregisterUrl=YOUR_INMOBILE_ENDPOINT_URL logUrl=YOUR_INMOBILE_ENDPOINT_URL accountGuid=YOUR_ACCOUNT_GUID serverKeysMessage=server_keys_message_hosted.json
Configurazione e inizializzazione anticipata di Mercado Pago
- Aggiungi il repository di Mercado Libre in
settings.gradle.kts:
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven(url = "https://artifacts.mercadolibre.com/repository/android-releases/")
}
}- Aggiungi la dipendenza in
app/build.gradle.kts:
dependencies {
implementation("com.mercadolibre.android.device:sdk:4.0.1")
}- Pre-riscaldamento dell'impronta digitale anticipato: Mercado Pago richiede fino a 3,5 secondi per eseguire il profiling hardware. Chiama
initializeFraudProvidersinApplication.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
}
)Chiamata diretta tramite 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")
}
}Passa fraudCredentials direttamente ai widget
Quando utilizzi i widget DEUNA, passa le tue credenziali direttamente tramite fraudCredentials. L'SDK genera l'identificatore internamente al momento dell'acquisto:
PaymentWidgetConfiguration(
sdkInstance = deunaSDK,
orderToken = "YOUR_ORDER_TOKEN",
callbacks = callbacks,
fraudCredentials = mapOf(
"RISKIFIED" to mapOf(
"storeDomain" to "yourdomain.com"
),
"MERCADOPAGO" to emptyMap()
)
)Note sul comportamento
- Zero-bloat & Crash-safe: Se un provider è incluso nei parametri ma la sua dipendenza nativa non è stata collegata, l'SDK lo salta in modo sicuro senza crash.
- Esecuzione parallela: Tutti i fornitori richiesti eseguono il profiling contemporaneamente su thread in background.
- Comportamento di fallback: Se non sono configurati o disponibili fornitori validi sul dispositivo,
generateFraudIdsi risolve innull.
Riferimento a callback e ciclo di vita#
| Callback / Metodo | Dialog | Incorporato | Descrizione |
|---|---|---|---|
onSuccess | ✅ | ✅ | Operazione di pagamento o archiviazione carta completata con successo. Riceve il payload dell'ordine o delle credenziali. Chiama deunaSDK.close() (dialogo) o destroy() (incorporato). |
onError | ✅ | ✅ | Errore verificatosi durante l'inizializzazione o l'elaborazione del pagamento. Riceve un PaymentsError o ElementsError. |
onClosed | ✅ | ❌ | Dialogo chiuso. Riceve CloseAction.USER_ACTION (chiuso manualmente) o CloseAction.SYSTEM_ACTION (chiuso dal cliente) o close()). |
onPaymentProcessing | ✅ | ✅ | Attivato quando il cliente tocca paga e inizia l'elaborazione del pagamento. Usa per disabilitare i pulsanti e mostrare indicatori di progresso. |
onCardBinDetected | ✅ | ✅ | Attivato quando viene rilevato o cancellato un BIN di carta (null Attivato quando viene rilevato o cancellato un BIN di carta (restituisce |
onInstallmentSelected | ✅ | ✅ | Attivato quando il cliente seleziona rate differite (null Attivato quando il cliente seleziona un piano di rateizzazione (restituisce |
onEventDispatch | ✅ | ✅ | Attivato quando il cliente richiede il download del voucher o della ricevuta. CheckoutEvent o ElementsEvent occorrenze con payload di dati. |
close() | ✅ | ❌ | Chiude il dialogo modale attivo dopo il completamento delle schede URL esterne. |
destroy() | ❌ | ✅ | Pulisce le risorse WebView quando il composable contenitore viene smontato. |
per registrazione personalizzata e analisi.onError)
Ispeziona error.type Ispeziona l'errore
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 -> {}
}
}Esempi e codice sorgente ufficiali#
Consulta il file ExploreViewModel.kt per i factory di configurazione e EmbeddedScreen.kt per la gestione del ciclo di vita di WebView.