Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,6 @@ dependencies {
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation("com.ts.sdk:identityverification:1.1.1")
implementation("com.ts.sdk:identityverification:1.2.+")
}

56 changes: 41 additions & 15 deletions android/src/main/java/com/tsidv/TsIdvModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.WritableMap
import com.facebook.react.modules.core.DeviceEventManagerModule
import com.transmit.identityverification.ITSFaceAuthenticationStatus
import com.transmit.identityverification.ITSIdentityVerificationMosaicUIStatus
import com.transmit.identityverification.ITSIdentityVerificationStatus
import com.transmit.identityverification.TSIdentityVerification
import com.transmit.identityverification.TSIdentityVerification.registerForStatus
Expand All @@ -19,7 +20,7 @@ import com.transmit.identityverification.TSRecaptureReason
import com.ts.coresdk.TSLog

class TsIdvModule(private val reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext),
ITSIdentityVerificationStatus, ITSFaceAuthenticationStatus {
ITSIdentityVerificationStatus, ITSFaceAuthenticationStatus, ITSIdentityVerificationMosaicUIStatus {

private val idvStatusChangeEventName: String = "idv_status_change_event"
private val TAG = "IDV"
Expand Down Expand Up @@ -49,6 +50,12 @@ class TsIdvModule(private val reactContext: ReactApplicationContext) : ReactCont
FaceAuthenticationFail("faceAuthenticationDidFail")
}

enum class MosaicUIAuthStatusType(val status: String) {
mosaicUIVerificationDidComplete("mosaicUIVerificationDidComplete"),
mosaicUIVerificationDidCancel("mosaicUIVerificationDidCancel"),
mosaicUIVerificationDidFail("mosaicUIVerificationDidFail")
}

// region IDV SDK API

@ReactMethod
Expand Down Expand Up @@ -82,7 +89,19 @@ class TsIdvModule(private val reactContext: ReactApplicationContext) : ReactCont
return
}
val activity = currentActivity!!
start(activity, startToken)
TSIdentityVerification.start(activity, startToken)
promise.resolve(true)
}

@ReactMethod
fun startMosaicUI(startToken: String, promise: Promise) {
Log.d(TAG, "startMosaicUI")
if (currentActivity == null) {
promise.reject("Error during startMosaicUI", "currentActivity is NULL")
return
}
val activity = currentActivity!!
TSIdentityVerification.startWithSmartUI(activity, startToken);
promise.resolve(true)
}

Expand Down Expand Up @@ -197,24 +216,31 @@ class TsIdvModule(private val reactContext: ReactApplicationContext) : ReactCont

// endregion

// region Helpers
// region Identity Verification Mosaic UI Status

// private fun parseLogLevel(jsLogLevel: String): TSLogLevel? {
// return when (jsLogLevel) {
// "verbose" -> TSLogLevel.VERBOSE
// "debug" -> TSLogLevel.DEBUG
// "info" -> TSLogLevel.INFO
// "warning" -> TSLogLevel.WARNING
// "error" -> TSLogLevel.ERROR
// "crytical" -> TSLogLevel.CRITICAL
// "off" -> TSLogLevel.OFF
// else -> null
// }
// }
override fun mosaicUIVerificationCompleted() {
reportIDVStatusChange(MosaicUIAuthStatusType.mosaicUIVerificationDidComplete.status, null)
}

override fun mosaicUIVerificationCanceled() {
reportIDVStatusChange(MosaicUIAuthStatusType.mosaicUIVerificationDidCancel.status, null)
}

override fun mosaicUIVerificationFailed(error: TSIdentityVerificationError) {
Log.d("MosaicUI verificationDidFail", error.name)
val errorMap: WritableMap = Arguments.createMap()
errorMap.putString("error", error.name)
reportIDVStatusChange(MosaicUIAuthStatusType.mosaicUIVerificationDidFail.status, errorMap)
}

// endregion

// region Helpers

private fun registerSDKStatus() {
registerForStatus(this)
TSIdentityVerification.registerForFaceAuthStatus(this)
TSIdentityVerification.registerForStatusMosaicUI(this)
}


