sotaid_pluging 1.1.1+1 copy "sotaid_pluging: ^1.1.1+1" to clipboard
sotaid_pluging: ^1.1.1+1 copied to clipboard

A Flutter plugin for integrating SotaBoost's identity verification service into Flutter applications

Flutter SDK for SotaId #

A Flutter plugin for SotaID identity verification integration with NFC document reading capabilities and comprehensive API access.

Installation #

Features #

  • App-Controlled Verification Process: The app decides whether to show complete verification (document + face) or face-only verification
  • Multiple Verification Types: Support for ID verification, face matching, and liveness detection
  • Document Capture: Capture front and back of identity documents
  • Face Verification: Record face videos for verification
  • NFC Document Reading: Read e-passports and ID cards using NFC technology
  • Permission Management: Automatic camera, storage, and NFC permission handling
  • Country Support: Dynamic country and document type selection
  • Session Management: Automatic storage and reminder for pending manual verifications
  • API Integration: Direct access to SotaID and SotaBoost APIs for verification sessions and customer management

API Resources #

The plugin provides direct access to both SotaBoost and SotaID APIs for comprehensive identity verification management.

SotaBoost API (Base) #

  • Verification Sessions: Create and manage verification sessions
  • Document Verification: Front/back document capture and verification
  • Face Verification: Liveness detection and face matching
  • NFC Integration: Document reading and verification

SotaID API (Extended) #

  • Verification Sessions: Retrieve and list verification sessions with real verification data
  • Customer Management: Create, read, update, and delete customers with actual customer records
  • Session Status: Real-time verification status tracking with live results

Available Methods #

Verification Session Management

// Get verification session by ID
Future<Map<String, dynamic>> getVerificationSession(String sessionId)

// List all verification sessions with optional filtering
Future<Map<String, dynamic>> listVerificationSessions({String? email, int? limit})

Example Response - getVerificationSession:

{
  "id": "vs_01982e011279c844e7e1ee6263eca6f4",
  "document_type": "id_card",
  "document_country": "BJ",
  "status": "verified",
  "verified_at": "2025-03-21T00:16:41.000000Z",
  "created_at": "2025-03-19T08:28:31.000000Z",
  "updated_at": "2025-03-21T00:16:41.000000Z",
  "expires_at": "2025-05-04T17:54:54.000000Z",
  "app_id": "01jpgh0xygvb28n40c0fv3rqws",
  "customer_id": null,
  "client_reference_id": null,
  "mode": "test",
  "options": {},
  "verified_outputs": {
    "sex": "M",
    "name": "John",
    "surname": "Doe",
    "country": "BEN",
    "full_name": "M. John Doe",
    "nationality": "BEN",
    "date_of_birth": "1988-03-25",
    "document_type": "I",
    "document_number": "100679613",
    "expiration_date": "2029-10-15",
    "personal_number": "2462343165"
  },
  "metadata": {},
  "last_error": [],
  "return_url": null,
  "url": "https://www.sotaid.com/verify/vs_01982e011279c844e7e1ee6263eca6f4",
  "document": {
    "name": "Carte nationale d'identité",
    "country": "Bénin"
  }
}

Example Response - listVerificationSessions:

{
  "results": [
    {
      "id": "vs_01982e011279c844e7e1ee6263eca6f4",
      "document_type": "id_card",
      "document_country": "BJ",
      "status": "verified",
      "created_at": "2025-03-19T08:28:31.000000Z",
      "updated_at": "2025-03-21T00:16:41.000000Z"
    },
    {
      "id": "vs_01982e011279c844e7e1ee6263eca6f5",
      "document_type": "passport",
      "document_country": "FR",
      "status": "pending",
      "created_at": "2025-03-20T10:15:22.000000Z",
      "updated_at": "2025-03-20T10:15:22.000000Z"
    }
  ],
  "next": "https://api.sotaid.com/verification_sessions?cursor=...",
  "previous": null
}

