Skip to main content

Incode Onboarding Flutter SDK

Incode Onboarding provides effortless onboarding where security matters. Incode Onboarding is part of Incode's Omnichannel Biometric Identity Platform, which is powered by Incode's world class face recognition, liveness detection and ID validation models.

In this repo you can find an example onboarding an app that uses Incode Onboarding Flutter SDK to enable remote account opening.

Contents:

SDK Setup

Requirements

  • Flutter version >=1.20.0

Installation

flutter-incode-sdk:
git:
url: git@github.com:Incode-Technologies-Example-Repos/IncdOnboardingFlutter.git
ref: master

Additional setup for iOS

After installation, it's necessary to do the linking for the iOS, after running the command above.

  1. Change your Podfile so it adds Incode sources and so it requires deployment target 11 or higher:
source 'https://github.com/CocoaPods/Specs.git'
source 'git@github.com:Incode-Technologies-Example-Repos/IncdDistributionPodspecs.git'
-platform :ios, '10.0'
+platform :ios, '11.0'
  1. Run pod install
cd ios && pod install cd ..
  1. Adapt Info.plist by adding:
  • NSCameraUsageDescription - The SDK uses the camera in order to verify the identity of the customer, e.g. in ID scan, selfie scan and so on.
  • NSLocationWhenInUseUsageDescription - The SDK uses the user's current location in order to detect exact location for the geolocation step.
  • NSMicrophoneUsageDescription - The SDK uses a microphone for performing video calls during the video conference step, or for doing speech recognition during a video selfie.

Additional setup for Android

  1. Modify app/build.gradle so that you enable multiDexEnabled and set the minimum API level to 17:
defaultConfig {

multiDexEnabled true
minSdkVersion 17
}
  1. Modify your build.gradle so it contains an artifactory username and password, provided by Incode:
allprojects {
repositories {
...
+ jcenter()
+ maven {
+ url "https://repo.incode.com/artifactory/libs-incode-welcome"
+ credentials {
+ username = "ARTIFACTORY_USERNAME"
+ password = "ARTIFACTORY_PASSWORD"
+ }
+ }
...
}
}

Updating to latest version

Run flutter pub upgrade or flutter packages upgrade, and in case iOS SDK version was updated run pod install --repo-update and pod update IncdOnboarding inside your ios folder.

Usage example

  1. Initialize the SDK
IncodeOnboardingSdk.init(
apiKey: 'YOUR_API_KEY',
apiUrl: 'YOUR_API_URL',
testMode: false,
onError: (String error) {
print('Incode init failed: $error');
},
onSuccess: () {
// Update UI, safe to start Onboarding
print('Incode initialize successfully!');
},
);

apiUrl and apiKey will be provided to you by Incode. If you are running the app on a simulator, please set the testMode parameter to 'true'.

  1. Configure Onboarding Flow First, create an instance of OnboardingFlowConfiguration like this:
OnboardingFlowConfiguration flowConfig = OnboardingFlowConfiguration()

Depending on your needs you should specify the steps you want to include. An example of this could be:

flowConfig.addPhone();
flowConfig.addIdScan();
flowConfig.addSelfieScan();
flowConfig.addFaceMatch();
flowConfig.addGeolocation();
flowConfig.addVideoSelfie();
flowConfig.addUserScore();
flowConfig.addApproval();

The steps will be executed in the order you added them to the flowConfig.

Second, you should create an instance of OnboardingSessionConfiguration:

OnboardingSessionConfiguration sessionConfig = OnboardingSessionConfiguration();
  1. Start the onboarding like this:
IncodeOnboardingSdk.startOnboarding(
sessionConfig: sessionConfig,
flowConfig: flowConfig,
onSuccess: () {
print('Incode Onboarding completed!');
},
onError: (String error) {
print('Incode onboarding error: $error');
},
onSelfieScanCompleted: (SelfieScanResult result) {
print('Selfie completed');
},
onIdValidationCompleted: (IdValidationResult result) {
print('ID validation completed');
},
);

Once all the steps are completed by the user the onSuccess method will be called. In case some error occured that stopped the flow from completing, the onError method will be called.

To listen for the results of the steps in the flow as soon as they're completed, you can add optional callback methods, ie. onSelfieScanCompleted and onIdValidationCompleted that were added in the above example.

Modules

