Overview
Bring secure Telr payments to your React Native app fast. Our plug-in launches the checkout flow, manages the payment steps behind the scenes, and returns a clear success or failure result, so your team ships quicker and supports less.
Requirements
- React Native ≥ 0.75
- iOS: iOS 14+, Xcode 15+, Swift 5.9+
- Android: minSdk 24+, targetSdk 34, Kotlin 1.9+
- 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
Install the package in your React Native app:
npm install @telrsdk/rn-telr-sdk
# or
yarn add @telrsdk/rn-telr-sdkPlatform Setup
iOS
- Ensure your
ios/Podfiletargets iOS 15.1 or newer and has New Architecture enabled for the best performance.
Minimal example:
platform :ios, '15.1'
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
target 'YourApp' do
config = use_native_modules!
use_react_native!(
:path => config[:reactNativePath],
:new_arch_enabled => true
)
use_frameworks! :linkage => :static
end- Install pods with New Architecture enabled:
cd ios && RCT_NEW_ARCH_ENABLED=1 pod installIf CocoaPods cannot find the TelrSDK pod, make sure you have access to Telr's podspec source as provided by Telr and that your Podfile declares the appropriate source entries. Then run pod repo update and re-install.
Android
No additional setup required
Usage
import TelrPayments, {
TelrInitResult,
TelrResult,
TelrStatus,
ConfigureOptions,
} from '@telrsdk/rn-telr-sdk';
async function checkout() {
// 1) Initialize
const init: TelrInitResult = await TelrPayments.initialize();
if (!init.success) {
// Show a friendly message; you may allow retry
console.warn('Telr SDK initialization failed', init.error);
return;
}
// 2) Fetch tokenUrl/orderUrl from your backend
const { tokenUrl, orderUrl } = await fetch('/api/checkout')
.then(r => r.json());
// 3) Present native payment UI
const result: TelrResult = await TelrPayments.presentPayment({
tokenUrl,
orderUrl,
});
// 4) Handle result
switch (result.status) {
case TelrStatus.Succeeded:
// Optional: submit transactionId or metadata to your backend
console.log('Payment successful');
break;
case TelrStatus.Canceled:
console.log('Payment canceled by user');
break;
case TelrStatus.Failed:
console.log('Payment failed', result.errorCode, result.message);
break;
}
}
API Reference
presentPayment(tokenURL: string, orderURL: string): Promise<PaymentResponse>- Presents the Telr payment UI modally (full screen) on iOS.
- Resolves with
{ success: boolean; message: string }when the flow completes.
Types
type PaymentResponse = { success: boolean; message: string };Notes
- The payment view is presented full-screen using UIKit/SwiftUI under the hood and dismissed automatically when a result is available.
- Make sure your
tokenURLandorderURLare accessible from the device/simulator and use HTTPS.
Troubleshooting
-
TurboModule 'TelrSDK' is null or undefined
- Ensure New Architecture is enabled (
:new_arch_enabled => truein Podfile, orRCT_NEW_ARCH_ENABLED=1when installing pods) and re-runpod install.
- Ensure New Architecture is enabled (
-
CocoaPods cannot find
TelrSDK- Ensure your Podfile includes Telr's private spec repo or the correct pod source as provided by Telr, then run
pod repo updateandpod install.
- Ensure your Podfile includes Telr's private spec repo or the correct pod source as provided by Telr, then run
-
Build fails due to iOS version
- Ensure your app targets
platform :ios, '15.1'or newer.
- Ensure your app targets
Add Card Flow
Use launchAddCardActivity when you want to verify and save a new card (without immediate checkout capture).
Merchant-side flow
-
Merchant backend creates a VERIFY order.
-
Merchant backend returns
tokenUrl+orderUrlto the app. -
App opens SDK add-card sheet with those URLs.
-
SDK handles card entry, 3DS, and completion callback.
-
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 using
class: 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
-
Merchant backend creates a SALE order.
-
Merchant backend returns tokenUrl + orderUrl to the app.
-
App opens the SDK saved-card sheet with those URLs and the saved card details.
-
SDK displays the masked card (read-only) and prompts for CVV only.
-
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
UselaunchPayWithCardActivitywhen you want to collect card details and process an immediate payment (e.g., gift card purchases) without saving the card.
Merchant-side flow
-
Merchant backend creates a SALE order.
-
Merchant backend returns tokenUrl + orderUrl to the app.
-
App opens SDK pay-with-card sheet with those URLs.
-
SDK handles card entry, BIN lookup (including international card blocking), 3DS, and completion callback.
-
On success callback, the payment is complete.
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 -> 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.SUCCESSPaymentStatus.FAILUREPaymentStatus.CANCELLED
SDK Errors
Common error codes returned in SDKResult.sdkError:
E001: Context must be aComponentActivityE002: Unable to register for Activity Result (init must run on app load)E003: SDK not initialised (callCore.init()first)E004: Unable to fetch result from Payment IntentE005: Missing/invalid auth/order parametersE006: Authentication failed/expiredE007: Fetch order failed (invalid order or node)E008: Make payment API failed or session expiredE009: Unable to get 3DS validation statusE010: Unable to get 3DS URL
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
-
Core.init()returns FAILED- Ensure you pass a
ComponentActivityinstance - Call
initbefore launching payment
- Ensure you pass a
-
Network or Timeout errors
- Verify
tokenUrlandorderUrl - Check device connectivity and SSL configuration
- Verify
-
Payment not processing
- Confirm your backend endpoints return valid token/order responses
- Ensure the order links include allowed operations and methods
-
3DS challenge not returning
- Check if the device can reach the ACS URL
- Verify
threeDslinks in the order are valid
Debugging Tips
- Log the
SDKResultandsdkErrorfor 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 launchPaymentActivity(
context: Context,
paymentRequest: PaymentRequest,
callback: (SDKResult) -> Unit
)
}PaymentRequest
@Parcelize
data class PaymentRequest(
val tokenUrl: String,
val orderUrl: String
) : ParcelableSDKInitResult
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?
) : ParcelablePaymentStatus
enum class PaymentStatus { SUCCESS, 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.