# Integrace mobilního SDK (/cs/in-store/integration/sdk_integration)





Tapaya Accept SDK vkládá zpracování plateb kartou přímo do vaší aplikace. Je k dispozici pro &#x2A;*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 [#installation]

<CodeBlockTabs defaultValue="kotlin" groupId="accept-language">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="kotlin">
      Android (Kotlin)
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="typescript">
      React Native (TypeScript)
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="kotlin">
    ```kotlin title="build.gradle.kts"
    dependencies {
        implementation("com.tapaya:accept:1.15.0")
    }
    ```
  </CodeBlockTab>

  <CodeBlockTab value="typescript">
    ```json title="app.json"
    {
      "expo": {
        "plugins": ["@tapayadot/accept-react-native"]
      }
    }
    ```
  </CodeBlockTab>
</CodeBlockTabs>

**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 [#initialization]

`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 [#step-1-initialize]

<CodeBlockTabs defaultValue="kotlin" groupId="accept-language">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="kotlin">
      Android (Kotlin)
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="typescript">
      React Native (TypeScript)
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="kotlin">
    ```kotlin
    // 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)
    ```
  </CodeBlockTab>

  <CodeBlockTab value="typescript">
    ```typescript
    import Accept from '@tapayadot/accept-react-native';

    // Sandbox is the default
    Accept.initialize();

    // Target production explicitly
    Accept.initialize({ isProduction: true });

    // Or drive it from your build
    Accept.initialize({ isProduction: !__DEV__ });
    ```
  </CodeBlockTab>
</CodeBlockTabs>

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

### Krok 2: Autentizace [#step-2-authenticate]

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*.

<CodeBlockTabs defaultValue="kotlin" groupId="accept-language">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="kotlin">
      Android (Kotlin)
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="typescript">
      React Native (TypeScript)
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="kotlin">
    ```kotlin
    // 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
    }
    ```
  </CodeBlockTab>

  <CodeBlockTab value="typescript">
    ```typescript
    try {
        const sdkToken = await myBackendApi.getSdkToken();
        await Accept.auth.authenticate(sdkToken);
        // Accept.state is now 'authenticated'
    } catch (error) {
        // handle authentication failure
    }
    ```
  </CodeBlockTab>
</CodeBlockTabs>

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

<CodeBlockTabs defaultValue="kotlin" groupId="accept-language">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="kotlin">
      Android (Kotlin)
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="typescript">
      React Native (TypeScript)
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

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

  <CodeBlockTab value="typescript">
    ```typescript
    // Accept.state is a plain getter; subscribe for changes
    const subscription = Accept.addStateListener((state) => {
        if (state === 'authenticated') loadMerchant();
    });

    // later
    subscription.remove();
    ```
  </CodeBlockTab>
</CodeBlockTabs>

## Základní koncepty [#core-concepts]

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

| Rozhraní          | Účel                                                                                                 |
| :---------------- | :--------------------------------------------------------------------------------------------------- |
| `Accept.auth`     | Autentizace relace obchodníka.                                                                       |
| `Accept.merchant` | Profil obchodníka, konfigurace, stav onboardingu.                                                    |
| `Accept.payments` | Vytváření a správa plateb kartou.                                                                    |
| `Accept.plugin`   | Instalace a aktivace terminálu (pluginové aplikace).                                                 |
| `Accept.displays` | Informace o displejích zařízení pro oboustranné terminály („double-sided“).                          |
| `Accept.sdk`      | Verze SDK, prostředí, ID zařízení, minimální částky.                                                 |
| `Accept.state`    | Stav životního cyklu: `StateFlow<SdkState>` v Kotlinu, getter a `addStateListener()` v React Native. |

### Přijetí platby [#taking-a-payment]

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](./card_terminal#create-a-payment).

<Callout title="V React Native" type="info">
  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`.
</Callout>

<div className="bg-background relative h-auto w-full overflow-hidden rounded-lg border px-10">
    <img alt="Průběh platby" src="__img0" />
</div>