Customer Management

// Create a new customer
Future<Map<String, dynamic>> createCustomer(Map<String, dynamic> customerData)

// Update an existing customer
Future<Map<String, dynamic>> updateCustomer(String customerId, Map<String, dynamic> customerData)

// Get customer by ID
Future<Map<String, dynamic>> getCustomer(String customerId)

// List all customers with optional filtering
Future<Map<String, dynamic>> listCustomers({String? email, int? limit})

// Delete a customer
Future<bool> deleteCustomer(String customerId)

Example Response - createCustomer:

{
  "id": "cus_01982dfc50c7fb71bd3e1544a5a5b928",
  "name": "John Doe",
  "email": "[email protected]",
  "phone": "+33123456789",
  "description": "Test customer",
  "mode": "test",
  "metadata": {
    "company": "Example Corp",
    "department": "Engineering"
  },
  "created_at": "2025-03-19T08:28:31.000000Z",
  "updated_at": "2025-03-19T08:28:31.000000Z"
}

Example Response - getCustomer:

{
  "id": "cus_01982dfc50c7fb71bd3e1544a5a5b928",
  "name": "John Doe",
  "email": "[email protected]",
  "phone": "+33123456789",
  "description": "Test customer",
  "mode": "test",
  "metadata": {
    "company": "Example Corp",
    "department": "Engineering"
  },
  "created_at": "2025-03-19T08:28:31.000000Z",
  "updated_at": "2025-03-21T00:16:41.000000Z"
}

Example Response - listCustomers:

{
  "results": [
    {
      "id": "cus_01982dfc50c7fb71bd3e1544a5a5b928",
      "name": "John Doe",
      "email": "[email protected]",
      "phone": "+33123456789",
      "created_at": "2025-03-19T08:28:31.000000Z"
    },
    {
      "id": "cus_01982dfc50c7fb71bd3e1544a5a5b929",
      "name": "Jane Smith",
      "email": "[email protected]",
      "phone": "+33987654321",
      "created_at": "2025-03-20T14:30:15.000000Z"
    }
  ],
  "next": "https://api.sotaid.com/customers?cursor=...",
  "previous": null
}

Example Response - updateCustomer:

{
  "id": "cus_01982dfc50c7fb71bd3e1544a5a5b928",
  "name": "John Smith",
  "email": "[email protected]",
  "phone": "+33123456789",
  "description": "Updated customer",
  "mode": "test",
  "metadata": {
    "company": "Updated Corp",
    "department": "Engineering"
  },
  "created_at": "2025-03-19T08:28:31.000000Z",
  "updated_at": "2025-03-21T00:16:41.000000Z"
}

Example Response - deleteCustomer:

true

NFC Document Reading

// Read document data using NFC
Future<Map<String, dynamic>?> readNfcDocument(String documentType)

Example Response - readNfcDocument:

{
  "name": "John",
  "surname": "Doe",
  "personal_number": "123456789",
  "gender": "MALE",
  "date_of_birth": "1988-03-25",
  "date_of_expiry": "2029-10-15",
  "document_number": "100679613",
  "nationality": "BEN",
  "issuer_authority": "Ministry of Interior",
  "document_type": "id_card",
  "document_country": "BJ",
  "faceImageBase64": "iVBORw0KGgoAAAANSUhEUgAA...",
  "portraitImageBase64": "iVBORw0KGgoAAAANSUhEUgAA...",
  "signatureBase64": "iVBORw0KGgoAAAANSUhEUgAA..."
}

Verification Flow Responses

// Complete verification response
Future<VerificationResponse> startCompleteVerification(...)

// Face verification response  
Future<VerificationResponse> startFaceVerification(...)

// Liveness detection response
Future<VerificationResponse> startVerificationFlow(...)

Example Response - VerificationResponse:

