React Native Plugin

Integration Options

This page sets out step-by-step instructions for setting up your App Drop-in via the React Native Plugin.

Prerequisites

  • You need your API credential set.

  • Provide your Fourthline delivery manager with the GitHub usernames and email addresses of your staff who need access to our repositories.

  • Check the following prerequisites and specifications for your operating system:

  • Minimum iOS version: 12
  • Minimum XCode version: 14.3
  • Minimum iOS deployment target: 12.4
  • MRZ detection in the document scanner requires minimum iOS 13.

The plugin contains the following:

ContentDescription
Source files Fourthline.swift
and Fourthline.m
Bridge the React Native environment and the FourthlineScanners framework
FourthlineScanners iOS frameworkContains the following drop-in modules:
• Identity Verification flow
• Workflows API
• Document, Biometrics, and NFC scanners
• Location provider
• Identity data validator and zipper
fourthline-adapters-json Android libraryProvides JSON interfacing with FourthlineScanners
iOS frameworksProvide functionalities for FourthlineScanners:
FourthlineCore: Orchestration and analytics functionality
FourthlineVision: Document and Biometrics scanners
FourthlineNFC: NFC scanner
FourthlineKYC: Identity data management functionality
FourthlineSDK

Before you set up the plugin, make the following preparations:

1. In the main project's General > Frameworks, libraries, and embedded content section, add libswiftVision.tbd.

2. In the Info.plist file, add the keys required to access the camera and NFC functionalities:

<key>NSCameraUsageDescription</key>
<string>To verify your identity, please allow us to access your camera once only.</string>

3. Optionally, for the NFC flow, add to the Info.plist file the keys required to access the NFC functionality:

<key>NFCReaderUsageDescription</key>
<string>To read the chip in your identity document, please enable NFC.</string>
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
 <string>A0000002471001</string>
 <string>A00000045645444C2D3031</string>
</array>

4. In the XCode Signing & capabilities tab, enable the Near Field Communication Tag Reading capability.

5. Optionally, to record audio in the document and selfie videos, add to the Info.plist file the key required to access the microphone functionality:

<key>NSMicrophoneUsageDescription</key>
<string>To verify your identity, please allow access to your microphone.</string>

6. Optionally, for the Location module, add to the Info.plist file the keys required to access the location functionality:

<key>NSLocationWhenInUseUsageDescription</key>
<string>To verify your identity, please allow access to your location.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>To verify your identity, please allow access to your location.</string>
<key>NSLocationTemporaryUsageDescriptionDictionary</key>
<dictionary>
    <key>FourthlineFullAuthorizationPurposeKey</key>
 <string>To verify your identity, your exact location is shared with us once only.</string>
</dictionary>

7. If customizing the fonts in the UI, add the font files to your project and to the projects' Info.plist file:

<key>UIAppFonts</key>
    <array>
        <string>Your-Font-Medium.ttf</string>
        <string>Your-Font-Regular.ttf</string>
    </array>
Note
Notes
• Data is transferred between React Native and our plugin API via JSON formatted Strings, both as input configuration options and payload responses.
• Fourthline's scanners are designed to be implemented and tested on a real mobile device. Launching them on the iOS simulator throws a scanner error.

Configuration

Age requirement

Configurable Configurable

You can dynamically configure the minimum client age requirement and the related checks during Identity Verification workflows.

Document data

Configurable Configurable

Discuss with your Fourthline delivery manager what data to extract from identity document photos via optical character recognition (OCR):

Data typeDescription
MRZ dataDocument data is extracted from the MRZ only and is processed offline by the SDK.
MRZ and
VIZ data
For greater accuracy, document data is extracted from the MRZ and VIZ and processed by our AI agent in real time.

Identity data

Configurable Configurable

If you want to receive a copy of the identity data gathered by the App Drop-in when it's uploaded to our backend (before case processing), let your Fourthline delivery manager know.

Real-time feedback

Configurable Configurable

