npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@get-id/react-native-sdk

v0.2.25

Published

GetID react native SDK

Downloads

624

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:

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.

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;