Skip to main content

sdk_ekyc_flutter 1.0.0 copy "sdk_ekyc_flutter: ^1.0.0" to clipboard
sdk_ekyc_flutter: ^1.0.0 copied to clipboard

Identity verification screens for Flutter that run on the phone: scan the front and back of a Vietnamese citizen ID or a passport photo page with a document liveness check, then a face liveness check [...]

sdk_ekyc_flutter #

Two full-screen Flutter widgets for identity verification. Everything runs on the phone; nothing is uploaded by the package.

Widget What the user does What you get back
IdDocumentScanner Holds a Vietnamese citizen ID (front, then back) or a passport photo page inside the frame and taps the shutter The document cropped from the photo, plus the full frame
FaceLivenessScanner Looks straight, then left, then right, following the text under the oval A straight-on photo of the face

A document liveness model checks every camera frame and tells the user what to fix: card not in the frame, wrong side, glare, a finger over the card, a photo of a screen. The face flow runs face detection and a liveness model on each frame.

Send the returned images to your own verification backend for OCR and face matching.

Requirements #

  • Flutter 3.38.1 or newer (Dart 3.10). Tested on 3.47.7.
  • Android: compileSdk 36, Java 17, minSdk from your Flutter version (flutter.minSdkVersion).
  • iOS 12.0 or newer, on a real device. The simulator has no camera.

Install #

dependencies:
  sdk_ekyc_flutter: ^1.0.0
flutter pub get

The package uses the official camera plugin from pub.dev. No overrides or git dependencies are needed.

Platform setup #

Android. In android/gradle.properties, add:

kotlin.jvm.target.validation.mode=warning
android.uniquePackageNames=false

tflite_flutter declares Java 11 and pulls in two LiteRT libraries that share a namespace. With Android Gradle Plugin 9 and Kotlin 2 (the default for new Flutter projects) both are build errors; these two lines turn them back into warnings. They do nothing on older projects.

Make sure android/app/build.gradle compiles against SDK 36 with Java 17:

android {
    compileSdk 36
    defaultConfig { minSdkVersion flutter.minSdkVersion }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }
}

The camera permission comes with the camera plugin.

iOS. Add both keys to ios/Runner/Info.plist. Without the camera key iOS terminates the app the first time the camera opens; the microphone key is required by App Store review because the camera plugin links the audio APIs, even though nothing is recorded.

<key>NSCameraUsageDescription</key>
<string>The camera is used to photograph your ID and your face for identity verification.</string>
<key>NSMicrophoneUsageDescription</key>
<string>The microphone is not used.</string>

If your Podfile sets a platform, use at least platform :ios, '12.0', then cd ios && pod install.

Scan an ID document #

import 'package:flutter/material.dart';
import 'package:sdk_ekyc_flutter/sdk_ekyc_flutter.dart';

class FrontOfIdPage extends StatefulWidget {
  const FrontOfIdPage({super.key});

  @override
  State<FrontOfIdPage> createState() => _FrontOfIdPageState();
}

class _FrontOfIdPageState extends State<FrontOfIdPage> {
  bool _checking = false;

  Future<void> _onCaptured(DocumentScanResult result) async {
    setState(() => _checking = false);
    if (result.isAccepted) {
      await result.closeCamera();
      if (mounted) Navigator.of(context).pop(result.documentImagePath);
      return;
    }
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(result.message)));
    await result.scanAgain();
  }

  @override
  Widget build(BuildContext context) {
    return Stack(children: [
      IdDocumentScanner(
        page: DocumentPage.citizenIdFront,
        onCaptured: _onCaptured,
        onBusyChanged: (busy) => setState(() => _checking = busy),
      ),
      if (_checking) const Center(child: CircularProgressIndicator()),
    ]);
  }
}
Parameter Type
page DocumentPage citizenIdFront, citizenIdBack (citizen ID or the older ID card) or passport
onCaptured FutureOr<void> Function(DocumentScanResult) Called once after each shutter press
onBusyChanged ValueChanged<bool> Optional. Called with true when the captured photo starts being checked

DocumentScanResult:

Member
isAccepted Whether the photo passed the document liveness check
documentImagePath JPEG of the document only, cropped. This is the one to upload. Empty if the capture failed
fullFrameImagePath JPEG of the whole camera frame. Empty if the capture failed
message Vietnamese text for the user, for example why the photo was refused
scanAgain() Resumes the camera so the user can retake the photo
closeCamera() Releases the camera. Call it before leaving the screen
pauseCamera() Keeps the camera paused

The camera is paused when onCaptured runs and stays paused until you call scanAgain() or closeCamera(). The package never calls onBusyChanged(false); hide your progress indicator in onCaptured.

Face liveness #

FaceLivenessScanner(
  texts: const FaceLivenessTexts(
    lookStraight: 'Nhìn thẳng vào camera',
    turnLeft: 'Quay mặt sang trái',
    turnRight: 'Quay mặt sang phải',
    completed: 'Hoàn tất',
  ),
  onCompleted: (result) => Navigator.of(context).pop(result.faceImagePath),
  onCameraUnavailable: () => Navigator.of(context).pop(),
)
Parameter Type
texts FaceLivenessTexts The line of text under the oval for each pose. There is no built-in text
onCompleted FutureOr<void> Function(FaceCheckResult) Called once, when all three poses have passed. result.faceImagePath is the straight-on photo
onProgress void Function(FaceCheckProgress) Optional. Called for every analysed frame while the user is moving: framePassed, status (what the detector saw), message
onCameraUnavailable VoidCallback Optional. Permission refused or camera in use

Each pose has a time limit; when it runs out the flow starts over by itself and onProgress reports status RESTART_ALL_STEP. Nothing is recorded.

Images #

All images are JPEG files in the app's temporary directory (getTemporaryDirectory()). The OS can remove that directory at any time, so upload or copy them straight away, and delete them once uploaded.

Network and privacy #

The package sends no images or user data anywhere. The only network access is google_fonts fetching Roboto from fonts.gstatic.com the first time a screen opens. To avoid it, bundle the Roboto .ttf files with your app and set GoogleFonts.config.allowRuntimeFetching = false in main().

Example app #

example/ opens each flow from a list: ID front, ID back, passport, face. Run it on a phone:

cd example && flutter run
0
likes
100
points
42
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Identity verification screens for Flutter that run on the phone: scan the front and back of a Vietnamese citizen ID or a passport photo page with a document liveness check, then a face liveness check that asks the user to look straight, left and right. Android and iOS.

Topics

#ekyc #liveness #identity-verification #camera

License

unknown (license)

Dependencies

camera, device_info_plus, ffi, flex_color_scheme, flutter, flutter_svg, google_fonts, image, image_picker, path_provider, provider, scidart, sliding_up_panel, tflite_flutter

More

Packages that depend on sdk_ekyc_flutter

Packages that implement sdk_ekyc_flutter