Android

Overview

The Telr Mobile Payment SDK for Android is a comprehensive payment solution that enables merchants to accept payments seamlessly within their Android applications. Built with modern Android components (Kotlin, Activities, ViewModel, LiveData, and Material 3), it provides a clean, secure, and customizable payment experience.

Key Features

  • Multiple Payment Methods: Credit/Debit Cards; Apple Pay routes are modeled in API but not available on Android devices
  • 3D Secure Support: Built‑in 3DS authentication flow
  • Saved Cards: Tokenization and saved card payments (when enabled by order)
  • Modern UI: Material components with light/dark themes
  • Internationalization: Multi‑language support (English, Arabic)
  • Security: Token‑based authentication and secure network stack
  • Accessibility: Compatible with Android accessibility features

Requirements

  • Android minSdk 21+
  • Target/Compile SDK 34
  • Kotlin 1.9+
  • Gradle Android Plugin 8+
  • Your backend must return two URLs taken directly from the createOrder API response:
    • tokenUrl — value of _links.auth.href
    • orderUrl — value of _links.self.href

Installation

Gradle (Recommended)

Add the dependency from Maven Central (group and artifact):

// In your app module build.gradle.kts
dependencies {
    implementation("com.telr.android:payment-sdk:4.4.1")
}

If using Groovy:

dependencies {
    implementation 'com.telr.android:payment-sdk:4.4.1'
}

Ensure Maven Central is in your repositories (usually already present):

repositories {
    mavenCentral()
}

Manifest and Permissions

The SDK requires network permissions. If your app doesn’t already declare them, add to your app AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

The SDK internally defines required activities. No additional <activity> entries are required in your app manifest.

Quick Start

Basic Implementation

Initialize the SDK once from a ComponentActivity, then launch the payment flow with your token and order URLs. The SDK now registers an Activity Result launcher on demand, so the activity you pass to launchPaymentActivity just needs to be in the foreground—no persistent launcher to keep around.

import androidx.activity.ComponentActivity
import com.telr.android.payment.sdk.Core
import com.telr.android.payment.sdk.data.sdk.PaymentRequest
import com.telr.android.payment.sdk.data.sdk.PaymentStatus

class CheckoutActivity : ComponentActivity() {
    override fun onStart() {
        super.onStart()
        val initResult = Core.getInstance().init(this)
        // Optionally handle initResult.sdkError
    }

    private fun startPayment(tokenUrl: String, orderUrl: String) {
        Core.getInstance().launchPaymentActivity(
            this,
            PaymentRequest(
                tokenUrl = tokenUrl,
                orderUrl = orderUrl
            )
        ) { result ->
            when (result.paymentStatus) {
                PaymentStatus.SUCCESS -> handleSuccess()
                PaymentStatus.PENDING -> handlePending(result.sdkError?.description)
                PaymentStatus.FAILURE -> handleFailure(result.sdkError?.description)
                PaymentStatus.CANCELLED -> handleCancelled(result.sdkError?.code)
            }
        }
    }
}

Sample Flow

  • Your backend creates an order and returns tokenUrl and orderUrl to your app.
  • Call Core.init(activity) once per ComponentActivity (e.g., in onCreate).
  • Whenever you need to start checkout, call Core.launchPaymentActivity(activity, PaymentRequest(tokenUrl, orderUrl)). A fresh Activity Result launcher is registered against that activity and automatically cleaned up.
  • Receive SDKResult in the callback on completion/cancel/failure.

Configuration

The Android SDK is intentionally minimal in required configuration. It automatically sets up networking and user‑agent headers. You should:

  • Call Core.getInstance().init(activity) from a ComponentActivity prior to launching any payment UI.
  • Provide valid server endpoints for tokenUrl and orderUrl.

Build variants expose a BuildConfig.DEBUG_MODE flag for internal logging behavior. For custom logging, hook into the result callback and your app’s own logger.

Custom Colors (Theming)

