Tapaya
Přijímání plateb v prodejněPrůvodce integracíIntegrace mobilního SDK

Integrace mobilního SDK

Android

Integrujte Tapaya Accept SDK do své mobilní aplikace.

Tapaya Accept SDK vkládá zpracování plateb kartou přímo do vaší aplikace. Je k dispozici pro Android (Kotlin) a pro React Native / Expo, přičemž obě varianty cílí na zařízení s Androidem. Balíček pro React Native je tenká vrstva nad Android SDK, takže rozhraní, typy a chybové stavy popsané níže jsou v obou variantách stejné.

Každá ukázka kódu na této stránce má záložky podle jazyka. Vyberte jeden a celá stránka se přizpůsobí.

Instalace

build.gradle.kts
dependencies {
    implementation("com.tapaya:accept:1.15.0")
}

Android: přidejte závislost do souboru build.gradle.kts na úrovni modulu a poté projekt synchronizujte.

React Native: nainstalujte balíček příkazem npx expo install @tapayadot/accept-react-native, přidejte konfigurační plugin podle ukázky, poté nativní projekt znovu vygenerujte příkazem npx expo prebuild --clean a spusťte jej příkazem npx expo run:android.

Inicializace

Accept je vstupním bodem ke všem funkcím SDK. Inicializujte jej jednou při spuštění aplikace (na Androidu obvykle ve třídě Application) a poté se samostatně autentizujte tokenem obchodníka.

Krok 1: Inicializace

// 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)

V React Native se context nepředává; drží jej za vás nativní modul.

Krok 2: Autentizace

Po inicializaci zavolejte Accept.auth.authenticate() a přihlaste obchodníka tokenem získaným z vašeho backendu. Volání je asynchronní a při selhání skončí chybou SDK. Po úspěšné autentizaci se stav SDK změní na 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
}

Sledujte životní cyklus, abyste mohli reagovat na tyto přechody: idle → initialized → authenticated.

// Accept.state is a StateFlow<SdkState>
Accept.state.collect { state ->
    if (state == SdkState.Authenticated) loadMerchant()
}

Základní koncepty

Objekt Accept zpřístupňuje SDK prostřednictvím několika rozhraní:

RozhraníÚčel
Accept.authAutentizace relace obchodníka.
Accept.merchantProfil obchodníka, konfigurace, stav onboardingu.
Accept.paymentsVytváření a správa plateb kartou.
Accept.pluginInstalace a aktivace terminálu (pluginové aplikace).
Accept.displaysInformace o displejích zařízení pro oboustranné terminály („double-sided“).
Accept.sdkVerze SDK, prostředí, ID zařízení, minimální částky.
Accept.stateStav životního cyklu: StateFlow<SdkState> v Kotlinu, getter a addStateListener() v React Native.

Přijetí platby

Zavolejte Accept.payments.pay() s částkou (v nejmenší jednotce měny) a kódem měny podle ISO 4217 a poté sledujte proud událostí PaymentEvent, které metoda hlásí: nejprve průběh, pak konečný výsledek. pay() nikdy nevyhazuje výjimku; selhání při vytváření platby místo toho přijde jako událost CreationFailed.

Liší se jen způsob, jakým tento proud sledujete: Kotlin vrací Flow<PaymentEvent>, který sbíráte v korutině, kdežto React Native přijímá listener a vrací odběr, který můžete zrušit metodou remove().

amount a currency jsou povinné. Volitelné parametry (paymentToken, receiptConfig, nfcPosition, metadata, tip, transactionTimeout, display) popisuje Vytvoření platby.

V React Native

Tytéž parametry se předávají jako jediný objekt PaymentRequest, pay({ amount, currency, tip, … }), s number místo Long a Record<string, string> místo Map<String, String>. Jeden parametr se jmenuje jinak: časový limit je transactionTimeoutMs a přijímá prosté milisekundy (0…120000) místo Duration.

Průběh platby

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())
        }
    }

Konečná událost s výsledkem nese PayResult: úspěch (s paymentToken, metadata, authCode, receiptDetails), zamítnutí (metadata, receiptDetails), zrušení (metadata) nebo selhání (reason, metadata). Kotlin je modeluje jako podtřídy PayResult.Success / Declined / Canceled / Failed; React Native jako diskriminované sjednocení, ve kterém větvíte podle payResult.type === 'success'. Úplný rozpis najdete v části Výsledek platby. Stav platby můžete později zjistit pomocí Accept.payments.status(paymentToken), zastavit ji pomocí Accept.payments.cancel(paymentToken) nebo ji vrátit pomocí Accept.payments.refund(paymentToken, reason).

Pouze výsledek (React Native)

