easymerchant_reader_sdk

Flutter plugin for EasyMerchant MagTek Mobile Reader payments.

Use MagTek BLE card readers (e.g. DynaFlex II Go) from a Flutter app: create a client_token on your backend, start a reader transaction, and complete the charge with encrypted ARQC data. Native SDK screens handle reader connect, tap-to-pay, cancel confirmation, and success / failure UI (light or dark theme).

Platform Status
Android startTransaction with client token, light/dark UI, and simulation
iOS startTransaction with the same simulation UI and JSON as Android. Live charges use the existing MagTek reader screens and return a JSON string. makePayment remains for older hosts.

Install

dependencies:
  easymerchant_reader_sdk: ^0.1.7
flutter pub get

Merchant app / backend
  └─ POST /paymentintent  (X-Api-Key + X-Api-Secret)
       └─ client_token
            └─ Magteksdk.startTransaction(amount, clientToken: …)
                 └─ Native UI: connect → tap → charge (client-token header)

Never put API key / secret inside the SDK or the mobile app for production. Generate client_token on your server and pass it into Flutter.

Pass environment as one of: sandbox, staging, or production (values provided by EasyMerchant for your account).


Quick start (Android and iOS)

import 'package:easymerchant_reader_sdk/magteksdk.dart';

final sdk = Magteksdk();

// clientToken comes from your backend: POST /paymentintent
final result = await sdk.startTransaction(
  '100.00',
  environment: 'sandbox', // sandbox | staging | production
  clientToken: clientToken,
  theme: MagtekSdkTheme.dark, // or MagtekSdkTheme.light
  // idempotencyKey: 'order-123', // optional; UUID generated if omitted
  // simulate: true,              // optional; skip BLE, play UI demo
  // simulateSuccess: true,       // optional; only when simulate is true
);

print(result);

Simulation (no MagTek hardware)

Use these flags to exercise the native reader UI without a MagTek device. Both default to false. When simulate is true, clientToken is optional. Android and iOS play the same sequence (preparing → tap → processing → result). Tapping Done (or Go back on failure) returns the JSON string below.

Flag Value Behavior
simulate true Skip BLE / hardware; play preparing → tap → processing → result
simulateSuccess true End on payment successful; return approved charge JSON
simulateSuccess false End on payment failed; return failure JSON
// Success path
final successJson = await sdk.startTransaction(
  '25.00',
  simulate: true,
  simulateSuccess: true,
);

// Failure path
final failureJson = await sdk.startTransaction(
  '25.00',
  simulate: true,
  simulateSuccess: false,
);

Success response (simulate: true, simulateSuccess: true):

{
  "status": true,
  "message": "Payment processed successfully. ",
  "charge_id": "cha_53206aa9380552d75",
  "outcome": "approved",
  "processor_transaction_id": "dd21ffe8-4d87-4ed9-88e7-063d4ad85bdf",
  "customer_transaction_id": "cha_5320948ced786bfb16a6c824e860",
  "data": "NA",
  "currency": "USD",
  "last_4": null,
  "card_last_4": null,
  "card_brand_name": null,
  "exp_month": "",
  "exp_year": null,
  "payment_method": "card"
}

Failure response (simulate: true, simulateSuccess: false):

{
  "status": false,
  "simulated": true,
  "message": "Simulated payment failed",
  "amount": "25.00"
}

Cancel during simulation returns status: false with "Simulated transaction cancelled".

Themes

MagtekSdkTheme.light  // light native screens
MagtekSdkTheme.dark   // dark native screens

Native screens (Android, and iOS simulation) include: preparing terminal, tap to pay, processing, payment successful, and payment failed. Light and dark themes use the same colors on both platforms.


Android host setup

1. MagTek mtusdk.aar

Place MagTek’s mtusdk.aar in your app’s android/ folder (next to settings.gradle), or under android/libs/.

In android/app/build.gradle:

dependencies {
    implementation files('../mtusdk.aar')
    // or: implementation files('libs/mtusdk.aar')
}

configurations {
    all {
        exclude group: 'net.sf.kxml', module: 'kxml2'
    }
}

Native reader UI and payment code ship inside this Flutter plugin (android/vendor/…). You do not need GitHub Packages, Maven credentials, or a separate em-MobileReaderSDK-Android dependency.

2. Permissions

BLE / location permissions are declared by the plugin and requested at runtime. Ensure your app targets a supported minSdk (plugin uses 21+).

3. Optional: MainActivity wiring

If the plugin does not auto-register on your Flutter embedding, wire MagteksdkPlugin in MainActivity as shown in the example app.


iOS host setup

Minimum iOS version is 15.0 (POS apps in this repo use 16.0).

1. Podfile

easymerchant_reader_sdk depends on the local MobileReaderRuntime pod (it is not on the CocoaPods trunk). Add it next to the Flutter pods. The path below is for an app that sits beside the em-MobileReaderSDK repo; change it if your checkout layout differs.

platform :ios, '16.0'

target 'Runner' do
  use_frameworks!
  use_modular_headers!

  pod 'MobileReaderRuntime', :path => '../../em-MobileReaderSDK/packages/ios/MobileReaderRuntime'

  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
    target.build_configurations.each do |config|
      # This Xcode only accepts 15.0+; keep pods aligned with the app.
      config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '16.0'
    end
  end
end

Also set the Runner target iOS Deployment Target to 16.0 in Xcode (IPHONEOS_DEPLOYMENT_TARGET). Targets left at 9.0 or 13.0 fail on current simulator SDKs.

2. Bluetooth usage

Add this to ios/Runner/Info.plist for a live reader connection:

<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app requires Bluetooth to connect to payment readers.</string>

3. Install pods and run

cd ios && pod install
cd .. && flutter run

4. Payment call

Use the same startTransaction API as Android. Simulation does not need a reader or a client token:

final result = await Magteksdk().startTransaction(
  '25.00',
  environment: 'sandbox',
  theme: MagtekSdkTheme.dark,
  simulate: true,
  simulateSuccess: true,
);

makePayment is still available for older iOS hosts. It returns a map and uses the existing MagTek reader storyboard, not the simulation screens.

MagTek MTUSDK / MTSCRA frameworks ship inside the plugin.


API overview

Magteksdk

Method Platform Description
startTransaction(amount, { environment, clientToken, idempotencyKey, theme, simulate, simulateSuccess }) Android and iOS Opens native reader UI. simulate / simulateSuccess play the same preparing → tap → processing → result screens on both platforms and return the JSON documented above. On iOS, simulate: false uses the existing MagTek reader UI and still returns a JSON string.
makePayment(amount, { environment, apiKey, secretKey }) iOS Older entry point. Returns a map from the MagTek storyboard flow.
getPlatformVersion() Both Debug helper

Charge headers (Android)

The native layer sends:

  • client-token — from clientToken
  • Idempotency-Key — your key, or a generated UUID per payment
  • Body includes arqc, amount, description, payment_mode, etc.

Example app

cd example
cp env.json.example env.json   # fill EM_API_KEY / EM_API_SECRET (sandbox)
flutter run --dart-define-from-file=env.json

QA APK:

./scripts/build-qa-apk.sh

Support


License

Proprietary — EasyMerchant. See LICENSE. Distribution and use require EasyMerchant authorization. MagTek SDKs remain subject to MagTek’s license terms.

Libraries

magtek_sdk_theme
magteksdk
magteksdk_method_channel
magteksdk_platform_interface
mobile_reader_sdk
Unified Flutter façade for the EasyMerchant mobile reader SDKs.