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
Payment flow (recommended)
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— fromclientTokenIdempotency-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
- Issues: GitHub Issues
- Related checkout plugin: easymerchantsdk
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.