Pokud vaše UI nezobrazuje mezistavy, payAsync() zredukuje celý proud na konečný PayResult a ve všech případech, které by pay() ohlásila jako creationFailed, odmítne promise s chybou AcceptError. V Kotlinu nemá obdobu; tam sbírejte Flow, nebo si vezměte jen jeho poslední událost.

const result = await Accept.payments.payAsync({ amount: 15000, currency: 'CZK' });
if (result.type === 'success') {
    console.log(result.paymentToken, result.receiptUrl);
}

Informace o obchodníkovi a SDK

Accept.merchant zpřístupňuje profil a platební konfiguraci přihlášeného obchodníka. Accept.sdk poskytuje údaje o sestavení SDK a o tomto zařízení. Každý z níže uvedených členů vyžaduje předchozí volání Accept.initialize() (kromě Accept.sdk.version) a vše na Accept.merchant navíc vyžaduje dokončené Accept.auth.authenticate(), jinak volání vyhodí NotInitialized nebo NotAuthenticated.

Obchodník

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
ČlenVracíPopis
info()MerchantInformation?Registrovaný firemní profil obchodníka. null, pokud profil zatím není k dispozici.
config()MerchantConfigPlatební konfigurace obchodníka.
availableCurrencies()List<String>Kódy ISO 4217, ve kterých může obchodník přijímat platby. Zkratka pro config().availableCurrencies.
onboardingStatus()OnboardingStatusZda už obchodník smí přijímat platby.

Všechny čtyři jsou suspend a při selhání vyhazují NotAuthenticated, NoInternetConnection nebo Unknown.

MerchantInformation nese registrovaný firemní profil. Vždy obsahuje: merchantId (UUID), email, businessType (BusinessType), legalName, registrationNumber, mcc a registrovanou adresu (addressLine1, city, country). Volitelně (null, pokud je obchodník nevyplnil): vatNumber, incorporationDate, addressLine2, postalCode, state, phone, averageItemValue, expectedMonthlyTurnover, businessModelDescription, numberOfEmployees, annualTurnover, balanceSheetTotal, statementDescriptor, termsVersion.

BusinessType nabývá jedné z hodnot INDIVIDUAL, COMPANY, NONPROFIT_ORGANIZATION, GOVERNMENT_ENTITY nebo PARTNERSHIP.

MerchantConfig obsahuje availableCurrencies: List<String> a výchozí měnu obchodníka currency: String?.

OnboardingStatus je sealed interface: buď ReadyForPayments, nebo RequiresAction(state), kde state je OnboardingState: NOT_STARTED, PENDING, ACTIVE, ATTENTION_NEEDED, ACTION_REQUIRED, BLOCKED, WAITING_FOR_KYB, WAITING_FOR_STAKEHOLDERS nebo PENDING_ACQUIRER_APPROVAL. Co jednotlivé stavy znamenají, popisuje Onboarding obchodníků.

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)
ČlenVracíPopis
versionStringVerze SDK. Lze ji číst ještě před initialize().
isProductionBooleanZda initialize() cílilo na produkci (true), nebo na sandbox (false).
deviceId()String?Stálé ID tohoto zařízení, přidělené při prvním úspěšném authenticate() a zachované až do odinstalace aplikace. Do té doby null. Uvádějte jej v žádostech o podporu.
minimumAmounts()List<MinimumAmount>Minimální částka platby pro každou podporovanou měnu. Každá položka je currency: String, amount: Long v nejmenší jednotce měny.

Pluginová aplikace

Každá platba kartou se předává aplikaci Tapaya Terminal, pluginové aplikaci Tapaya; ta je vždy nutná a neexistuje žádný způsob platby kartou, který by ji obešel. Ověřte, zda je nainstalovaná, a poté aktivujte terminál, nebo otevřete stránku aplikace v obchodě, aby si ji obchodník mohl nainstalovat.

K tomu slouží Accept.plugin.isInstalled(), Accept.plugin.activateTerminal() a Accept.plugin.install(). Kód a všechny možné výsledky aktivace najdete v části Instalace a aktivace terminálu.

Aktuální stav pluginu zjistíte pomocí Accept.plugin.status() a obchodníka z pluginu odhlásíte pomocí Accept.plugin.logout().

Oprávnění

Platby kartou vyžadují, aby hostitelská aplikace měla oprávnění k poloze (ACCESS_FINE_LOCATION). SDK si o něj nežádá samo; před voláním pay() zajistěte jeho udělení pomocí standardních API pro oprávnění v Androidu.

class PaymentActivity : AppCompatActivity() {
    private val requestLocation = registerForActivityResult(
        ActivityResultContracts.RequestPermission()
    ) { granted ->
        if (granted) launchPaymentFlow() else showPermissionRationale()
    }

