Integrazione dell'SDK mobile
AndroidIntegri Tapaya Accept SDK nella Sua applicazione mobile.
Tapaya Accept SDK integra l'elaborazione dei pagamenti con carta direttamente nella Sua app. È disponibile per Android (Kotlin) e per React Native / Expo, ed entrambe le versioni sono destinate a dispositivi Android. Il pacchetto React Native è un sottile wrapper dell'SDK Android, quindi le interfacce, i tipi e i casi di errore descritti di seguito sono gli stessi in entrambi.
Ogni esempio di codice in questa pagina è suddiviso in schede per linguaggio. Ne scelga uno e l'intera pagina si adegua.
Installazione
dependencies {
implementation("com.tapaya:accept:1.15.0")
}Android: aggiunga la dipendenza al file build.gradle.kts a livello di modulo, quindi sincronizzi il progetto.
React Native: installi il pacchetto con npx expo install @tapayadot/accept-react-native, aggiunga il config plugin come
mostrato, quindi rigeneri il progetto nativo con npx expo prebuild --clean e lo avvii con
npx expo run:android.
Inizializzazione
Accept è il punto di accesso a tutte le funzionalità dell'SDK. Lo inizializzi una sola volta all'avvio dell'app (su Android,
di solito nella classe Application), quindi esegua l'autenticazione separatamente con un token dell'esercente.
Passaggio 1: inizializzazione
// Sandbox is the default (isProduction = false)
Accept.initialize(context = this)
// Target production explicitly
Accept.initialize(context = this, isProduction = true)
// Or drive it from your build type
Accept.initialize(context = this, isProduction = !BuildConfig.DEBUG)Su React Native non c'è alcun context: lo gestisce il modulo nativo.
Passaggio 2: autenticazione
Dopo l'inizializzazione, chiami Accept.auth.authenticate() per far accedere un esercente con un token ottenuto dal Suo
backend. La chiamata è asincrona e, in caso di errore, fallisce con un errore dell'SDK. In caso di successo, lo stato dell'SDK diventa authenticated.
// suspend; call from a coroutine
try {
val sdkToken = myBackendApi.getSdkToken()
Accept.auth.authenticate(sdkToken)
// Accept.state now emits SdkState.Authenticated
} catch (e: AcceptException) {
// handle authentication failure
}Osservi il ciclo di vita per reagire a queste transizioni: idle → initialized → authenticated.
// Accept.state is a StateFlow<SdkState>
Accept.state.collect { state ->
if (state == SdkState.Authenticated) loadMerchant()
}Concetti fondamentali
L'oggetto Accept espone l'SDK tramite un piccolo insieme di interfacce:
| Interfaccia | Scopo |
|---|---|
Accept.auth | Autenticare una sessione dell'esercente. |
Accept.merchant | Profilo dell'esercente, configurazione, stato dell'onboarding. |
Accept.payments | Creare e gestire i pagamenti con carta. |
Accept.plugin | Installazione e attivazione del terminale (app plugin). |
Accept.displays | Informazioni sui display del dispositivo per i terminali a doppia faccia (“double-sided”). |
Accept.sdk | Versione dell'SDK, ambiente, ID del dispositivo, importi minimi. |
Accept.state | Stato del ciclo di vita: StateFlow<SdkState> in Kotlin, un getter più addStateListener() in React Native. |
Accettare un pagamento
Chiami Accept.payments.pay() con l'importo (nell'unità minima della valuta) e un codice valuta ISO 4217, quindi
osservi il flusso di eventi PaymentEvent che restituisce: prima l'avanzamento, poi l'esito finale. pay() non genera mai
eccezioni; un errore nella creazione del pagamento arriva invece come evento CreationFailed.
L'unica differenza è il modo in cui si osserva il flusso: Kotlin restituisce un Flow<PaymentEvent> da raccogliere
in una coroutine, mentre React Native accetta un listener e restituisce una sottoscrizione che si può chiudere con remove().
amount e currency sono obbligatori. Per i parametri facoltativi (paymentToken, receiptConfig, nfcPosition,
metadata, tip, transactionTimeout, display), consulti Creare un pagamento.
In React Native
Gli stessi parametri arrivano come un unico oggetto PaymentRequest, pay({ amount, currency, tip, … }), con
number al posto di Long e Record<string, string> al posto di Map<String, String>. Un solo nome cambia: il
timeout è transactionTimeoutMs e accetta semplici millisecondi (0…120000) anziché una Duration.

