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 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-kalapa-ekyc

v1.3.2

Published

React Native SDK for Kalapa eKYC integration

Readme

Kalapa eKYC React Native SDK Documentation

Complete guide for integrating Kalapa eKYC functionality into your React Native applications.


Changelog

1.3.2

  • iOS: Re-enable QR Code step

1.3.1

  • Android: Optimize QR-code step

1.3.0

  • TypeScript: Fix default export being inferred as any. Spreading the native module (...NativeModules.KalapaEkyc) into the exported object previously erased all typing, so KalapaEkyc.start() and its result fell back to any in consumer code. The module is now declared via a KalapaEkycModule interface, so start() is fully typed and returns Promise<KalapaEkycResponse> ({ kalapa_result: KalapaResult; session?: string }) — no casting needed to access kalapa_result or its methods.
  • Android: Update to latest version of Kalapa eKYC to use latest version of Android Camera X 1.6.1.

1.2.10

  • Android: Fix switch fall-through in onError callback — prevents Promise being rejected multiple times
  • Android: Fix getCurrentActivity() == null case now rejects Promise with ACTIVITY_NULL instead of leaving it pending forever
  • Android: Fix native crash when optional config keys are missing — all boolean/int fields now use safe hasKey guards
  • Android: SDK now runs on UI thread to safely open Activity
  • Android: Bump compileSdkVersion and targetSdkVersion to 35
  • iOS: Fix handleResult crash when ocr_data.data.fields is nil (e.g. nfc_only flow)
  • iOS: Fix qr_code response format — now correctly wrapped as { data: { decoded_text } } to match TypeScript parser
  • iOS: Unify EventSessionExpired error code to EXPIRED (was UNAUTHORIZED)
  • TypeScript: config parameter is now fully typed (KalapaEkycConfig), no more any
  • TypeScript: flow parameter is now typed as KalapaEkycFlow union
  • TypeScript: Added KalapaEkycErrorCode union type for all error codes
  • TypeScript: Native module linkage guard — throws descriptive error with fix instructions if autolinking fails
  • TypeScript: nfc_data parser now handles camelCase field names from Android (idNumber, dateOfBirth, etc.)

1.2.9

  • React-Native: Add customer_language into config.
  • Android: Fix obfuscation error

1.2.8

  • Android: Update stable version for NFC step.

1.2.7

  • Android: Update config to scan QR code or not.
  • React-Native: Introduce config require_qr in AppConfig

1.2.6

  • Android: Minor update, UI / UX optimize. Stable version

1.2.5

  • Android: Fix NFC step error UNKNOWN rarely happens on some device like Samsung Note 10

1.2.4

  • Android: Optimize UI / UX in NFC step
  • React-Native: show to skip / show confirm screen.

1.2.3

  • Android: Optimize UI / UX in NFC step

1.2.2

  • iOS: Maintain UI config
  • Android: Maintain / Optimize NFC step

1.2.1

  • successColor / failureColor: Now can be configured via sdkConfig

1.2.0

  • Documentation: Complete overhaul of KalapaResult class documentation

1.1.3

  • Android: Removed GIF dependencies to satisfy Google Play requirement (16KB pages size)
  • Stable version

1.1.2

  • Android: Removed unnecessary jitpack.io repository
  • Android: Updated animation to avoid GIF usage

1.1.1

  • Android: Removed unnecessary jcenter repository

1.1.0

  • Android: Support target SDK version 35 & edge-to-edge display
  • Android: Support base64 library
  • UI & UX: General optimization improvements

1.0.7

  • General: Applied new flow for both Android & iOS platforms
  • iOS: UI & UX optimization
  • Android: UI & UX optimization

Requirements

Version Matrix

| Dependency | Version | |---|---| | React Native | >= 0.66 | | Android minSdkVersion | 24 | | Android compileSdkVersion | 35 | | Android targetSdkVersion | 35 | | iOS Deployment Target | >= 13.0 | | Kalapa Android SDK | 2.12.0 |

Android

