Tapaya
Prijímanie platieb v predajniSprievodca integráciouIntegrácia mobilného SDK

Integrácia mobilného SDK

Android

Integrujte Tapaya Accept SDK do svojej mobilnej aplikácie.

Tapaya Accept SDK vkladá spracovanie platieb kartou priamo do vašej aplikácie. Je dostupné pre Android (Kotlin) a pre React Native / Expo a obe verzie sú určené pre zariadenia s Androidom. Balík pre React Native je tenká vrstva nad Android SDK, takže rozhrania, typy a chybové prípady uvedené nižšie sú v oboch rovnaké.

Každá ukážka kódu na tejto stránke má karty pre jednotlivé jazyky. Keď jeden vyberiete, prepne sa naň celá stránka.

Inštalácia

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

Android: pridajte závislosť do súboru build.gradle.kts na úrovni modulu a potom synchronizujte projekt.

React Native: nainštalujte balík príkazom npx expo install @tapayadot/accept-react-native, pridajte konfiguračný plugin podľa ukážky, potom pregenerujte natívny projekt príkazom npx expo prebuild --clean a spustite ho príkazom npx expo run:android.

Inicializácia

Accept je vstupný bod pre všetky funkcie SDK. Inicializujte ho raz pri spustení aplikácie (na Androide zvyčajne vo vašej triede Application) a potom sa samostatne autentifikujte tokenom obchodníka.

Krok 1: Inicializácia

// 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 sa context neodovzdáva; drží ho za vás natívny modul.

Krok 2: Autentifikácia

Po inicializácii zavolajte Accept.auth.authenticate(), aby ste prihlásili obchodníka pomocou tokenu získaného z vášho backendu. Volanie je asynchrónne a pri zlyhaní skončí chybou SDK. Pri úspechu sa stav SDK zmení 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, aby ste mohli reagovať na tieto prechody: idle → initialized → authenticated.

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

Základné koncepty

Objekt Accept sprístupňuje SDK prostredníctvom niekoľkých rozhraní:

RozhranieÚčel
Accept.authAutentifikácia relácie obchodníka.
Accept.merchantProfil obchodníka, konfigurácia, stav onboardingu.
Accept.paymentsVytváranie a správa platieb kartou.
Accept.pluginInštalácia a aktivácia terminálu (pluginovej aplikácie).
Accept.displaysInformácie o displejoch zariadenia pre obojstranné terminály (s displejom na oboch stranách).
Accept.sdkVerzia SDK, prostredie, ID zariadenia, minimálne sumy.
Accept.stateStav životného cyklu: v Kotline StateFlow<SdkState>, v React Native getter a addStateListener().

Prijatie platby

Zavolajte Accept.payments.pay() so sumou (v najmenšej jednotke meny) a kódom meny podľa ISO 4217 a potom sledujte prúd udalostí PaymentEvent, ktoré hlási: najprv priebeh, potom konečný výsledok. pay() nikdy nevyhadzuje výnimku; zlyhanie pri vytváraní platby namiesto toho príde ako udalosť CreationFailed.

Jediné, čím sa verzie líšia, je spôsob sledovania tohto prúdu: Kotlin vracia Flow<PaymentEvent>, ktorý odoberáte (collect) v korutine, zatiaľ čo React Native prijíma listener a vracia odber (subscription), ktorý môžete zrušiť cez remove().

amount a currency sú povinné. Voliteľné parametre (paymentToken, receiptConfig, nfcPosition, metadata, tip, transactionTimeout, display) nájdete v časti Vytvorenie platby.

V React Native

Rovnaké parametre sa odovzdávajú ako jeden objekt PaymentRequest, pay({ amount, currency, tip, … }), pričom sa používa number namiesto Long a Record<string, string> namiesto Map<String, String>. Jeden parameter je premenovaný: časový limit je transactionTimeoutMs a namiesto hodnoty Duration prijíma obyčajné milisekundy (0…120000).

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

Udalosť s konečným výsledkom nesie PayResult: úspech (s paymentToken, metadata, authCode, receiptDetails), zamietnutie (metadata, receiptDetails), zrušenie (metadata) alebo zlyhanie (reason, metadata). Kotlin ich modeluje ako podtriedy PayResult.Success / Declined / Canceled / Failed; React Native ako discriminated union, v ktorom vetvíte podľa payResult.type === 'success'. Úplný prehľad nájdete v časti Výsledok platby. Stav platby môžete neskôr zistiť cez Accept.payments.status(paymentToken), platbu zastaviť cez Accept.payments.cancel(paymentToken) alebo ju vrátiť cez Accept.payments.refund(paymentToken, reason).