    fun startPayment() {
        requestLocation.launch(Manifest.permission.ACCESS_FINE_LOCATION)
    }
}

Pokud v okamžiku spuštění pay() chybí poloha nebo ji nelze zjistit, proud vyšle PaymentEvent.CreationFailed s příčinou LocationPermissionRequired, LocationUnavailable nebo LocationTimeout.

Zpracování chyb

Každé ošetřované selhání nese jeden z níže uvedených názvů. V Kotlinu je každé z nich podtřídou sealed třídy AcceptException; v React Native jde vždy o jedinou třídu AcceptError, jejíž code obsahuje název, a pole s doplňujícími údaji (minimum, currency, state, …) jsou přímo na témže objektu.

Asynchronní volání (authenticate, merchant.*, payments.status/cancel/refund, plugin.activateTerminal/status/logout/updateInfo, clear) selhávají s jedním z nich. Výjimkou je payments.pay(): nikdy nevyhazuje výjimku a stejná selhání hlásí jako událost CreationFailed nesoucí příčinu.

Typy výjimek

VýjimkaPopis
Životní cyklus
NotInitializedVolání vyžaduje předchozí Accept.initialize().
NotAuthenticatedVolání vyžaduje předchozí Accept.auth.authenticate().
SessionExpiredPlatnost autentizované relace vypršela; znovu se autentizujte.
UnknownEnvironment(key)Klíč prostředí nebyl rozpoznán (interní přetížení metody initialize).
Platby
PaymentInProgressPředchozí pay() stále čeká na výsledek.
CurrencyNotAvailableForMerchant(code)Měna není pro obchodníka nakonfigurována.
UnsupportedCurrency(code)SDK měnu nerozpoznalo.
AmountBelowMinimum(minimum, currency)Částka je nižší než nakonfigurované minimum.
TransactionTimeoutOutOfRange(transactionTimeout)transactionTimeout je mimo rozsah 0 až 120 sekund.
PaymentCreationFailed(cause)Jakékoli jiné selhání při vytváření platby.
PaymentNotFoundToken pro status()/cancel()/refund() backend nezná.
Poloha
LocationPermissionRequiredHostitelská aplikace nemá oprávnění k poloze.
LocationUnavailableŽádný poskytovatel nedokázal určit polohu.
LocationTimeoutPoloha nebyla určena včas.
Plugin / terminál
PluginUnavailablePluginová aplikace není nainstalovaná nebo se nepodařilo připojit k její službě.
PluginTimeoutPlugin neodpověděl včas.
ActivationInProgressPředchozí activateTerminal() stále čeká na výsledek.
NoTidsAvailableForMerchantObchodníkovi nezbyl žádný nepřiřazený terminál (TID) k aktivaci.
PluginAlreadyAuthenticatedPlugin je pro tohoto obchodníka již autentizován.
PluginMerchantMismatchPlugin je autentizován pod jiným obchodníkem; nejprve zavolejte plugin.logout().
PluginNotReadyForPayments(status)pay() bylo spuštěno, když plugin nebyl ve stavu PluginStatus.ReadyForPayments; status nese aktuální stav.
MerchantOnboardingIncomplete(state)Obchodník nedokončil onboarding.
Systém
NoInternetConnectionZařízení nemá připojení k síti.
Unknown(cause)Jakékoli selhání, které SDK nerozpozná jako vlastní.

Výsledek vs. výjimka

Platba, která dorazí do terminálu, ale neproběhne úspěšně, není výjimka; přijde jako PaymentEvent.Result s PayResult.Declined, Canceled nebo Failed(reason). Obdobně aktivace terminálu hlásí ActivateTerminalResult.Failed(reason).

Ošetření výjimek

Obalte volání blokem try/catch, větvěte podle konkrétních případů, které ošetřujete, a pro ostatní použijte obecné zachycení. Kotlin větví podle podtřídy výjimky; React Native ověřuje pomocí AcceptError.is() a větví podle 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}")
}

Logování

Během vývoje zapněte ladicí logování, abyste mohli řešit problémy.

Accept.setDebugLoggingEnabled(true)

Odhlášení

Vymažte veškerý lokálně uložený stav SDK (autentizační token, ID zařízení, konfiguraci v mezipaměti) a vraťte stav SDK zpět na idle. Volejte to při odhlášení uživatele. Chcete-li obchodníka odhlásit i z aplikace Tapaya Terminal, zavolejte nejprve Accept.plugin.logout().

Accept.plugin.logout() // suspend; signs out of the Tapaya Terminal app
Accept.clear()         // suspend; clears local SDK state
Chybí vám něco na této stránce?Navrhněte funkci. Připojíme tuto stránku, aby tým viděl souvislosti.