Minimum SDK Requirements:

  • minSdkVersion = 24
  • compileSdkVersion = 35
  • targetSdkVersion = 35
  • android.useAndroidX = true
  • Kotlin = 1.8.0+

Compile Options:

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

iOS

  • iOS Deployment Target >= 13.0

Getting Started

Install the SDK

Using Yarn

yarn add react-native-kalapa-ekyc

Using npm

npm install react-native-kalapa-ekyc

Manual Installation

Add to your package.json:

"dependencies": {
    "react-native-kalapa-ekyc": "^1.2.10"
}

Configuration

Android

ProGuard / R8 (minifyEnabled true)

If you enable code shrinking for your release build, add the ProGuard rules below to prevent the SDK from being obfuscated or stripped — otherwise the eKYC steps (OCR, NFC, liveness) may crash at runtime.

  • app/proguard-rules.pro
# Retain generic signatures and exception types for reflection
-keepattributes Signature, InnerClasses, EnclosingMethod, Exceptions, *Annotation*

# Prevent obfuscation of Retrofit annotations and method structures
-keep class retrofit2.** { *; }
-dontwarn retrofit2.**

# Keep interfaces containing Retrofit HTTP annotations
-keepclasseswithmembers class * {
    @retrofit2.http.* <methods>;
}

# Keep the platform-specific call adapters from being stripped
-keep class retrofit2.Platform$* { *; }

-keepclassmembers,allowobfuscation class * {
    @com.google.gson.annotations.SerializedName <fields>;
}

iOS

Declare Camera and NFC Permissions

Update your Info.plist with the following:

<key>NFCReaderUsageDescription</key>
<string>This eKYC app needs NFC reader to scan chip</string>

<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
    <string>A0000002471001</string>
    <string>A0000002472001</string>
    <string>00000000000000</string>
</array>

<key>NSCameraUsageDescription</key>
<string>This eKYC app needs to use camera to scan document</string>

Enable NFC Capability

Add the Near Field Communication Tag Reading capability to your project target in Xcode.

View Xcode capability documentation


Implementation Guide

1. Initialize a Session

Each eKYC profile requires a unique session ID (JWT access token). The SDK uses this session ID to perform all eKYC steps.

Important Notes:

  • Failure to provide a valid session ID results in an EXPIRED error
  • Sessions are valid for 10 minutes by default (adjustable)
  • Each session ID should be used for a single eKYC flow

Check the API documentation for creating a new session.


2. Define SDK Configuration

TypeScript Interface

import KalapaEkyc, { KalapaEkycConfig, KalapaEkycFlow } from 'react-native-kalapa-ekyc';

const configInfo: KalapaEkycConfig = {
    domain: 'https://ekyc-sdk.kalapa.vn',
    main_color: '#1F69E6',
    main_text_color: '#000000',
    btn_text_color: '#FFFFFF',
    background_color: '#FFFFFF',
    success_color: '#388E3C',
    failure_color: '#F44336',
    language: 'vi',
    liveness_version: 3,
    with_confirm_screen: true,
    require_qr: false,
    allow_mrz_rescan_on_nfc_mismatch: true,
};

Configuration Parameters

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | domain | string | https://ekyc-sdk.kalapa.vn | Base URL for SDK API requests | | main_color | string | #1F69E6 | Hex color for buttons and primary UI elements | | main_text_color | string | #000000 | Hex color for main text | | btn_text_color | string | #FFFFFF | Hex color for text inside filled buttons | | background_color | string | #FFFFFF | Hex color for SDK background | | success_color | string | #388E3C | Hex color for success state indicators | | failure_color | string | #F44336 | Hex color for failure state indicators | | language | 'vi' | 'en' | 'en' | SDK UI language | | customer_language | string | '' | Custom language key — contact Kalapa to enable | | liveness_version | 1 | 2 | 3 | 0 | Liveness detection version: 3 = 3 random actions, 2 = move face toward camera, 1 = no action | | face_data | string | — | Base64 face data. If valid, skips liveness step | | mrz | string | — | Pre-filled MRZ. If valid, skips MRZ scan. Invalid input throws MRZ_INVALID | | qr_code | string | — | Pre-filled QR code. If valid, skips QR scan | | allow_mrz_rescan_on_nfc_mismatch | boolean | false | Allow user to rescan MRZ when NFC chip data doesn't match | | with_confirm_screen | boolean | false | Show confirm screen before submitting | | require_qr | boolean | false | Require QR code scan — may reduce the MRZ step in NFC flow | | session_id | string | — | Resume a previous leftover session |


