Tapaya
Integration GuideMobile SDK Integration

Mobile SDK Integration

Integrate the Tapaya Accept SDK into your mobile application.

The Tapaya Accept SDK for Android provides a robust, secure, and easy-to-use toolkit for embedding payment processing directly into your Android application. Designed with modern Android development practices in mind, it supports Kotlin Coroutines, lifecycle-aware components, and a clean API surface.

Installation

Add the Tapaya Accept SDK dependency to your module-level build.gradle file.

dependencies {
    implementation("com.tapaya:accept:1.1.0")
}

Initialization

The AcceptSDK singleton is the entry point for all SDK functionality. Initialize it once — typically in your Application class — then authenticate separately with a merchant token.

Step 1 — Initialize

// Explicit environment
AcceptSDK.initialize(context = this, environment = AcceptEnvironment.SANDBOX)

// Convenience overload
AcceptSDK.initialize(context = this, demo = BuildConfig.DEBUG)

Step 2 — Authenticate

Call authenticate() after initialization to log in a merchant. Use a TokenProvider in production so the SDK can refresh the token automatically.

// TokenProvider (Recommended for Production)
val tokenProvider = object : TokenProvider {
    override fun getToken(): String {
        return myBackendApi.getMerchantToken()
    }
}

AcceptSDK.authenticate(
    tokenProvider = tokenProvider,
    onSuccess = { /* proceed */ },
    onError = { e -> /* handle AcceptSDKException */ }
)

// Static token (testing only)
AcceptSDK.authenticate(
    token = AcceptSDK.DEMO_TOKEN,
    onSuccess = { /* proceed */ }
)

Core Concepts

Payment Interface

The SDK exposes specialized "Terminal" objects for different payment methods. These are lazily initialized and handle the specific logic for each payment type.

Payment Flow

MethodDescriptionUse Case
cardTerminalNFC Card ReaderContactless EMV payments.
sepaTerminalSEPA InstantBank-to-bank transfers via QR code.
certisTerminalCertis PaymentsSpecialized instant payment network. For more information, see the official CERTIS documentation.

Onboarding

Before processing payments, you may need to verify the merchant's status or collect additional information (KYC/KYB). The AcceptSDK.identity module manages these flows.

Onboarding

// Check if the merchant is approved for Card payments
val status = AcceptSDK.identity.loadStatus(PaymentMethod.CARD)

if (status == IdentityStatus.VERIFIED) {
    // Ready to process payments
} else {
    // Launch KYB onboarding UI (optionally prefill known data)
    AcceptSDK.identity.presentKyb()
}

Permissions

Processing payments, especially contactless card payments, requires specific Android permissions and hardware capabilities (NFC). The AcceptSDK.helper simplifies managing these requirements.

Lifecycle Management

To ensure the helper can correctly handle permission results, link it to your Activity's lifecycle.

class PaymentActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // Register lifecycle observer
        AcceptSDK.helper.onCreate(this)
    }

    override fun onDestroy() {
        AcceptSDK.helper.onDestroy()
        super.onDestroy()
    }
}

Requesting Permissions

Request the necessary permissions before starting a transaction. The SDK handles the complexity of different Android versions.

fun startPayment() {
    AcceptSDK.helper.requestLocationPermission(this,
        onLocationPermissionGranted = {
            // Permission granted, proceed to payment
            launchPaymentFlow()
        },
        onLocationPermissionDenied = {
            // Show rationale to user
            showPermissionRationale()
        }
    )
}

Error Handling

The SDK uses a unified exception hierarchy rooted at AcceptSDKException. All exceptions are wrapped in AcceptSDKExceptionWrapper to preserve the original cause while providing a consistent interface.

Exception Hierarchy