Agree with your Fourthline delivery manager whether you want to enable real-time feedback. The SDKs send the document photos to our backend as soon as they are captured, where we assess the image quality and provide the client feedback in the UI in real time. This ensures higher-quality photos are ultimately uploaded, reduces sendbacks>, and improves user experience.

Supported devices

Support
Support
For questions about supported devices, contact your Fourthline delivery manager.


Identity Verification

Setup

To setup the plugin, follow these steps:

1. In your React Native project root, execute the following command:

npm install https://github.com/Fourthline-com/Fourthline-React-Native

2. Go to the iOS folder, and then execute the following command:

pod install

3. In the source files that will use our plugin, add the following import:

import { NativeModules } from 'react-native';

4. Pass the following JSON configuration to the workflow:

{
 "configuration": WorkflowConfiguration,
 "customization": WorkflowCustomization
}

WorkflowConfiguration has the following format:

{
 "networkEnvironment": NetworkEnvironment, // To test a workflow locally use .mock, and to test workflow networking use .sandbox
 "validationCode": string, // Returned in the Create SDK session response
}

NetworkEnvironment can have the following values:

ValueDescription
ProductionLive environment
SandboxRemote testing environment
mockLocal testing environment with stubbed data

To get the ValidationCode, make a Create SDK session request.

WorkflowCustomization is an optional field with the following format:

{
 "flavor": string
}

To customize the look and feel of the UI, see App UI Customization.

Example

var config = `{
 "configuration": {
 "validationCode": "123456",
 "networkEnvironment": "sandbox"
 },
 "customization": {
 "flavor": {
 "colors": ${orcaColors},
 "fonts": ${orcaFonts},
 "localization": ${orcaLocalization},
 "layouts": ${orcaLayout}
 }
 }
}`;

NativeModules.Fourthline.startWorkflow(config)
	.then((msg) => {
 // Client has successfully completed the workflow
 // No further action required
	})
	.catch((error) => {
		// Extract and process the information received in JSON error string format
		var jsonError = JSON.parse(error.message);
	});

Success handling

If the workflow is successful, all results are already processed and no additional response is returned.

Error handling

If the workflow is unsuccessful, the following JSON string is returned:

{
 "errorCode": number,
 "errorDescription": string
}

The following error codes are possible:

Error codeDescriptionAction
800Decoding errorCheck the errorDescription for more information.
802Invalid or missing fontCheck the errorDescription for more information.
803User canceledThe client explicitly canceled the workflow.
830JSON parse errorCheck the JSON provided.
850Incorrect configurationEnsure the workflow is configured correctly.
870Unexpected + messageInform your Fourthline delivery manager immediately.
1000ClientRejectedThe client isn't eligible for the workflow.
You cannot retry.
1001InvalidValidationCodeMake a new Create SDK session request.
1002Module error + messageThe client encountered an error in one of the workflow modules.
Check the message for more information.
1003ConfigurationNotSupported + messageThe workflow created using the validationCode isn't supported.
Consider updating to the latest plugin version.
1004InvalidWorkflowStatusCheck if the workflow module is already completed successfully or with an error.

Testing

To view a mock version, launch the various modules using the following mock validation codes:

ProductMock validation code
Identity VerificationIDV
Qualified Electronic Signature moduleQES
Bank Account Verification moduleBAV
CombinationsIDVandBAV
IDVandQES
IDVandBAVandQES
IDVandQESandBAV

Example code:

NativeModules.Fourthline.startWorkflow(config)
  .then((result) => {
        // User has successfully completed the Workflow process.
        // No further action needed.
  })
  .catch((error) => {
        // Extract and process information from the error String received in JSON format
        var jsonError = JSON.parse(error.message);
  });

Biometric Authentication

Action
Important
What was previously called Client Authentication is now referred to as Biometric Authentication. Biometric Authentication is supported in both v1 and v2 integrations.

Setup

The configuration passed has the following JSON format:

{
  "customization": CcrCustomization
}