{
  "status": "verified",
  "message": "Identity verification completed successfully",
  "sessionId": "vs_01982e011279c844e7e1ee6263eca6f4",
  "verifiedAt": "2025-03-21T00:16:41.000000Z",
  "documentData": {
    "documentType": "id_card",
    "documentCountry": "BJ",
    "documentNumber": "100679613",
    "expiryDate": "2029-10-15"
  },
  "faceData": {
    "livenessScore": 0.98,
    "faceMatchScore": 0.95,
    "qualityScore": 0.92
  }
}

Example Response - Pending Verification:

{
  "status": "requires_manual_verification",
  "message": "Verification is being processed manually",
  "sessionId": "vs_01982e011279c844e7e1ee6263eca6f4",
  "estimatedCompletion": "2025-03-22T00:00:00.000000Z"
}

Example Response - Failed Verification:

{
  "status": "failed",
  "message": "Document verification failed - poor image quality",
  "sessionId": "vs_01982e011279c844e7e1ee6263eca6f4",
  "errors": [
    "Document image is blurry",
    "MRZ line not clearly visible",
    "Face image quality below threshold"
  ]
}

Real Data Response Examples #

Verification Session Response

When you call getVerificationSession(), you'll receive real verification data like this:

{
  "id": "vs_01982e011279c844e7e1ee6263eca6f4",
  "document_type": "id_card",
  "document_country": "BJ",
  "status": "verified",
  "verified_at": "2025-03-21T00:16:41.000000Z",
  "created_at": "2025-03-19T08:28:31.000000Z",
  "updated_at": "2025-03-21T00:16:41.000000Z",
  "expires_at": "2025-05-04T17:54:54.000000Z",
  "app_id": "01jpgh0xygvb28n40c0fv3rqws",
  "customer_id": null,
  "client_reference_id": null,
  "mode": "test",
  "options": {},
  "verified_outputs": {
    "sex": "M",
    "name": "John",
    "surname": "Doe",
    "country": "BEN",
    "full_name": "M. John Doe",
    "nationality": "BEN",
    "date_of_birth": "1988-03-25",
    "document_type": "I",
    "document_number": "100679613",
    "expiration_date": "2029-10-15",
    "personal_number": "2462343165"
  },
  "metadata": {},
  "last_error": [],
  "return_url": null,
  "url": "https://www.sotaid.com/verify/vs_01982e011279c844e7e1ee6263eca6f4",
  "document": {
    "name": "Carte nationale d'identité",
    "country": "Bénin"
  }
}

Customer Response

When you call getCustomer(), you'll receive real customer data like this:

{
  "id": "cus_01982dfc50c7fb71bd3e1544a5a5b928",
  "name": "John Doe",
  "email": "[email protected]",
  "phone": null,
  "description": null,
  "mode": "test",
  "metadata": {},
  "created_at": "2025-03-19T08:28:31.000000Z",
  "updated_at": "2025-03-21T00:16:41.000000Z"
}

List Response

When you call listVerificationSessions() or listCustomers(), you'll receive paginated results with real data:

{
  "results": [
    // Array of actual verification sessions or customers
  ],
  "next": "https://api.sotaid.com/verification_sessions?cursor=...",
  "previous": null
}

Important Notes About Real Data #

Live Data: All API responses contain real, live data from your SotaID account ✅ Real-Time Updates: Verification status and customer information are updated in real-time ✅ Production Ready: Data includes actual verification results, customer records, and session information ✅ Secure: All data is transmitted securely using your bearer token authentication ✅ Filtered: You only see data associated with your app ID and authentication credentials

Note: The examples above show the actual data structure you'll receive. Replace the placeholder values with your real bearer token and app configuration to get live data from your SotaID account.

NFC Features #

Supported Document Types #

  • e-Passports (ICAO 9303 compliant)
  • e-ID Cards with NFC capabilities
  • National ID Cards with embedded chips

