Digified Flutter Plugin

pub package

Flutter plugin for integrating Digified's proprietary Arabic eKYC (electronic Know Your Customer) and eContract (electronic Contract) SDKs into your Flutter applications. Digified provides end-to-end digital identity verification and electronic contract solutions optimized for Arabic markets.

Features

  • Arabic eKYC: Full Arabic electronic identity verification solution with:

    • Document digitization and OCR for Arabic IDs
    • Face matching and anti-spoofing detection
    • Government database authentication
    • Fraud detection and compliance
    • Seamless customer onboarding
  • eContract: Complete electronic contract management with:

    • Digital contract templates
    • Electronic signatures
    • Face matching for signer verification
    • Payment verification integration
    • OTP verification
    • Real-time contract status tracking
  • Cross-Platform: Native Android and iOS SDK integration

  • Easy Integration: Simple API with comprehensive documentation

  • Production Ready: Used by financial institutions and enterprises across the Middle East

Installation

Add this to your package's pubspec.yaml file:

dependencies:
  digified_flutter_plugin: ^0.0.6

Then run:

flutter pub get

Platform Setup

Android Setup

1. Add Maven Central Repository

The Digified Android SDK (version 0.0.3) is available on Maven Central. Ensure your Android project has Maven Central in the repository list.

In your project's android/settings.gradle.kts file (or settings.gradle for Groovy):

dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral() // Make sure this is present
        maven { url = uri("https://jitpack.io") }
    }
}

2. Update Minimum SDK Version

In your android/app/build.gradle.kts (or build.gradle), set the minimum SDK to 24:

android {
    defaultConfig {
        minSdk = 24
        // ...
    }
}

3. Configure Hilt Dependency Injection

The Digified SDK requires Hilt for dependency injection. Add the following to your Android project:

In android/settings.gradle.kts:

pluginManagement {
    plugins {
        id("com.google.dagger.hilt.android") version "2.57.1" apply false
    }
}

In android/app/build.gradle.kts:

plugins {
    id("com.android.application")
    id("kotlin-android")
    id("com.google.dagger.hilt.android")
    id("kotlin-kapt")
}

dependencies {
    implementation("androidx.appcompat:appcompat:1.7.1")
    implementation("com.google.android.material:material:1.12.0")
    implementation("com.google.dagger:hilt-android:2.57.1")
    implementation("androidx.hilt:hilt-work:1.3.0")
    implementation("androidx.work:work-runtime-ktx:2.10.5")
    implementation("io.digified:digified-ekyc:0.0.3")
    
    kapt("com.google.dagger:hilt-compiler:2.57.1")
}

4. Host Flutter in an AppCompatActivity (Required)

Important: The native Digified Android SDK requires an AppCompatActivity host. You cannot use the default FlutterActivity directly.

Use AppCompatActivity with a FlutterFragment to properly host Flutter while maintaining SDK compatibility:

android/app/src/main/kotlin/your/package/name/MainActivity.kt:

package your.package.name

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import io.flutter.embedding.android.FlutterFragment

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (savedInstanceState == null) {
            val flutterFragment = FlutterFragment.withNewEngine()
                .initialRoute("/")
                .build<FlutterFragment>()

            supportFragmentManager
                .beginTransaction()
                .replace(android.R.id.content, flutterFragment)
                .commit()
        }
    }
}

If using Hilt, add the annotation:

import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    // ... same implementation
}

Key Points:

  • Replace your.package.name with your actual package name
  • If you have a custom layout, replace android.R.id.content with your container view ID
  • The plugin will show a clear error at runtime if the host activity is not an AppCompatActivity#### 5. Create Application Class with WorkManager Configuration

The Digified SDK uses WorkManager for background tasks. Configure your Application class as follows:

android/app/src/main/kotlin/your/package/name/MainApplication.kt:

package your.package.name

import android.app.Application
import dagger.hilt.android.HiltAndroidApp
import javax.inject.Inject

import androidx.work.Configuration
import io.digified.mobile.android.sdk.ekyc.DaggerWorkerFactory

@HiltAndroidApp
class MainApplication : Application(), Configuration.Provider {

    @Inject
    lateinit var workerFactory: DaggerWorkerFactory