customization is an optional field. For more information, see App UI Customization.

CcrCustomization has the following format:

{
  "flavor": String
}

Example

import { NativeModules } from 'react-native'

// Use an empty json config if you do not wish to customize the Ccr flow
var config = `{}`;
// or pass the desired customization
var config = `{
  "customization": {
    "flavor": {
      "colors": ${orcaColors},
      "fonts": ${orcaFonts},
      "localization": ${orcaLocalization},
      "layouts": ${orcaLayout}
    }
  }
}`;

NativeModules.Fourthline.startCcr(config)
  .then((msg) => {
        // Extract and process information from the result String received in JSON format
        var jsonResult = JSON.parse(msg);
    })
  .catch((error) => {
       // Extract and process information from the error String received in JSON format
       var jsonError = JSON.parse(error.message);
  });

Success handling

If the flow ends successfully, the outcome is returned as a JSON string:

{
  "image":"String",
  "video":{
    "url":"String",
    "duration":"String",
    "location":{
      "latitude":"Number",
      "longitude":"Number"
    }
  },
  "metadata":{
    "location":{
      "latitude":"Number",
      "longitude":"Number"
    },
    "ipAddress":"String",
    "region":"String",
    "analyticsID":"String",
    "osVersion":"String",
    "model":"String",
    "sdkVersion":"String",
    "language":"String",
    "osCompromised":"Bool"
  }
}
Attributes
AttributeDescriptionRequired
image
String
The absolute filepath to the selfie photo.Required
video
Object
The selfie video data.
CautionImportant: Delete the video files when they are no longer needed.
Optional
video.url
String
The absolute url filepath to the selfie video.Optional
video.duration
String
The length of the selfie video.
The selfie scanner duration parameter is always set to default.
Optional
video.location
Object
The coordinates of the selfie video.Optional
video.location.latitude
String
The latitude of the selfie video.
Format: Float between -90 and 90
Example: 45.464664
Optional
video.location.longitude
String
The longitude of the selfie video.
Format: Float between -90 and 90
Example: 45.464664
Optional
metadata
Object
The metadata of the client's device.Required
metadata.location
Object
The coordinates of the client's device.Required
metadata.location.latitude
String
The latitude of the client's device.
Format: Float between -90 and 90
Example: 45.464664
Required
metadata.location.longitude
String
The longitude of the client's device.
Format: Float between -90 and 90
Example: 45.464664
Required
metadata.ipAddress
String
The IP address of the client's device.Optional
metadata.region
String
The region code of the client's device.Auto-filled
metadata.analyticsID
String
The analytics identifier.Auto-filled
metadata.osVersion
String
The OS version of the client's device.Auto-filled
metadata.model
String
The client's device model.Auto-filled
metadata.sdkVersion
String
The version of Fourthline's SDK.Auto-filled
metadata.language
String
The language of the client's device.Auto-filled
metadata.osCompromised
Bool
True: The client's device was jailbroken.
False: The client's device wasn't jailbroken.
Auto-filled

Error handling

If the flow ends unsuccessfully, the error is returned as a JSON string:

{
  "errorCode": Number,
  "errorDescription": String
}

You need to handle the following error values:

ErrorDescription
800 Decoding errorThere was an input decoding error.
For more information, see errorDescription.
802 Invalid or missing fontThe font provided wasn't found.
For more information, see errorDescription.
803 User canceledThe client explicitly canceled the flow.
830 Json parse errorWe couldn't parse the json provided.
850 Incorrect configurationThe configuration is incorrect.
870 UnexpectedAn unexpected error occurred. Immediately report this issue to Fourthline along with the errorDescription.

Testing

Example code:

import { NativeModules } from 'react-native'

var config = `{
  "enableTestMe": true
}`;

NativeModules.Fourthline.startCcr(config)
  .then((msg) => {
        // will never be called
    })
  .catch((error) => {
       // will never be called
  });
Caution
Caution
Only use TestMe in debug mode because it doesn't return an outcome or CDD Report and isn't configurable. It throws an IllegalStateException when started outside a debuggable build.


