verifai_sdk 1.1.0 copy "verifai_sdk: ^1.1.0" to clipboard
verifai_sdk: ^1.1.0 copied to clipboard

The official Flutter package for Verifai's mobile (iOS and Android) SDK's.

Verifai Flutter SDK #

The official Flutter package for Verifai's mobile (iOS and Android) SDK's.

Verifai offers seamless identity verification solutions for every use case. Easy to implement and customize, while taking the highest privacy and security standards in mind. Integrates effortlessly into mobile and web applications.

Table of contents #

Getting started #

If you're new to Flutter please check out their extensive guides on how to setup your environment here. Otherwise we can go right ahead and get to installing Verifai.

Install Verifai #

To integrate the sdk in your project:

flutter pub add verifai_sdk

This will add it to your pubspec.yaml, more info in the installing tab above.

Add licence #

The Verifai SDK does not work without a valid licence. The licence can be copied from the dashboard, and has to be set with CoreApi's setLicence method, see usage.

Licenses can be made through our dashboard. You'll have to have a solution and add an implementation for iOS and one for Android. Please ensure the identifiers are the same as the bundle identifier (iOS) and package name (Android) you're using in your apps.

An easy way to store the licence and keep it outside version control, is to copy it in a local licence.dart file next to your main.dart. Add licence.dart to your .gitignore file. It can look approximately like this:

var verifaiLicence = '''=== Verifai Licence file V2 ===
VQUHzC3sNld8uy8pBHMTFtLxrItlQlkL+7wX3QdVi3tFlXgxUnJhqPD510hLplCxp83o6gwOftCm
...
...
HF/w/+n6SRQso55nIQSUX8uYP8WpJVmi+Gi9aA==''';

Then import the licence variable in your main.dart like this:

import 'licence.dart';

Android #

In order for the sdk to find the native Android libraries add the Verifai maven repository in your root build.gradle file:

allprojects {
    repositories {
        maven { url 'https://dashboard.verifai.com/downloads/sdk/maven/' }
    }
}

To avoid conflicts between native Android runtime libraries, add the packagingOptions code snippet in the build.gradle file of your app, not in the root!

android {
    packagingOptions {
        jniLibs {
            pickFirsts += ['**/*.so']
        }
    }
}

If you run into memory errors during the build of your app, uncomment (or if it is not there add) the following line in your gradle.properties file:

org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

iOS #

The dependencies required for iOS are all handled by Flutter. So as long as you've run flutter pub get then all the native dependencies should have been installed.

Usage #

The SDK has 3 modules:

  • Core: The core scanning functionality
  • NFC: Performs an NFC scan on the document (compatible device required)
  • Liveness: Performs a liveness check and optionally a face matching check

Core #

An example on how to run the most basic core functionality

import 'package:verifai_sdk/verifai_sdk.dart';

// Import licence variable stored in a local licence.dart file that is ignored by
// version control
import 'licence.dart';

// When the Core module finishes, an action is cancelled or an error is given these
// listeners will handle the returned object. The result object in the onSuccess
// listener conforms to the `CoreResult` object. The image results have been
// reworked to return something react native can understand. Read the
// documentation for more info.

// First set up the listeners, a good way of doing this is to 
// define a class that extends Flutter's `ChangeNotifier`.
// In the example folder you can see an example of this.
class CoreResultImpl with ChangeNotifier implements CoreResultApi {
    
  CoreResultImpl() {
    CoreResultApi.setup(this);
  }

  var _data = CoreResult();
  CoreResult get data => _data;
  set data(CoreResult value) {
    print(value.mrzData?.firstName);
    print(value.mrzData?.lastName);
    _data = value;
    notifyListeners();
  }

  @override
  void onSuccess(CoreResult result) {
    data = result;
  }

  @override
  void onCancelled() {
    print('cancelled');
  }

  @override
  void onError(String message) {
    throw Exception(message);
  }
}

// Define the Core's api implementation
var api = CoreApi();

// Set the licence (more info in the documentation)
// the `verifaiLicence` variable is defined in licence.dart as
// we talked about above
await api.setLicence(verifaiLicence);

// You can configure many aspects of the SDK, check 
// our documentation or further down in this README for more 
// info. First we'll just do something very simple.
api.configure(Configuration(enableVisualInspection: true));

// Start the SDK, this displays the SDK on the screen. 
// The result is returned through the listeners
await api.start();

NFC #

