prism_ekyc 0.1.0 copy "prism_ekyc: ^0.1.0" to clipboard
prism_ekyc: ^0.1.0 copied to clipboard

Prism eKYC – NFC + Camera + Face Verification Flutter package for Japanese ID documents.

prism_ekyc #

A Flutter package for end-to-end electronic KYC (eKYC) of Japanese IC identity cards. The package presents a self-contained UI flow, reads the card chip over NFC and returns a strongly-typed result.

Supported cards

Card Authentication input
Residence Card (在留カード) Card number (e.g. UH73843905EA)
Driver's License (運転免許証) PIN 1 + PIN 2
My Number Card (マイナンバーカード) 4-digit PIN

How it works — end to end #

Welcome
  └─ Nationality selector
       └─ ID card instructions
            └─ NFC scan  ← card number / PIN entered here
                 │
                 ├─ flutter_libjeid reads chip over NFC
                 │      • card front PNG image
                 │      • holder face photo
                 │      • chip-direct text fields (DL / My Number)
                 │      • runs on card front PNG
                 │      • extracts: name, nationality, DOB, gender,
                 │        address, visa status, dates
                 │
                 └─ NfcScanResult built (chip data takes priority; OCR fills gaps)
                      │
                      ├─ Backside capture  (camera — photo of card back)
                      ├─ Face verification (liveness check + face match)
                      └─ Registration form (pre-filled, user confirms)
                               │
                               └─ onComplete(EkycResult)

NFC layer — flutter_libjeid #

Card type is auto-detected from the number the user types:

Input format Detected type Scan call
2 letters + 8 digits + 2 letters (e.g. UH73843905EA) Residence Card scanResidentCard(cardNumber:)
12 digits Driver's License scanDriverLicenseCard(pin1:, pin2:)
Anything else My Number Card scanMyNumberCard(pin:)

The NFC scan screen shows PIN input fields automatically when the input matches a Driver's License or My Number format.

Form auto-fill #

Once NfcScanResult is built, UserFormData.fromNfc() pre-populates the Registration Form screen. The user can review and edit every field before submitting.


Platform requirements #

Platform Minimum Notes
iOS 13.0 Physical device only — NFC unavailable on Simulator
Android API 24 (7.0) Requires NFC hardware

Installation #

dependencies:
  prism_ekyc:
    path: ../prism_ekyc   # local
    # or git / pub.dev reference when published

iOS setup #

1 — NFC entitlement #

In Xcode: Signing & Capabilities → + Capability → Near Field Communication Tag Reading

This adds to your .entitlements file:

<key>com.apple.developer.nfc.readersession.formats</key>
<array>
  <string>TAG</string>
</array>

2 — Info.plist usage descriptions #

<key>NFCReaderUsageDescription</key>
<string>Used to read your ID card chip for identity verification.</string>

<key>NSCameraUsageDescription</key>
<string>Used to photograph your ID card and verify your face.</string>

3 — Podfile #

No extra pods are required. flutter_libjeid ships its own iOS implementation and prism_ekyc links only Apple's Vision framework (for face comparison).


Android setup #

1 — AndroidManifest.xml #

The plugin manifest already declares NFC permission. Confirm your android/app/src/main/AndroidManifest.xml has:

<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="false" />

Set required="false" if you want the app installable on non-NFC devices (the scan step will return an error at runtime on those devices).

Your <activity> tag must use singleTop launch mode so NFC intents are delivered to the running activity:

<activity
    android:name=".MainActivity"
    android:launchMode="singleTop"
    ...>

2 — MainActivity #

No changes required. flutter_libjeid registers its own ActivityAware plugin and handles foreground NFC dispatch internally.

Quick start #

import 'package:prism_ekyc/prism_ekyc.dart';

Navigator.push(
  context,
  MaterialPageRoute(
    builder: (_) => PrismEkyc.screen(
      PrismEkycConfig(
        onComplete: (EkycResult result) {
          print(result.formData.fullName);
          print(result.nfcData?.dateOfBirth);
          print(result.nfcData?.nationality);
        },
      ),
    ),
  ),
);

Configuration — PrismEkycConfig #

PrismEkycConfig({
  void Function(EkycResult)? onComplete,
  PrismLanguage defaultLanguage = PrismLanguage.english,
  List<PrismLanguage> availableLanguages = const [...],
  List<SupportedCountry> supportedCountries = const [...],
  bool debugBypassNfc = false,
})
Parameter Type Description
onComplete void Function(EkycResult)? Called with the full result when the user submits the form. If omitted the package silently pops.
defaultLanguage PrismLanguage Initial UI language. Defaults to english.
availableLanguages List<PrismLanguage> Languages shown in the switcher. Defaults to both.
supportedCountries List<SupportedCountry> Countries in the nationality picker. Defaults to all 9.
debugBypassNfc bool Skip NFC and inject mock data. Useful during UI development.

Available languages #

PrismLanguage.english
PrismLanguage.japanese

Supported countries #

SupportedCountry.brazil       SupportedCountry.indonesia
SupportedCountry.philippines  SupportedCountry.vietnam
SupportedCountry.southKorea   SupportedCountry.china
SupportedCountry.malaysia     SupportedCountry.singapore
SupportedCountry.thailand

Result types #

EkycResult #

class EkycResult {
  final NfcScanResult?  nfcData;              // chip + OCR extracted data
  final Uint8List?      backsideImage;        // card back photo (JPEG bytes)
  final bool            faceVerified;         // liveness challenges passed
  final double?         faceMatchConfidence;  // 0.0–1.0, null if no face photo
  final UserFormData    formData;             // confirmed form values
}