Iba výsledok (React Native)

Ak vaše UI nevykresľuje priebežné stavy, payAsync() zredukuje celý prúd na jeho konečný PayResult a pri všetkom, čo by pay() nahlásilo ako creationFailed, odmietne promise (reject) s chybou AcceptError. V Kotline nemá obdobu; tam odoberajte Flow alebo si vezmite iba jeho poslednú udalosť.

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

Informácie o obchodníkovi a SDK

Accept.merchant sprístupňuje profil a platobnú konfiguráciu prihláseného obchodníka. Accept.sdk sprístupňuje údaje o zostavení SDK a o tomto zariadení. Každý člen uvedený nižšie vyžaduje najprv Accept.initialize() (okrem Accept.sdk.version) a všetko na Accept.merchant navyše vyžaduje dokončené Accept.auth.authenticate(), inak volanie vyhodí NotInitialized alebo 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
ČlenVraciaPopis
info()MerchantInformation?Registrovaný firemný profil obchodníka. null, ak profil ešte nie je k dispozícii.
config()MerchantConfigPlatobná konfigurácia obchodníka.
availableCurrencies()List<String>Kódy ISO 4217, ktoré obchodník môže prijímať. Skratka pre config().availableCurrencies.
onboardingStatus()OnboardingStatusČi obchodník už môže prijímať platby.

Všetky štyri sú suspend a pri zlyhaní vyhadzujú NotAuthenticated, NoInternetConnection alebo Unknown.

MerchantInformation nesie registrovaný firemný profil. Vždy prítomné: merchantId (UUID), email, businessType (BusinessType), legalName, registrationNumber, mcc a registrovaná adresa (addressLine1, city, country). Voliteľné (null, pokiaľ ich obchodník nezadal): vatNumber, incorporationDate, addressLine2, postalCode, state, phone, averageItemValue, expectedMonthlyTurnover, businessModelDescription, numberOfEmployees, annualTurnover, balanceSheetTotal, statementDescriptor, termsVersion.

BusinessType je jedna z hodnôt INDIVIDUAL, COMPANY, NONPROFIT_ORGANIZATION, GOVERNMENT_ENTITY alebo PARTNERSHIP.

MerchantConfig obsahuje availableCurrencies: List<String> a predvolenú menu obchodníka currency: String?.

OnboardingStatus je sealed interface: buď ReadyForPayments, alebo RequiresAction(state), kde state je OnboardingState: NOT_STARTED, PENDING, ACTIVE, ATTENTION_NEEDED, ACTION_REQUIRED, BLOCKED, WAITING_FOR_KYB, WAITING_FOR_STAKEHOLDERS alebo PENDING_ACQUIRER_APPROVAL. Čo jednotlivé stavy znamenajú, nájdete v časti Onboarding obchodníkov.

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)
ČlenVraciaPopis
versionStringVerzia SDK. Dá sa prečítať aj pred initialize().
isProductionBooleanČi initialize() cielilo na produkciu (true), alebo na sandbox (false).
deviceId()String?Stabilné ID tohto zariadenia, pridelené pri prvom úspešnom authenticate() a zachované až do odinštalovania aplikácie. Dovtedy null. Uvádzajte ho v požiadavkách na podporu.
minimumAmounts()List<MinimumAmount>Minimálna suma platby pre každú podporovanú menu. Každá položka je currency: String, amount: Long v najmenšej jednotke meny.

Pluginová aplikácia

Každá platba kartou sa odovzdáva aplikácii Tapaya Terminal, pluginovej aplikácii Tapaya; je vždy povinná, neexistuje žiadna cesta platby kartou, ktorá by ju obišla. Skontrolujte, či je nainštalovaná, a potom aktivujte terminál, alebo otvorte jej stránku v obchode, aby ju obchodník mohol nainštalovať.

Použite na to Accept.plugin.isInstalled(), Accept.plugin.activateTerminal() a Accept.plugin.install(). Kód a všetky výsledky aktivácie nájdete v časti Inštalácia a aktivácia terminálu.

Aktuálny stav pluginu zistíte cez Accept.plugin.status() a obchodníka z pluginu odhlásite cez Accept.plugin.logout().

Oprávnenia

Platby kartou vyžadujú, aby hostiteľská aplikácia mala oprávnenie na prístup k polohe (ACCESS_FINE_LOCATION). SDK oň nežiada za vás; pred volaním pay() ho získajte pomocou štandardných API pre oprávnenia v Androide.

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

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

Ak poloha chýba alebo ju nie je možné zistiť v čase spustenia pay(), prúd vyšle PaymentEvent.CreationFailed s príčinou LocationPermissionRequired, LocationUnavailable alebo LocationTimeout.