Expand Down
2 changes: 1 addition & 1 deletion example/ios/.xcode.env
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export NODE_BINARY=/usr/local/bin/node
export NODE_BINARY='/usr/local/bin/node'
32 changes: 16 additions & 16 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
PODS:
- AccountProtection (2.1.4):
- TSCoreSDK (~> 1.0.24)
- AccountProtection (2.1.10):
- TSCoreSDK (~> 1.0.27)
- boost (1.84.0)
- DoubleConversion (1.1.6)
- FBLazyVector (0.75.2)
- fmt (9.1.0)
- glog (0.3.5)
- IdentityVerification (1.1.2):
- AccountProtection (~> 2.1.3)
- TSCoreSDK (~> 1.0.23)
- IdentityVerification (1.2.2):
- AccountProtection (~> 2.1.9)
- TSCoreSDK (~> 1.0.27)
- RCT-Folly (2024.01.01.00):
- boost
- DoubleConversion
Expand Down Expand Up @@ -1214,10 +1214,10 @@ PODS:
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- react-native-ts-idv (1.0.4):
- react-native-ts-idv (1.0.5):
- DoubleConversion
- glog
- IdentityVerification (~> 1.1.2)
- IdentityVerification (~> 1.2.2)
- RCT-Folly (= 2024.01.01.00)
- RCTRequired
- RCTTypeSafety
Expand Down Expand Up @@ -1479,7 +1479,7 @@ PODS:
- React-logger (= 0.75.2)
- React-perflogger (= 0.75.2)
- React-utils (= 0.75.2)
- ReactNativeHost (0.4.12):
- ReactNativeHost (0.5.3):
- DoubleConversion
- glog
- RCT-Folly (= 2024.01.01.00)
Expand All @@ -1501,12 +1501,12 @@ PODS:
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- ReactTestApp-DevSupport (3.10.1):
- ReactTestApp-DevSupport (3.10.22):
- React-Core
- React-jsi
- ReactTestApp-Resources (1.0.0-dev)
- SocketRocket (0.7.0)
- TSCoreSDK (1.0.24)
- TSCoreSDK (1.0.27)
- Yoga (0.0.0)

DEPENDENCIES:
Expand Down Expand Up @@ -1715,13 +1715,13 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/yoga"

SPEC CHECKSUMS:
AccountProtection: d34c382ae6eed651f2d72baf4856a2f95a45d749
AccountProtection: 9154d08c86586d632ef1821962953e22a4f313f3
boost: 4cb898d0bf20404aab1850c656dcea009429d6c1
DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5
FBLazyVector: 38bb611218305c3bc61803e287b8a81c6f63b619
fmt: 4c2741a687cc09f0634a2e2c72a838b99f1ff120
glog: 69ef571f3de08433d766d614c73a9838a06bf7eb
IdentityVerification: 2ca41a6c740105bf5165266ffa4b2ac55288bfb8
IdentityVerification: e48bf94fd0f858f7fb70a2ace1d07160140ec1d3
RCT-Folly: 4464f4d875961fce86008d45f4ecf6cef6de0740
RCTDeprecation: 34cbf122b623037ea9facad2e92e53434c5c7422
RCTRequired: 24c446d7bcd0f517d516b6265d8df04dc3eb1219
Expand Down Expand Up @@ -1751,7 +1751,7 @@ SPEC CHECKSUMS:
React-logger: 8db32983d75dc2ad54f278f344ccb9b256e694fc
React-Mapbuffer: 1c08607305558666fd16678b85ef135e455d5c96
React-microtasksnativemodule: e8efd9e5df1ab51a58e45326b98787cf21d47e6e
react-native-ts-idv: 15f4f7012cea8db1fcc535c82192f8fab2741247
react-native-ts-idv: cc1712cd435ec9a1b66b1f7801a34a2aad7f41aa
React-nativeconfig: 57781b79e11d5af7573e6f77cbf1143b71802a6d
React-NativeModulesApple: e35ceb132b4005f4bb8924a3a87b9fd3c21b15ee
React-perflogger: 8a360ccf603de6ddbe9ff8f54383146d26e6c936
Expand All @@ -1777,11 +1777,11 @@ SPEC CHECKSUMS:
React-utils: 87f64cff8c1fe244bf688a7a48395a70eb61a509
ReactCodegen: f8ed6f835a2fffe2a3666dfbce5ff1b120f24982
ReactCommon: a33f215e2ca23410f8f44b0a94ab93120882e5e5
ReactNativeHost: 6452a9f39ec92ef8ce5f752ec2e1fa0cd2180b8e
ReactTestApp-DevSupport: 6a2de08b780d695cb5d2fbe3e2222ea471de5866
ReactNativeHost: 478750aa4ff0e22768467a4193c64ddb959f26de
ReactTestApp-DevSupport: 42abce6b0c88dfb47c86e80aa22831b2abcc3144
ReactTestApp-Resources: 7db90c026cccdf40cfa495705ad436ccc4d64154
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
TSCoreSDK: b480415b11b5b202cbf43275b1ea40f68b546b6e
TSCoreSDK: 750f7723e2c8c8e7501f050021674bc30e48de37
Yoga: a1d7895431387402a674fd0d1c04ec85e87909b8

PODFILE CHECKSUM: 73892cfbb7baf5a735ea7d27759f1ed18058b6d7
Expand Down
30 changes: 22 additions & 8 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@