You can theme the SDK's payment UI to match your brand by passing SDKColorConfig at init via .withColors(...). Provide light and/or dark variants; each color is an optional hex string ("#RRGGBB" or "#AARRGGBB").

import com.telr.android.payment.sdk.data.sdk.SDKColorConfig
import com.telr.android.payment.sdk.data.sdk.SDKColors

val colors = SDKColorConfig(
    light = SDKColors(
        primary = "#0057FF",              // Pay button, selected tick, checkbox, links, back chevron
        background = "#FFFFFF",           // payment sheet / surface background
        textLabel = "#101828",            // primary text (merchant name, amount, method names, card details)
        border = "#E4E7EC",               // field/card outlines, dividers
        buttonText = "#FFFFFF",           // text drawn on the Pay button
        textFieldText = "#101828",        // text the user types into inputs
        textFieldBackground = "#F2F4F7"   // input field fill
    ),
    dark = SDKColors(
        primary = "#4C8DFF",
        background = "#101828",
        textLabel = "#F2F4F7",
        border = "#344054",
        buttonText = "#FFFFFF",
        textFieldText = "#F2F4F7",
        textFieldBackground = "#1D2939"
    )
)

val config = PaymentSDKConfiguration.builder()
    .withColors(colors)
    .build()

Core.getInstance().init(this, config)

Color tokens

TokenApplies to
primaryPay button fill, selected radio tick, save-card checkbox, links, back chevron
backgroundPayment sheet / surface background
textLabelPrimary text: merchant name, amount, method names, masked card details
borderInput-field & card-row outlines, dividers
buttonTextText drawn on the Pay button
textFieldTextText the user types into input fields (also derives placeholder & field icons at reduced opacity)
textFieldBackgroundInput-field fill

Two secondary tones are derived automatically (no separate keys): muted text (expiry on card rows, section labels, card/delete icons) is textLabel at reduced opacity, and placeholder/hint text is textFieldText at reduced opacity — so they always belong to your palette.

Precedence
Colors resolve per token as: init colors (withColors) → store colors from the Telr backend → SDK default. Any token you leave null falls through to the next source. If you don't call .withColors(...) at all, the SDK uses your store-configured colors, then its built-in defaults.

📘

Provide both light and dark if you want full control in both system themes — store colors are applied per-mode and do not cross-fill between modes.

Payment Methods

Supported Payment Methods

Payment method availability is determined by the order returned from your backend:

  1. Credit/Debit Cards
    • Visa, Mastercard, American Express (and others where enabled)
    • 3D Secure authentication
    • Saved card payments (tokenized)
  2. Apple Pay
    • Represented in API models but not available to initiate natively on Android devices.
  3. Google Pay
    • When enabled by your backend and available on the user device, the SDK shows a Google Pay button and handles the payment flow. See "Google Pay (Android)" below for details.
  4. Samsung Pay (Network Token)
    • When enabled by your backend and available on the user device, the SDK shows a Samsung Pay option and handles token generation and posting to your backend. See "Samsung Pay (Android)" below for details.
  5. Tabby (Buy Now Pay Later)
    • Shown when your order enables allowedPaymentMethods.type = TABBY and the required links/fields are present.
    • The SDK handles Tabby redirect/return flow inside the checkout experience.
  6. Tamara (Buy Now Pay Later)
    • Shown when your order enables allowedPaymentMethods.type = TAMARA and the required links/fields are present.
    • The SDK handles Tamara redirect/return flow inside the checkout experience.
  7. STC Bank
    • Shown when your order enables allowedPaymentMethods.type = STC_BANK and the required links/fields are present.
    • The SDK handles STC Bank form collection and submit flow through the order links.
  8. Click to Pay
    • Shown when your order enables allowedPaymentMethods.type = CLICK_TO_PAY (or order._links.clicktopay.href is present).
    • No SDK configuration or merchant registration required. dpaId, acquirer config, and locale come from the order response — Telr's backend owns the network registration.
    • The SDK handles consumer recognition, email entry, OTP authentication, saved-card listing, manual card entry, the network DCF challenge UI, and 3DS internally.
    • Recognition tokens are persisted on-device per dpaId so returning users skip the email/OTP step on the next session.