    override val workManagerConfiguration: Configuration
        get() = Configuration.Builder()
            .setWorkerFactory(workerFactory)
            .build()
}

Important: This configuration is required for the Digified SDK's background processing to work correctly.

6. Update AndroidManifest.xml

android/app/src/main/AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="your.package.name">

    <application
        android:name=".MainApplication"
        android:theme="@style/Theme.MaterialComponents.Light.NoActionBar"
        android:label="Your App Name"
        android:icon="@mipmap/ic_launcher">
        
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/Theme.MaterialComponents.Light.NoActionBar"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />

        <!-- Disable automatic WorkManager initialization -->
        <provider
            android:name="androidx.startup.InitializationProvider"
            android:authorities="${applicationId}.androidx-startup"
            android:exported="false"
            tools:node="merge">
            <meta-data
                android:name="androidx.work.WorkManagerInitializer"
                android:value="androidx.startup"
                tools:node="remove" />
        </provider>
    </application>
</manifest>

Key Changes:

  • Add xmlns:tools="http://schemas.android.com/tools" to the manifest root
  • Include android:name=".MainApplication" to reference your custom Application class
  • Add the provider configuration to disable automatic WorkManager initialization (required because we configure it manually in MainApplication)

iOS Setup

1. Update Deployment Target

Set the minimum iOS deployment target to 16.0 in your ios/Podfile:

platform :ios, '16.0'

Also update the deployment target in your Xcode project settings to 16.0.

2. Add Digified CocoaPod

Add the Digified SDK to your ios/Podfile:

source 'https://github.com/CocoaPods/Specs.git'
source 'https://git.digified.io/contrib/digified-ios.git'

target 'Runner' do
  use_frameworks! :linkage => :static
  use_modular_headers!

  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
  
  # Add Digified SDK
  pod 'DigifiedSDK', '~> 1.5.3'
end

3. Install Pods

cd ios
pod install

4. Configure Camera Permissions

The Digified SDK requires camera access for document scanning and face verification. Add the following key to your ios/Runner/Info.plist:

<key>NSCameraUsageDescription</key>
<string>This app requires camera access to verify your identity through document scanning and face recognition.</string>

You can customize the message to match your app's requirements.

Usage

Import the plugin in your Dart code:

import 'package:digified_flutter_plugin/digified_flutter_plugin.dart';

Enable Debug Logging (Optional)

For development and debugging purposes, you can enable detailed SDK logging. This should be done before launching any SDK flows:

import 'package:digified_flutter_plugin/digified_flutter_plugin.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // Enable logging during development
  await DigifiedFlutterPlugin.setLoggingEnabled(true);
  
  runApp(MyApp());
}

Important: Disable logging in production builds to minimize console noise:

// Disable logging for production
await DigifiedFlutterPlugin.setLoggingEnabled(false);

When enabled, the SDK will output detailed logs prefixed with [Digified] on iOS to help with debugging.

Launching eKYC Flow

The eKYC flow performs identity verification and returns a session ID upon completion:

import 'package:digified_flutter_plugin/digified_flutter_plugin.dart';
import 'package:flutter/services.dart';

try {
  final String? ekycSessionId = await DigifiedFlutterPlugin.presentEKYC(
    apiKey: "your_api_key_here", // Required
    baseUrl: "https://api.digified.io/", // Optional, defaults to production
  );
  
  if (ekycSessionId != null) {
    print("eKYC completed successfully!");
    print("Session ID: $ekycSessionId");
    // Use this session ID for eContract or backend verification
  }
} on PlatformException catch (e) {
  print("eKYC failed: ${e.message}");
  // Handle error (user cancelled, verification failed, etc.)
}

Launching eContract Flow

The eContract flow allows users to sign electronic contracts:

import 'package:digified_flutter_plugin/digified_flutter_plugin.dart';
import 'package:flutter/services.dart';