Let's look at an example on how to run the most basic NFC functionality. The NFC module can only be run after a scan from the Core module has been performed.


// When the Core module finishes, an action is cancelled or an error is given these
// listeners will handle the returned object. The result object in the onSuccess
// listener conforms to the `NfcResult ` object. The image results have been
// reworked to return something react native can understand. Read the
// documentation for more info.

// First set up the listeners, a good way of doing this is to 
// define a class that extends Flutter's `ChangeNotifier`.
// In the example folder you can see an example of this.
class NfcResultImpl with ChangeNotifier implements NfcResultApi {
  NfcResultImpl() {
    NfcResultApi.setup(this);
  }

  var _data = NfcResult();
  NfcResult get data => _data;
  set data(NfcResult value) {
    _data = value;
    notifyListeners();
  }

  @override
  void onSuccess(NfcResult result) {
    data = result;
  }

  @override
  void onCancelled() {
    print('cancelled');
  }

  @override
  void onError(String message) {
    print(message);
    throw Exception(message);
  }
}

// Now we can start the NFC SDK. This will present the scanning screen. There
// are a few things we can setup while starting the NFC check to see the full
// list check out the documentation. Important: For the NFC check to work
// properly the core scan should have been performed.
var api = NfcApi();
var coreData = context.read<CoreResultImpl>().data;
if (coreData.mrzData != null) {
  await api.start(NfcConfiguration(retrieveImage: true), coreData);
  Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => const NfcResult()),
  );
} else {
  print("No core result mrz data");
}

Liveness #

An example on how to run the most basic Liveness functionality. The Liveness module can only be run after a scan from the Core module has been performed. Also you need to make sure the licence has been setup by the Core before running the Liveness module.

// When the Core module finishes or an error is given these
// listeners will handle the returned object. The result object in the onSuccess
// listener conforms to the `LivenessResult` object. The image results have been
// reworked to return something react native can understand. Read the
// documentation for more info.

// First set up the listeners, a good way of doing this is to 
// define a class that extends Flutter's `ChangeNotifier`.
// In the example folder you can see an example of this.
class LivenessResultImpl with ChangeNotifier implements LivenessResultApi {
  LivenessResultImpl() {
    LivenessResultApi.setup(this);
  }

  var _data = LivenessResult();
  LivenessResult get data => _data;
  set data(LivenessResult value) {
    _data = value;
    notifyListeners();
  }

  @override
  void onSuccess(LivenessResult result) {
    data = result;
    print(result.automaticChecksPassed);
    print(result.successRatio);
    print(result.resultList);
  }

  @override
  void onError(String message) {
    print(message);
    throw Exception(message);
  }
}

// Now we can start the liveness check, this shows the liveness check screen
// There are a few things we can setup while starting the liveness check to see
// the full list check out the documentation. Important: For the liveness check
// to work properly the main scan should have been performed
var api = LivenessApi();

var checks = [
  LivenessCheck(type: LivenessCheckType.closeEyes, args: {"numberOfSeconds": 3}),
  LivenessCheck(type: LivenessCheckType.tilt, args: {"faceAngleRequirement": 25}),
];
var image = context.read<CoreResultImpl>().data.frontImage;
if (image != null) {
  checks.add(LivenessCheck(
      type: LivenessCheckType.faceMatching,
      args: {"documentImage": image}));
}
api.start(LivenessConfiguration(showDismissButton: true, checks: checks));

Customization #

Each module has extensive custimzation options to control the SDK's behavior. You can customize options while scanning, scan help instruction, pre scan instruction. You can also customize what kind of documents are allowed or filter which options a user can choose from.

Extensive documentation on this is available in our documentation.

Below you can find some examples on how to setup some components to give you an idea of what you can setup.

Core settings #

The core offers several settings that allow you too better setup the SDK and which flows a user gets.

Below is an example of the settings you can set, you can customize these to fit your own need. For extensive explanation of what eacht setting does please check out our documentation. You can set these values when initiating a Configuration object. And then you can sent this object to the SDK via the CoreApi's configure method.

Configuration(
    requireDocumentCopy: true,
    enablePostCropping: true,
    enableManual: true,
    requireMrzContents: false,
    requireNfcWhenAvailable: false,
    readMrzContents: true,
    documentFiltersAutoCreateValidators: true,
    customDismissButtonTitle: null,
    requireCroppedImage: true, 
    enableVisualInspection: true
);

Core - Instruction screens #