Document Authentication

Setup

The configuration passed has the following JSON format:

{
  "configuration": CdrConfiguration,
  "customization": CdrCustomization
}

CdrConfiguration requires a list of supported countries and has the following format:

{
  "supportedCountries": Array
}

CdrCustomization has the following format:

{
  "flavor": String
}

customization is an optional field. For more information, see App UI Customization.

Example

import { NativeModules } from 'react-native'

// or pass the desired customization
var config = '{
  "configuration":{
      "supportedCountries": $supportedCountries
   },
  "customization": {
    "flavor": {
      "colors": $orcaColors,
      "fonts": $orcaFonts,
      "localization": $orcaLocalization,
      "layouts": $orcaLayout
    }
  }
}';

NativeModules.Fourthline.startCdr(config)
    .then((msg) => {
        var jsonResult = JSON.parse(msg);
    })
    .catch((error) => {
        var jsonError = JSON.parse(error.message);
    });

Success handling

If the flow ends successfully, the outcome is returned as a JSON string:

{
   "document":{
      "expirationDate": String,
      "images":[
         {
            "fileSide": String,
            "image": String,
            "isAngled": Boolean,
            "timestamp": String
         }
      ],
      "number": String,
      "type": String,
      "videoRecording":{
         "duration": String,
         "url":  String
      }
   },
   "person":{
      "birthDate": String,
      "firstName": String,
      "gender": String,
      "lastName": String,
      "nationalityCode": String
   }
}
Attributes
AttributeDescription
document
Object
The identity document data.
document.expirationDate
String
The identity document expiry date.
document.images
Object
The document photo data.
document.images.fileSide
String
The side of the identity document.
document.images.image
String
The document photo.
document.images.isAngled
Boolean
True: The photo is tilted.
False: The photo is flat.
document.images.timestamp
String
The timestamp for when the document photo was captured.
document.number
String
The identity document number.
document.type
String
The identity document type.
document.videoRecording
Object
The document video data.
document.videoRecording.duration
String
The length of the document video.
document.videoRecording.url
String
The URL to the document video.
person
Object
The client's personal data .
person.birthDate
String
The client's date of birth.
Format: Date YYYY-MM-DD
person.firstName
String
The client's first name.
Format: Alphabetical characters, spaces, hyphens, and apostrophes
person.gender
String
The client's sex.
Female: Female in line with identity document
Male: Male in line with identity document
Other: identity document contains a value other than Male or Female
Unknown: identity document contains no gender field
person.lastName
String
The client's last name.
Format: Alphabetical characters, spaces, hyphens, and apostrophes
person.nationalityCode
String
The client's nationality.
Format: ISO 3166-1 alpha-3 country code

Error handling

If the flow ends unsuccessfully, the error is returned as a JSON string:

{
  "errorCode": Number,
  "errorDescription": String
}

You need to handle the following error values:

ErrorDescription
800 Decoding errorThere was an input decoding error.
For more information, see errorDescription.
802 Invalid or missing fontThe font provided wasn't found.
For more information, see errorDescription.
803 User canceledThe client explicitly canceled the flow.
830 Json parse errorWe couldn't parse the json provided.
850 Incorrect configurationThe configuration is incorrect.
870 UnexpectedAn unexpected error occurred. Immediately report this issue to Fourthline along with the errorDescription.
900 Document expiredThe client's identity document has expired.
901 Document type not supportedThe client's identity document type isn't supported.
902 Issuing country not supportedThe identity document issuing country isn't supported.
903 Nationality not supportedThe client's nationality isn't supported.
904 Person not adultThe client is underage.
905 Document type is invalidThe client's identity document type isn't valid.

Testing

Example code:

import { NativeModules } from 'react-native'

var config = '
{
  "enableTestMe": true
}
';

NativeModules.Fourthline.startCdr(config)
    .then((msg) => {
        // will never be called
    })
    .catch((error) => {
        // will never be called
    });