3. Define the SDK Flow

Flow Types

| Flow | Scan Document | Scan Face | Scan NFC Chip | |------|:---:|:---:|:---:| | ekyc | ✓ | ✓ | ✗ | | nfc_ekyc | ✓ | ✓ | ✓ | | nfc_only | ✗ | ✓ | ✓ |

Flow Selection Guidelines

The SDK flow typically matches the flow set during session creation. However, there are special use cases:

Example — nfc_only retry: If a user completed ekyc but failed the NFC scan, you can reuse the same session ID with nfc_only to allow NFC scanning without re-scanning the document and face.

Best Practice: Use separate sessions for different flows to simplify data management.


4. Start the SDK

import KalapaEkyc, { KalapaResult, KalapaEkycConfig, KalapaEkycFlow } from 'react-native-kalapa-ekyc';

const configInfo: KalapaEkycConfig = {
    domain: 'https://ekyc-sdk.kalapa.vn',
    language: 'vi',
    liveness_version: 3,
    with_confirm_screen: true,
};

const flow: KalapaEkycFlow = 'nfc_ekyc';

KalapaEkyc.start(sessionId, flow, configInfo)
    .then(({ kalapa_result }) => {
        const result: KalapaResult = kalapa_result;

        if (result.isApproved()) {
            // Store or display non-sensitive fields
            saveVerificationResult({
                decision: result.decision,
                session: result.session,
                idNumberMasked: result.id_number.replace(/.(?=.{4})/g, '*'),
            });
        } else if (result.isManualReview()) {
            // Notify backend for manual review
        }
    })
    .catch((error) => {
        switch (error.code) {
            case 'EXPIRED':
                // Prompt user to restart — session timed out
                break;
            case 'CANCELED':
                // User backed out — no action needed
                break;
            case 'PERMISSION_DENIED':
                // Guide user to grant camera/NFC permission in Settings
                break;
            case 'DEVICE_NOT_ACCEPTABLE':
                // Block flow — emulator, rooted, or jailbroken device
                break;
            case 'MRZ_INVALID':
                // Invalid pre-filled MRZ was passed in config
                break;
            case 'NFC_NOT_MATCH':
                // NFC chip data doesn't match scanned document
                break;
            case 'UNSUPPORTED':
                // Device doesn't support NFC
                break;
            case 'CONFIG_ERROR':
                // Invalid domain, session, or SDK config
                break;
            case 'ACTIVITY_NULL':
                // Android only — app was backgrounded when SDK launched
                break;
            case 'OTHER':
            default:
                break;
        }
    });

Exception Handling

Error Codes

| Error Code | Platform | Description | |------------|----------|-------------| | EXPIRED | Android, iOS | Session expired (default 10-minute timeout) | | CANCELED | Android, iOS | User canceled the eKYC process | | PERMISSION_DENIED | Android | Camera or NFC permission denied | | DEVICE_NOT_ACCEPTABLE | Android | Emulator, rooted, or virtual camera detected | | MRZ_INVALID | Android | Pre-filled MRZ input is invalid | | NFC_NOT_MATCH | Android | MRZ does not match NFC chip data | | UNSUPPORTED | Android, iOS | Device doesn't support required features (NFC) | | CONFIG_ERROR | Android, iOS | Domain, session, or SDK configuration error | | ACTIVITY_NULL | Android | App Activity was null when SDK tried to launch | | OTHER | Android, iOS | Unexpected error |


Result Objects

KalapaResult Class

The SDK returns a KalapaResult instance in the resolved value of start(). No manual parsing is needed.