<CodeBlockTabs defaultValue="kotlin" groupId="accept-language">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="kotlin">
      Android (Kotlin)
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="typescript">
      React Native (TypeScript)
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="kotlin">
    ```kotlin
    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())
            }
        }
    ```
  </CodeBlockTab>

  <CodeBlockTab value="typescript">
    ```typescript
    const subscription = Accept.payments.pay(
        { amount: 15000, currency: 'CZK' }, // 150.00 Kč
        (event) => {
            switch (event.type) {
                case 'creating':
                    setStatus('Creating payment…');
                    break;
                case 'created':
                    // The payment token and receipt URL exist before the plugin is launched.
                    setReceiptUrl(event.receiptUrl);
                    break;
                case 'launched':
                    setStatus('Waiting for the card…');
                    break;
                case 'result':
                    setResult(event.payResult);
                    break;
                case 'creationFailed':
                    setError(event.error); // the payment never started
                    break;
            }
        },
    );

    // The stream ends itself after `result` or `creationFailed`.
    // Call subscription.remove() only to stop listening early.
    ```
  </CodeBlockTab>
</CodeBlockTabs>

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](./card_terminal#payment-outcome). 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) [#just-the-outcome-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.

```typescript
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 [#merchant--sdk-info]

`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 [#merchant]

<CodeBlockTabs defaultValue="kotlin" groupId="accept-language">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="kotlin">
      Android (Kotlin)
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="typescript">
      React Native (TypeScript)
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="kotlin">
    ```kotlin
    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
    ```
  </CodeBlockTab>

  <CodeBlockTab value="typescript">
    ```typescript
    const info = await Accept.merchant.info();                      // MerchantInformation | null
    const config = await Accept.merchant.config();                  // MerchantConfig
    const currencies = await Accept.merchant.availableCurrencies(); // string[]
    const status = await Accept.merchant.onboardingStatus();        // OnboardingStatus
    ```
  </CodeBlockTab>
</CodeBlockTabs>

| Člen                    | Vrací                  | Popis                                                                                                 |
| :---------------------- | :--------------------- | :---------------------------------------------------------------------------------------------------- |
| `info()`                | `MerchantInformation?` | Registrovaný firemní profil obchodníka. `null`, pokud profil zatím není k dispozici.                  |
| `config()`              | `MerchantConfig`       | Platební 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()`    | `OnboardingStatus`     | Zda 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ů](/merchants/onboarding).

### SDK [#sdk]

<CodeBlockTabs defaultValue="kotlin" groupId="accept-language">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="kotlin">
      Android (Kotlin)
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="typescript">
      React Native (TypeScript)
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="kotlin">
    ```kotlin
    Accept.sdk.version            // String, e.g. "1.15.0"
    Accept.sdk.isProduction       // Boolean
    Accept.sdk.deviceId()         // String?  (suspend)
    Accept.sdk.minimumAmounts()   // List<MinimumAmount>  (suspend)
    ```
  </CodeBlockTab>

  <CodeBlockTab value="typescript">
    ```typescript
    Accept.sdk.version                  // string, e.g. "1.15.0"
    Accept.sdk.isProduction             // boolean
    await Accept.sdk.deviceId()         // string | null
    await Accept.sdk.minimumAmounts()   // MinimumAmount[]
    ```
  </CodeBlockTab>
</CodeBlockTabs>

| Člen               | Vrací                 | Popis                                                                                                                                                                   |
| :----------------- | :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `version`          | `String`              | Verze SDK. Lze ji číst ještě před `initialize()`.                                                                                                                       |
| `isProduction`     | `Boolean`             | Zda `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 [#plugin-app]

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](./card_terminal#install-and-activate-the-terminal).

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í [#permissions]

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.

<CodeBlockTabs defaultValue="kotlin" groupId="accept-language">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="kotlin">
      Android (Kotlin)
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="typescript">
      React Native (TypeScript)
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="kotlin">
    ```kotlin
    class PaymentActivity : AppCompatActivity() {
        private val requestLocation = registerForActivityResult(
            ActivityResultContracts.RequestPermission()
        ) { granted ->
            if (granted) launchPaymentFlow() else showPermissionRationale()
        }

        fun startPayment() {
            requestLocation.launch(Manifest.permission.ACCESS_FINE_LOCATION)
        }
    }
    ```
  </CodeBlockTab>

  <CodeBlockTab value="typescript">
    ```typescript
    import { PermissionsAndroid } from 'react-native';

    const granted = await PermissionsAndroid.request(
        PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
    );

    if (granted === PermissionsAndroid.RESULTS.GRANTED) launchPaymentFlow();
    else showPermissionRationale();
    ```
  </CodeBlockTab>
</CodeBlockTabs>

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 [#error-handling]

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 [#exception-types]

| Výjimka                                            | Popis                                                                                                           |
| :------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------- |
| **Životní cyklus**                                 |                                                                                                                 |
| `NotInitialized`                                   | Volání vyžaduje předchozí `Accept.initialize()`.                                                                |
| `NotAuthenticated`                                 | Volání vyžaduje předchozí `Accept.auth.authenticate()`.                                                         |
| `SessionExpired`                                   | Platnost autentizované relace vypršela; znovu se autentizujte.                                                  |
| `UnknownEnvironment(key)`                          | Klíč prostředí nebyl rozpoznán (interní přetížení metody initialize).                                           |
| **Platby**                                         |                                                                                                                 |
| `PaymentInProgress`                                | Př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.                                                                     |
| `PaymentNotFound`                                  | Token pro `status()`/`cancel()`/`refund()` backend nezná.                                                       |
| **Poloha**                                         |                                                                                                                 |
| `LocationPermissionRequired`                       | Hostitelská aplikace nemá oprávnění k poloze.                                                                   |
| `LocationUnavailable`                              | Žádný poskytovatel nedokázal určit polohu.                                                                      |
| `LocationTimeout`                                  | Poloha nebyla určena včas.                                                                                      |
| **Plugin / terminál**                              |                                                                                                                 |
| `PluginUnavailable`                                | Pluginová aplikace není nainstalovaná nebo se nepodařilo připojit k její službě.                                |
| `PluginTimeout`                                    | Plugin neodpověděl včas.                                                                                        |
| `ActivationInProgress`                             | Předchozí `activateTerminal()` stále čeká na výsledek.                                                          |
| `NoTidsAvailableForMerchant`                       | Obchodníkovi nezbyl žádný nepřiřazený terminál (TID) k aktivaci.                                                |
| `PluginAlreadyAuthenticated`                       | Plugin je pro tohoto obchodníka již autentizován.                                                               |
| `PluginMerchantMismatch`                           | Plugin 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**                                         |                                                                                                                 |
| `NoInternetConnection`                             | Zařízení nemá připojení k síti.                                                                                 |
| `Unknown(cause)`                                   | Jakékoli selhání, které SDK nerozpozná jako vlastní.                                                            |

<Callout title="Výsledek vs. výjimka" type="info">
  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)`.
</Callout>

### Ošetření výjimek [#handling-exceptions]

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`.

<CodeBlockTabs defaultValue="kotlin" groupId="accept-language">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="kotlin">
      Android (Kotlin)
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="typescript">
      React Native (TypeScript)
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="kotlin">
    ```kotlin
    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}")
    }
    ```
  </CodeBlockTab>

  <CodeBlockTab value="typescript">
    ```typescript
    import Accept, { AcceptError } from '@tapayadot/accept-react-native';

    try {
        const status = await Accept.payments.status(paymentToken);
    } catch (error) {
        if (!AcceptError.is(error)) throw error;

        switch (error.code) {
            case 'SessionExpired':
                // Re-authenticate
                break;
            case 'NoInternetConnection':
                // Ask the user to check connectivity
                break;
            case 'AmountBelowMinimum':
                // Payload fields sit on the error itself
                alert(`Minimum is ${error.minimum} ${error.currency}`);
                break;
            default:
                throw error;
        }
    }
    ```
  </CodeBlockTab>
</CodeBlockTabs>

### Logování [#logging]

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

<CodeBlockTabs defaultValue="kotlin" groupId="accept-language">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="kotlin">
      Android (Kotlin)
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="typescript">
      React Native (TypeScript)
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="kotlin">
    ```kotlin
    Accept.setDebugLoggingEnabled(true)
    ```
  </CodeBlockTab>

  <CodeBlockTab value="typescript">
    ```typescript
    Accept.setDebugLoggingEnabled(true);
    ```
  </CodeBlockTab>
</CodeBlockTabs>

### Odhlášení [#logging-out]

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()`.

<CodeBlockTabs defaultValue="kotlin" groupId="accept-language">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="kotlin">
      Android (Kotlin)
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="typescript">
      React Native (TypeScript)
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="kotlin">
    ```kotlin
    Accept.plugin.logout() // suspend; signs out of the Tapaya Terminal app
    Accept.clear()         // suspend; clears local SDK state
    ```
  </CodeBlockTab>

  <CodeBlockTab value="typescript">
    ```typescript
    await Accept.plugin.logout(); // signs out of the Tapaya Terminal app
    await Accept.clear();         // clears local SDK state
    ```
  </CodeBlockTab>
</CodeBlockTabs>