Caution
Caution
Only use TestMe in debug mode because it doesn't return an outcome or CDD Report and isn't configurable. It throws an IllegalStateException when started outside a debuggable build.


Analytics

The FourthlineCore module collects and processes metrics. To learn more, contact your customer success manager.


Data observer

To receive notifications for each data group that the SDK uploads to Fourthline and a copy of the data itself, add a data observer:

import { NativeEventEmitter, NativeModules } from 'react-native'
const eventManagerEmitter = new NativeEventEmitter(NativeModules.Fourthline);
// Subscribe
workflowDataListener = eventManagerEmitter(
      ‘fourthlineWorkflowData’,
       (dataJson) => {
         // Handle the workflow data
    });
// Unsubscribe
workflowDataListener.remove();
NativeModules.Fourthline.removeListener('fourthlineWorkflowData');

The notifications per data type have the following JSON structure:

"idv":{
  "document":{
    "type":"string",
    "number":"string",
    "issueDate":"string", // Optional, format YYYY-MM-DD
    "expirationDate":"string", // Optional, format YYYY-MM-DD
    "images":[
      {
        "image":"string",
        "fileSide":"string",
        "isAngled":"boolean",
        "timestamp":"string", // Optional, format "YYYY-MM-dd'T'HH:mm:ssZZZZZ"
        "location":{
          "latitude":"number",
          "longitude":"number"
        }
      }
    ]
  }
}
"idv":{
  "documentVideo":{
    "url":"string",
    "duration":"string", // Default / extended
    "location":{ // Optional
      "latitude":"number",
      "longitude":"number"
    }
  }
}
"idv":{
  "selfie":{
    "image":"string",
    "timestamp":"string", // Optional
    "location":{ // Optional
      "latitude":"number",
      "longitude":"number"
    }
  }
}
"idv":{
  "selfieVideo":{
    "url":"string",
    "duration":"string", // Default / extended
    "location":{ // Optional
      "latitude":"number",
      "longitude":"number"
    }
  }
}
"idv":{
  "nfc":{
    "image":"string", // Optional
    "timestamp":"string",
    "location":{ // Optional
      "latitude":"number",
      "longitude":"number"
    },
    "mrz":"string",
    "dataGroups":[ // Optional
      {
        "groupNumber":"Int",
        "data":"string"
      }
    ]
  }
}
"idv":{
  "address":{
    "street":"string",
    "streetNumber":"Int",
    "streetNumberSuffix":"string", // Optional
    "postalCode":"string",
    "city":"string",
    "countryCode":"string",
    "region":"string" // Optional
  }
}
"idv":{
  "person":{
    "firstName":"string",
    "middleName":"string", // Optional
    "lastName":"string",
    "gender":"string",
    "nationalityCode":"string",
    "birthCountryCode":"string", // Optional
    "birthPlace":"string", // Optional
    "birthDate":"string" // Format YYYY-MM-DD
  }
}
"idv":{
  "deviceMetadata":{
    "model":"string",
    "sdkVersion":"string",
    "osVersion":"string",
    "language":"string",
    "osCompromised":"string",
    "location":{ // Optional
      "latitude":"number",
      "longitude":"number"
    }
  }
}

Temporary files

The plugins store some data collected during workflows (e.g. selfie and document videos) in the tmp/fourthline folder in the client's device filesystem. This is because the videos must remain available until collected, packaged into the case zipfile, and uploaded to our backend.

You must delete the temporary files when they are no longer needed, e.g. after the SDK has uploaded all data to Fourthline or immediately before the app is terminated in:

  • Android: onDestroy()
  • iOS: applicationWillTerminate
import { NativeModules } from 'react-native'

NativeModules.Fourthline.deleteFourthlineFiles().then(() => {
 	// Fourthline files deleted
 });

Success
Success
You have configured and set up your App Drop-in!
To integrate your solutions, see the Integration Guides section.

Top of page

Accordion in HTML5