NFC Reading Capabilities #

  • MRZ (Machine Readable Zone) Scanning: Automatic capture of document data line
  • Biometric Data Extraction: Face images from document chips
  • Personal Information: Name, date of birth, nationality, document number
  • Document Details: Issuing authority, document type, expiry date
  • Additional Data: Address, profession, place of birth (when available)

Security Features #

  • BAC (Basic Access Control): Secure authentication with document
  • PACE (Password Authenticated Connection Establishment): Enhanced security protocol
  • Encrypted Communication: All NFC communication is encrypted
  • Data Integrity: Verification of document authenticity

Getting Started #

Add the plugin to your pubspec.yaml:

dependencies:
  sotaid_pluging: ^latest_version

Android Setup #

1. Permissions

Add the following permissions to your android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

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

2. Application Configuration

Add the following to your android/app/src/main/AndroidManifest.xml inside the <application> tag:

<!-- NFC Reader Plugin Activities -->
<activity
    android:name="com.sotaid.nfc_reader.MRZReaderActivity"
    android:exported="false"
    android:theme="@style/NfcReaderTheme"
    android:label="@string/title_activity_mrzreader"
    tools:replace="android:theme" />
<activity
    android:name="com.sotaid.nfc_reader.NfcReaderActivity"
    android:theme="@style/NfcReaderTheme"
    tools:replace="android:theme" />

<!-- NFC Reader Plugin Meta-data -->
<meta-data
    android:name="com.google.mlkit.vision.DEPENDENCIES"
    android:value="ocr" />
<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="com.sotaid.nfc_reader.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

3. Dependencies

Add NFC reader dependencies to your android/app/build.gradle.kts:

dependencies {
    // NFC Reader Dependencies
    implementation("org.jmrtd:jmrtd:0.7.26")
    implementation("net.sf.scuba:scuba-sc-android:0.0.23")
    implementation("com.github.mhshams:jnbis:1.0.5")
    implementation("edu.ucar:jj2000:5.2")
    implementation("com.google.code.gson:gson:2.13.0")
    
    // ML Kit for MRZ scanning
    implementation("com.google.android.gms:play-services-vision:20.1.3")
    implementation("com.google.mlkit:text-recognition:16.0.0")
    implementation("com.google.mlkit:text-recognition-chinese:16.0.0")
    implementation("com.google.mlkit:text-recognition-devanagari:16.0.0")
    implementation("com.google.mlkit:text-recognition-japanese:16.0.0")
    implementation("com.google.mlkit:text-recognition-korean:16.0.0")
    implementation("com.google.mlkit:vision-common:17.3.0")
    
    // Camera support
    implementation("androidx.camera:camera-core:1.3.1")
    implementation("androidx.camera:camera-camera2:1.3.1")
    implementation("androidx.camera:camera-lifecycle:1.3.1")
    implementation("androidx.camera:camera-video:1.3.1")
    implementation("androidx.camera:camera-view:1.3.1")
    
    // AndroidX dependencies
    implementation("androidx.activity:activity:1.8.2")
    implementation("androidx.activity:activity-compose:1.8.2")
    implementation("androidx.constraintlayout:constraintlayout:2.1.4")
    implementation("androidx.lifecycle:lifecycle-livedata:2.7.0")
    implementation("androidx.lifecycle:lifecycle-viewmodel:2.7.0")
    implementation("androidx.navigation:navigation-fragment:2.7.6")
    implementation("androidx.navigation:navigation-ui:2.7.6")
    implementation("androidx.appcompat:appcompat:1.6.1")
    implementation("com.google.android.material:material:1.11.0")
}

4. Resource Files

Create the following resource files in your android/app/src/main/res/ directory:

res/xml/file_paths.xml:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Pour accès au cache -->
    <cache-path name="cache" path="." />

    <!-- (optionnel) Pour enregistrer dans files/ -->
    <files-path name="files" path="." />

    <!-- (optionnel) Pour accès au stockage public (ex: Movies/) -->
    <external-path name="external" path="." />