try {
  await DigifiedFlutterPlugin.presentEContract(
    templateVersionID: "ectv_xxxxx", // Required: Your template version ID
    apiKey: "your_api_key_here", // Optional
    baseUrl: "https://api.digified.io/", // Optional
    faceMatchingApiKey: "your_fm_api_key", // Optional
    faceMatchingBaseUrl: "https://facematching.digified.io/", // Optional
    eKYCSessionID: ekycSessionId, // Optional: From previous eKYC flow
    variables: { // Optional: Pre-fill contract fields
      "customer_name": "Ahmed Mohamed",
      "customer_email": "ahmed@example.com",
      "contract_amount": "50000",
    },
  );
  
  print("eContract completed successfully!");
} on PlatformException catch (e) {
  print("eContract failed: ${e.message}");
  // Handle error
}

Complete Example

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:digified_flutter_plugin/digified_flutter_plugin.dart';

void main() {
  runApp(MyApp());
}

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

class _MyAppState extends State<MyApp> {
  String? _ekycSessionId;

  Future<void> _launchEKYC() async {
    try {
      final sessionId = await DigifiedFlutterPlugin.presentEKYC(
        apiKey: "your_api_key_here",
      );
      
      setState(() {
        _ekycSessionId = sessionId;
      });
      
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('eKYC completed! Session: $sessionId')),
      );
    } on PlatformException catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('eKYC failed: ${e.message}')),
      );
    }
  }

  Future<void> _launchEContract() async {
    try {
      await DigifiedFlutterPlugin.presentEContract(
        templateVersionID: "your_template_version_id",
        apiKey: "your_api_key_here",
        eKYCSessionID: _ekycSessionId,
        variables: {
          "customer_name": "Ahmed Mohamed",
          "customer_email": "ahmed@example.com",
        },
      );
      
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('eContract completed successfully!')),
      );
    } on PlatformException catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('eContract failed: ${e.message}')),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Digified Demo'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: _launchEKYC,
                child: Text('Launch eKYC'),
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: _ekycSessionId != null ? _launchEContract : null,
                child: Text('Launch eContract'),
              ),
              if (_ekycSessionId != null)
                Padding(
                  padding: EdgeInsets.all(16),
                  child: Text('Session ID: $_ekycSessionId'),
                ),
            ],
          ),
        ),
      ),
    );
  }
}

Getting API Keys

To use the Digified SDK, you need API keys. Contact Digified customer support through the official website to obtain your API keys and access credentials.

SDK Dependencies

Android

  • Minimum SDK: API 24 (Android 7.0)
  • Kotlin: 2.2.21
  • Hilt: 2.57.1
  • AppCompat & Material Components

iOS

  • iOS 16.0+
  • Swift 5.0+

Troubleshooting

Android Issues

"Activity is null" or "Activity is not AppCompatActivity"

  • Ensure your MainActivity extends AppCompatActivity (see Android Setup section)
  • Verify the @AndroidEntryPoint annotation is present

Hilt Component Generation Failed

  • Check that Hilt plugin is properly configured in both settings.gradle.kts and build.gradle.kts
  • Ensure KAPT is applied: id("kotlin-kapt")
  • Clean and rebuild: flutter clean && flutter run

Build Errors with Material Components

  • Verify your app theme is Theme.MaterialComponents.* in AndroidManifest.xml
  • Check that Material Components dependency is present

Kotlin Version Mismatch

  • Ensure Kotlin version is 2.2.21 or compatible with the SDK
  • Update in android/settings.gradle.kts: kotlin("android") version "2.2.21"

iOS Issues

CocoaPods Installation Failed

  • Verify the private CocoaPods source is added to your Podfile
  • Run pod repo update to refresh the CocoaPods repository
  • Try pod install --repo-update

SDK Not Found

  • Ensure you have access to the Digified private CocoaPods repository
  • Contact Digified support for repository access credentials

Deployment Target Issues

  • Ensure iOS deployment target is set to 16.0 or higher
  • Update in Podfile: platform :ios, '16.0'
  • Update in Xcode project settings: IPHONEOS_DEPLOYMENT_TARGET = 16.0
  • Clean and rebuild: cd ios && pod install && cd .. && flutter clean && flutter run

Additional Resources

License

This plugin is released under the MIT License. See LICENSE for details.

The Digified Android and iOS SDKs are proprietary software owned by Digified. Use of the SDKs requires appropriate licensing from Digified.

Author

Hussein Kishk - hussein.kishk@digified.io

Digified - Digital Identity Verification Solutions

Copyright © 2025 Digified. All rights reserved.