emvnfc – EMV NFC Card Reader SDK (Flutter)

emvnfc is a Flutter plugin that reads EMV payment card data over NFC. It exposes a simple Dart API and integrates a native Android core shipped as an obfuscated binary to avoid exposing sensitive implementation details.

The SDK is designed for a guided flow: start a listening session, react to card events from a stream, request the PIN, and receive structured card data.

Quick Start

  1. Add the dependency to your Flutter app’s pubspec.yaml:
dependencies:
  emvnfc:
    path: ../Emvnfc
  1. Initialize and start listening:
import 'package:emvnfc/emvnfc.dart';

final sdk = Emvnfc();

Future<void> start(String amount, String licenseKey) async {
  // Start a listening session (60s default timeout)
  await sdk.startCardListening(
    amountText: amount,
    licenseKey: licenseKey, // keep this secret
  );

  // Subscribe to the stream once (do this at init time in your UI)
  sdk.monitorStream.listen((monitor) {
    switch (monitor.state) {
      case 'Loading':
        // show progress: monitor.message / monitor.progress
        break;
      case 'CardDetected':
        // show PIN UI, then submit
        // sdk.submitPin('1234');
        break;
      case 'CardData':
        // monitor.cardData contains structured EMV data
        // monitor.transactionData contains the same as a Map
        final card = monitor.cardData!;
        // use card.maskedPan, card.formattedExpiry, etc.
        break;
      case 'CardReadTimeOut':
      case 'CallBackError':
        // show monitor.message
        break;
    }
  });
}
  1. Submitting the PIN when prompted:
// After you capture the PIN from UI:
sdk.submitPin(pin);
  1. Canceling:
await sdk.cancel();

Android Setup Notes

  • minSdkVersion: 24
  • NFC permission and feature are declared by the plugin and merged into the app manifest
  • The core is minified/obfuscated in release to reduce reverse‑engineering risk

iOS and Web

The streaming API works cross‑platform, but the hardened native core described here applies to Android. iOS/Web follow the regular plugin behavior.

API Overview

Class: Emvnfc

  • Future<void> startCardListening({ required String amountText, required String licenseKey, Duration timeout = const Duration(seconds: 60) })
  • Stream<TransactionMonitor> get monitorStream
  • void submitPin(String pin)
  • Future<void> cancel()

Model: TransactionMonitor

  • state: 'Loading' | 'CardDetected' | 'CardData' | 'CardReadTimeOut' | 'CallBackError'
  • message: status or error text
  • progress: 0–1
  • cardData: structured EMV card object (when state == 'CardData')

Model: CardData (selected fields)

  • applicationPrimaryAccountNumber, formattedPan, maskedPan
  • expirationDate, formattedExpiry
  • cardHolderName, detectedScheme
  • Multiple EMV tags exposed via named properties

License Key Handling

  • Always keep your licenseKey secret; never commit it to source control
  • Inject it via environment variables, runtime configuration, or secure storage
  • The README intentionally uses licenseKey placeholders only
  • To request a license key, contact odejinmiabraham@gmail.com

Troubleshooting

  • Build fails with “Missing emvnfc_core binary”: ensure android/libs/emvnfc_core-release.jar or .aar exists
  • No CardData event: confirm you are listening to monitorStream and submitting the PIN after CardDetected
  • Timeout: increase the timeout or move the phone/card to improve NFC signal

Example App

See the included example under example/ for a working UI that collects the amount, prompts for PIN, and displays card details.