Intégration du SDK mobile
AndroidIntégrez le Tapaya Accept SDK dans votre application mobile.
Le Tapaya Accept SDK intègre le traitement des paiements par carte directement dans votre application. Il est disponible pour Android (Kotlin) et pour React Native / Expo, et tous deux ciblent les appareils Android. Le package React Native est une fine surcouche du SDK Android : les interfaces, les types et les cas d’échec décrits ci-dessous sont donc identiques sur les deux.
Chaque exemple de code de cette page est proposé dans des onglets par langage. Choisissez-en un et toute la page s’aligne sur ce choix.
Installation
dependencies {
implementation("com.tapaya:accept:1.15.0")
}Android : ajoutez la dépendance au fichier build.gradle.kts de votre module, puis synchronisez le projet.
React Native : installez le package avec npx expo install @tapayadot/accept-react-native, ajoutez le plugin de configuration comme
indiqué, puis régénérez le projet natif avec npx expo prebuild --clean et lancez-le avec
npx expo run:android.
Initialisation
Accept est le point d’entrée de toutes les fonctionnalités du SDK. Initialisez-le une seule fois au démarrage de l’application (sur Android,
généralement dans votre classe Application), puis authentifiez-vous séparément avec un jeton commerçant.
Étape 1 : initialiser
// 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)Il n’y a pas de context sur React Native ; le module natif le conserve pour vous.
Étape 2 : s’authentifier
Appelez Accept.auth.authenticate() après l’initialisation pour connecter un commerçant avec un jeton obtenu depuis votre
backend. L’appel est asynchrone et échoue avec une erreur du SDK. En cas de succès, l’état du SDK passe à 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
}Observez le cycle de vie pour réagir à ces transitions : idle → initialized → authenticated.
// Accept.state is a StateFlow<SdkState>
Accept.state.collect { state ->
if (state == SdkState.Authenticated) loadMerchant()
}Concepts clés
L’objet Accept expose le SDK au travers d’un petit nombre d’interfaces :
| Interface | Rôle |
|---|---|
Accept.auth | Authentifier une session commerçant. |
Accept.merchant | Profil du commerçant, configuration, statut d’onboarding. |
Accept.payments | Créer et gérer les paiements par carte. |
Accept.plugin | Installation et activation du terminal (application plugin). |
Accept.displays | Informations sur les écrans de l’appareil pour les terminaux à double face (« double-sided »). |
Accept.sdk | Version du SDK, environnement, identifiant de l’appareil, montants minimaux. |
Accept.state | État du cycle de vie : StateFlow<SdkState> en Kotlin, un getter plus addStateListener() sur React Native. |
Accepter un paiement
Appelez Accept.payments.pay() avec le montant (dans la plus petite unité de la devise) et un code de devise ISO 4217, puis
observez le flux d’événements PaymentEvent qu’il émet : d’abord la progression, puis le résultat final. pay() ne lève jamais
d’exception ; un échec de création du paiement arrive à la place sous forme d’événement CreationFailed.
Seule la manière d’observer ce flux diffère : Kotlin renvoie un Flow<PaymentEvent> que vous collectez
depuis une coroutine, tandis que React Native prend un listener et renvoie un abonnement que vous pouvez résilier avec remove().
amount et currency sont obligatoires. Pour les paramètres facultatifs (paymentToken, receiptConfig, nfcPosition,
metadata, tip, transactionTimeout, display), consultez Créer un paiement.
Sur React Native
Les mêmes paramètres sont transmis dans un seul objet PaymentRequest, pay({ amount, currency, tip, … }), avec
number à la place de Long et Record<string, string> à la place de Map<String, String>. Un seul renommage : le
délai d’expiration s’appelle transactionTimeoutMs et prend de simples millisecondes (0…120000) au lieu d’une 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’événement de résultat final contient un PayResult : succès (avec paymentToken, metadata, authCode,
receiptDetails), refus (metadata, receiptDetails), annulation (metadata) ou échec (reason,
metadata). Kotlin les modélise sous forme de sous-classes PayResult.Success / Declined / Canceled / Failed ;
React Native sous forme d’union discriminée dont vous distinguez les cas avec payResult.type === 'success'. Consultez
Résultat du paiement pour le détail complet. Interrogez un paiement ultérieurement avec
Accept.payments.status(paymentToken), arrêtez-le avec Accept.payments.cancel(paymentToken) ou remboursez-le avec
Accept.payments.refund(paymentToken, reason).
Uniquement le résultat (React Native)
Si votre interface n’affiche pas les états intermédiaires, payAsync() réduit l’ensemble du flux à son PayResult
final, et sa promesse est rejetée avec une AcceptError dans tous les cas que pay() aurait signalés comme
creationFailed. Cette méthode n’a pas d’équivalent en Kotlin : côté Kotlin, collectez le Flow, ou ne prenez que son dernier événement.
const result = await Accept.payments.payAsync({ amount: 15000, currency: 'CZK' });
if (result.type === 'success') {
console.log(result.paymentToken, result.receiptUrl);
}Informations sur le commerçant et le SDK
Accept.merchant expose le profil et la configuration de paiement du commerçant connecté. Accept.sdk expose
des informations sur le build du SDK et sur cet appareil. Chaque membre ci-dessous nécessite d’abord Accept.initialize() (sauf
Accept.sdk.version), et tout ce qui relève de Accept.merchant nécessite en outre un appel
Accept.auth.authenticate() abouti ; sinon, l’appel lève NotInitialized ou NotAuthenticated.
Commerçant
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| Membre | Renvoie | Description |
|---|---|---|
info() | MerchantInformation? | Le profil d’entreprise enregistré du commerçant. null si le profil n’est pas encore disponible. |
config() | MerchantConfig | La configuration de paiement du commerçant. |
availableCurrencies() | List<String> | Codes ISO 4217 que le commerçant peut accepter. Raccourci pour config().availableCurrencies. |
onboardingStatus() | OnboardingStatus | Indique si le commerçant peut déjà accepter des paiements. |
Ces quatre fonctions sont suspend et lèvent NotAuthenticated, NoInternetConnection ou Unknown en cas d’échec.
MerchantInformation contient le profil d’entreprise enregistré. Toujours présents : merchantId (UUID),
email, businessType (BusinessType), legalName, registrationNumber, mcc et l’adresse enregistrée
(addressLine1, city, country). Facultatifs (null sauf si le commerçant les a fournis) : vatNumber,
incorporationDate, addressLine2, postalCode, state, phone, averageItemValue,
expectedMonthlyTurnover, businessModelDescription, numberOfEmployees, annualTurnover,
balanceSheetTotal, statementDescriptor, termsVersion.
BusinessType prend l’une des valeurs INDIVIDUAL, COMPANY, NONPROFIT_ORGANIZATION, GOVERNMENT_ENTITY ou
PARTNERSHIP.
MerchantConfig contient availableCurrencies: List<String> et la devise par défaut du commerçant, currency: String?.
OnboardingStatus est une interface scellée : soit ReadyForPayments, soit RequiresAction(state), où
state est un OnboardingState : NOT_STARTED, PENDING, ACTIVE, ATTENTION_NEEDED, ACTION_REQUIRED,
BLOCKED, WAITING_FOR_KYB, WAITING_FOR_STAKEHOLDERS ou PENDING_ACQUIRER_APPROVAL. Consultez
Onboarding des commerçants pour la signification de chaque état.
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)| Membre | Renvoie | Description |
|---|---|---|
version | String | La version du SDK. Lisible avant initialize(). |
isProduction | Boolean | Indique si initialize() a ciblé la production (true) ou la sandbox (false). |
deviceId() | String? | L’identifiant stable de cet appareil, attribué lors du premier authenticate() réussi et conservé jusqu’à la désinstallation de l’application. null avant cela. Indiquez-le dans vos demandes de support. |
minimumAmounts() | List<MinimumAmount> | Le montant minimal payable par devise prise en charge. Chaque entrée est de la forme currency: String, amount: Long, dans la plus petite unité de la devise. |
Application plugin
Chaque paiement par carte est confié à Tapaya Terminal, l’application plugin de Tapaya ; elle est toujours requise, aucun parcours de paiement par carte ne s’en passe. Vérifiez si elle est installée, puis activez le terminal, ou ouvrez sa fiche dans le store pour que le commerçant puisse l’installer.
Utilisez pour cela Accept.plugin.isInstalled(), Accept.plugin.activateTerminal() et Accept.plugin.install(). Consultez
Installer et activer le terminal pour le code et tous les
résultats d’activation possibles.
Lisez l’état actuel du plugin avec Accept.plugin.status(), ou déconnectez le commerçant du plugin avec
Accept.plugin.logout().
Autorisations
Les paiements par carte exigent que l’application hôte dispose de l’autorisation de localisation (ACCESS_FINE_LOCATION). Le SDK ne la
demande pas à votre place ; accordez-la avec les API d’autorisation Android standard avant d’appeler 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)
}
}Si la localisation est absente ou ne peut pas être déterminée lors de l’exécution de pay(), le flux émet PaymentEvent.CreationFailed
avec pour cause LocationPermissionRequired, LocationUnavailable ou LocationTimeout.
Gestion des erreurs
Chaque échec contrôlé porte l’un des noms ci-dessous. En Kotlin, chacun est une sous-classe de la classe scellée
AcceptException ; sur React Native, ils relèvent tous d’une seule classe AcceptError dont le code contient le nom, les
champs de payload (minimum, currency, state, …) étant rattachés au même objet.
Les appels asynchrones (authenticate, merchant.*, payments.status/cancel/refund,
plugin.activateTerminal/status/logout/updateInfo, clear) échouent en levant l’une de ces erreurs. payments.pay() fait
exception : il ne lève jamais d’exception et signale ces mêmes échecs sous forme d’événement CreationFailed portant la cause.
Types d’exception
| Exception | Description |
|---|---|
| Cycle de vie | |
NotInitialized | Un appel nécessite d’abord Accept.initialize(). |
NotAuthenticated | Un appel nécessite d’abord Accept.auth.authenticate(). |
SessionExpired | La session authentifiée a expiré ; authentifiez-vous de nouveau. |
UnknownEnvironment(key) | Clé d’environnement non reconnue (surcharge interne d’initialize). |
| Paiements | |
PaymentInProgress | Un pay() précédent attend encore un résultat. |
CurrencyNotAvailableForMerchant(code) | Devise non configurée pour le commerçant. |
UnsupportedCurrency(code) | Devise non reconnue par le SDK. |
AmountBelowMinimum(minimum, currency) | Montant inférieur au minimum configuré. |
TransactionTimeoutOutOfRange(transactionTimeout) | transactionTimeout hors de la plage de 0 à 120 secondes. |
PaymentCreationFailed(cause) | Tout autre échec lors de la création d’un paiement. |
PaymentNotFound | Jeton de status()/cancel()/refund() inconnu du backend. |
| Localisation | |
LocationPermissionRequired | L’application hôte ne dispose pas de l’autorisation de localisation. |
LocationUnavailable | Aucun fournisseur n’a pu déterminer la position. |
LocationTimeout | La position n’a pas été déterminée à temps. |
| Plugin / terminal | |
PluginUnavailable | Application plugin non installée, ou impossible de se lier à son service. |
PluginTimeout | Le plugin n’a pas répondu à temps. |
ActivationInProgress | Un activateTerminal() précédent attend encore un résultat. |
NoTidsAvailableForMerchant | Le commerçant n’a plus de terminal (TID) non attribué à activer. |
PluginAlreadyAuthenticated | Plugin déjà authentifié pour ce commerçant. |
PluginMerchantMismatch | Plugin authentifié pour un autre commerçant ; appelez d’abord plugin.logout(). |
PluginNotReadyForPayments(status) | pay() a été exécuté alors que le plugin n’était pas à l’état PluginStatus.ReadyForPayments ; status contient l’état actuel. |
MerchantOnboardingIncomplete(state) | Le commerçant n’a pas terminé l’onboarding. |
| Système | |
NoInternetConnection | L’appareil n’a pas de connexion réseau. |
Unknown(cause) | Tout échec que le SDK ne reconnaît pas comme l’un des siens. |
Résultat ou exception
Un paiement qui atteint le terminal mais n’aboutit pas n’est pas une exception ; il arrive sous forme de
PaymentEvent.Result contenant PayResult.Declined, Canceled ou Failed(reason). De même, l’activation
du terminal renvoie ActivateTerminalResult.Failed(reason).
Gérer les exceptions
Encapsulez l’appel dans un try/catch et traitez séparément les cas que vous gérez, avec un catch générique en dernier recours.
Kotlin distingue les cas par sous-classe d’exception ; React Native vérifie avec AcceptError.is() puis fait un switch sur 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}")
}Journalisation
Activez la journalisation de débogage pendant le développement pour diagnostiquer les problèmes.
Accept.setDebugLoggingEnabled(true)Déconnexion
Effacez tout l’état du SDK conservé localement (jeton d’authentification, identifiant de l’appareil, configuration en cache) et ramenez l’état du SDK à
idle. Appelez cette méthode lorsque l’utilisateur se déconnecte. Pour déconnecter également le commerçant de l’application Tapaya Terminal, appelez
d’abord Accept.plugin.logout().
Accept.plugin.logout() // suspend; signs out of the Tapaya Terminal app
Accept.clear() // suspend; clears local SDK state