Exception ClassDescription
Initialization
AcceptSDKUninitializedExceptionTerminal is not initialized, call AcceptSDK.initialize() first.
AcceptSDKServiceStartingExceptionService failed to start. Ensure app is in foreground.
AcceptSDKServiceInitializationExceptionUnable to initialize payment service. Payments may not be working properly.
AcceptSDKTokenInitializationErrorExceptionError in your TokenProvider implementation.
AcceptSDKInitializationExceptionAccept SDK initialization failed.
AcceptSDKLoginExpiredExceptionSession expired or not found. Call AcceptSDK.initialize() first.
AcceptSDKInitializeWithoutDataExceptionDevice restarted payment service. Waiting for proper start.
Permissions & Environment
AcceptSDKLocationPermissionExceptionMissing required location permissions (ACCESS_COARSE_LOCATION / ACCESS_FINE_LOCATION).
AcceptSDKLocationDisabledExceptionAndroid Location services are disabled.
AcceptNFCDisabledExceptionNFC is disabled on the device.
AcceptSDKNotDebuggableExceptionProduction app detected, but SDK registered in DEMO mode. Use AcceptSDK.initialize(..., demo = false).
AcceptSDKDebuggableNotDemoExceptionDebug app detected, but SDK registered in PROD mode. Use AcceptSDK.initialize(..., demo = true).
Reader & Connection
AcceptSDKReaderNotFoundExceptionNo Tap-to-Pay terminal reader found on this device.
AcceptSDKReaderNotReadyYetExceptionMerchant KYB data missing or processing for the specific terminal reader.
AcceptSDKReaderBadConnectionExceptionConnection issues detected while communicating with the reader.
AcceptSDKOfflineExceptionInternet connection not available.
Transactions & Operations
AcceptSDKInitializeTransactionExceptionUnable to initialize transaction.
AcceptSDKFinalizeTransactionExceptionTransaction finalization failed. Verify status manually via backend.
AcceptSDKOperationTimeoutExceptionThe operation timed out.
AcceptSDKPaymentNotFoundExceptionThe requested payment record was not found.
AcceptSDKServerErrorExceptionServer error occurred.
AcceptSDKClientErrorExceptionClient error occurred.
AcceptSDKCancellationExceptionUser cancelled the operation manually.
Onboarding & Location Metadata
AcceptSDKOnboardingExceptionError occurred during terminal onboarding.
AcceptSDKDuplicatedOnboardingExceptionDuplicated onboarding provided.
AcceptSDKMissingKYBDetailsExceptionOnboarding not completed for the specified payment method.
AcceptSDKLocationNotFoundExceptionUnable to resolve location coordinates.
AcceptSDKLocationIdNotFoundExceptionStripe/Internal location identifier not found.
System
AcceptSDKUnknownExceptionUnknown SDK error.
AcceptSDKUnknownMessageExceptionUnknown SDK error with message.

Handling Exceptions

When using Coroutines, wrap SDK calls in a try-catch block to handle these specific scenarios.

try {
    AcceptSDK.cardTerminal.process(...)
} catch (e: AcceptSDKCancellationException) {
    // User cancelled, do nothing
} catch (e: AcceptSDKLocationPermissionException) {
    // Prompt user for permissions
} catch (e: AcceptSDKException) {
    // Handle other SDK-specific errors
    Log.e("Payment", "Error: ${e.message}")
}

Logging

Enable verbose logging during development to troubleshoot issues.

// Enable debug logs
AcceptSDK.setLogLevel(LogLevel.DEBUG)

The Tapaya Accept SDK for iOS provides a secure, easy-to-use toolkit for embedding payment processing directly into your iOS application. Built with Swift 6 and modern concurrency in mind, it offers a clean async/await API and tight integration with the Tapaya Accept companion app.

Requirements

RequirementMinimum Version
iOS26.0
Swift6.2
Xcode26.0

Installation

The SDK is distributed via Swift Package Manager from the public repository.

In Xcode: go to File → Add Package Dependencies, paste the repository URL, and add the AcceptSDK product to your target.

In Package.swift:

dependencies: [
    .package(url: "https://github.com/tapayadot/accept-ios.git", from: "1.1.2")
],
targets: [
    .target(
        name: "MyApp",
        dependencies: [
            .product(name: "AcceptSDK", package: "accept-ios")
        ]
    )
]

App Configuration

The SDK requires two Info.plist entries to function correctly.

1. Companion app detection — allows the SDK to check whether the Tapaya Accept companion app is installed:

Info.plist
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>tapaya-accept</string>
</array>

2. Callback URL scheme — required for deep link callbacks (e.g. after KYB onboarding). Replace myapp with your app's unique scheme:

Info.plist
<key>AcceptCallbackScheme</key>
<string>myapp</string>

Required

If AcceptCallbackScheme is missing or empty, Accept.initialize() will throw .notInitialized.

Forward inbound URLs to the SDK so it can handle callbacks (e.g. returning from the companion app or KYB flows).

// SwiftUI
.onOpenURL { url in
    Accept.handle(url: url)
}

// UIKit
func application(_ app: UIApplication, open url: URL, options: [...]) -> Bool {
    Accept.handle(url: url)
}

Initialization

AcceptSDK is the single entry point for all SDK functionality. Initialize it once at app launch — for example in your App struct or AppDelegate — before calling any other method.

// Sandbox environment (default — safe for testing)
try await Accept.initialize()

// Explicit environment
try await Accept.initialize(environment: .production)

// Convenience: true → sandbox, false → production
try await Accept.initialize(demo: isTestMode)

Authentication

After initialization, authenticate the merchant using a token obtained from your backend.

do {
    let merchantToken = try await myBackend.login()
    try await Accept.authenticate(merchantToken: merchantToken)
} catch AcceptSDKError.failedToAuthenticateMerchant {
    // Invalid credentials or network failure — prompt the user to retry
}

Logout

To log out the current merchant and clear the session, call logout().

try await Accept.logout()

Companion App

The Tapaya Accept companion app is required for card payment flows. Check whether it is installed and guide the merchant to install it if needed.

Companion App

if await Accept.isCompanionAppInstalled() {
    // Pair the device — launches the companion app to complete authentication
    try await Accept.pairWithCompanionApp()
} else {
    // Show the App Store product page as an in-app sheet
    try await Accept.presentCompanionAppSheet()
}

Permissions

Card payments require location access. Request the permission before starting a payment flow.

do {
    try await Accept.requestLocationPermission()
    // Permission granted — safe to initiate a payment
} catch AcceptSDKError.locationPermissionsNotGranted {
    // Prompt the user to enable Location in Settings
}

Onboarding

Before processing payments, the merchant must complete KYB (Know Your Business) onboarding. Check the verification status and launch the onboarding UI if needed.

iOS Onboarding

let result = try await Accept.presentKyb()

switch result {
case .submitted:
    // KYB form submitted — await processor approval
case .cancelled:
    // Merchant dismissed without submitting
case .failed:
    // Submission failed
}

You can optionally prefill known fields to reduce friction:

let prefill = KybPrefillData(
    businessType: .company,
    countryCode: "CZ",
    legalName: "My Company s.r.o.",
    registrationNumber: "12345678",
    businessEmail: "jan@example.com"
)
let result = try await Accept.presentKyb(prefilling: prefill)

Core Concepts

Payment Interface

Companion App Required

Card payments require the Tapaya Accept companion app to be installed on the device. Use Accept.isCompanionAppInstalled() to check, and Accept.presentCompanionAppSheet() to prompt installation if needed. See the Companion App section above.

Each payment method has a dedicated intent type. Create an intent and pass it to Accept.pay(_:).

Payment Flow

Intent TypeDescriptionUse Case
AcceptCardPaymentIntentNFC Card ReaderContactless EMV payments.
AcceptSepaPaymentIntentSEPA InstantBank-to-bank transfers via QR code.
AcceptCertisPaymentIntentCertis PaymentsSpecialized instant payment network. For more information, see the official CERTIS documentation.