There are several ways of customizing the instruction screens. The easiest way is to use our own design but customize the values yourself, place these values inside the Configuration object:

Configuration(
    enableVisualInspection: true,
    instructionScreenConfiguration: InstructionScreenConfiguration(
      showInstructionScreens: true,
      instructionScreens: [
        InstructionScreen(
            screen: InstructionScreenId.mrzPresentFlowInstruction,
            type: InstructionScreenType.media,
            // Values for MEDIA based instruction screens
            title: "Custom Instruction",
            continueButtonLabel: "Let's do it!",
            header: "Check out the video below",
            mp4FileName: "DemoMp4", // This file needs to be available in your main bundle on the native side of things
            instruction: "This is some custom instruction text that you can provide. In this example we're customizing the screen that asks if the document has an MRZ (Machine Readable Zone). So does the document have a MRZ? Answer below."
        )
      ],
   )
);

You can also use a web based instruction screen:

Configuration(
    enableVisualInspection: true,
    instructionScreenConfiguration: InstructionScreenConfiguration(
      showInstructionScreens: true,
      instructionScreens: [
        InstructionScreen(
            screen: InstructionScreenId.mrzPresentFlowInstruction,
            type: InstructionScreenType.web,
            title: "Custom web based instruction",
            continueButtonLabel: "Let's do it!",
            url: "https://www.verifai.com/en/support/supported-documents/
        )
      ],
   )
);

For exact options and possible values check out our documentation.

NFC - Instruction screens #

It's also possible to setup the NFC's instruction screens.

The most simple way is to use our own design but customize the values yourself, place these values when calling the NFC module's start function:

// Setup the NFC instruction screens, check out docs for more info
NfcConfiguration(retrieveImage: true,
  instructionScreenConfiguration:
  NfcInstructionScreenConfiguration(showInstructionScreens: true,
      instructionScreens: [
        NfcInstructionScreen(
          screen: NfcInstructionScreenId.nfcScanFlowInstruction,
          type: InstructionScreenType.media,
          title: "Custom NFC Instruction",
          continueButtonLabel: "Let's do it!",
          header: "Check out the video below",
          mp4FileName: "DemoMp4", // This file needs to be available in your main bundle on the native side of things
          instruction: "The US passport has the NFC chip in a very peculiar place. You need to open up the booklet and look for the image of a satellite looking spacecraft on the back (the voyager spacecraft). Place the top back part of your device in one swift motion on top of that spacecraft to start the NFC scan process.",
        )
      ]
  ),
);

You could also use a web based instruction screen:

// Setup the NFC instruction screens, check out docs for more info
NfcConfiguration(retrieveImage: true,
  instructionScreenConfiguration:
  NfcInstructionScreenConfiguration(showInstructionScreens: true,
      instructionScreens: [
        NfcInstructionScreen(
          screen: NfcInstructionScreenId.nfcScanFlowInstruction,
          type: InstructionScreenType.media,
          title: "Custom NFC Instruction",
          continueButtonLabel: "Let's do it!",
          url: "https://www.verifai.com/en/support/supported-documents/",
        )
      ]
  ),
);

Scan help #

When a scan fails or if we detect the user is having difficulties scanning we offer help screens that give more detailed information about scanning.

In the case of the Core module we also offer an optional fallback option so that if all else fails, the user can at least take an image of the document that can be processed manually by a human. For the scan help we let you configure the instruction and video shown to the user. Please keep in mind the video is muted.

You can customize this screen in the following way, place these values inside the Configuration object when setting up the Core module:

// Setup scan help, scan help in this case gets shown when scanning fails,
// check out docs for more info
Configuration(scanHelpConfiguration: 
  ScanHelpConfiguration(
    showScanHelp: true,
    customScanHelpScreenInstructions: "Our own custom instruction", 
    customScanHelpScreenMp4FileName: "DemoMp4"
  )
);

In the NFC module we also offer scan help when an NFC scan fails. For the scan help we let you configure the instruction and video shown to the user. Please keep in mind the video is muted.

You can customize this screen in the following way, place these values in the NFC module's configuration:

// Setup scan help, scan help in this case gets shown when NFC scanning fails,
// check out docs for more info
NfcConfiguration(
    scanHelpConfiguration: 
    ScanHelpConfiguration(
        showScanHelp: true,
        customScanHelpScreenInstructions: "Our own custom instruction", 
        customScanHelpScreenMp4FileName: "DemoMp4"
    )   
);