import React from 'react';
import {
NativeModules, NativeEventEmitter, SafeAreaView,

Check failure on line 10 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Replace `·NativeEventEmitter,` with `⏎··NativeEventEmitter,⏎·`
type EmitterSubscription, ActivityIndicator, View,

Check failure on line 11 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Replace `·ActivityIndicator,` with `⏎··ActivityIndicator,⏎·`
StyleSheet, Platform, Alert, PermissionsAndroid

Check failure on line 12 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Replace `·Platform,·Alert,·PermissionsAndroid` with `⏎··Platform,⏎··Alert,⏎··PermissionsAndroid,`
} from 'react-native';
import MockServer, {
type AccessTokenResponse, type FaceAuthSessionResponse, type VerificationResultsResponse,

Check failure on line 15 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Replace `·type·FaceAuthSessionResponse,` with `⏎··type·FaceAuthSessionResponse,⏎·`
type VerificationSessionResponse

Check failure on line 16 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Insert `,`
} from './services/mock_server';

import HomeScreen from './home';
Expand All @@ -30,17 +30,17 @@
export type State = {
isVerificationResultsModalVisible: boolean;
isRecaptureModalVisible: boolean;
verificationResultsResponse: VerificationResultsResponse | null

Check failure on line 33 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Insert `;`
errorMessage: string;
isProcessing: boolean;
lastVerificationSessionID: string | null;
};

const enum VerificationStatus {
verificationDidCancel = "verificationDidCancel",

Check failure on line 40 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Replace `"verificationDidCancel"` with `'verificationDidCancel'`
verificationDidComplete = "verificationDidComplete",

Check failure on line 41 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Replace `"verificationDidComplete"` with `'verificationDidComplete'`
verificationDidFail = "verificationDidFail",

Check failure on line 42 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Replace `"verificationDidFail"` with `'verificationDidFail'`
verificationDidStartCapturing = "verificationDidStartCapturing",

Check failure on line 43 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Replace `"verificationDidStartCapturing"` with `'verificationDidStartCapturing'`
verificationDidStartProcessing = "verificationDidStartProcessing",
verificationRequiresRecapture = "verificationRequiresRecapture",

Expand All @@ -48,7 +48,11 @@
faceAuthenticationDidComplete = "faceAuthenticationDidComplete",
faceAuthenticationDidFail = "faceAuthenticationDidFail",
faceAuthenticationDidStartCapturing = "faceAuthenticationDidStartCapturing",
faceAuthenticationDidStartProcessing = "faceAuthenticationDidStartProcessing"
faceAuthenticationDidStartProcessing = "faceAuthenticationDidStartProcessing",

mosaicUIVerificationDidComplete = "mosaicUIVerificationDidComplete",
mosaicUIVerificationDidCancel = "mosaicUIVerificationDidCancel",
mosaicUIVerificationDidFail = "mosaicUIVerificationDidFail",
}

export default class App extends React.Component<any, State> {
Expand All @@ -69,7 +73,7 @@
}

componentDidMount(): void {
this.onAppReady().catch(e => void e);

Check warning on line 76 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Expected 'undefined' and instead saw 'void'
}