</paths>

res/xml/nfc_tech_filter.xml:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.IsoDep</tech>
    </tech-list>
</resources>

res/values/strings.xml (add these strings):

<resources>
    <!-- NFC Reader Plugin Messages - French -->
    
    <!-- Reading process messages -->
    <string name="reading_document">Lecture du document. Ne déplacez ni le document ni le téléphone pendant la lecture.</string>
    <string name="document_read_success">Document lu avec succès !</string>
    <string name="document_read_failed">Échec de la lecture du document ou aucun document détecté.</string>
    <string name="unexpected_error">Erreur inattendue : </string>
    <string name="error">Erreur : </string>
    
    <!-- NFC related messages -->
    <string name="nfc_not_supported">NFC non pris en charge</string>
    <string name="nfc_reading_title">Lire la puce NFC</string>
    <string name="nfc_reading_description">Placez le téléphone sur le document. Ne déplacez ni le document ni le téléphone pendant la lecture.</string>
    <string name="start_reading">Démarrer la lecture</string>
    <string name="reading_document_nfc">Lecture du document. Ne déplacez ni le document ni le téléphone pendant la lecture.</string>
    <string name="document_read_success_nfc">Lecture document réussie ✅</string>
    
    <!-- Permission messages -->
    <string name="permissions_not_granted">Permissions non accordées</string>
    <string name="camera_permission_required">Permission caméra requise pour scanner les documents</string>
    <string name="nfc_permission_required">Permission NFC requise pour lire les documents</string>
    
    <!-- Document types -->
    <string name="passport">Passeport</string>
    <string name="id_card">Carte d\'identité</string>
    <string name="other">Autre</string>
    
    <!-- Document fields -->
    <string name="name">Nom</string>
    <string name="surname">Prénom</string>
    <string name="personal_number">Numéro personnel</string>
    <string name="gender">Genre</string>
    <string name="date_of_birth">Date de naissance</string>
    <string name="date_of_expiry">Date d\'expiration</string>
    <string name="document_number">Numéro de document</string>
    <string name="nationality">Nationalité</string>
    <string name="issuer_authority">Autorité émettrice</string>
    <string name="document_type">Type de document</string>
    <string name="document_country">Pays du document</string>
    
    <!-- UI elements -->
    <string name="start">Commencer</string>
    <string name="begin">Démarrer</string>
    <string name="cancel">Annuler</string>
    <string name="ok">OK</string>
    <string name="retry">Réessayer</string>
    <string name="close">Fermer</string>
    
    <!-- Status messages -->
    <string name="processing">Traitement...</string>
    <string name="scanning">Numérisation...</string>
    <string name="connecting">Connexion...</string>
    <string name="authenticating">Authentification...</string>
    <string name="reading_data">Lecture des données...</string>
    
    <!-- Image related messages -->
    <string name="no_image_available">Aucune image disponible</string>
    <string name="image_load_failed">Échec du chargement de l\'image</string>
    <string name="image_not_available">Image non disponible</string>
    
    <!-- Section headers -->
    <string name="personal_information">Informations personnelles</string>
    <string name="document_information">Informations document</string>
    
    <!-- Legacy strings -->
    <string name="hello_blank_fragment">Hello blank fragment</string>
    <string name="title_activity_mrzreader">MRZReaderActivity</string>
    <string name="title_home">Home</string>
    <string name="title_dashboard">Dashboard</string>
    <string name="title_notifications">Notifications</string>
</resources>

res/values/colors.xml (add these colors):

<resources>
    <!-- NFC Reader Plugin Colors -->
    <color name="colorPrimary">#2196F3</color>
    <color name="colorPrimaryDark">#1976D2</color>
    <color name="colorAccent">#FF4081</color>
</resources>

res/values/styles.xml (add this style):

<resources>
    <!-- NFC Reader Plugin Theme -->
    <style name="NfcReaderTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowFullscreen">false</item>
    </style>
