Інтеграція мобільного SDK
AndroidІнтегруйте Tapaya Accept SDK у свій мобільний застосунок.
Tapaya Accept SDK вбудовує обробку платежів карткою безпосередньо у ваш застосунок. Він доступний для Android (Kotlin) і для React Native / Expo, причому обидва варіанти орієнтовані на пристрої з Android. Пакет для React Native є тонкою обгорткою над Android SDK, тож інтерфейси, типи та випадки помилок, описані нижче, однакові в обох варіантах.
Кожен приклад коду на цій сторінці має вкладки за мовами. Виберіть одну, і вся сторінка перемкнеться на неї.
Встановлення
dependencies {
implementation("com.tapaya:accept:1.15.0")
}Android: додайте залежність до файлу build.gradle.kts на рівні модуля, а потім синхронізуйте проєкт.
React Native: встановіть пакет командою npx expo install @tapayadot/accept-react-native, додайте конфігураційний плагін, як
показано, потім повторно згенеруйте нативний проєкт командою npx expo prebuild --clean і запустіть його командою
npx expo run:android.
Ініціалізація
Accept є точкою входу до всіх функцій SDK. Ініціалізуйте його один раз під час запуску застосунку (на Android
зазвичай у класі Application), а потім окремо автентифікуйтеся за допомогою токена мерчанта.
Крок 1: ініціалізація
// 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)У React Native context не передається; його зберігає за вас нативний модуль.
Крок 2: автентифікація
Після ініціалізації викличте Accept.auth.authenticate(), щоб виконати вхід мерчанта за допомогою токена, отриманого з вашого
бекенду. Виклик асинхронний і в разі невдачі завершується помилкою SDK. У разі успіху стан SDK змінюється на 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
}Відстежуйте життєвий цикл, щоб реагувати на ці переходи: idle → initialized → authenticated.
// Accept.state is a StateFlow<SdkState>
Accept.state.collect { state ->
if (state == SdkState.Authenticated) loadMerchant()
}Основні поняття
Об'єкт Accept надає доступ до SDK через невеликий набір інтерфейсів:
| Інтерфейс | Призначення |
|---|---|
Accept.auth | Автентифікація сесії мерчанта. |
Accept.merchant | Профіль мерчанта, конфігурація, статус онбордингу. |
Accept.payments | Створення платежів карткою та керування ними. |
Accept.plugin | Встановлення та активація термінала (застосунку-плагіна). |
Accept.displays | Інформація про дисплеї пристрою для двобічних терміналів («double-sided»). |
Accept.sdk | Версія SDK, середовище, ID пристрою, мінімальні суми. |
Accept.state | Стан життєвого циклу: StateFlow<SdkState> у Kotlin, getter і addStateListener() у React Native. |
Прийом платежу
Викличте Accept.payments.pay() із сумою (у найменшій одиниці валюти) і кодом валюти за ISO 4217, а потім
відстежуйте потік подій PaymentEvent, які повідомляє метод: спочатку перебіг, потім остаточний результат. pay() ніколи
не викидає винятків; невдача під час створення платежу натомість надходить як подія CreationFailed.
Відрізняється лише спосіб, у який ви відстежуєте цей потік: Kotlin повертає Flow<PaymentEvent>, який ви збираєте
в корутині, тоді як React Native приймає listener і повертає підписку, яку можна скасувати методом remove().
amount і currency обов'язкові. Необов'язкові параметри (paymentToken, receiptConfig, nfcPosition,
metadata, tip, transactionTimeout, display) описано в розділі Створення платежу.
У React Native
Ті самі параметри передаються одним об'єктом PaymentRequest, pay({ amount, currency, tip, … }), з
number замість Long і Record<string, string> замість Map<String, String>. Один параметр має іншу назву:
тайм-аут називається transactionTimeoutMs і приймає звичайні мілісекунди (0…120000), а не 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())
}
}Остаточна подія з результатом містить PayResult: успіх (з paymentToken, metadata, authCode,
receiptDetails), відмову (metadata, receiptDetails), скасування (metadata) або невдачу (reason,
metadata). Kotlin моделює їх як підкласи PayResult.Success / Declined / Canceled / Failed;
React Native як дискриміноване об'єднання, у якому ви розгалужуєте логіку за payResult.type === 'success'. Повний
розбір наведено в розділі Результат платежу. Пізніше можна запитати статус платежу за допомогою
Accept.payments.status(paymentToken), зупинити його за допомогою Accept.payments.cancel(paymentToken) або повернути кошти за допомогою
Accept.payments.refund(paymentToken, reason).
Лише результат (React Native)
Якщо ваш UI не відображає проміжні стани, payAsync() зводить увесь потік до остаточного
PayResult і відхиляє проміс із помилкою AcceptError у всіх випадках, про які pay() повідомив би як
creationFailed. У Kotlin відповідника немає; там збирайте Flow або беріть лише його останню подію.
const result = await Accept.payments.payAsync({ amount: 15000, currency: 'CZK' });
if (result.type === 'success') {
console.log(result.paymentToken, result.receiptUrl);
}Інформація про мерчанта та SDK
Accept.merchant надає профіль і платіжну конфігурацію мерчанта, який увійшов у систему. Accept.sdk надає
відомості про збірку SDK і цей пристрій. Кожен член, наведений нижче, потребує попереднього виклику Accept.initialize() (крім
Accept.sdk.version), а все в Accept.merchant додатково потребує завершеного
Accept.auth.authenticate(), інакше виклик викидає NotInitialized або NotAuthenticated.
Мерчант
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| Член | Повертає | Опис |
|---|---|---|
info() | MerchantInformation? | Зареєстрований бізнес-профіль мерчанта. null, якщо профіль ще недоступний. |
config() | MerchantConfig | Платіжна конфігурація мерчанта. |
availableCurrencies() | List<String> | Коди ISO 4217, у яких мерчант може приймати платежі. Скорочення для config().availableCurrencies. |
onboardingStatus() | OnboardingStatus | Чи може мерчант уже приймати платежі. |
Усі чотири є suspend і в разі невдачі викидають NotAuthenticated, NoInternetConnection або Unknown.
MerchantInformation містить зареєстрований бізнес-профіль. Завжди присутні: merchantId (UUID),
email, businessType (BusinessType), legalName, registrationNumber, mcc і зареєстрована адреса
(addressLine1, city, country). Необов'язкові (null, якщо мерчант їх не вказав): vatNumber,
incorporationDate, addressLine2, postalCode, state, phone, averageItemValue,
expectedMonthlyTurnover, businessModelDescription, numberOfEmployees, annualTurnover,
balanceSheetTotal, statementDescriptor, termsVersion.
BusinessType набуває одного зі значень INDIVIDUAL, COMPANY, NONPROFIT_ORGANIZATION, GOVERNMENT_ENTITY або
PARTNERSHIP.
MerchantConfig містить availableCurrencies: List<String> і валюту мерчанта за замовчуванням currency: String?.
OnboardingStatus є sealed interface: або ReadyForPayments, або RequiresAction(state), де
state є OnboardingState: NOT_STARTED, PENDING, ACTIVE, ATTENTION_NEEDED, ACTION_REQUIRED,
BLOCKED, WAITING_FOR_KYB, WAITING_FOR_STAKEHOLDERS або PENDING_ACQUIRER_APPROVAL. Що означає кожен стан,
описано в розділі Онбординг мерчантів.
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)| Член | Повертає | Опис |
|---|---|---|
version | String | Версія SDK. Її можна прочитати ще до initialize(). |
isProduction | Boolean | Чи initialize() було спрямовано на робоче середовище (true) або на пісочницю (false). |
deviceId() | String? | Стабільний ID цього пристрою, який призначається під час першого успішного authenticate() і зберігається до видалення застосунку. До того null. Вказуйте його в запитах до підтримки. |
minimumAmounts() | List<MinimumAmount> | Мінімальна сума платежу для кожної підтримуваної валюти. Кожен елемент має вигляд currency: String, amount: Long у найменшій одиниці валюти. |
Застосунок-плагін
Кожен платіж карткою передається в Tapaya Terminal, застосунок-плагін Tapaya; він потрібен завжди, і немає жодного способу платежу карткою, який би його оминав. Перевірте, чи його встановлено, а потім активуйте термінал або відкрийте сторінку застосунку в магазині, щоб мерчант міг його встановити.
Для цього використовуйте Accept.plugin.isInstalled(), Accept.plugin.activateTerminal() і Accept.plugin.install(). Код
і всі можливі результати активації наведено в розділі Встановлення та активація термінала.
Поточний стан плагіна можна отримати за допомогою Accept.plugin.status(), а вийти з облікового запису мерчанта в плагіні можна за допомогою
Accept.plugin.logout().
Дозволи
Для платежів карткою хост-застосунок повинен мати дозвіл на доступ до геолокації (ACCESS_FINE_LOCATION). SDK не
запитує його за вас; надайте його за допомогою стандартних API дозволів Android перед викликом 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)
}
}Якщо на момент виконання pay() геолокація відсутня або її неможливо визначити, потік видає PaymentEvent.CreationFailed
із причиною LocationPermissionRequired, LocationUnavailable або LocationTimeout.
Обробка помилок
Кожна контрольована помилка має одну з наведених нижче назв. У Kotlin кожна з них є підкласом sealed-класу
AcceptException; у React Native усі вони належать до одного класу AcceptError, поле code якого містить назву, а
поля з додатковими даними (minimum, currency, state, …) розташовані безпосередньо в тому самому об'єкті.
Асинхронні виклики (authenticate, merchant.*, payments.status/cancel/refund,
plugin.activateTerminal/status/logout/updateInfo, clear) завершуються з однією з них. Винятком є
payments.pay(): він ніколи не викидає винятків і повідомляє про ті самі помилки як про подію CreationFailed із причиною.
Типи винятків
| Виняток | Опис |
|---|---|
| Життєвий цикл | |
NotInitialized | Виклик потребує попереднього Accept.initialize(). |
NotAuthenticated | Виклик потребує попереднього Accept.auth.authenticate(). |
SessionExpired | Термін дії автентифікованої сесії минув; автентифікуйтеся повторно. |
UnknownEnvironment(key) | Ключ середовища не розпізнано (внутрішнє перевантаження методу initialize). |
| Платежі | |
PaymentInProgress | Попередній pay() досі очікує на результат. |
CurrencyNotAvailableForMerchant(code) | Валюту не налаштовано для мерчанта. |
UnsupportedCurrency(code) | SDK не розпізнає валюту. |
AmountBelowMinimum(minimum, currency) | Сума менша за налаштований мінімум. |
TransactionTimeoutOutOfRange(transactionTimeout) | transactionTimeout поза діапазоном від 0 до 120 секунд. |
PaymentCreationFailed(cause) | Будь-яка інша помилка під час створення платежу. |
PaymentNotFound | Бекенду невідомий токен для status()/cancel()/refund(). |
| Геолокація | |
LocationPermissionRequired | Хост-застосунок не має дозволу на доступ до геолокації. |
LocationUnavailable | Жоден провайдер не зміг визначити місцезнаходження. |
LocationTimeout | Місцезнаходження не вдалося визначити вчасно. |
| Плагін / термінал | |
PluginUnavailable | Застосунок-плагін не встановлено або не вдалося під'єднатися до його служби. |
PluginTimeout | Плагін не відповів вчасно. |
ActivationInProgress | Попередній activateTerminal() досі очікує на результат. |
NoTidsAvailableForMerchant | У мерчанта не залишилося непризначених терміналів (TID) для активації. |
PluginAlreadyAuthenticated | Плагін уже автентифіковано для цього мерчанта. |
PluginMerchantMismatch | Плагін автентифіковано під іншим мерчантом; спочатку викличте plugin.logout(). |
PluginNotReadyForPayments(status) | pay() виконано, коли плагін не перебував у стані PluginStatus.ReadyForPayments; status містить поточний стан. |
MerchantOnboardingIncomplete(state) | Мерчант не завершив онбординг. |
| Система | |
NoInternetConnection | Пристрій не має підключення до мережі. |
Unknown(cause) | Будь-яка помилка, яку SDK не розпізнає як власну. |
Результат чи виняток
Платіж, який дійшов до термінала, але не був успішним, не є винятком; він надходить як
PaymentEvent.Result із PayResult.Declined, Canceled або Failed(reason). Так само активація
термінала повідомляє ActivateTerminalResult.Failed(reason).
Обробка винятків
Обгорніть виклик у try/catch, розгалужте логіку за конкретними випадками, які ви обробляєте, а для решти використайте загальне перехоплення.
Kotlin розгалужує логіку за підкласом винятку; React Native перевіряє за допомогою AcceptError.is() і перемикається за 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}")
}Журналювання
Під час розробки ввімкніть налагоджувальне журналювання, щоб діагностувати проблеми.
Accept.setDebugLoggingEnabled(true)Вихід
Очистьте весь локально збережений стан SDK (токен автентифікації, ID пристрою, кешовану конфігурацію) і поверніть стан SDK до
idle. Викликайте це, коли користувач виходить з облікового запису. Щоб також вийти з облікового запису мерчанта в застосунку Tapaya Terminal, спочатку викличте
Accept.plugin.logout().
Accept.plugin.logout() // suspend; signs out of the Tapaya Terminal app
Accept.clear() // suspend; clears local SDK state