Supported Currencies

CaseISO Code
.czkCZK
.eurEUR
.gbpGBP

Transaction Status

The .status field on a completed payment is an AcceptTransactionStatus:

CaseDescription
.pendingPayment is pending.
.successPayment completed successfully.
.cancelledPayment was cancelled.
.refundedPayment was refunded.
.failedPayment failed.
.actionNeededPayment requires further action.

Payment Outcome

Accept.pay(_:) returns an AcceptPaymentOutcome — either .completed(status) or .canceled.

Making a Payment

try await Accept.requestLocationPermission()

let intent = AcceptCardPaymentIntent(
    amount: 1000, // smallest currency unit — 10.00 CZK
    requestedCurrency: .czk,
    settlementCurrency: .czk
)

do {
    let outcome = try await Accept.pay(intent)
    switch outcome {
    case .completed(let status):
        print("Payment succeeded: \(status.paymentToken)")
        print("Status: \(status.status)")
    case .canceled:
        print("User dismissed the payment flow")
    }
} catch AcceptSDKError.paymentAlreadyInProgress {
    // A payment flow is already on screen — wait for it to finish
} catch {
    // Handle other AcceptSDKError cases
}

Checking Payment Status

Retrieve the status of a previously initiated payment by its token — useful after an app restart or when verifying a payment initiated on another session.

let status = try await Accept.getPaymentStatus(for: paymentToken)

Error Handling

All SDK methods throw AcceptSDKError. The error conforms to LocalizedError, so error.localizedDescription always returns a human-readable message.

CaseDescription
.notInitializedAccept.initialize() has not been called, or AcceptCallbackScheme is missing from Info.plist.
.merchantNotAuthenticatedAccept.authenticate(merchantToken:) has not been called.
.failedToAuthenticateMerchantAuthentication failed — invalid token or network error.
.locationPermissionsNotGrantedLocation permission was denied or restricted.
.companionAppNotInstalledThe Tapaya Accept companion app is not installed.
.paymentAlreadyInProgressA payment flow is already being presented.
.kybAlreadyInProgressA KYB onboarding flow is already being presented.
.failedToPresentNo visible view controller found to present from.
.paymentNotFoundNo payment matched the provided token.
.unexpectedPaymentResultInternal SDK invariant violated — report as a bug.
do {
    let outcome = try await Accept.pay(intent)
} catch AcceptSDKError.merchantNotAuthenticated {
    // Re-authenticate before retrying
} catch AcceptSDKError.locationPermissionsNotGranted {
    // Prompt the user to allow location access
} catch AcceptSDKError.companionAppNotInstalled {
    try await Accept.presentCompanionAppSheet()
} catch {
    // Catch-all for other AcceptSDKError cases
    print("Payment failed: \(error.localizedDescription)")
}

The Tapaya Accept SDK for React Native is a robust, secure, and easy-to-use toolkit that lets you embed payment processing directly into your React Native application. Built to integrate seamlessly with the React Native ecosystem, it offers a clean API, reliable performance, and a developer-friendly experience across platforms.

Installation

Install NPM Package

Add the dependency to your project.

npm i @tapayadot/accept-react-native

Register the plugin in your app.json.

app.json
"plugins": [
    [
        "@tapayadot/accept-react-native"
    ]
]

Before first Expo run

Run npx expo prebuild --clean to generate the native bindings before building your app.

Initialization

The AcceptSDK object is the entry point for all SDK functionality. Call initialize() once at app launch.

import AcceptSDK from '@tapayadot/accept-react-native';

// set true for testing environment
await AcceptSDK.initialize(true);

Authentication

After initialization, authenticate the merchant using a token obtained from your backend.

const merchantToken = await myBackend.login();
await AcceptSDK.authenticate(merchantToken);

Core Concepts