Spracovanie chýb

Každé ošetrené zlyhanie nesie jeden z názvov uvedených nižšie. V Kotline je každé podtriedou sealed triedy AcceptException; v React Native ide vždy o jedinú triedu AcceptError, ktorej code obsahuje názov a polia s údajmi (minimum, currency, state, …) sú na tom istom objekte.

Asynchrónne volania (authenticate, merchant.*, payments.status/cancel/refund, plugin.activateTerminal/status/logout/updateInfo, clear) zlyhávajú s jedným z nich. Výnimkou je payments.pay(): nikdy nevyhadzuje výnimku a tie isté zlyhania hlási ako udalosť CreationFailed s príčinou.

Typy výnimiek

VýnimkaPopis
Životný cyklus
NotInitializedVolanie vyžaduje najprv Accept.initialize().
NotAuthenticatedVolanie vyžaduje najprv Accept.auth.authenticate().
SessionExpiredPlatnosť autentifikovanej relácie vypršala; znova sa autentifikujte.
UnknownEnvironment(key)Kľúč prostredia nebol rozpoznaný (interné preťaženie metódy initialize).
Platby
PaymentInProgressPredchádzajúce volanie pay() stále čaká na výsledok.
CurrencyNotAvailableForMerchant(code)Mena nie je pre obchodníka nakonfigurovaná.
UnsupportedCurrency(code)SDK menu nerozpoznáva.
AmountBelowMinimum(minimum, currency)Suma je pod nakonfigurovaným minimom.
TransactionTimeoutOutOfRange(transactionTimeout)transactionTimeout je mimo rozsahu 0 až 120 sekúnd.
PaymentCreationFailed(cause)Akékoľvek iné zlyhanie pri vytváraní platby.
PaymentNotFoundBackend nepozná token zadaný v status()/cancel()/refund().
Poloha
LocationPermissionRequiredHostiteľská aplikácia nemá oprávnenie na prístup k polohe.
LocationUnavailableŽiadny poskytovateľ polohy nedokázal určiť polohu.
LocationTimeoutPoloha nebola určená včas.
Plugin / terminál
PluginUnavailablePluginová aplikácia nie je nainštalovaná alebo sa nepodarilo pripojiť k jej službe.
PluginTimeoutPlugin neodpovedal včas.
ActivationInProgressPredchádzajúce volanie activateTerminal() stále čaká na výsledok.
NoTidsAvailableForMerchantObchodníkovi nezostal žiadny nepridelený terminál (TID) na aktiváciu.
PluginAlreadyAuthenticatedPlugin je už autentifikovaný pre tohto obchodníka.
PluginMerchantMismatchPlugin je autentifikovaný pod iným obchodníkom; najprv zavolajte plugin.logout().
PluginNotReadyForPayments(status)pay() sa spustilo, keď plugin nebol v stave PluginStatus.ReadyForPayments; status nesie aktuálny stav.
MerchantOnboardingIncomplete(state)Obchodník nedokončil onboarding.
Systém
NoInternetConnectionZariadenie nemá pripojenie k sieti.
Unknown(cause)Akékoľvek zlyhanie, ktoré SDK nerozpozná ako jedno z vlastných.

Výsledok vs. výnimka

Platba, ktorá sa dostane na terminál, ale neuspeje, nie je výnimkou; príde ako PaymentEvent.Result s PayResult.Declined, Canceled alebo Failed(reason). Podobne aj aktivácia terminálu hlási ActivateTerminalResult.Failed(reason).

Ošetrenie výnimiek

Volanie obaľte do try/catch, vetvite podľa konkrétnych prípadov, ktoré ošetrujete, a ostatné zachyťte všeobecným catch. Kotlin vetví podľa podtriedy výnimky; React Native overuje typ cez AcceptError.is() a vetví podľa 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}")
}

Logovanie

Počas vývoja zapnite ladiace logovanie, aby ste mohli riešiť problémy.

Accept.setDebugLoggingEnabled(true)

Odhlásenie

Vymažte všetok lokálne uložený stav SDK (autentifikačný token, ID zariadenia, konfiguráciu vo vyrovnávacej pamäti) a vráťte stav SDK späť na idle. Toto volanie použite pri odhlásení používateľa. Ak chcete obchodníka odhlásiť aj z aplikácie Tapaya Terminal, najprv zavolajte Accept.plugin.logout().

Accept.plugin.logout() // suspend; signs out of the Tapaya Terminal app
Accept.clear()         // suspend; clears local SDK state
Chýba vám niečo na tejto stránke?Navrhnite funkciu. Pripojíme túto stránku, aby tím videl súvislosti.