Google Pay (Android)

Google Pay is supported via the Google Pay API for Android.

Prerequisites

  • A Google Pay merchant account registered in the Google Pay & Wallet Console.
  • Your backend must return an order where order._links.googlePay.href is present.
  • The user's device must have Google Play Services with a card provisioned in Google Wallet.

SDK configuration

Initialize the SDK with Google Pay parameters (typically on app start):

import com.telr.android.payment.sdk.Core
import com.telr.android.payment.sdk.runtime.PaymentSDKConfiguration

val config = PaymentSDKConfiguration.builder()
    .withPreferredLanguageCode("en")
    .withDebugLoggingEnabled(BuildConfig.DEBUG)
    .withGooglePayGatewayMerchantId("<YOUR_GATEWAY_MERCHANT_ID>")
    .withGooglePayMerchantId("<YOUR_GOOGLE_MERCHANT_ID>") // from Google Pay & Wallet Console
    .build()

Core.getInstance().init(this, config)

Visibility and gating

The SDK shows the Google Pay button only when:

  • Backend gating: order._links.googlePay?.href exists and is not blank.
  • Device gating: Google Pay isReadyToPay returns true on the device.

No additional UI code is required; the button appears in the Payment Options screen when both gates pass.

Server interaction

On successful Google Pay authentication, the SDK posts the paymentMethodData to your backend using the order._links.googlePay.href link from the order:

{
  "paymentToken": {
    "type": "CARD",
    "info": { ... },
    "tokenizationData": { ... }
  }
}

Your backend should process this according to the Telr Google Pay payment flow and update the order status accordingly.

📘

If customer details (name, phone, address) are not provided when creating the order, the SDK will request billing address from Google Pay automatically. The billing address is included inside paymentToken.info.billingAddress.

Dedicated method (your own button)

If you want to show your own Google Pay button instead of the SDK's payment-options screen, call launchGooglePayPayment. The SDK owns the whole Google Pay session (sheet, tokenization, backend post) and returns only the final SDKResult — with orderRef and /code populated for server-side verification. No SDK payment UI is shown.

val paymentRequest = PaymentRequest(tokenUrl = checkoutTokenUrl, orderUrl = checkoutOrderUrl)

Core.getInstance().launchGooglePayPayment(this, paymentRequest) { result ->
    when (result.paymentStatus) {
        PaymentStatus.SUCCESS -> {
            // result.orderRef, result.transactionRef
        }
        PaymentStatus.CANCELLED -> { /* user dismissed Google Pay */ }
        else -> { /* result.sdkError?.description */ }
    }
}

context must be a ComponentActivity (the SDK registers an activity-result launcher for the Google Pay IntentSender). Requires googlePayGatewayMerchantId configured and an order with a Google Pay link; readiness is validated internally.

For the button itself, use Google's official com.google.android.gms.wallet.button.PayButton (from play-services-wallet) and call launchGooglePayPayment

Samsung Pay (Android)

Samsung Pay is supported in Network Token mode via Samsung Wallet.

Prerequisites

  • Register as a Samsung Pay partner at the Samsung Pay Developers portal and obtain a Service ID. Samsung registers the Service ID against your app's package name and signing certificate SHA-256 — debug and release builds have different SHAs, so register both (or use separate sandbox / production Service IDs).
  • Ensure Samsung Wallet is installed and provisioned with a card on the device. The SDK only shows Samsung Pay when the device reports SPAY_READY.
  • Your backend must return an order where order._links.samsungPay.href is present.
  • Samsung Pay is region-locked; availability depends on the device's country.

SDK configuration

Initialize the SDK with Samsung Pay parameters (typically on app start):

import com.telr.android.payment.sdk.Core
import com.telr.android.payment.sdk.runtime.PaymentSDKConfiguration