</resources>

4.1 Files to copy from the example app (NFC)

Copy the following files from the example app into your app to enable NFC:

  • From example/android/app/src/main/res/xml/file_paths.xml → to android/app/src/main/res/xml/file_paths.xml

  • From example/android/app/src/main/res/xml/nfc_tech_filter.xml → to android/app/src/main/res/xml/nfc_tech_filter.xml

  • Merge from example/android/app/src/main/res/values/strings.xml → into your android/app/src/main/res/values/strings.xml

    • Include the NFC-related strings shown above (reading messages, permission texts, titles)
  • Merge from example/android/app/src/main/res/values/colors.xml → into your android/app/src/main/res/values/colors.xml

    • Ensure colorPrimary, colorPrimaryDark, colorAccent exist (or adapt to your theme names)
  • Merge from example/android/app/src/main/res/values/styles.xml → into your android/app/src/main/res/values/styles.xml

    • Ensure NfcReaderTheme exists as shown above
  • Java sources (NFC package): copy the entire folder

    • From: example/android/app/src/main/java/com/sotaid/nfc_reader/
    • To: android/app/src/main/java/com/sotaid/nfc_reader/
  • Generated plugin registrant (only if your build setup requires it)

    • From: example/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java
    • To: android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java
    • Note: this file is normally auto-generated by Flutter; copy only if the file is missing or you are creating a pure-native host that doesn't run Flutter's codegen.
  • Raw resources (audio cues used by the reader UI)

    • From: example/android/app/src/main/res/raw/
    • To: android/app/src/main/res/raw/
    • Files:
      • notification_decorative_01.wav
      • notification_decorative_02.wav

And update your manifest (android/app/src/main/AndroidManifest.xml) by copying these blocks from the example and adapting the authorities to your applicationId:

<!-- Activities -->
<activity
    android:name="com.sotaid.nfc_reader.MRZReaderActivity"
    android:exported="false"
    android:theme="@style/NfcReaderTheme"
    android:label="@string/title_activity_mrzreader"
    tools:replace="android:theme" />
<activity
    android:name="com.sotaid.nfc_reader.NfcReaderActivity"
    android:theme="@style/NfcReaderTheme"
    tools:replace="android:theme" />

<!-- ML Kit dependency declaration -->
<meta-data
    android:name="com.google.mlkit.vision.DEPENDENCIES"
    android:value="ocr" />

<!-- File provider for camera/NFC plugin -->
<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="<your.application.id>.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

ProGuard rules: copy the NFC-related rules from example/android/app/proguard-rules.pro into your app’s android/app/proguard-rules.pro (append if the file exists).

Gradle dependencies: replicate the NFC and ML Kit dependencies from the example into your android/app/build.gradle(.kts) as shown in the Dependencies section above.

5. Proguard Rules

Add to your android/app/proguard-rules.pro:

# ProGuard rules for NFC functionality
# Exclude Java AWT classes that don't exist on Android
-dontwarn java.awt.**
-keep class java.awt.** { *; }

# Exclude jj2000 display classes that use AWT
-dontwarn jj2000.disp.**
-keep class jj2000.disp.** { *; }

# Keep core jj2000 functionality
-keep class jj2000.j2k.decoder.Decoder { *; }
-keep class jj2000.j2k.util.ParameterList { *; }
-keep class jj2000.j2k.image.** { *; }

# Keep Flutter and plugin classes
-keep class io.flutter.** { *; }
-keep class io.flutter.plugins.** { *; }
-keep class com.example.sotaid_pluging.** { *; }
-keep class com.sotaid.nfc_reader.** { *; }

# Keep Google Play Core classes
-keep class com.google.android.play.core.** { *; }
-dontwarn com.google.android.play.core.**

# Keep ML Kit classes
-keep class com.google.mlkit.** { *; }
-dontwarn com.google.mlkit.**