Payment Interface

Companion App Required (iOS)

On iOS, card payments require the Tapaya Accept companion app to be installed. Use AcceptSDK.isCompanionAppInstalled() to check, and AcceptSDK.presentCompanionAppSheet() to prompt installation if needed.

The SDK exposes payment methods through the AcceptSDK.payments object.

MethodDescriptionUse Case
startCardPaymentNFC Card ReaderContactless EMV payments.
startSepaPaymentSEPA InstantBank-to-bank transfers via QR code.
startCertisPaymentCertis PaymentsSpecialized instant payment network. For more information, see the official CERTIS documentation.

Example of starting a card payment:

import AcceptSDK, { Currency, CardPaymentIntent } from '@tapayadot/accept-react-native';

const paymentIntent: CardPaymentIntent = {
    paymentIntentId: Crypto.randomUUID(),
    amount: 10000, // 100.00 CZK
    requestedCurrency: Currency.CZK,
};

try {
    const result = await AcceptSDK.payments.startCardPayment(
        paymentIntent,
        (status) => {
            console.log("Payment Status Update:", status);
        },
        (message, exception) => {
            console.error("Payment Error:", message, exception);
        }
    );
    console.log("Payment Successful:", result);
} catch (error) {
    console.error("Payment Failed:", error);
}

Onboarding

Before processing payments, you may need to verify the merchant's status or collect additional information (KYC/KYB). The AcceptSDK.identity module manages these flows.

Onboarding

import AcceptSDK, { KybPrefillData } from '@tapayadot/accept-react-native';

// Launch onboarding UI
await AcceptSDK.identity.presentKyb();

// Optionally prefill known fields
const prefill: KybPrefillData = {
    businessType: 'company',
    countryCode: 'CZ',
    legalName: 'My Company s.r.o.',
    registrationNumber: '12345678',
};
await AcceptSDK.identity.presentKyb(prefill);

Permissions

Processing payments, especially contactless card payments, requires specific permissions (like Location).

const granted = await AcceptSDK.requestLocationPermission();

if (granted) {
    // Proceed with payment
} else {
    // Show rationale
}

Error Handling

The SDK returns errors through the error callback in payment methods. The error code is an enum AcceptSDKError.

Error CodeNameDescription
1UninitializedSDK is not initialized.
2ServiceStartingService is starting.
3ServiceInitializationService initialization failed.
4TokenInitializationErrorError initializing token.
5InitializationGeneral initialization error.
6LoginExpiredLogin session expired.
7InitializeWithoutDataInitialized without necessary data.
8LocationPermissionLocation permission missing.
9LocationDisabledLocation services disabled.
10NFCDisabledNFC is disabled.
11NotDebuggableApp is not debuggable.
12DebuggableNotDemoDebuggable app in non-demo mode.
13ReaderNotFoundCard reader not found.
14ReaderNotReadyYetReader is not ready.
15ReaderBadConnectionBad connection to reader.
16OfflineDevice is offline.
17InitializeTransactionTransaction initialization failed.
18FinalizeTransactionTransaction finalization failed.
19OperationTimeoutOperation timed out.
20PaymentNotFoundPayment not found.
21ServerErrorServer error occurred.
22ClientErrorClient error occurred.
23OnboardingOnboarding error.
24DuplicatedOnboardingOnboarding duplicated.
25MissingKYBDetailsMissing KYB details.
26LocationNotFoundLocation not found.
27LocationIdNotFoundLocation ID not found.
28UnknownUnknown error.
29UnknownMessageUnknown error message.
30CancellationOperation cancelled.

Other Operations

Get Status

Check the current status of the SDK.

const status = await AcceptSDK.getStatus();

Get Transaction Info

Retrieve information about a specific payment intent.

const result = await AcceptSDK.getPaymentStatus("payment_intent_id");

Log Out

Clear the current session.

await AcceptSDK.logOut();

On this page