val config = PaymentSDKConfiguration.builder()
    .withPreferredLanguageCode("en")
    .withDebugLoggingEnabled(BuildConfig.DEBUG)
    .withSamsungPayServiceId("<YOUR_SERVICE_ID>")
    .withSamsungPayMerchantId(null) // optional
    .build()

Core.getInstance().init(this, config)

Required AndroidManifest meta-data

When enabling Samsung Pay, your app must declare the following meta-data entries under the tag in your app's AndroidManifest.xml:

<application
    ...>
    <!-- Samsung Pay SDK requirements -->
    <meta-data android:name="spay_sdk_api_level" android:value="2.22" />
    <!-- Production builds must use "N". Set to "Y" only for local development. -->
    <meta-data android:name="debug_mode" android:value="N" />
    ...
</application>
📘

Use spay_sdk_api_level="2.22" exactly — this matches the Samsung Pay SDK bundled inside the Telr SDK. If a future Telr SDK release upgrades it, this value will be updated here.

Common reasons Samsung Pay does not appear

  • App not registered with Samsung against your package name + signing SHA-256 — the most common cause. Debug and release builds have different SHAs. Use a sandbox Service ID with the debug-keystore SHA and a production Service ID with the release-keystore SHA, or register both SHAs against one Service ID.
  • Device is not Samsung, or Samsung Wallet has no provisioned card — the SDK reports SPAY_NOT_READY and hides the option.
  • Backend did not return order._links.samsungPay.href — confirm with your Telr account manager that Samsung Pay is enabled for your merchant account.
  • Country / region not supported — Samsung Pay is region-locked. The device must be in a supported country.
  • Manifest meta-data missing or wrong versionspay_sdk_api_level must match the value documented above. Filter logcat for SamsungPayRequirements to see validation warnings emitted by the SDK.
    • debug_mode must be N in production. Set to Y only in development builds — shipping Y to production causes Samsung Pay to behave unpredictably. Guard via build variants if needed.
    • Also configure serviceId and optional merchantId via PaymentSDKConfiguration.

      If these entries are missing, the Samsung Pay SDK may throw an exception when reading application meta-data. The Telr SDK guards against crashes and hides Samsung Pay when misconfigured, but we strongly recommend adding the entries above to avoid runtime issues and enable full functionality.

Visibility and gating

The SDK shows the Samsung Pay option only when:

  • Backend gating: order._links.samsungPay?.href exists and is not blank.
  • Device gating: Samsung Wallet status is SPAY_READY on the device.

No additional UI code is required; the option appears in the Payment Options screen when both gates pass.

Server interaction

On successful Samsung Pay authentication, the SDK posts the paymentCredential to your backend using the order._links.samsungPay.href link from the order:

{
  "paymentToken": {
    "encryptedMessage": "<paymentCredential>"
  }
}

Your backend should process this according to your gateway’s Network Token flow and update the order status accordingly.

Dedicated method (your own button)

If you want to show your own Samsung Pay button instead of the SDK's payment-options screen, call launchSamsungPayPayment. The SDK owns the Samsung Pay session (custom sheet, credential post) and returns only the final SDKResult — with orderRef and transactionRef populated. No SDK payment UI is shown.

val paymentRequest = PaymentRequest(tokenUrl = checkoutTokenUrl, orderUrl = checkoutOrderUrl)

Core.getInstance().launchSamsungPayPayment(this, paymentRequest) { result ->
    when (result.paymentStatus) {
        PaymentStatus.SUCCESS -> {
            // result.orderRef, result.transactionRef
        }
        PaymentStatus.CANCELLED -> { /* user cancelled Samsung Pay */ }
        else -> { /* result.sdkError?.description */ }
    }
}

Requires samsungPayServiceId configured, the manifest meta-data described above, and an order with a Samsung Pay link; device readiness (SPAY_READY) is validated internally.

