GetID react native SDK
npm install @get-id/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.
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
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 and SDK KEY. While the API KEY allows for public and SDK API calls, the SDK KEY is exclusive to SDK API calls. It's safer to use SDK KEY when using the SDK.
Ensure the SDK can access the device camera.
Add the following usage descriptions to your Info.plist (usually found at: ios/PROJECT_NAME/)
```
Add the following uses-permission to your AndroidManifest.xml (usually found at: android/src/main/)
``
`bash`
yarn add https://cdn.getid.cloud/sdk/react-native/[version]/get-id-react-native-sdk.tgz
yarn add react-native-vision-camera@4.0.5
yarn add react-native-worklets-core@1.2.0
yarn add react-native-svg@15.2.0
yarn add react-native-photo-manipulator@1.5.0
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 react-native-image-picker@7.1.2
yarn add vision-camera-resize-plugin@https://github.com/mrousavy/vision-camera-resize-plugin.git#ff3b6d25c035e96d9d68fd17a131abd14d33f9a1
yarn add lottie-react-native@5.1.6
yarn add lottie-ios@3.4.0
cd ios; pod install; cd ..
Unless a flow is already created, use the GetID Admin Panel in the backoffice to create a new flow (Flows > Add new flow).
Here's an example of how you can import the GetID SDK in your React Native app:
`tsx
// App.tsx
import React from 'react';
import { GetIdSdk } from '@get-id/react-native-sdk';
const App = () => {
return (
// Your component here
);
};
`
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
`javascript`
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.SDK KEY
Your backend should have the 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:
`bash`
$ 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:
`javascript`
import { GetIdSdk } from '@get-id/react-native-sdk';
const sdk = await GetIdSdk.initialiseSDK({
apiUrl: '[YOUR_END_POINT]',
token: '[JWT_TOKEN]',
flow: '[YOUR_FLOW]',
});
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().GetidDocScanWrapper.tsx
Let's create a component called and pass the SDK instance that was created in the parent component.
`tsx
/// 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
};
const GetidDocScanWrapper = ({
sdk,
onNextStep,
onComplete,
docType,
}: DocScanProps) => {
const [GetIdDocScanCmp, setGetIdDocScanCmp] = useState
const [hintMessage, setHintMessage] = useState
const [sdkFunctions, setSdkFunctions] = useState
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 (
{GetIdDocScanCmp}
Please scan your {docType} document
{uploadingDoc &&
{!uploadingDoc &&
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);
});
}}
/>
title="Take Picture"
onPress={() => {
setUploadingDoc(true);
sdkFunctions.takePicture?.();
}}
/>
);
};
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:
`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
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 (
);
}
if (verificationCompleted || loading) {
return (
{loading ? 'Loading...' : 'Verification Completed'}
);
}
return (
{step === 0 && (
onNextStep={nextStep}
docType="front"
/>
)}
{step === 1 && (
onNextStep={nextStep}
docType="back"
onComplete={() => onComplete()}
/>
)}
);
}
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.
You can find the full flow config on the sdk instance in sdk.config.configuration. Example:
`json`
{
...
"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:
`javascript`
const screens = sdk.config.configuration.flow.map((s) => s.component); // ['document', 'selfie', 'liveness'];
You can get the document scan config as follows:
`javascript``
const docConfig = sdk.config.configuration.flow.find(
(s) => s.component === 'document'
);
const { allowFromGallery, useNFC } = docConfig;