# Keep specific ML Kit text recognition classes
-keep class com.google.mlkit.vision.text.chinese.** { *; }
-keep class com.google.mlkit.vision.text.devanagari.** { *; }
-keep class com.google.mlkit.vision.text.japanese.** { *; }
-keep class com.google.mlkit.vision.text.korean.** { *; }

# Keep NFC reader plugin classes
-keep class com.sotaid.nfc_reader.** { *; }
-keep class org.jmrtd.** { *; }
-keep class net.sf.scuba.** { *; }
-keep class com.github.mhshams.** { *; }
-keep class edu.ucar.** { *; }
-keep class org.bouncycastle.** { *; }

# Keep NFC reader plugin activities
-keep public class com.sotaid.nfc_reader.NfcReaderActivity
-keep public class com.sotaid.nfc_reader.MRZReaderActivity

# Keep native methods
-keepclasseswithmembernames class * {
    native <methods>;
}

# Keep Parcelable implementations
-keepclassmembers class * implements android.os.Parcelable {
    static ** CREATOR;
}

# Keep Serializable classes
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

Basic Usage #

Plugin Initialization #

import 'package:sotaid_pluging/sotaid_plugin.dart';

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final SotaIdPlugin _plugin = SotaIdPlugin();
  String _bearerToken = 'your_bearer_token'; // Replace with your actual token

  @override
  void initState() {
    super.initState();
    _plugin.initialize(bearerToken: _bearerToken);
  }
}

Verification Flows #

1. Full Verification Flow (Complete KYC) #

void _startCompleteVerification() async {
  await _plugin.startCompleteVerification(
    context: context,
    onVerificationComplete: (response) {
      print('Verification completed: ${response.status}');
      // Handle successful verification
    },
    onError: (error) {
      print('Verification error: $error');
      // Handle verification error
    },
  );
}

2. Face Matching Verification #

void _startFaceVerification() async {
  // Navigate to image upload page first
  final result = await Navigator.of(context).push(
    MaterialPageRoute(
      builder: (context) => ImageUploadPage(
        bearerToken: _bearerToken,
      ),
    ),
  );
}

3. Liveness Detection #

void _startLivenessVerification() async {
  await _plugin.startVerificationFlow(
    context: context,
    verificationType: VerificationType.liveness,
    onVerificationComplete: (response) {
      print('Liveness detection completed: ${response.status}');
    },
    onError: (error) {
      print('Liveness detection error: $error');
    },
  );
}

NFC Document Reading #

// Check NFC availability
Future<void> _checkNfcAvailability() async {
  final isAvailable = await _plugin.isNfcAvailable();
  final isEnabled = await _plugin.isNfcEnabled();
  
  print('NFC Available: $isAvailable');
  print('NFC Enabled: $isEnabled');
}

// Read NFC document
Future<void> _readNfcDocument() async {
  try {
    final result = await _plugin.readNfcDocument('passport'); // or 'id_card'
    
    if (result != null) {
      print('Document read successfully!');
      print('Name: ${result['name']}');
      print('Surname: ${result['surname']}');
      print('Personal Number: ${result['personal_number']}');
      print('Nationality: ${result['nationality']}');
      print('Issuer Authority: ${result['issuer_authority']}');
      print('Document Type: ${result['document_type']}');
      print('Document Country: ${result['document_country']}');
      print('Date of Birth: ${result['date_of_birth']}');
      print('Date of Expiry: ${result['date_of_expiry']}');
      print('Document Number: ${result['document_number']}');
      print('Gender: ${result['gender']}');
      
      // Face image is available as base64
      if (result['faceImageBase64'] != null) {
        print('Face image available: ${result['faceImageBase64'].length} characters');
      }
    }
  } catch (e) {
    print('NFC reading error: $e');
  }
}

Configuration #

Bearer Token #

The plugin requires a bearer token for API authentication. Define your bearer token as a variable in your app (replace with your actual token):

