sotaid_pluging 1.1.1+1
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→ toandroid/app/src/main/res/xml/file_paths.xml -
From
example/android/app/src/main/res/xml/nfc_tech_filter.xml→ toandroid/app/src/main/res/xml/nfc_tech_filter.xml -
Merge from
example/android/app/src/main/res/values/strings.xml→ into yourandroid/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 yourandroid/app/src/main/res/values/colors.xml- Ensure
colorPrimary,colorPrimaryDark,colorAccentexist (or adapt to your theme names)
- Ensure
-
Merge from
example/android/app/src/main/res/values/styles.xml→ into yourandroid/app/src/main/res/values/styles.xml- Ensure
NfcReaderThemeexists as shown above
- Ensure
-
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/
- From:
-
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.
- From:
-
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.wavnotification_decorative_02.wav
- From:
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:
- Check NFC availability on device startup
- Request NFC permissions when needed
- Handle NFC state changes automatically
- 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_verificationstatus, 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:
- Remove verification type selection UI from your app
- Use the new app-controlled API (
startCompleteVerification()orstartFaceVerification()) - Decide verification type in your app logic based on your business requirements
- Update your verification flow calls to include the required
verificationTypeparameter - Add NFC functionality if needed for e-document reading
License #
This project is licensed under the MIT License - see the LICENSE file for details.