import KalapaEkyc, { KalapaResult } from 'react-native-kalapa-ekyc';

const { kalapa_result } = await KalapaEkyc.start(sessionId, flow, config);
// kalapa_result is already a KalapaResult instance

Security note: KalapaResult contains sensitive personal data — CCCD number, date of birth, MRZ, and a base64 face image from the NFC chip. Do not log these fields directly. Use result.id_number.replace(/.(?=.{4})/g, '*') or equivalent masking before any logging. Do not store nfc_data.face_image unless legally required and properly secured.

Core Properties

| Property | Type | Description | |----------|------|-------------| | decision | DecisionType | "APPROVED", "MANUAL", "REJECTED", or "UNKNOWN" | | session | string | Session JWT token | | selfie_data | SelfieData | Face matching results | | nfc_data | NfcData | NFC chip data | | mrz_data | MrzData \| null | Parsed MRZ fields | | qr_code | QrCode \| null | QR code data from document | | rawResult | any | Original unprocessed response |

Root-Level Personal Information

| Property | Type | Description | |----------|------|-------------| | name | string | Full name | | id_number | string | ID card number | | birthday | string | Birth date | | gender | string | Gender | | country | string | Country | | national | string | Nationality | | ethnicity | string | Ethnicity | | religion | string | Religion | | features | string | Personal identification marks | | poi | string | Place of issue | | doe | string | Date of expiry | | doi | string | Date of issuance | | home | string | Home address (full text) | | home_entities | AddressEntities | Parsed home address | | resident | string | Residential address (full text) | | resident_entities | AddressEntities | Parsed residential address | | type | string | Document type |


SelfieData Object

| Property | Type | Description | |----------|------|-------------| | is_matched | boolean | Whether face matched the document | | matching_score | number | Matching confidence score (0–100) |


NfcData Object

Security note: face_image is a base64-encoded portrait from the NFC chip. Treat it as biometric data — do not log, cache, or transmit without explicit user consent and appropriate security controls.

Personal Information

| Property | Type | Description | |----------|------|-------------| | name | string | Full name | | id_number | string | ID card number | | old_id_number | string | Previous ID number (if any) | | date_of_birth | string | Birth date (DD/MM/YYYY) | | date_of_expiry | string | Expiry date (DD/MM/YYYY) | | date_of_issuance | string | Issuance date (DD/MM/YYYY) | | gender | string | Gender | | nationality | string | Nationality | | nation | string | Nation/ethnicity |

Address Information

| Property | Type | Description | |----------|------|-------------| | address | string | Current residential address | | hometown | string | Hometown/place of origin |

Family Information

| Property | Type | Description | |----------|------|-------------| | father_name | string | Father's full name | | mother_name | string | Mother's full name | | spouse_name | string | Spouse's full name |

Additional Information

| Property | Type | Description | |----------|------|-------------| | religion | string | Religion | | personal_identification | string | Personal identification marks | | face_image | string | Base64 face image from NFC chip — handle as biometric data | | mrz | string | Raw MRZ string |


AddressEntities Object

| Property | Type | Description | |----------|------|-------------| | district | string | District name | | ward | string | Ward name | | province | string | Province name | | unknown | string | Unparsed address components |


MrzData Object

| Property | Type | Description | |----------|------|-------------| | data.fields.birthday | string | undefined | Birth date from MRZ | | data.fields.doe | string | undefined | Date of expiry from MRZ | | data.fields.gender | string | undefined | Gender from MRZ | | data.fields.id_number | string | undefined | ID number from MRZ | | data.fields.name | string | undefined | Name from MRZ | | data.raw_mrz | string | undefined | Raw MRZ string | | error.code | number | undefined | Error code if parsing failed | | error.message | string | undefined | Error message if parsing failed |


QrCode Object

| Property | Type | Description | |----------|------|-------------| | data.decoded_text | string | undefined | Decoded QR code text | | data.stage | number | undefined | Processing stage | | error.code | number | undefined | Error code if decoding failed | | error.message | string | undefined | Error message if decoding failed |


Convenience Methods

Decision Methods