The modules supported by the SDK are listed here, and elaborated in more detail throughout the rest of this document.

  • Phone - Ask the user to enter a phone number.
  • IdScan - Ask the user to capture an ID or Passport.
  • ProcessId - Process the ID in case the Id Scan was separated to front and back captures.
  • SelfieScan - Ask the user to capture a selfie.
  • FaceMatch - Perform a face match between the captured ID and selfie
  • Geolocation - Get the information about the users current location.
  • VideoSelfie - Records the device's screen while the user needs to do a selfie, show his ID, answer a couple of questions and verbally confirms that they accept the terms and conditions. The recorded video is then uploaded and stored for later usage.
    • ⚠️ Android note: Available only for API level 21+.
  • UserScore - Shows the info and scoring for all the steps performed
  • Signature - Ask the user to draw a signature
  • DocumentScan - Ask the user to capture a document
  • Captcha - Ask the user to complete CAPTCHA
  • CURP - Validate user's CURP from the ID
  • Approve - Approves the current onboarding session and adds the user to the Omni database (based on a score).

Modules configuration

Below is the list of all available modules, with additional configuration parameters:

  • Phone
    • no additional parameters
  • IdScan
    • showTutorials (optional, defaults to true): boolean
    • idType (optional): IdType.id or IdType.passport. If omitted, the app will display a chooser to the user.
    • idCategory (optional): IdCategory.primary or IdCategory.secondary
    • scanStep (otpional): If you wish to separate the front and back ID scan, specify ScanStepType.front or ScanStepType.back. ScanStepType.both is the default and will capture both the front and back of the ID, and process the ID afterwards. If you specify ScanStepType.front or ScanStepType.back you will have to add the ProcessId module after the captures.
  • ProcessId (used only if ScanStepType.front or ScanStepType.back were specified as scanStep for IdScan module)
    • idCategory (optional): IdCategory.primary or IdCategory.secondary
    • Note: Please make sure to call this module only after both the ScanStepType.front and ScanStepType.back IdScans are completed.
  • SelfieScan
    • showTutorials (optional, defaults to true): bool?
  • FaceMatch
    • idCategory (optional, defaults to primary): IdCategory.primary or IdCategory.secondary
    • Note: has to be specified after IDScan and SelfieScan modules.
  • Geolocation
    • no additional parameters
  • VideoSelfie:
    • showTutorials (optional, defaults to true): boolean. Show tutorial for video selfie.
    • selfieScanMode (optional, defaults to selfieMatch): SelfieScanMode.selfieMatch or SelfieScanMode.faceMatch; Specify if you would like to do a selfie comparison, or comparison with the photo from the ID.
    • selfieLivenessCheck (optional, defaults to false): boolean. Check for user liveness during video selfie.
    • showIdScan (optional, defaults to true): bool?. Ask for ID scan during video selfie.
    • showDocumentScan (optional, defaults to true): boolean. Ask for proof of address during video selfie
    • showVoiceConsent (optional, defaults to true): boolean. Ask for voice consent during video selfie
    • voiceConsentQuestionsCount (optional, defaults to 3): integer. Choose a number of questions for video selfie voice consent steps.
  • UserScore
    • mode (optional, defaults to accurate): UserScoreFetchMode.accurate or UserScoreFetchMode.fast. If accurate, the results will be fetched from the server, which may exhibit some latency, but will rely on server-side processing of information. This option may be more reliable than on-device processing. If fast, then results based on on-device processing will be shown.
  • Approve
    • forceApproval (optional, defaults to false): boolean - if true, the user will be force-approved
  • Signature
    • no additional parameters
  • DocumentScan
    • showTutorials (optional, defaults to true): boolean. Show the tutorial for document scan.
    • showDocumentProviderOptions (optional, defaults to false).
    • documentType (optional, defaults to DocumentType.addressStatement).
  • Captcha
    • no additional parameters
  • CURP
    • no additional parameters

Modules interdependencies

  • ProcessId module expects IdScan both ScanStepType.front or ScanStepType.back to have executed.
  • FaceMatch module expects IdScan and SelfieScan to have been executed, in order to perform the match. In other words, IdScan and SelfieScan must precede FaceMatch
  • VideoSelfie module expects IdScan in faceMatch mode, or SelfieScan in selfieMatch mode.
  • UserScore module should succeed all other modules (must be at the end)
  • Approve module should succeed all other modules (must be at the end)
  • The UserScore and Approve modules do not depend on each other, so their order can be arbitrary.

SDK results

Phone

Specify onAddPhoneNumberCompleted to the startOnboarding method, to receive PhoneNumberResult:

  • phone : String, the phone number the user entered