NfcScanResult — chip + OCR extracted fields #

Field Source Notes
cardNumber User input Uppercased
cardType Detected "1" RC · "dl" DL · "mn" My Number
name OCR (RC) / chip (DL, MN) Romaji, ALL CAPS
nationality OCR (RC) / chip (DL, MN) Katakana or English
dateOfBirth OCR (RC) / chip (DL, MN) yyyy-MM-dd
gender OCR (RC) / chip (MN) "male" · "female" · ""
address Chip (all) Japanese address string
status OCR (RC) Visa / residence status in Japanese
permissionToLand OCR (RC) yyyy-MM-dd or ""
issuanceDate OCR (RC) / chip (DL) yyyy-MM-dd or ""
expiryDate OCR (RC) / chip (DL, MN) yyyy-MM-dd or ""
chipAddress Chip (RC) Address directly from chip data files
addressCode Chip (RC) JIS address code
comprehensivePermission Chip (RC) Activity permission string
individualPermission Chip (RC) Individual permission string
updateStatus Chip (RC) Update status code
cardFrontPng Chip (all) PNG image of card front, used for OCR
facePhotoJpeg2000 Chip (all) Holder face photo for face matching

RC = Residence Card fields are populated via OCR because the free-tier libjeid API does not expose personal text fields (name, DOB, nationality) directly from the chip. The card front image is read from the chip and OCR is run on it.

UserFormData — confirmed form values #

Field Type
fullName String
firstNameRomaji String
middleNameRomaji String
lastNameRomaji String
address String
dateOfBirth DateTime?
nationality String
gender FormGendermale · female · notSpecified
cardNumber String
expiryDate DateTime?
visaStatus String
permissionToLand DateTime?
permissionToStay DateTime?
isAutoFilled booltrue when pre-filled from NFC + OCR

Face match confidence #

faceMatchConfidence is derived from the feature-print distance between the chip face photo and the live selfie captured during face verification:

Value Meaning
>= 0.7 Strong match
0.5 – 0.69 Match
null No chip face photo, or comparison was skipped

faceVerified is always true when onComplete fires — a mismatch blocks progression and the user must retake the selfie.


Debug mode #

Set debugBypassNfc: true to skip the NFC step entirely and inject a mock NfcScanResult. This is useful for testing the UI flow and form auto-fill without a physical card or NFC device.

PrismEkyc.screen(
  PrismEkycConfig(
    debugBypassNfc: true,
    onComplete: (result) { ... },
  ),
)

Full example #

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

class VerifyPage extends StatelessWidget {
  const VerifyPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () => _start(context),
          child: const Text('Start Identity Verification'),
        ),
      ),
    );
  }

  void _start(BuildContext context) {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (_) => PrismEkyc.screen(
          PrismEkycConfig(
            defaultLanguage: PrismLanguage.english,
            availableLanguages: const [
              PrismLanguage.english,
              PrismLanguage.japanese,
            ],
            supportedCountries: const [
              SupportedCountry.vietnam,
              SupportedCountry.philippines,
              SupportedCountry.indonesia,
            ],
            onComplete: (EkycResult result) {
              _submit(result);
            },
          ),
        ),
      ),
    );
  }

  Future<void> _submit(EkycResult result) async {
    final payload = {
      'name':            result.formData.fullName,
      'cardNumber':      result.formData.cardNumber,
      'dob':             result.nfcData?.dateOfBirth,
      'nationality':     result.nfcData?.nationality,
      'visaStatus':      result.nfcData?.status,
      'expiryDate':      result.nfcData?.expiryDate,
      'faceConfidence':  result.faceMatchConfidence,
      // Images — send as base64 or multipart
      'facePhoto':       result.nfcData?.facePhotoJpeg2000,
      'cardFront':       result.nfcData?.cardFrontPng,
      'cardBack':        result.backsideImage,
    };
    // ... POST to your API
  }
}

Error handling #

All errors during NFC, OCR, camera, and face verification are handled internally. The user gets a descriptive message and up to 3 retry attempts per step. After exhausting retries a Return to Start button appears.

onComplete is only invoked on full success. If the user backs out or quits at any step, onComplete is never called — treat its absence as abandonment.


Package dependencies #

Package Purpose
flutter_libjeid NFC reading of Japanese IC cards (free tier)
camera Backside card capture + face selfie
google_mlkit_text_recognition OCR on card front image (Japanese script)
google_mlkit_face_detection Face detection for liveness + face match

Known limitations #

  • Residence Card personal fields via OCR: OCR accuracy depends on card condition, lighting during NFC capture, and ML Kit model quality on the device. Fields that fail to parse are returned as empty strings; the user can fill them manually in the Registration Form.
  • iOS Simulator: NFC is unavailable. Use debugBypassNfc: true during simulator development.
  • Android NFC sensitivity: Some Android devices require the card to be held very still during the ~3-second read. A TAG_LOST error triggers a retry.

License #

Proprietary — RubiLabs. See LICENSE for details.

0
likes
0
points
116
downloads

Publisher

unverified uploader

Weekly Downloads

Prism eKYC – NFC + Camera + Face Verification Flutter package for Japanese ID documents.

Homepage

License

unknown (license)

Dependencies

camera, flutter, flutter_libjeid, google_mlkit_face_detection, google_mlkit_text_recognition

More

Packages that depend on prism_ekyc

Packages that implement prism_ekyc