| Method | Returns | Description | |--------|---------|-------------| | isApproved() | boolean | true if decision is "APPROVED" | | isManualReview() | boolean | true if decision is "MANUAL" | | isRejected() | boolean | true if decision is "REJECTED" |

Face Matching Methods

| Method | Returns | Description | |--------|---------|-------------| | isFaceMatched() | boolean | true if face matched successfully | | getFaceMatchingScore() | number | Face matching confidence score |

Formatted Getters

| Method | Returns | Description | |--------|---------|-------------| | getDisplayName() | string | Name from nfc_data, or "N/A" | | getIdNumber() | string | ID number from nfc_data, or "N/A" | | getDateOfBirth() | string | Birth date from nfc_data, or "N/A" | | getFaceImage() | string | Base64 face image from NFC chip |

Utility Methods

| Method | Returns | Description | |--------|---------|-------------| | toJSON() | object | Plain object suitable for storage or network transmission | | fromRawResult(raw) | KalapaResult | Static factory — creates a KalapaResult from a raw object |


Complete Usage Example

import KalapaEkyc, { KalapaResult, KalapaEkycConfig, KalapaEkycFlow } from 'react-native-kalapa-ekyc';

const runEkyc = async (sessionId: string) => {
    const config: KalapaEkycConfig = {
        domain: 'https://ekyc-sdk.kalapa.vn',
        language: 'vi',
        liveness_version: 3,
        with_confirm_screen: true,
        allow_mrz_rescan_on_nfc_mismatch: true,
    };

    const flow: KalapaEkycFlow = 'nfc_ekyc';

    try {
        const { kalapa_result: result } = await KalapaEkyc.start(sessionId, flow, config);

        // Decision
        if (result.isApproved()) {
            console.log('Approved');
        } else if (result.isManualReview()) {
            console.log('Manual review required');
        } else if (result.isRejected()) {
            console.log('Rejected');
        }

        // Face matching
        if (result.isFaceMatched()) {
            console.log(`Face matched — score: ${result.getFaceMatchingScore()}`);
        }

        // Address entities
        if (result.home_entities) {
            const { province, district, ward } = result.home_entities;
            console.log(`Home: ${ward}, ${district}, ${province}`);
        }

        // MRZ data
        if (result.mrz_data?.data?.fields) {
            const { id_number, name } = result.mrz_data.data.fields;
            console.log(`MRZ parsed — name: ${name}`); // avoid logging id_number directly
        }

        // QR code data
        if (result.qr_code?.data?.decoded_text) {
            console.log('QR decoded');
        }

        // Export for backend — avoid logging the full object as it contains PII
        const payload = result.toJSON();
        await submitToBackend(payload);

    } catch (error: any) {
        switch (error.code) {
            case 'EXPIRED':
                showAlert('Session expired', 'Please start over.');
                break;
            case 'CANCELED':
                // User backed out — no UI needed
                break;
            case 'PERMISSION_DENIED':
                showAlert('Permission required', 'Enable camera and NFC in Settings.');
                break;
            case 'DEVICE_NOT_ACCEPTABLE':
                showAlert('Unsupported device', 'Please use a physical device.');
                break;
            case 'NFC_NOT_MATCH':
                showAlert('NFC mismatch', 'Please rescan your document.');
                break;
            case 'ACTIVITY_NULL':
                // Android: app was backgrounded — ask user to retry
                break;
            default:
                showAlert('Error', error.message ?? 'An unexpected error occurred.');
        }
    }
};

Summary

The Kalapa eKYC React Native SDK provides identity verification with document scanning, face matching, and NFC chip reading. Key features:

  • Three flexible flow types (ekyc, nfc_ekyc, nfc_only)
  • Fully typed TypeScript API — KalapaEkycConfig, KalapaEkycFlow, KalapaEkycErrorCode
  • Customizable UI (colors, language, confirm screen)
  • Three liveness detection versions
  • Type-safe KalapaResult with convenience methods
  • Unified error codes across Android and iOS

For API documentation and session creation, refer to the Kalapa API documentation.