Telr Mobile Payment SDK


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 tokenURL and orderURL

Install

Add to pubspec.yaml and fetch:

dependencies:
  telr_mobile_payment_sdk: ^4.4.0
flutter pub get

Updating the plugin version

  1. Update the version in pubspec.yaml and run:
flutter clean
flutter pub get
  1. For iOS, update pods to the latest TelrSDK:
cd ios
pod deintegrate
pod install --repo-update
pod update TelrSDK

iOS setup

  1. Set minimum iOS in ios/Podfile and enable static frameworks:
platform :ios, '15.1'

target 'Runner' do
  use_frameworks! :linkage => :static
end
  1. Install pods:
cd ios && pod install
  • If CocoaPods cannot find TelrSDK, run pod repo update then re-install. The TelrSDK pod is published from github.com/Telr-PG/telr-sdk-ios and resolves via the standard CocoaPods CDN.

Android setup

  1. Ensure repositories in android/settings.gradle:
dependencyResolutionManagement {
  repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
  repositories {
    google()
    mavenCentral()
  }
}
  1. Set SDK versions in android/app/build.gradle:
android {
  compileSdkVersion 34

  defaultConfig {
    minSdkVersion 21
    targetSdkVersion 34
  }
}
  1. 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, init applies language, debug logging, and Apple Pay options.
  • On Android, init applies 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 (a TelrColorConfig) to theme the SDK's payment UI — see Custom Colors (Theming).
  • 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 savedCard is populated — persist it to reuse later via payWithSavedCard.
  • 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/transactionRef populated on success). On Android it resolves to a failure with errorCode: "unsupported_platform".
  • 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".
  • 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".
  • payWithSavedCard(tokenURL, orderURL, savedCard)Future<PaymentResponse>
    • Pays using a previously saved card. The savedCard parameter is a TelrSavedCard object obtained from a prior addCard (or a payWithCard where the user opted to save).
  • 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.
  • 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 tokenURL and orderURL from your backend.
  • Ensure device/emulator can reach both URLs.
  • Handle the returned result to confirm/cancel the order server-side.

Apple Pay (iOS)

  1. Apple Developer Portal: Enable Apple Pay for your App ID and create a Merchant Identity Certificate under Certificates, Identifiers & Profiles > Identifiers > Merchant IDs.
  2. Xcode: Open ios/Runner.xcworkspace, add the Apple Pay capability to the Runner target, and select your Merchant ID.
  3. 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)

  1. 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).
  2. AndroidManifest.xml: Add under the <application> tag in android/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_mode must be N in production. Set to Y only in development builds — shipping Y to production causes Samsung Pay to behave unpredictably.
  1. 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

  1. 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.
  2. Device is not Samsung, or Samsung Wallet has no provisioned card — the SDK reports SPAY_NOT_READY and hides the option.
  3. Backend did not return order._links.samsungPay.href — confirm with your Telr account manager that Samsung Pay is enabled for your merchant account.
  4. Country / region not supported — Samsung Pay is region-locked. The device must be in a supported country.
  5. 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.

Google Pay (Android)

  1. Configure Google Pay for your Telr merchant account so the backend order includes order._links.googlePay.href.
  2. 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 dpaId so 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(...) in main() before runApp().
  • iOS: CocoaPods cannot find TelrSDK: Configure Telr spec source, run pod repo update, then pod 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.

License

MIT