@get-id/react-native-sdk
v0.2.25
Published
GetID react native SDK
Downloads
24
Readme
Getting Started with the GetID React Native SDK
Note: Please note that the SDK does not work with React Native apps created with Expo because this project uses the react-native-camera-kit plugin for the camera, which is not supported by Expo.
Overview
The SDK offers a comprehensive toolkit for capturing identity documents and performing selfie and liveness checks. Once captured, the data is sent to the GetID server for verification. The result can either be returned by the SDK, or you can rely on webhooks from the backoffice, or a combination of both.
The essential parts to the implementation are to:
- Generate a token for the session (via your backend)
- Initialise the SDK with the needed configuration (flow, token)
- Trigger documentscan of front side
- If needed, trigger documentscan of back side
- Trigger selfie and liveness (if configured)
- Trigger verification of the session
Getting started
Obtaining an SDK key
Start by fetching the SDK KEY
and API URL
:
- Access these from your GetID Dashboard.
- Alternatively, contact our integration support.
Security Reminder: Your GetID Dashboard provides both
API KEY
andSDK KEY
. While theAPI KEY
allows for public and SDK API calls, theSDK KEY
is exclusive to SDK API calls. It's safer to useSDK KEY
when using the SDK.
Camera Permissions
Ensure the SDK can access the device camera.
Add the following usage descriptions to your Info.plist (usually found at: ios/PROJECT_NAME/)
<key>NSCameraUsageDescription</key>
<string>For taking photos</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>For saving photos</string>
Add the following uses-permission to your AndroidManifest.xml (usually found at: android/src/main/)
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Installation
yarn add https://cdn.getid.cloud/sdk/react-native/[version]/get-id-react-native-sdk.tgz
yarn add [email protected]
yarn add [email protected]
yarn add [email protected]
yarn add [email protected]
yarn add @get-id/react-native-fast-tflite@https://cdn.getid.cloud/sdk/react-native/getid-react-native-fast-tflite/1.2.0/get-id-react-native-fast-tflite.tgz
yarn add [email protected]
yarn add vision-camera-resize-plugin@https://github.com/mrousavy/vision-camera-resize-plugin.git#ff3b6d25c035e96d9d68fd17a131abd14d33f9a1
yarn add [email protected]
yarn add [email protected]
cd ios; pod install; cd ..
Usage
Unless a flow is already created, use the GetID Admin Panel in the backoffice to create a new flow (Flows > Add new flow).
Importing the Getid SDK library in your app
Here's an example of how you can import the GetID SDK in your React Native app:
// App.tsx
import React from 'react';
import { GetIdSdk } from '@get-id/react-native-sdk';
const App = () => {
return (
// Your component here
);
};
Initialising the SDK
There are two ways to initialise the SDK: using the SDK KEY
or using a JWT
. We recommend using JWT in the production environment. But during the development, you can use SDK KEY
, because it's a little bit more convenient.
Using SDK KEY
import { GetIdSdk } from '@get-id/react-native-sdk';
const sdk = await GetIdSdk.initialiseSDK({
apiUrl: '[YOUR_END_POINT]',
sdkKey: '[SDK_KEY]',
flow: '[YOUR_FLOW]',
});
Using a JWT
To start the verification flow using a JWT
, your app should obtain the token from your backend.
Your backend should have the SDK KEY
to request the token from GetID server. Don't store the SDK KEY
inside the app in a production environment.
To obtain a JWT
make a POST request on your API URL
with SDK KEY
in the header:
$ curl -H "Content-Type: application/json" -H "x-sdk-key: SDK_KEY" -X POST API_URL/sdk/v2/token
Then pass the received token to GetIdSdk.initialiseSDK
method:
import { GetIdSdk } from '@get-id/react-native-sdk';
const sdk = await GetIdSdk.initialiseSDK({
apiUrl: '[YOUR_END_POINT]',
token: '[JWT_TOKEN]',
flow: '[YOUR_FLOW]',
});
How to use GetID SDK
Once the SDK is initialized, you need to call the initialiseFrontDocumentScan
function and other SDK functions to open up the camera feed and interact with the SDK.
To do that, let's create another component that will act as the wrapper for the camera feed, and where you can add your custom UI at the top and trigger camera functions like takePicture()
, uploadDocument()
, and capture()
.
Let's create a component called GetidDocScanWrapper.tsx
and pass the SDK instance that was created in the parent component.
/// GetidDocScanWrapper.tsx
import { View, StyleSheet, Button, Text } from 'react-native';
import React, { memo, useCallback, useEffect, useState } from 'react';
import HintMessage from './HintMessage';
import { type GetIdSdk, GetidSdkTypes } from '@get-id/react-native-sdk';
import { Alert } from 'react-native';
type DocScanProps = {
sdk: GetIdSdk;
docType: 'front' | 'back';
onNextStep?: () => void;
onComplete?: () => void;
};
type DocScanFunctions = {
takePicture?: Function;
capture?: Function;
uploadDocument?: () => Promise<GetidSdkTypes.ScannedDocument>;
};
const GetidDocScanWrapper = ({
sdk,
onNextStep,
onComplete,
docType,
}: DocScanProps) => {
const [GetIdDocScanCmp, setGetIdDocScanCmp] = useState<React.JSX.Element>();
const [hintMessage, setHintMessage] = useState<string>('');
const [sdkFunctions, setSdkFunctions] = useState<DocScanFunctions>({});
const [uploadingDoc, setUploadingDoc] = useState(false);
const onUserHintChange = useCallback((hint: any) => {
console.log(`onUserHintChange: ${hint}`);
setHintMessage(hint);
}, []);
const onDocumentScanServerValidationStarted = useCallback(() => {
console.log(
'onDocumentScanServerValidationStarted: Document scan server validation started'
);
}, []);
const handleScannedDocument = (
scannedDocument: GetidSdkTypes.ScannedDocument
) => {
console.log('Scanned Document:', scannedDocument);
if (scannedDocument.conclusion === 'back-side-missing') {
onNextStep?.();
}
if (scannedDocument.conclusion === 'ok') {
// Once the document conclusion is ok, you can submit the document for verification
onComplete?.();
}
if (scannedDocument.conclusion === 'unknown-sides') {
Alert.alert(
'unknown-sides',
'Cant recognize the document side, please try again'
);
setUploadingDoc(false);
}
};
useEffect(() => {
const initDocScan = async () => {
const initialiseDocumentScan =
docType === 'front'
? sdk.initialiseFrontDocumentScan
: sdk.initialiseBackDocumentScan;
const { component, ...functions } = await initialiseDocumentScan({
onDocumentScanServerValidationStarted,
onUserHintChange,
});
setGetIdDocScanCmp(() => component);
setSdkFunctions(functions);
};
initDocScan();
}, [sdk, onDocumentScanServerValidationStarted, onUserHintChange, docType]);
return (
<View style={styles.containerFullPage}>
{GetIdDocScanCmp}
<Text style={styles.titleDescription}>
Please scan your {docType} document
</Text>
{uploadingDoc && <Text style={styles.textLoading}>Scanning...</Text>}
{!uploadingDoc && <HintMessage message={hintMessage} />}
<View style={styles.btnTakePicture}>
<Button
title="Capture"
disabled={uploadingDoc}
onPress={() => {
// subcribe to the capture promise, whenever the takePicture func is called, this promise will be resolved
sdkFunctions.capture?.().then((scannedDocument: any) => {
handleScannedDocument(scannedDocument);
});
}}
/>
<Button
title="Take Picture"
onPress={() => {
setUploadingDoc(true);
sdkFunctions.takePicture?.();
}}
/>
</View>
</View>
);
};
const styles = StyleSheet.create({
containerFullPage: {
flex: 1,
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
justifyContent: 'flex-end',
},
btnTakePicture: {
color: 'white',
textAlign: 'center',
marginBottom: 50,
marginHorizontal: 10,
// flexDirection: 'row',
justifyContent: 'space-around',
backgroundColor: 'rgba(0, 0, 0, 0.9)',
},
textLoading: {
color: 'white',
fontSize: 24,
textAlign: 'center',
fontWeight: 'bold',
marginBottom: 50,
},
titleDescription: {
color: 'white',
fontSize: 16,
textAlign: 'center',
fontWeight: 'bold',
marginBottom: 'auto',
marginTop: 80,
alignSelf: 'center',
},
});
export default memo(GetidDocScanWrapper);
Then, we can use that component in our main root component. Here is the full code of App.tsx
:
// App.tsx
import { SafeAreaView, Button, StyleSheet, Text } from 'react-native';
import React, { useState } from 'react';
import { GetIdSdk } from '@get-id/react-native-sdk';
import GetidDocScanWrapper from './components/GetidDocScanWrapper';
import Config from 'react-native-config';
const API_URL = Config.API_URL || '';
const SDK_KEY = Config.SDK_KEY || '';
export default function App() {
const [getidSdkInstance, setGetidSdkInstance] = useState<GetIdSdk>();
const [step, setStep] = useState(0);
const [verificationCompleted, setVerificationCompleted] = useState(false);
const [loading, setLoading] = useState(false);
const startGetIdSdk = () => {
GetIdSdk.initialiseSDK({
sdkKey: SDK_KEY,
flow: 'doc-only',
apiUrl: API_URL,
})
.then((sdk) => {
setGetidSdkInstance(sdk);
})
.catch((error) => {
console.error('Error:', error);
});
};
const nextStep = () => setStep(step + 1);
const onComplete = async () => {
try {
setLoading(true);
await getidSdkInstance?.submitForVerification();
} catch (error) {
console.error('Error:', error);
} finally {
setVerificationCompleted(true);
setLoading(false);
}
};
if (!getidSdkInstance) {
return (
<SafeAreaView style={styles.container}>
<Text style={styles.header}> Klarna APP </Text>
<Button title="Start GetId SDK" onPress={startGetIdSdk} />
</SafeAreaView>
);
}
if (verificationCompleted || loading) {
return (
<SafeAreaView style={styles.container}>
<Text style={styles.header}>
{loading ? 'Loading...' : 'Verification Completed'}
</Text>
</SafeAreaView>
);
}
return (
<SafeAreaView style={styles.container}>
{step === 0 && (
<GetidDocScanWrapper
sdk={getidSdkInstance}
onNextStep={nextStep}
docType="front"
/>
)}
{step === 1 && (
<GetidDocScanWrapper
sdk={getidSdkInstance}
onNextStep={nextStep}
docType="back"
onComplete={() => onComplete()}
/>
)}
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
header: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
margin: 10,
fontFamily: 'monospace',
marginVertical: 50,
},
});
In the above code, we first check if the getidSdkInstance is available. If not, we display a "Loading" message. Once the instance is available, we render the GetidDocScanWrapper component and pass the sdk instance and an onComplete callback function that will be called when the front document scan is completed.
Accessing config
You can find the full flow config on the sdk
instance in sdk.config.configuration
. Example:
{
...
"flow": [
{
"allowFromGallery": true,
"allowSkippingValidation": 3,
"component": "document",
"countriesDocumentTypes": [],
"requiredFields": [],
"showDocumentChoice": false,
"showGuide": true,
"useNFC": false
},
{
"component": "selfie",
"showGuide": true
},
{
"component": "liveness",
}
],
"name": "klarna-native",
"responseCode": 200,
...
}
You can get the flow screens dynamically as follows:
const screens = sdk.config.configuration.flow.map((s) => s.component); // ['document', 'selfie', 'liveness'];
You can get the document scan config as follows:
const docConfig = sdk.config.configuration.flow.find(
(s) => s.component === 'document'
);
const { allowFromGallery, useNFC } = docConfig;