// Example: define your bearer token (replace with your actual token)
String _bearerToken = 'your_bearer_token';

// Initialize plugin with the token
_plugin.initialize(bearerToken: _bearerToken);

Environment Mode #

The plugin defaults to sandbox mode. You can change this during initialization:

_plugin.initialize(
  sandboxMode: false, // Set to false for production
  bearerToken: _bearerToken,
);

NFC Configuration #

NFC is automatically configured when the plugin is initialized. The plugin will:

  1. Check NFC availability on device startup
  2. Request NFC permissions when needed
  3. Handle NFC state changes automatically
  4. Provide user feedback during NFC operations

Permissions #

The plugin automatically handles camera, storage, and NFC permissions. Users will be prompted for permissions when needed during the verification process.

Required Permissions #

  • Camera: For document and face capture
  • Storage: For temporary file storage
  • NFC: For reading e-documents (Android only)
  • Vibration: For NFC feedback

Session Management #

The plugin automatically manages verification sessions, especially for manual verification processes:

Automatic Session Storage #

  • When a verification returns requires_manual_verification status, the session is automatically stored locally
  • Session information includes session ID, status, and creation timestamp

Pending Verification Reminder #

  • When users try to start a new verification, the plugin checks for existing pending verifications
  • If a pending manual verification exists, users are prompted with options:
    • "Vérifier le statut": Check the current status of the pending verification
    • "Nouvelle vérification": Start a new verification process

Status Checking #

  • Users can check the status of pending verifications
  • The plugin fetches the latest status from the server
  • Shows appropriate messages based on current status:
    • Verified: Success message with option to clear session
    • Failed: Error message with option to start new verification
    • Pending: Shows time since submission with current status

Automatic Cleanup #

  • Sessions are automatically cleared when verification completes (success or failure)
  • No manual cleanup required

NFC Troubleshooting #

Common Issues #

NFC Not Available

  • Check device compatibility: Ensure device supports NFC
  • Enable NFC: Go to Settings > Connected devices > Connection preferences > NFC
  • Check Android version: NFC requires Android 4.0+

NFC Reading Fails

  • Check document compatibility: Ensure document has NFC chip
  • Position correctly: Hold device close to document chip
  • Remove case: Metal cases can interfere with NFC
  • Check battery: Low battery can affect NFC performance

MRZ Scanning Issues

  • Good lighting: Ensure document is well-lit
  • Clean document: Remove any dirt or damage
  • Hold steady: Keep device steady during scanning
  • Check angle: Ensure MRZ line is clearly visible

Debug Information #

Enable debug logging to troubleshoot NFC issues:

// Check NFC status
final isAvailable = await _plugin.isNfcAvailable();
final isEnabled = await _plugin.isNfcEnabled();

print('NFC Status:');
print('  Available: $isAvailable');
print('  Enabled: $isEnabled');

Example #

See the example/ directory for a complete working example demonstrating:

  • App-controlled verification API
  • Legacy verification flow
  • NFC document reading
  • Permission handling
  • Error handling

Migration from Previous Versions #

If you were using the previous version where users could choose verification types:

  1. Remove verification type selection UI from your app
  2. Use the new app-controlled API (startCompleteVerification() or startFaceVerification())
  3. Decide verification type in your app logic based on your business requirements
  4. Update your verification flow calls to include the required verificationType parameter
  5. Add NFC functionality if needed for e-document reading

License #

This project is licensed under the MIT License - see the LICENSE file for details.

0
likes
125
points
0
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter plugin for integrating SotaBoost's identity verification service into Flutter applications

Homepage

Documentation

API reference

License

MIT (license)

Dependencies

camera, dio, dropdown_button2, flutter, http, http_parser, image, image_picker, plugin_platform_interface, shared_preferences, video_player

More

Packages that depend on sotaid_pluging

Packages that implement sotaid_pluging