componentWillUnmount(): void {
Expand All @@ -78,10 +82,11 @@

render() {
return (
<SafeAreaView style={{ flex: 1 }}>

Check warning on line 85 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { flex: 1 }
<HomeScreen
onStartIDV={this.onStartVerificationProcess}
onStartFaceAuth={this.onStartFaceAuth}
onStartMosaicUI={this.onStartMosaicUI}
isInSession={this.state.lastVerificationSessionID !== null}
errorMessage={this.state.errorMessage}
/>
Expand Down Expand Up @@ -163,6 +168,20 @@
}
}

onStartMosaicUI = async (): Promise<void> => {
try {
const accessToken = this.accessTokenResponse?.token || "";

this.verificationSession = await this.mockServer.createVerificationSession(accessToken);
await IdentityVerification.startMosaicUI(this.verificationSession.startToken);

this.logAppEvent("Started identity verification with MosaicUI process");
} catch (error) {
this.logAppEvent(`Error verifying user identity: ${error}`);
this.setState({ errorMessage: `${error}` });
}
}

private identityVerificationCompleted = async (sessionId: string, accessToken: string): Promise<void> => {

try {
Expand Down Expand Up @@ -197,13 +216,8 @@
}

IdentityVerification.setLogLevel(TSIDV.IDVLogLevel.verbose);

if (Platform.OS === "android") {
await IdentityVerification.initializeSDK();
} else {
await IdentityVerification.initialize(config.clientId);
}

await IdentityVerification.initialize(config.clientId);

this.registerForEvents();
this.requestCameraPermissions();

Expand Down Expand Up @@ -252,8 +266,8 @@
}

private onVerificationStatus = async (params: any) => {
const status = params["status"];

Check warning on line 269 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

["status"] is better written in dot notation
const additionalData = params["additionalData"];

Check warning on line 270 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

["additionalData"] is better written in dot notation

switch (status) {
// Identity Verification Events:
Expand All @@ -268,7 +282,7 @@
await this.handleIdentityVerificationComplete();
break;
case VerificationStatus.verificationDidFail:
const error: TSIDV.IdentityVerificationError = additionalData["error"];

Check warning on line 285 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

["error"] is better written in dot notation
this.setState({ errorMessage: `Verification Failed: ${error}`, isProcessing: false });
this.logAppEvent(`verificationDidFail`);
break;
Expand All @@ -281,7 +295,7 @@
this.setState({ errorMessage: ``, isProcessing: true });
break;
case VerificationStatus.verificationRequiresRecapture:
const reason: string = additionalData["error"];

Check warning on line 298 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

["error"] is better written in dot notation
this.setState({ errorMessage: `Require Recapture: ${reason}`, isProcessing: false, isRecaptureModalVisible: true });
this.logAppEvent(`verificationRequiresRecapture: ${additionalData}`);
break;
Expand All @@ -299,7 +313,7 @@
await this.handleFaceAuthComplete();
break;
case VerificationStatus.faceAuthenticationDidFail:
this.setState({ errorMessage: `Face Authentication Failed: ${additionalData["error"]}`, isProcessing: false });

Check warning on line 316 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

["error"] is better written in dot notation
this.logAppEvent(`faceAuthenticationDidFail`);
break;
case VerificationStatus.faceAuthenticationDidStartCapturing:
Expand Down
18 changes: 16 additions & 2 deletions example/src/home.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import React, { ReactElement } from 'react';
import React, { type ReactElement } from 'react';
import { Button, StyleSheet, Text, View } from 'react-native';

export type Props = {
onStartIDV: () => void;
onStartFaceAuth: () => void;
onStartMosaicUI: () => void;
isInSession: boolean;
errorMessage: string;
};

const HomeScreen: React.FC<Props> = ({ onStartIDV, onStartFaceAuth, isInSession, errorMessage }) => {
const HomeScreen: React.FC<Props> = ({ onStartIDV, onStartFaceAuth, onStartMosaicUI, isInSession, errorMessage }) => {

return (
<View style={styles.container}>
<Text style={styles.sectionTitle}>{"Identinty Verification"}</Text>
{ renderStartIDVWithMosaicUIButton() }
{ renderStartIDVButton() }
{ renderStartFaceAuthVButton() }
{ renderStatusLabel() }
Expand All @@ -21,7 +23,7 @@

function renderStatusLabel(): ReactElement {
return (
<View style={{marginTop: 24}}>

Check warning on line 26 in example/src/home.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { marginTop: 24 }
<Text style={styles.statusLabel}>{errorMessage}</Text>
</View>
)
Expand All @@ -30,7 +32,7 @@
function renderStartIDVButton(): ReactElement {
if (isInSession) { return <></> }
return (
<View style={{marginTop: 24}}>

Check warning on line 35 in example/src/home.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { marginTop: 24 }
<Button
title="Start Identity Verification"
onPress={onStartIDV}
Expand All @@ -39,6 +41,18 @@
)
}

function renderStartIDVWithMosaicUIButton(): ReactElement {
if (isInSession) { return <></> }
return (
<View style={{marginTop: 24}}>

Check warning on line 47 in example/src/home.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { marginTop: 24 }
<Button
title="Start MosaicUI Identity Verification"
onPress={onStartMosaicUI}
/>
</View>
)
}

function renderStartFaceAuthVButton(): ReactElement {
if (!isInSession) { return <></> }

Expand Down
1 change: 0 additions & 1 deletion example/src/services/mock_server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ class MockServer {
// MARK: -Document Verification methods

createVerificationSession = async (accessToken: string): Promise<VerificationSessionResponse> => {

try {
const resp = await fetch(
`${config.baseAPIURL}/verify/api/v1/verification`,
Expand Down
2 changes: 2 additions & 0 deletions ios/TsIdv.mm
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ @interface RCT_EXTERN_MODULE(TsIdv, NSObject)
RCT_EXTERN_METHOD(recapture:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
RCT_EXTERN_METHOD(startFaceAuth:(NSString *)deviceSessionId withResolver:(RCTPromiseResolveBlock)resolve
withRejecter:(RCTPromiseRejectBlock)reject)
RCT_EXTERN_METHOD(startMosaicUI:(NSString *)startToken withResolver:(RCTPromiseResolveBlock)resolve
withRejecter:(RCTPromiseRejectBlock)reject)

+ (BOOL)requiresMainQueueSetup
{
Expand Down
Loading
Loading