Validators #

Just like for the native SDK we've opened up the possibility to setup validators via the flutter package. For an extensive explanation on what validators are please check out our main documentation. We currently don't provide the option to setup custom validators via the bridge. The package provides access to the following validator types:

// Enum that describes a document Validator type
enum ValidatorType {
  countryAllowlist, // Validator that only allows documents from the countries provided
  countryBlocklist, // Validator that blocks the documents from the countries provided   
  hasMrz, // Validator that checks if document has an MRZ
  documentTypes, // Validator that only validates certain document types 
  mrzAvailable, // Validator that requires the MRZ to be correct
  nfcKeyWhenAvailable, // Validators that ensure the NFC key if available is correct
}

In the example below we setup one of each validator as an example. Please be aware that if setup incorrectly validators can cancel each other out. Like adding the same countries to allow and block lists.

// Example of adding validators
Configuration(
  validators: [
    Validator(
      type: ValidatorType.countryAllowlist,
      args: {
        "countryList": ["NL"]
      }
    ),
    Validator(
        type: ValidatorType.countryBlocklist,
        args: {
          "countryList": ["BE"]
        }
    ),
    Validator(
        type: ValidatorType.hasMrz
    ),
    Validator(
        type: ValidatorType.documentTypes,
        args: {
          "validDocumentTypes": [
            DocumentType.driversLicence.index,
            DocumentType.passport.index
          ]
        }
    ),
    Validator(
        type: ValidatorType.mrzAvailable
    ),
    Validator(
        type: ValidatorType.nfcKeyWhenAvailable
    ),
  ]
);

Document Filters #

We've also opened up the possibility to setup document filters via the flutter package. Document filters allow you to cntrol which dcuments a uer can choose when using the manual flow of the SDK. More information about this is available in the documentation.

We provide the following document filters:

// Enum that describes document filters that filter the available documents in
// the manual document selection flow
enum DocumentFilterType {
  documentTypeAllowList, // Filter that only allows certain document types
  documentAllowList, // Filter that only allows documents from certain provided countries
  documentBlockList, // Filter that blocks certain document countries
}

Here's an example on how to set the document filters, pass these values when configuring the core module.

// Setting document filters example
Configuration(
  documentFilters: [
    DocumentFilter(type: DocumentFilterType.documentAllowList,
        args: {
          "countryList": ["NL"]
        }
    ),
    DocumentFilter(type: DocumentFilterType.documentBlockList,
        args: {
          "countryList": ["BE"]
        }
    ),
    DocumentFilter(type: DocumentFilterType.documentTypeAllowList,
        args: {
          "validDocumentTypes": [
            DocumentType.passport.index,
            DocumentType.idCard.index
          ]
        }
    )
  ]
);

Liveness checks #

We also offer a bridge to the liveness checks tat the SDK provides. The following Liveness checks are available:

// Enum of possible liveness checks
enum LivenessCheckType {
  closeEyes, // Check where a user is asked to close their eyes for x amount of time
  tilt, // Check where a user is asked to tilt their head a certain amount of degrees
  speech, // Check where the user is asked to say certain words
  faceMatching, // Check where the user is asked to take a selfie and the face is matched with the one on the document or NFC
}

Below you can find an example of each liveness check, you can configure the values to match your needs or just pass an empty list and the SDK will use a default set of checks.

You can set these values by passing them when starting the liveness check with the LivenessConfiguration object.

LivenessConfiguration(
  checks: [
    LivenessCheck(
        type: LivenessCheckType.closeEyes,
        args: {"numberOfSeconds": 3}
    ),
    LivenessCheck(
        type: LivenessCheckType.tilt,
        args: {"faceAngleRequirement": 5}
    ),
    LivenessCheck(
        type: LivenessCheckType.speech,
        args: {
          "speechRequirement": "Apple Banana Pizza"
        }
    ),
    LivenessCheck(
        type: LivenessCheckType.faceMatching,
        args: {"documentImage": image}
    )
  ]
);

Support #

For additional support remember to consult our main documentation or reach out to us via our support channels.

10
likes
100
pub points
21%
popularity

Publisher

verified publisherverifai.com

The official Flutter package for Verifai's mobile (iOS and Android) SDK's.

Homepage

Documentation

Documentation
API reference

License

unknown (LICENSE)

Dependencies

flutter, pigeon, provider

More

Packages that depend on verifai_sdk