IdScan

1) Specify onIdFrontCompleted, onIdBackCompleted to the startOnboarding method, to receive IdScanResult results:

  • image: Captured ID image
  • base64Image: String. Captured front ID in base64 format
  • croppedFace: Cropped face from captured ID image
  • chosenIdType: User chosen type on ID selection screen - id or passport
  • classifiedIdType: type of the captured ID
  • idCategory: IdCategory. Category of the scanned ID
  • scanStatus: If the status has a value other than IdValidationStatus.ok you can consider the ID scan and/or validation did not come through successfully. Other status messages are: errorClassification, noFacesFound, errorCropQuality, errorGlare, errorSharpness, errorTypeMismatch, userCancelled, unknown, errorAddress, errorPassportClassification.

2) Specify onIdProcessed to the startOnboarding method, to receive String OCR results:

  • ocrData: String. Raw JSON containing full OCR data ie. exteriorNumber, interiorNumber, typeOfId, documentFrontSubtype

SelfieScan

Specify onSelfieScanCompleted to the startOnboarding method, to receive SelfieScanResult:

  • image: Uint8List. Captured Selfie image
  • spoofAttempt: boolean. false means that the person trying to do selfie is a real person. true means it is a spoof attempt, meaning that person is trying to spoof the system by pretending to be someone else using physical paper, a digital photo or other methods. nil means that an unexpected error occured, so it couldn't be determined if the selfie scan was a spoof attempt or not.
  • base64Images: SelfieScanBase64Images. Contains an image, in different formats, taken during selfie scan
    • selfieBase64: String. Captured selfie base64 image
    • selfieEncryptedBase64: String. Captured selfie encrypted base64 image

FaceMatch

Specify onFaceMatchCompleted to the startOnboarding method, to receive FaceMatchResult:

  • faceMatched: boolean. true means the person's selfie matched successfully with the front ID. false means that the person's selfie isn't matched with the front ID image. null means that the front ID image wasn't uploaded at all, so the face match service didn't have data to compare with the selfie
  • idCategory : IdCategory. Category of the ID that was used for face match.
  • existingUser: boolean. Indicates whether the user is a new or existing one.
  • existingInterviewId: String. If user is existing this field is populated with an existing interview ID.

Geolocation

Specify onGeolocationCompleted to the startOnboarding method, to receive GeoLocationResult:

  • city: String
  • colony: String
  • postalCode: String
  • state: String
  • street: String

VideoSelfie

Specify onVideoSelfieCompleted to the startOnboarding method, to receive VideoSelfieResult:

  • success: boolean, true if the video selfie was performed successfully, false otherwise.

UserScore

Specify onUserScoreFetched to the startOnboarding method, to receive UserScoreResult.

Example UserScoreResult for completion of the module:

{
ovarall: {
value: '0.0/100',
status: 'ok'
},
faceRecognition: {
value: '0.0/100',
status: 'warn',
},
liveness: {
value: '95.2/100',
status: 'manual',
},
idValidation: {
value: '79.0/100',
status: 'fail',
},
}

The field status can have one of the following values: warning, unknown, manual, fail or ok.

Approve

Specify onApproveCompleted to the startOnboarding method, to receive ApprovalResult.

  • success: boolean. true if the approval was successful, false otherwise.
  • uuid : String. Customer II of the newly created customer if approval was successful, null otherwise.
  • customerToken : String. Customer token for newly created customer if approval was successful, null otherwise.

Signature

Specify onSignatureCollected to the startOnboarding method, to receive SignatureResult.

  • signature: Uint8List?. Collected signature image.

Document

Specify onDocumentScanCompleted to the startOnboarding method, to receive DocumentScanResult.

  • image: Uint8List. Document scan image.
  • documentType: DocumentType. Type of scanned document.
  • address: Map<String, dynamic>?. Address fetched from the document. Will be available only for DocumentType.addressStatement
  • ocrData: Raw JSON containing full OCR data

Captcha

Specify onCaptchaCompleted to the startOnboarding method, to receive CaptchaResult.

  • captcha: String. Entered captcha.

CURP

Specify onCurpValidationCompleted to the startOnboarding method, to receive CurpValidationResult.

  • curp: String. User's CURP.
  • valid: boolean. Indicates if the user's CURP is valid. Null means there is no result (user decided to skip).
  • data: Map<String, dynamic>. The user's CURP data.

Advanced Usage