Samsung does not provide a button widget — use the Samsung Pay branded button image (per Samsung's brand guidelines) in an ImageView and call launchSamsungPayPayment from its click listener; see MerchantCheckoutActivity in the sample app.

📘

Merchant name is derived automatically from the order (order.store?.name) and defaults to an empty string when not present. When consuming the SDK from Maven, no extra Samsung SDK setup is required in your app. When building from this repository, the Samsung Pay SDK JAR is already bundled within the SDK module.

3D Secure Authentication

  • Automatic 3DS challenge handling via an internal activity.
  • Seamless return to your app with SDKResult.

Add Card Flow

Use launchAddCardActivity when you want to verify and save a new card (without immediate checkout capture).

Merchant-side flow

  1. Merchant backend creates a VERIFY order.

  2. Merchant backend returns tokenUrl + orderUrl to the app.

  3. App opens SDK add-card sheet with those URLs.

  4. SDK handles card entry, 3DS, and completion callback.

  5. On success callback, app stores the saved card details and payment reference for future use.

Example

import com.telr.android.payment.sdk.Core
import com.telr.android.payment.sdk.data.sdk.PaymentRequest
import com.telr.android.payment.sdk.data.sdk.SDKAddCardResult

val paymentRequest = PaymentRequest(
    tokenUrl = addCardTokenUrl,
    orderUrl = addCardOrderUrl
)

Core.getInstance().launchAddCardActivity(this, paymentRequest) { result ->
    when (result.paymentStatus) {
        PaymentStatus.SUCCESS -> {
            // result.ref — payment reference from the VERIFY transaction (store for saved-card payments)
            // result.maskedName — masked cardholder name (store for SDKSavedCardInput)
            // result.savedCards — list of saved card details (token, maskedCard, expiry, scheme)
            val cards = result.savedCards
            val paymentRef = result.ref
        }
        PaymentStatus.CANCELLED -> { /* user cancelled */ }
        PaymentStatus.PENDING -> { /* order status being confirmed */ }
        PaymentStatus.FAILURE -> {
            // result.message contains the error description
            // result.errorCode contains the SDK error code (nullable)
        }
    }
}

SDKAddCardResult

@Parcelize
data class SDKAddCardResult(
    val paymentStatus: PaymentStatus,
    val message: String,
    val errorCode: String? = null,
    val ref: String? = null,             // payment reference for CONT transactions
    val savedCards: List<SDKSavedCardInput>? = null,
    val maskedName: String? = null       // e.g. "J*** D**"
) : Parcelable

Pay with Saved Card Flow

UselaunchSavedCardPaymentActivitywhen a customer selects a saved card and CVV re-entry and/or 3DS is required (typically for higher-value transactions per your risk policy).

📘

For low-value or recurring transactions, your backend can process the saved card silently usingclass: CONTwith the payment reference from the add-card flow — no CVV or user interaction needed. UselaunchSavedCardPaymentActivity(ECOM) when your risk policy requires CVV re-entry or 3DS authentication.

Merchant-side flow

  1. Merchant backend creates a SALE order.

  2. Merchant backend returns tokenUrl + orderUrl to the app.

  3. App opens the SDK saved-card sheet with those URLs and the saved card details.

  4. SDK displays the masked card (read-only) and prompts for CVV only.

  5. SDK handles payment, 3DS, and calls the completion callback.

Example

import com.telr.android.payment.sdk.Core
import com.telr.android.payment.sdk.data.sdk.SDKSavedCardInput
import com.telr.android.payment.sdk.data.sdk.SavedCardPaymentLaunchRequest
import com.telr.android.payment.sdk.data.sdk.PaymentStatus

val savedCard = SDKSavedCardInput(
    token = "card_token_here",
    maskedCard = "**** 1111",     // from add-card flow
    expiry = "12/30",
    scheme = "VISA",
    maskedName = "J*** D**"       // optional, shown on the sheet
)

val launchRequest = SavedCardPaymentLaunchRequest(
    tokenUrl = checkoutTokenUrl,
    orderUrl = checkoutOrderUrl,
    savedCard = savedCard
)

Core.getInstance().launchSavedCardPaymentActivity(this, launchRequest) { result ->
    when (result.paymentStatus) {
        PaymentStatus.SUCCESS -> handleSuccess()
        PaymentStatus.CANCELLED -> handleCancelled()
        else -> handleFailure(result.sdkError?.description)
    }
}

SDKSavedCardInput

@Parcelize
data class SDKSavedCardInput(
    val token: String,           // card token from add-card flow
    val maskedCard: String,      // e.g. "**** 1111"
    val expiry: String,          // e.g. "12/30"
    val scheme: String,          // e.g. "VISA"
    val maskedName: String? = null // optional, e.g. "J*** D**"
) : Parcelable

SavedCardPaymentLaunchRequest

@Parcelize
data class SavedCardPaymentLaunchRequest(
    val tokenUrl: String,
    val orderUrl: String,
    val savedCard: SDKSavedCardInput
) : Parcelable

Pay with Card Flow

Use launchPayWithCardActivity when you want to collect card details and process an immediate payment (e.g., gift card purchases). If the order supports saving cards, the sheet shows an optional "Save my card details" checkbox; when the user opts in, the card is saved and the result returns a savedCard reference you can reuse later via launchSavedCardPaymentActivity.

Merchant-side flow

  1. Merchant backend creates a SALE order.

  2. Merchant backend returns tokenUrl + orderUrl to the app.

  3. App opens SDK pay-with-card sheet with those URLs.

  4. SDK handles card entry, BIN lookup (including international card blocking), 3DS, and completion callback.

  5. On success callback, the payment is complete. If the user opted to save the card, result.savedCard contains the saved-card reference; persist it (in your DB) to reuse via launchSavedCardPaymentActivity.

Example

import com.telr.android.payment.sdk.Core
import com.telr.android.payment.sdk.data.sdk.PaymentRequest
import com.telr.android.payment.sdk.data.sdk.PaymentStatus

val paymentRequest = PaymentRequest(
    tokenUrl = checkoutTokenUrl,
    orderUrl = checkoutOrderUrl
)

Core.getInstance().launchPayWithCardActivity(this, paymentRequest) { result ->
    when (result.paymentStatus) {
        PaymentStatus.SUCCESS -> {
            // result.orderRef / result.transactionRef — references for reconciliation
            // result.savedCard — non-null if the user ticked "Save my card details";
            //   store it to reuse the card via launchSavedCardPaymentActivity
            handleSuccess()
        }
        PaymentStatus.CANCELLED -> handleCancelled()
        else -> handleFailure(result.sdkError?.description)
    }
}

Error Handling

SDK Result

Results are delivered via the callback from launchPaymentActivity:

import com.telr.android.payment.sdk.data.sdk.SDKResult
import com.telr.android.payment.sdk.data.sdk.PaymentStatus

// SDKResult(paymentStatus: PaymentStatus, sdkError: SDKError?)
  • PaymentStatus.SUCCESS
  • PaymentStatus.PENDING
  • PaymentStatus.FAILURE
  • PaymentStatus.CANCELLED

SDK Errors

Common error codes returned in SDKResult.sdkError:

  • E001: Context must be a ComponentActivity
  • E002: Unable to register for Activity Result (init must run on app load)
  • E003: SDK not initialised (call Core.init() first)
  • E004: Unable to fetch result from Payment Intent
  • E005: Missing/invalid auth/order parameters
  • E006: Authentication failed/expired
  • E007: Fetch order failed (invalid order or node)
  • E008: Make payment API failed or session expired
  • E009: Unable to get 3DS validation status
  • E010: Unable to get 3DS URL
  • E011: Samsung Pay payment failed
  • E012: Payment declined/failed
  • E013: Unable to delete saved card
  • E014: 3DS verification cancelled
  • E015: Payment was cancelled by user
  • E016: Unable to confirm payment
  • E017: Order status is being confirmed
  • E018: Google Pay payment failed

Handle errors by showing user‑friendly messages and optionally retrying where appropriate.

Internationalization

  • The SDK UI strings include English; Arabic is supported for RTL layout alignment when configured by your app’s locale.
  • The SDK follows the host app locale and supports RTL mirroring.

Troubleshooting

Common Issues

  1. Core.init() returns FAILED

    • Ensure you pass a ComponentActivity instance
    • Call init before launching payment
  2. Network or Timeout errors

    • Verify tokenUrl and orderUrl
    • Check device connectivity and SSL configuration
  3. Payment not processing

    • Confirm your backend endpoints return valid token/order responses
    • Ensure the order links include allowed operations and methods
  4. 3DS challenge not returning

    • Check if the device can reach the ACS URL
    • Verify threeDs links in the order are valid

Debugging Tips

  • Log the SDKResult and sdkError for diagnostics.
  • Use your app’s network logger or proxy to inspect traffic to your backend.

API Reference

Core

object Core {
    fun getInstance(): Core
    fun init(context: Context): SDKInitResult // context must be a ComponentActivity
    fun init(context: Context, configuration: PaymentSDKConfiguration): SDKInitResult
    fun launchPaymentActivity(
        context: Context,
        paymentRequest: PaymentRequest,
        callback: (SDKResult) -> Unit
    )
    fun launchAddCardActivity(
        context: Context,
        paymentRequest: PaymentRequest,
        callback: (SDKAddCardResult) -> Unit
    )
    fun launchPayWithCardActivity(
        context: Context,
        paymentRequest: PaymentRequest,
        callback: (SDKResult) -> Unit
    )
    fun launchSavedCardPaymentActivity(
        context: Context,
        request: SavedCardPaymentLaunchRequest,
        callback: (SDKResult) -> Unit
    )
    // Merchant-owned wallet buttons: run the wallet with no SDK payment UI.
    // orderRef/transactionRef populated on success.
    fun launchGooglePayPayment(
        context: Context,
        paymentRequest: PaymentRequest,
        callback: (SDKResult) -> Unit
    )
    fun launchSamsungPayPayment(
        context: Context,
        paymentRequest: PaymentRequest,
        callback: (SDKResult) -> Unit
    )
}

PaymentRequest

@Parcelize
data class PaymentRequest(
    val tokenUrl: String,
    val orderUrl: String
) : Parcelable

SDKColorConfig / SDKColors

@Parcelize
data class SDKColorConfig(
    val light: SDKColors? = null,
    val dark: SDKColors? = null
) : Parcelable

@Parcelize
data class SDKColors(
    val primary: String? = null,             // Pay button, selected tick, checkbox, links, back chevron
    val background: String? = null,          // payment sheet background
    val textLabel: String? = null,           // primary text
    val border: String? = null,              // field/card outlines, dividers
    val buttonText: String? = null,          // text on the Pay button
    val textFieldText: String? = null,       // text typed into inputs (also derives placeholder/hint)
    val textFieldBackground: String? = null  // input field fill
) : Parcelable

Pass via PaymentSDKConfiguration.builder().withColors(SDKColorConfig(...)). See Custom Colors (Theming).

SDKInitResult

enum class InitStatus { SUCCESS, FAILED }

data class SDKInitResult(
    val initStatus: InitStatus,
    val sdkError: SDKError? = null
)

SDKResult

@Parcelize
data class SDKResult(
    val paymentStatus: PaymentStatus,
    val sdkError: SDKError?,
    val orderRef: String? = null,             // Telr order reference (on success)
    val transactionRef: String? = null,       // transaction/payment reference (on success)
    val savedCard: SDKSavedCardInput? = null  // set when the user opts to save the card during pay-with-card
) : Parcelable
)

PaymentStatus

enum class PaymentStatus { SUCCESS, PENDING, FAILURE, CANCELLED }

Order and Amount (server response models)

data class Amount(val value: Double, val currency: String)

enum class OrderStatus { PENDING, AUTHORISED, PAID, CANCELLED, DECLINED }

Additional models include allowed payment methods, links, and 3DS details.