Telr Flutter Payments SDK
Accept Telr payments in your Flutter app with a single call. The SDK presents the Telr checkout, handles the flow, and returns a clear success/failure result.
Requirements
- Flutter: ≥ 3.19 (Dart ≥ 3)
- iOS: ≥ 15.1
- Android: minSdk ≥ 21, targetSdk ≥ 34
- Backend: HTTPS
tokenURLandorderURL
Install
Add to pubspec.yaml and fetch:
dependencies:
telr_mobile_payment_sdk: ^4.4.0
flutter pub get
Updating the plugin version
- Update the version in
pubspec.yamland run:
flutter clean
flutter pub get
- For iOS, update pods to the latest TelrSDK:
cd ios
pod deintegrate
pod install --repo-update
pod update TelrSDK
iOS setup
- Set minimum iOS in
ios/Podfileand enable static frameworks:
platform :ios, '15.1'
target 'Runner' do
use_frameworks! :linkage => :static
end
- Install pods:
cd ios && pod install
- If CocoaPods cannot find
TelrSDK, runpod repo updatethen re-install. TheTelrSDKpod is published from github.com/Telr-PG/telr-sdk-ios and resolves via the standard CocoaPods CDN.
Android setup
- Ensure repositories in
android/settings.gradle:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
- Set SDK versions in
android/app/build.gradle:
android {
compileSdkVersion 34
defaultConfig {
minSdkVersion 21
targetSdkVersion 34
}
}
- Optional: initialize on app load (configure language / wallet options)
Call the SDK initializer early (e.g., in main() before runApp()) when you need runtime configuration.
- On iOS,
initapplies language, debug logging, and Apple Pay options. - On Android,
initapplies language, debug logging, Samsung Pay, and Google Pay runtime configuration. - If you do not need runtime configuration, you can call
presentPayment(...)directly.
import 'package:flutter/widgets.dart';
import 'package:telr_mobile_payment_sdk/telr_mobile_payment_sdk.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await TelrSdk.init(
preferredLanguageCode: 'en',
debugLoggingEnabled: true,
samsungPayServiceId: null,
samsungPayMerchantId: null,
googlePayGatewayMerchantId: null,
googlePayMerchantId: null,
// iOS-only options (ignored on Android):
applePayMerchantIdentifier: null, // e.g. 'merchant.com.yourcompany.yourapp'
applePayButtonType: 'buy', // optional
applePayButtonStyle: 'automatic', // optional
);
runApp(const MyApp());
}
Supported Payment Methods
The SDK supports the following payment methods (availability is controlled by your Telr account and order configuration):
- Credit/Debit Cards — Visa, Mastercard, Amex, mada (with 3D Secure)
- Apple Pay (iOS) — requires Merchant Identity setup (see below)
- Google Pay (Android) — requires Google Pay merchant configuration (see below)
- Samsung Pay (Android) — requires Samsung device and manifest setup (see below)
- Click to Pay — Mastercard, Visa (with 3D Secure)
- Tabby — Buy Now Pay Later
- Tamara — Buy Now Pay Later
- STC Bank — direct bank payment
Use
Minimal example:
import 'package:flutter/material.dart';
import 'package:telr_mobile_payment_sdk/telr_mobile_payment_sdk.dart';
class PayButton extends StatelessWidget {
const PayButton({super.key});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () async {
try {
final res = await TelrSdk.presentPayment(
'https://merchant.example.com/token',
'https://merchant.example.com/order',
);
final msg = res.success
? 'Payment successful'
: 'Payment failed: ${res.message}';
if (context.mounted) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(msg)));
}
} catch (e) {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Unexpected error: $e')),
);
}
}
},
child: const Text('Pay with Telr'),
);
}
}
If you need to set language or iOS Apple Pay options, initialize once on app load as shown above, then call presentPayment when needed.
API
Methods
- init({ preferredLanguageCode, debugLoggingEnabled, samsungPayServiceId, samsungPayMerchantId, googlePayGatewayMerchantId, googlePayMerchantId, applePayMerchantIdentifier, applePayButtonType, applePayButtonStyle, colors }) →
Future<PaymentResponse>- Initializes the SDK bridge and applies supported runtime configuration for the current platform. Pass
colors(aTelrColorConfig) to theme the SDK's payment UI — see Custom Colors (Theming).
- Initializes the SDK bridge and applies supported runtime configuration for the current platform. Pass
- presentPayment(tokenURL, orderURL) →
Future<PaymentResponse>- Presents the full Telr payment UI (all payment methods) and resolves when completed.
- payWithCard(tokenURL, orderURL) →
Future<PaymentResponse>- Presents a card-only payment form. Use this when building a custom merchant checkout page. If the order supports saving cards, the form shows a "Save my card details" checkbox; when the user opts in, the result's
savedCardis populated — persist it to reuse later viapayWithSavedCard.
- Presents a card-only payment form. Use this when building a custom merchant checkout page. If the order supports saving cards, the form shows a "Save my card details" checkbox; when the user opts in, the result's
- payWithApplePay(tokenURL, orderURL) →
Future<PaymentResponse>(iOS only)- Runs Apple Pay with no SDK UI, for a merchant-owned Apple Pay button. Returns the final result only (
orderRef/transactionRefpopulated on success). On Android it resolves to a failure witherrorCode: "unsupported_platform".
- Runs Apple Pay with no SDK UI, for a merchant-owned Apple Pay button. Returns the final result only (
- launchGooglePayPayment(tokenURL, orderURL) →
Future<PaymentResponse>(Android only)- Runs Google Pay with no SDK UI, for a merchant-owned Google Pay button. On iOS it resolves to a failure with
errorCode: "unsupported_platform".
- Runs Google Pay with no SDK UI, for a merchant-owned Google Pay button. On iOS it resolves to a failure with
- launchSamsungPayPayment(tokenURL, orderURL) →
Future<PaymentResponse>(Android only)- Runs Samsung Pay with no SDK UI, for a merchant-owned Samsung Pay button. On iOS it resolves to a failure with
errorCode: "unsupported_platform".
- Runs Samsung Pay with no SDK UI, for a merchant-owned Samsung Pay button. On iOS it resolves to a failure with
- payWithSavedCard(tokenURL, orderURL, savedCard) →
Future<PaymentResponse>- Pays using a previously saved card. The
savedCardparameter is aTelrSavedCardobject obtained from a prioraddCard(or apayWithCardwhere the user opted to save).
- Pays using a previously saved card. The
- addCard(tokenURL, orderURL) →
Future<AddCardResponse>- Presents a form to save a card without charging. Returns saved card tokens that can be stored on your backend and used with
payWithSavedCard.
- Presents a form to save a card without charging. Returns saved card tokens that can be stored on your backend and used with
- getSdkVersion() →
Future<String>- Returns the underlying native SDK version string.
Types
enum TelrPaymentStatus { success, pending, failure, cancelled }
class PaymentResponse {
final bool success;
final TelrPaymentStatus status;
final String message;
final String? errorCode;
final String? orderRef; // Telr order reference (on success)
final String? transactionRef; // transaction/payment reference (on success)
final TelrSavedCard? savedCard; // set when the user opts to save during payWithCard
}
class AddCardResponse extends PaymentResponse {
final String? ref;
final String? maskedName;
final List<TelrSavedCard>? savedCards;
}
class TelrSavedCard {
final String token;
final String maskedCard;
final String expiry;
final String scheme;
final String? maskedName;
}
class TelrColorConfig {
final TelrColors? light;
final TelrColors? dark;
}
class TelrColors {
final String? primary; // Pay button, selected tick, links
final String? background; // payment sheet background
final String? textLabel; // primary text
final String? border; // field/card outlines, dividers
final String? buttonText; // text on the Pay button
final String? textFieldText; // text typed into inputs (also derives placeholder/hint)
final String? textFieldBackground; // input field fill
}
Merchant checkout page example
Build a custom checkout page using the individual payment methods:
// 1. Save a card
final addCardResult = await TelrSdk.addCard(tokenURL, orderURL);
if (addCardResult.status == TelrPaymentStatus.success) {
// Store addCardResult.savedCards on your backend
}
// 2. Pay with a saved card
final result = await TelrSdk.payWithSavedCard(tokenURL, orderURL, savedCard);
// 3. Pay with a new card (card-only form)
final result = await TelrSdk.payWithCard(tokenURL, orderURL);
Custom Colors (Theming)
Theme the SDK's payment UI to match your brand by passing colors at init. Provide light and/or dark variants; each color is an optional hex string ("#RRGGBB" or "#AARRGGBB").
await TelrSdk.init(
colors: const TelrColorConfig(
light: TelrColors(
primary: '#0057FF', // Pay button, selected tick, links
background: '#FFFFFF', // payment sheet / surface background
textLabel: '#101828', // primary text
border: '#E4E7EC', // field/card outlines, dividers
buttonText: '#FFFFFF', // text on the Pay button
textFieldText: '#101828', // text the user types into inputs
textFieldBackground: '#F2F4F7', // input field fill
),
dark: TelrColors(
primary: '#4C8DFF',
background: '#101828',
textLabel: '#F2F4F7',
border: '#344054',
buttonText: '#FFFFFF',
textFieldText: '#F2F4F7',
textFieldBackground: '#1D2939',
),
),
);
Colors resolve per token: init colors → store colors from the Telr portal → SDK default. Any token left null falls through to the next source. Two secondary tones are derived automatically (no separate keys): muted text is textLabel at reduced opacity, and placeholder/hint text is textFieldText at reduced opacity. Provide both light and dark for full control — store colors are applied per-mode and do not cross-fill between modes.
Dedicated wallet methods (your own button)
If you want to show your own wallet button instead of the SDK's payment screen, call the dedicated method from your button's tap handler. The SDK owns the whole wallet session and returns only the final result — with orderRef and transactionRef populated for server-side verification. No SDK payment UI is shown.
// iOS — from your own Apple Pay button:
final res = await TelrSdk.payWithApplePay(tokenURL, orderURL);
// Android — from your own Google Pay / Samsung Pay button:
final res = await TelrSdk.launchGooglePayPayment(tokenURL, orderURL);
final res2 = await TelrSdk.launchSamsungPayPayment(tokenURL, orderURL);
if (res.status == TelrPaymentStatus.success) {
// res.orderRef, res.transactionRef
}
Each method is platform-specific: calling the iOS method on Android (or vice-versa) resolves to a failure with errorCode: "unsupported_platform", so gate the button on Platform.isIOS / Platform.isAndroid. These require the same wallet configuration as the in-sheet flow (Apple Pay Merchant ID; Google Pay gateway/merchant IDs; Samsung Pay Service ID + manifest meta-data).
Merchant checklist
- Expose HTTPS
tokenURLandorderURLfrom your backend. - Ensure device/emulator can reach both URLs.
- Handle the returned result to confirm/cancel the order server-side.
Apple Pay (iOS)
- Apple Developer Portal: Enable Apple Pay for your App ID and create a Merchant Identity Certificate under Certificates, Identifiers & Profiles > Identifiers > Merchant IDs.
- Xcode: Open
ios/Runner.xcworkspace, add the Apple Pay capability to the Runner target, and select your Merchant ID. - SDK init: Pass your Merchant Identifier:
await TelrSdk.init(
applePayMerchantIdentifier: 'merchant.com.yourcompany.yourapp',
);
The SDK shows Apple Pay automatically when the device supports it and the user has cards in Wallet.
Samsung Pay (Android)
- Samsung Developers Portal: 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).
- AndroidManifest.xml: Add under the
<application>tag inandroid/app/src/main/AndroidManifest.xml:
<meta-data android:name="spay_sdk_api_level" android:value="2.22" />
<meta-data android:name="debug_mode" android:value="N" />
- 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. debug_modemust beNin production. Set toYonly in development builds — shippingYto production causes Samsung Pay to behave unpredictably.
- SDK init: Pass your Service ID:
await TelrSdk.init(
samsungPayServiceId: '<YOUR_SERVICE_ID>',
);
Samsung Pay only appears on Samsung devices with Samsung Wallet installed and provisioned, in supported regions.
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_READYand 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 version —
spay_sdk_api_levelmust match the value documented above. Filter logcat forSamsungPayRequirementsto see validation warnings emitted by the SDK.
Google Pay (Android)
- Configure Google Pay for your Telr merchant account so the backend order includes
order._links.googlePay.href. - Initialize the SDK with your Android Google Pay settings:
await TelrSdk.init(
googlePayGatewayMerchantId: '<YOUR_GATEWAY_MERCHANT_ID>',
googlePayMerchantId: '<YOUR_GOOGLE_MERCHANT_ID>',
);
Google Pay only appears when the backend enables it and Google Wallet is available and ready on the device.
Click to Pay
Click to Pay appears 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
dpaIdso returning users skip the email/OTP step on the next session.
No additional Flutter-side configuration is required — the option appears automatically in the payment sheet when the backend enables it.
Troubleshooting
- Android: E002 "Unable to register for Activity Result": Ensure initialization happens during app load. Call
TelrSdk.init(...)inmain()beforerunApp(). - iOS: CocoaPods cannot find
TelrSDK: Configure Telr spec source, runpod repo update, thenpod install. - iOS: Build fails due to iOS version: Set
platform :ios, '15.1'or newer. - Android: minSdk/targetSdk mismatch: Use min 21 / target 34 / compile 34.
- Network/HTTP errors: Verify backend endpoints and connectivity.
Security
- Always use HTTPS; validate server responses.
- Never embed secrets in the app or log cardholder data.
Links
- Package on pub.dev: telr_mobile_payment_sdk
- Example app: see
example/
License
MIT