If you would like to use SDK in a way that the default flow builder doesn't provide,
you can use SDK APIs for advanced usage where you'll be able to fully customize the experience of the flow.
For example, you can call individual SDK modules, or group SDK modules in sections, and return control to your host application in between.

Create new onboarding session

Before calling any other Onboarding SDK component, it is necessary to create a new onboarding session:

IncodeOnboardingSdk.createNewOnboardingSession(
sessionConfig: OnboardingSessionConfiguration(),
onError: (String error) {
print('Incode onboarding session error: $error');
},
onSuccess: (OnboardingSessionResult result) {
print('Incode Onboarding session created! $result');
},
);

Optionally, you can specify:

  • region: ALL by default
  • list of OnboardingValidationModule items. This list determines which modules are used for verification and calculation of the onboarding score. If you pass null as validationModuleList, the default values will be used: id, faceRecognition and liveness.
  • customFields: custom fields which are sent to the server.
  • externalId: User identifier outside of the Incode Omni database.
  • configurationId: Flow configurationId found on the Incode dashboard.

Configure section flow

Once the new onboarding session is created (See previous section), you can separate the Onboarding SDK flow into multiple sections based on your needs:

IncodeOnboardingFlowConfiguration flowConfig = IncodeOnboardingFlowConfiguration();
flowConfig.addIdScan();

Start onboarding section

Once the IncodeOnboardingFlowConfiguration is created, call the following method:

IncodeOnboardingSdk.startNewOnboardingSection(
flowConfig: flowConfig,
flowTag: 'idSection',
onError: (String error) {
print('Incode onboarding session error: $error');
},
onIdValidationCompleted: (IdValidationResult result) {
print(result);
onCompleted();
},
onOnboardingSectionCompleted: (String flowTag) {
print('section completed');
},
);

Finish onboarding session

Make sure to call finishFlow() at the end of the flow (when you are sure the user has finished all onboarding modules and you won't be reusing the same interviewId again).

IncodeOnboardingSdk.finishFlow();

Resuming an existing onboarding session

To continue an existing onboarding when the app is uninstalled and installed again in the middle of the flow, make sure to call the IncodeOnboardingSdk.setOnboardingSession() API. It is important to call this API prior to making any other API calls in order to reset the configuration that got lost during the uninstall. You can do this by following the code below:

IncodeOnboardingSdk.setOnboardingSession(
config: OnboardingSessionConfiguration(),
interviewId: 'Your interviewId',
onError: (String error) {
print('Incode set onboarding session error: $error');
},
onSuccess: (OnboardingSessionResult result) {
print('Incode set onboarding session success! $result');
},
);

Customization

To change theme and resources (text, images and videos) on an Android platform please look at a guide here.

To change resources on an iOS platform please look at a guide here.

To change themes on an iOS platform, specify the JSON theme configuration and call IncodeOnboardingSdk.setTheme(theme: theme):

Map<String, dynamic> theme = {
"buttons": {
"primary": {
"states": {
"normal": {
"cornerRadius": 16,
"textColor": "#ffffff",
"backgroundColor": "#ff0000"
},
"highlighted": {
"cornerRadius": 16,
"textColor": "#ffffff",
"backgroundColor": "#5b0000"
},
"disabled": {
"cornerRadius": 16,
"textColor": "#ffffff",
"backgroundColor": "#f7f7f7"
}
}
}
},
"labels": {
"title": {"textColor": "#ff0000"},
"secondaryTitle": {"textColor": "#ff0000"},
"subtitle": {"textColor": "#ff0000"},
"secondarySubtitle": {"textColor": "#ff0000"},
"smallSubtitle": {"textColor": "#ff0000"},
"info": {"textColor": "#ff0000"},
"secondaryInfo": {"textColor": "#ff0000"},
"body": {"textColor": "#ff0000"},
"secondaryBody": {"textColor": "#ff0000"},
"code": {"textColor": "#ff0000"}
}
};

IncodeOnboardingSdk.setTheme(theme: theme);

SDK Mode

You can choose between two modes: SdkMode.standard and SdkMode.captureOnly. SdkMode.standard is the default, but if you would like to skip the image upload and server validations for the ID and selfie scan, you can specify captureOnly mode using method:

IncodeOnboardingSdk.setSdkMode(sdkMode: SdkMode.captureOnly);

Known issues

  • Currently, running the app on iOS simulator from VSCode isn't supported. For now, please run the app from Xcode if you want to test it on an iOS Simulator. NOTE: Don't forget to set testMode to true before running the app.