Accept.payments.pay(amount = 15000, currency = "CZK") // 150.00 Kč
.collect { event ->
when (event) {
PaymentEvent.Creating -> Log.d("pay", "creating")
is PaymentEvent.Created -> Log.d("pay", "created ${event.paymentToken}")
PaymentEvent.Launched -> Log.d("pay", "launched")
is PaymentEvent.Result -> Log.d("pay", event.payResult.toString())
is PaymentEvent.CreationFailed -> Log.e("pay", event.cause.toString())
}
}L'evento finale con il risultato contiene un PayResult: riuscito (con paymentToken, metadata, authCode,
receiptDetails), rifiutato (metadata, receiptDetails), annullato (metadata) o non riuscito (reason,
metadata). Kotlin li modella come sottoclassi PayResult.Success / Declined / Canceled / Failed;
React Native come unione discriminata su cui si dirama con payResult.type === 'success'. Il dettaglio completo è in
Esito del pagamento. In seguito può interrogare un pagamento con
Accept.payments.status(paymentToken), interromperlo con Accept.payments.cancel(paymentToken) o rimborsarlo con
Accept.payments.refund(paymentToken, reason).
Solo l'esito (React Native)
Se la Sua interfaccia non mostra gli stati intermedi, payAsync() riduce l'intero flusso al PayResult
finale e viene rifiutata con un AcceptError per tutto ciò che pay() avrebbe segnalato come
creationFailed. Non ha un equivalente in Kotlin: lì raccolga il Flow oppure ne prenda solo l'ultimo evento.
const result = await Accept.payments.payAsync({ amount: 15000, currency: 'CZK' });
if (result.type === 'success') {
console.log(result.paymentToken, result.receiptUrl);
}Informazioni sull'esercente e sull'SDK
Accept.merchant espone il profilo e la configurazione di pagamento dell'esercente che ha effettuato l'accesso. Accept.sdk espone
informazioni sulla build dell'SDK e su questo dispositivo. Ogni membro descritto di seguito richiede prima Accept.initialize() (tranne
Accept.sdk.version), e tutto ciò che si trova su Accept.merchant richiede inoltre un
Accept.auth.authenticate() completato, altrimenti la chiamata genera NotInitialized o NotAuthenticated.
Esercente
val info = Accept.merchant.info() // MerchantInformation?
val config = Accept.merchant.config() // MerchantConfig
val currencies = Accept.merchant.availableCurrencies() // List<String>
val status = Accept.merchant.onboardingStatus() // OnboardingStatus| Membro | Restituisce | Descrizione |
|---|---|---|
info() | MerchantInformation? | Il profilo aziendale registrato dell'esercente. null se il profilo non è ancora disponibile. |
config() | MerchantConfig | La configurazione di pagamento dell'esercente. |
availableCurrencies() | List<String> | Codici ISO 4217 che l'esercente può accettare. Forma abbreviata di config().availableCurrencies. |
onboardingStatus() | OnboardingStatus | Indica se l'esercente può già accettare pagamenti. |
Tutti e quattro sono suspend e in caso di errore generano NotAuthenticated, NoInternetConnection o Unknown.
MerchantInformation contiene il profilo aziendale registrato. Sempre presenti: merchantId (UUID),
email, businessType (BusinessType), legalName, registrationNumber, mcc e l'indirizzo registrato
(addressLine1, city, country). Facoltativi (null se l'esercente non li ha forniti): vatNumber,
incorporationDate, addressLine2, postalCode, state, phone, averageItemValue,
expectedMonthlyTurnover, businessModelDescription, numberOfEmployees, annualTurnover,
balanceSheetTotal, statementDescriptor, termsVersion.
BusinessType è uno tra INDIVIDUAL, COMPANY, NONPROFIT_ORGANIZATION, GOVERNMENT_ENTITY o
PARTNERSHIP.
MerchantConfig contiene availableCurrencies: List<String> e la valuta predefinita dell'esercente, currency: String?.
OnboardingStatus è un'interfaccia sealed: ReadyForPayments oppure RequiresAction(state), dove
state è un OnboardingState: NOT_STARTED, PENDING, ACTIVE, ATTENTION_NEEDED, ACTION_REQUIRED,
BLOCKED, WAITING_FOR_KYB, WAITING_FOR_STAKEHOLDERS o PENDING_ACQUIRER_APPROVAL. Il significato di ogni stato è spiegato in
Onboarding degli esercenti.
SDK
Accept.sdk.version // String, e.g. "1.15.0"
Accept.sdk.isProduction // Boolean
Accept.sdk.deviceId() // String? (suspend)
Accept.sdk.minimumAmounts() // List<MinimumAmount> (suspend)| Membro | Restituisce | Descrizione |
|---|---|---|
version | String | La versione dell'SDK. Leggibile prima di initialize(). |
isProduction | Boolean | Indica se initialize() ha impostato la produzione (true) o la sandbox (false). |
deviceId() | String? | L'ID stabile di questo dispositivo, assegnato al primo authenticate() riuscito e conservato finché l'app non viene disinstallata. null prima di allora. Lo indichi nelle richieste di assistenza. |
minimumAmounts() | List<MinimumAmount> | L'importo minimo pagabile per ogni valuta supportata. Ogni voce è currency: String, amount: Long nell'unità minore della valuta. |
App plugin
Ogni pagamento con carta passa a Tapaya Terminal, l'app plugin di Tapaya; è sempre obbligatoria e non esiste alcun percorso di pagamento con carta che la salti. Verifichi se è installata, quindi attivi il terminale, oppure apra la scheda nello store affinché l'esercente possa installarla.
A questo scopo usi Accept.plugin.isInstalled(), Accept.plugin.activateTerminal() e Accept.plugin.install(). Il codice e tutti
gli esiti dell'attivazione sono descritti in Installare e attivare il terminale.
Legga lo stato attuale del plugin con Accept.plugin.status() oppure disconnetta l'esercente dal plugin con
Accept.plugin.logout().
Autorizzazioni
I pagamenti con carta richiedono che l'app host disponga dell'autorizzazione alla posizione (ACCESS_FINE_LOCATION). L'SDK non
la richiede al posto Suo: la ottenga con le API di autorizzazione standard di Android prima di chiamare pay().
class PaymentActivity : AppCompatActivity() {
private val requestLocation = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { granted ->
if (granted) launchPaymentFlow() else showPermissionRationale()
}
fun startPayment() {
requestLocation.launch(Manifest.permission.ACCESS_FINE_LOCATION)
}
}Se, quando viene eseguito pay(), l'autorizzazione alla posizione manca o la posizione non può essere determinata, il flusso emette PaymentEvent.CreationFailed
con causa LocationPermissionRequired, LocationUnavailable o LocationTimeout.
Gestione degli errori
Ogni errore gestito porta uno dei nomi riportati di seguito. In Kotlin ciascuno è una sottoclasse della classe sealed
AcceptException; in React Native sono tutti un'unica classe AcceptError il cui code contiene il nome, mentre i
campi del payload (minimum, currency, state, …) si trovano sullo stesso oggetto.
Le chiamate asincrone (authenticate, merchant.*, payments.status/cancel/refund,
plugin.activateTerminal/status/logout/updateInfo, clear) falliscono con uno di questi. payments.pay() è
l'eccezione: non genera mai eccezioni e segnala gli stessi errori come evento CreationFailed che ne riporta la causa.
Tipi di eccezione
| Eccezione | Descrizione |
|---|---|
| Ciclo di vita | |
NotInitialized | Una chiamata richiede prima Accept.initialize(). |
NotAuthenticated | Una chiamata richiede prima Accept.auth.authenticate(). |
SessionExpired | La sessione autenticata è scaduta; ripeta l'autenticazione. |
UnknownEnvironment(key) | Chiave di ambiente non riconosciuta (overload interno di initialize). |
| Pagamenti | |
PaymentInProgress | Un pay() precedente è ancora in attesa di un risultato. |
CurrencyNotAvailableForMerchant(code) | Valuta non configurata per l'esercente. |
UnsupportedCurrency(code) | Valuta non riconosciuta dall'SDK. |
AmountBelowMinimum(minimum, currency) | Importo inferiore al minimo configurato. |
TransactionTimeoutOutOfRange(transactionTimeout) | transactionTimeout al di fuori dell'intervallo da 0 a 120 secondi. |
PaymentCreationFailed(cause) | Qualsiasi altro errore durante la creazione di un pagamento. |
PaymentNotFound | Token di status()/cancel()/refund() sconosciuto al backend. |
| Posizione | |
LocationPermissionRequired | L'app host non dispone dell'autorizzazione alla posizione. |
LocationUnavailable | Nessun provider è riuscito a determinare la posizione. |
LocationTimeout | Posizione non determinata in tempo. |
| Plugin / terminale | |
PluginUnavailable | App plugin non installata, oppure non è stato possibile collegarsi al suo servizio. |
PluginTimeout | Il plugin non ha risposto in tempo. |
ActivationInProgress | Un activateTerminal() precedente è ancora in attesa di un risultato. |
NoTidsAvailableForMerchant | All'esercente non resta alcun terminale (TID) non assegnato da attivare. |
PluginAlreadyAuthenticated | Plugin già autenticato per questo esercente. |
PluginMerchantMismatch | Plugin autenticato con un altro esercente; chiami prima plugin.logout(). |
PluginNotReadyForPayments(status) | pay() è stato eseguito mentre il plugin non era in PluginStatus.ReadyForPayments; status riporta lo stato attuale. |
MerchantOnboardingIncomplete(state) | L'esercente non ha completato l'onboarding. |
| Sistema | |
NoInternetConnection | Il dispositivo non ha connettività di rete. |
Unknown(cause) | Qualsiasi errore che l'SDK non riconosce come proprio. |
Risultato o eccezione
Un pagamento che raggiunge il terminale ma non va a buon fine non è un'eccezione: arriva come
PaymentEvent.Result con PayResult.Declined, Canceled o Failed(reason). Allo stesso modo, l'attivazione
del terminale restituisce ActivateTerminalResult.Failed(reason).
Gestione delle eccezioni
Racchiuda la chiamata in un blocco try/catch e gestisca separatamente i casi specifici che Le interessano, ricorrendo a un catch generico per il resto.
Kotlin distingue in base alla sottoclasse dell'eccezione; React Native verifica con AcceptError.is() ed esegue uno switch su code.
try {
val status = Accept.payments.status(paymentToken)
} catch (e: SessionExpired) {
// Re-authenticate
} catch (e: NoInternetConnection) {
// Ask the user to check connectivity
} catch (e: AcceptException) {
// Handle any other SDK error
Log.e("Payment", "Error: ${e.message}")
}Logging
Durante lo sviluppo attivi il logging di debug per diagnosticare i problemi.
Accept.setDebugLoggingEnabled(true)Disconnessione
Cancelli tutto lo stato dell'SDK salvato localmente (token di autenticazione, ID del dispositivo, configurazione in cache) e riporti lo stato dell'SDK a
idle. Esegua questa operazione quando l'utente si disconnette. Per disconnettere l'esercente anche dall'app Tapaya Terminal, chiami prima
Accept.plugin.logout().
Accept.plugin.logout() // suspend; signs out of the Tapaya Terminal app
Accept.clear() // suspend; clears local SDK state