@finos_sdk/sdk-ekyc 1.4.5 → 1.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +1 -1
- package/android/src/main/java/finos/sdk/ekyc/EKYCModule.kt +86 -27
- package/dist/EKYCModule.d.ts +10 -0
- package/dist/EKYCModule.js +4 -1
- package/dist/package.json +1 -1
- package/dist/src/modules/FinosEKYCModule.d.ts +6 -0
- package/dist/src/modules/FinosESignModule.d.ts +2 -0
- package/dist/src/types/ekycLivenessType.d.ts +13 -0
- package/ios/EKYCModule.swift +25 -5
- package/package.json +1 -1
- package/src/modules/FinosEKYCModule.ts +6 -0
- package/src/modules/FinosESignModule.ts +2 -0
- package/src/types/ekycLivenessType.ts +16 -1
package/android/build.gradle
CHANGED
|
@@ -65,7 +65,7 @@ dependencies {
|
|
|
65
65
|
implementation 'com.facebook.react:react-android'
|
|
66
66
|
|
|
67
67
|
// Finos eKYC SDK dependencies from GitHub Packages Maven repository
|
|
68
|
-
def sdkVersion = "1.4.
|
|
68
|
+
def sdkVersion = "1.4.6.1"
|
|
69
69
|
implementation("finos.sdk.ekyc:ekyc:$sdkVersion")
|
|
70
70
|
implementation("finos.sdk.ekyc:ekycui:$sdkVersion")
|
|
71
71
|
implementation("finos.sdk.ekyc:nfc:$sdkVersion")
|
|
@@ -27,6 +27,7 @@ import finos.sdk.core.model.sdk.config.AppKeyConfig
|
|
|
27
27
|
import finos.sdk.core.model.sdk.config.C06Config
|
|
28
28
|
import finos.sdk.core.model.sdk.config.EKYCConfigSDK
|
|
29
29
|
import finos.sdk.core.model.sdk.config.FaceServiceConfig
|
|
30
|
+
import finos.sdk.core.model.sdk.config.LivenessBackConfirmConfig
|
|
30
31
|
import finos.sdk.core.model.sdk.config.LivenessConfig
|
|
31
32
|
import finos.sdk.core.model.sdk.config.NfcConfig
|
|
32
33
|
import finos.sdk.core.model.sdk.config.OcrConfig
|
|
@@ -235,7 +236,7 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
235
236
|
val eventMap =
|
|
236
237
|
Arguments.createMap().apply {
|
|
237
238
|
putString("event", event.name.toString())
|
|
238
|
-
putString("data",
|
|
239
|
+
putString("data", Gson().toJson(data))
|
|
239
240
|
}
|
|
240
241
|
sendEvent("onNfcScanStart", eventMap)
|
|
241
242
|
}
|
|
@@ -260,7 +261,7 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
260
261
|
val eventMap =
|
|
261
262
|
Arguments.createMap().apply {
|
|
262
263
|
putString("event", event.name.toString())
|
|
263
|
-
putString("data",
|
|
264
|
+
putString("data", Gson().toJson(data))
|
|
264
265
|
}
|
|
265
266
|
sendEvent("onNfcEvent", eventMap)
|
|
266
267
|
}
|
|
@@ -314,18 +315,19 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
314
315
|
ekycConfigSDK = ekycConfig,
|
|
315
316
|
callbackSuccess = { event, data ->
|
|
316
317
|
Log.d(TAG, "✅ checkC06() success")
|
|
318
|
+
val c06Json = Gson().toJson((data as? SDKEkycResult)?.checkC06Response)
|
|
317
319
|
|
|
318
320
|
// Create separate maps for event and promise
|
|
319
321
|
val eventMap =
|
|
320
322
|
Arguments.createMap().apply {
|
|
321
323
|
putString("event", event.name.toString())
|
|
322
|
-
putString("data",
|
|
324
|
+
putString("data", c06Json)
|
|
323
325
|
}
|
|
324
326
|
|
|
325
327
|
val promiseMap =
|
|
326
328
|
Arguments.createMap().apply {
|
|
327
329
|
putString("event", event.name.toString())
|
|
328
|
-
putString("data",
|
|
330
|
+
putString("data", c06Json)
|
|
329
331
|
}
|
|
330
332
|
sendEvent("onC06Success", eventMap)
|
|
331
333
|
promise.resolve(promiseMap)
|
|
@@ -389,7 +391,7 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
389
391
|
Log.d(TAG, "✅ startOcr() success")
|
|
390
392
|
val (eventMap, promiseMap) = createSeparateMaps { map ->
|
|
391
393
|
map.putString("event", event.name.toString())
|
|
392
|
-
map.putString("data", (data as SDKEkycResult).ocrResponse
|
|
394
|
+
map.putString("data", Gson().toJson((data as SDKEkycResult).ocrResponse))
|
|
393
395
|
}
|
|
394
396
|
sendEvent("onOcrSuccess", eventMap)
|
|
395
397
|
promise.resolve(promiseMap)
|
|
@@ -428,6 +430,8 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
428
430
|
activeActionCount: Int?,
|
|
429
431
|
forceCaptureTimeout: Double?,
|
|
430
432
|
isActiveLivenessColor: Boolean?,
|
|
433
|
+
isShowBackConfirmation: Boolean?,
|
|
434
|
+
backConfirmConfigJson: String?,
|
|
431
435
|
promise: Promise
|
|
432
436
|
) {
|
|
433
437
|
Log.d(TAG, "▶️ startLiveness() called")
|
|
@@ -461,6 +465,7 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
461
465
|
null
|
|
462
466
|
}
|
|
463
467
|
|
|
468
|
+
val backConfirmConfig = parseBackConfirmConfig(backConfirmConfigJson)
|
|
464
469
|
val livenessConfig =
|
|
465
470
|
LivenessConfig(
|
|
466
471
|
isActiveLiveness = isActiveLiveness ?: false,
|
|
@@ -475,7 +480,9 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
475
480
|
activeActionCount = activeActionCount ?: 2,
|
|
476
481
|
forceCaptureTimeout = (forceCaptureTimeout ?: 0.0).toLong(),
|
|
477
482
|
selfieImage = imageFile,
|
|
478
|
-
transactionId = transactionId
|
|
483
|
+
transactionId = transactionId,
|
|
484
|
+
isShowBackConfirmation = isShowBackConfirmation ?: false,
|
|
485
|
+
backConfirmConfig = backConfirmConfig,
|
|
479
486
|
)
|
|
480
487
|
val ekycConfig =
|
|
481
488
|
EKYCConfigSDK(
|
|
@@ -486,9 +493,9 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
486
493
|
eKYCFinOSLiveness.startEkyc(
|
|
487
494
|
ekycConfigSDK = ekycConfig,
|
|
488
495
|
callbackSuccess = { event, data ->
|
|
489
|
-
// LOG_SUCCESS = internal submit result event (v1.4.
|
|
496
|
+
// LOG_SUCCESS = internal submit result event (v1.4.6.1), don't resolve promise
|
|
490
497
|
if (event == EKYCEvent.LOG_SUCCESS) {
|
|
491
|
-
val logDataStr = data?.customData?.let { Gson().toJson(it) } ?: data?.
|
|
498
|
+
val logDataStr = data?.customData?.let { Gson().toJson(it) } ?: (data as? SDKEkycResult)?.checkLivenessResponse?.let { Gson().toJson(it) } ?: Gson().toJson(data)
|
|
492
499
|
Log.d(TAG, "LOG_SUCCESS [Liveness]: $logDataStr")
|
|
493
500
|
val logMap = Arguments.createMap().apply {
|
|
494
501
|
putString("event", event.name.toString())
|
|
@@ -500,7 +507,7 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
500
507
|
Log.d(TAG, "✅ startLiveness() success")
|
|
501
508
|
val (eventMap, promiseMap) = createSeparateMaps { map ->
|
|
502
509
|
map.putString("event", event.name.toString())
|
|
503
|
-
map.putString("data", (data as SDKEkycResult).checkLivenessResponse
|
|
510
|
+
map.putString("data", Gson().toJson((data as SDKEkycResult).checkLivenessResponse))
|
|
504
511
|
}
|
|
505
512
|
sendEvent("onLivenessSuccess", eventMap)
|
|
506
513
|
promise.resolve(promiseMap)
|
|
@@ -570,9 +577,10 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
570
577
|
eKYCFinOSFaceService.startEkyc(
|
|
571
578
|
ekycConfigSDK = ekycConfig,
|
|
572
579
|
callbackSuccess = { event, data ->
|
|
573
|
-
// LOG_SUCCESS = internal submit result event (v1.4.
|
|
580
|
+
// LOG_SUCCESS = internal submit result event (v1.4.6.1), don't resolve promise
|
|
574
581
|
if (event == EKYCEvent.LOG_SUCCESS) {
|
|
575
|
-
val
|
|
582
|
+
val faceResponse = (data as? SDKEkycResult)?.checkFaceResponse
|
|
583
|
+
val logDataStr = data?.customData?.let { Gson().toJson(it) } ?: faceResponse?.let { Gson().toJson(it) } ?: "null"
|
|
576
584
|
Log.d(TAG, "LOG_SUCCESS [FaceCompare]: $logDataStr")
|
|
577
585
|
val logMap = Arguments.createMap().apply {
|
|
578
586
|
putString("event", event.name.toString())
|
|
@@ -582,9 +590,24 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
582
590
|
return@startEkyc
|
|
583
591
|
}
|
|
584
592
|
Log.d(TAG, "✅ startFaceCompare() success")
|
|
593
|
+
val faceResponse = (data as? SDKEkycResult)?.checkFaceResponse
|
|
585
594
|
val (eventMap, promiseMap) = createSeparateMaps { map ->
|
|
586
595
|
map.putString("event", event.name.toString())
|
|
587
|
-
|
|
596
|
+
val resultMap = Arguments.createMap().apply {
|
|
597
|
+
putDouble("conf", faceResponse?.result?.conf?.toString()?.toDoubleOrNull() ?: 0.0)
|
|
598
|
+
putString("match", faceResponse?.result?.match?.toString())
|
|
599
|
+
putInt("matchScore", faceResponse?.result?.matchScore?.toString()?.toIntOrNull() ?: 0)
|
|
600
|
+
putString("toBeReviewed", faceResponse?.result?.toBeReviewed?.toString())
|
|
601
|
+
}
|
|
602
|
+
val faceMap = Arguments.createMap().apply {
|
|
603
|
+
putString("requestId", faceResponse?.requestId?.toString())
|
|
604
|
+
putMap("result", resultMap)
|
|
605
|
+
putString("status", faceResponse?.status?.toString())
|
|
606
|
+
putInt("statusCode", faceResponse?.statusCode?.toString()?.toIntOrNull() ?: 0)
|
|
607
|
+
putString("error", faceResponse?.error?.toString())
|
|
608
|
+
putString("type", faceResponse?.type?.toString())
|
|
609
|
+
}
|
|
610
|
+
map.putMap("data", faceMap)
|
|
588
611
|
}
|
|
589
612
|
sendEvent("onFaceCompareSuccess", eventMap)
|
|
590
613
|
promise.resolve(promiseMap)
|
|
@@ -783,6 +806,9 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
783
806
|
else -> AppIDType.NONE
|
|
784
807
|
}
|
|
785
808
|
|
|
809
|
+
val isShowBackConfirmation = extractBooleanValue(optionConfigJson, "isShowBackConfirmation") ?: false
|
|
810
|
+
val backConfirmConfig = parseBackConfirmConfig(extractObjectJson(optionConfigJson, "backConfirmConfig"))
|
|
811
|
+
|
|
786
812
|
val livenessConfig = if (finalFlow.contains(SDKType.LIVENESS)) {
|
|
787
813
|
LivenessConfig(
|
|
788
814
|
isActiveLiveness = isActiveLiveness,
|
|
@@ -790,6 +816,8 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
790
816
|
isShowCameraFont = switchFrontCamera,
|
|
791
817
|
customActions = customActionsList?.takeIf { it.isNotEmpty() },
|
|
792
818
|
activeActionCount = activeActionCount,
|
|
819
|
+
isShowBackConfirmation = isShowBackConfirmation,
|
|
820
|
+
backConfirmConfig = backConfirmConfig,
|
|
793
821
|
)
|
|
794
822
|
} else null
|
|
795
823
|
|
|
@@ -809,7 +837,7 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
809
837
|
callbackSuccess = { event, data ->
|
|
810
838
|
// LOG_SUCCESS = internal submit result event (v1.4.5), emit event only, don't resolve promise
|
|
811
839
|
if (event == EKYCEvent.LOG_SUCCESS) {
|
|
812
|
-
val logDataStr = data?.customData?.let { Gson().toJson(it) } ?:
|
|
840
|
+
val logDataStr = data?.customData?.let { Gson().toJson(it) } ?: Gson().toJson(data)
|
|
813
841
|
Log.d(TAG, "LOG_SUCCESS [EkycUI]: $logDataStr")
|
|
814
842
|
sendEvent("onEkycUISuccess", Arguments.createMap().apply {
|
|
815
843
|
putString("status", "log")
|
|
@@ -834,7 +862,7 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
834
862
|
val (eventMap, promiseMap) = createSeparateMaps { map ->
|
|
835
863
|
map.putString("status", "success")
|
|
836
864
|
map.putString("event", event.name.toString())
|
|
837
|
-
map.putString("data",
|
|
865
|
+
map.putString("data", Gson().toJson(data))
|
|
838
866
|
map.putString("transactionId", ekycTransactionId)
|
|
839
867
|
ekycFiles?.imageFace?.absolutePath?.let { map.putString("imageFacePath", it) }
|
|
840
868
|
ekycFiles?.imageOcrFront?.absolutePath?.let { map.putString("imageOcrFrontPath", it) }
|
|
@@ -895,32 +923,42 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
895
923
|
private fun parseOptionConfig(optionConfigJson: String): OptionConfig {
|
|
896
924
|
return try {
|
|
897
925
|
if (optionConfigJson.isBlank() || optionConfigJson == "{}") {
|
|
898
|
-
|
|
899
|
-
OptionConfig(
|
|
900
|
-
baseUrl = null,
|
|
901
|
-
countMaxRetry = 3,
|
|
902
|
-
language = null
|
|
903
|
-
)
|
|
926
|
+
OptionConfig()
|
|
904
927
|
} else {
|
|
905
|
-
// Simple JSON parsing (in real implementation, use proper JSON library)
|
|
906
928
|
val baseUrl = extractStringValue(optionConfigJson, "baseUrl")
|
|
907
929
|
val countMaxRetry = extractIntValue(optionConfigJson, "countMaxRetry") ?: 3
|
|
908
930
|
val language = extractStringValue(optionConfigJson, "language")
|
|
931
|
+
val networkTimeoutMs = extractLongValue(optionConfigJson, "networkTimeoutMs") ?: 30_000L
|
|
909
932
|
|
|
910
933
|
OptionConfig(
|
|
911
934
|
baseUrl = baseUrl,
|
|
912
935
|
countMaxRetry = countMaxRetry,
|
|
913
|
-
language = language
|
|
936
|
+
language = language,
|
|
937
|
+
networkTimeoutMs = networkTimeoutMs,
|
|
914
938
|
)
|
|
915
939
|
}
|
|
916
940
|
} catch (e: Exception) {
|
|
917
941
|
Log.e(TAG, "Error parsing optionConfig: ${e.message}", e)
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
942
|
+
OptionConfig()
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
private fun parseBackConfirmConfig(json: String?): LivenessBackConfirmConfig? {
|
|
947
|
+
if (json.isNullOrBlank() || json == "{}") return null
|
|
948
|
+
return try {
|
|
949
|
+
LivenessBackConfirmConfig(
|
|
950
|
+
titleVi = extractStringValue(json, "titleVi"),
|
|
951
|
+
titleEn = extractStringValue(json, "titleEn"),
|
|
952
|
+
bodyVi = extractStringValue(json, "bodyVi"),
|
|
953
|
+
bodyEn = extractStringValue(json, "bodyEn"),
|
|
954
|
+
confirmButtonVi = extractStringValue(json, "confirmButtonVi"),
|
|
955
|
+
confirmButtonEn = extractStringValue(json, "confirmButtonEn"),
|
|
956
|
+
cancelButtonVi = extractStringValue(json, "cancelButtonVi"),
|
|
957
|
+
cancelButtonEn = extractStringValue(json, "cancelButtonEn"),
|
|
923
958
|
)
|
|
959
|
+
} catch (e: Exception) {
|
|
960
|
+
Log.e(TAG, "Error parsing backConfirmConfig: ${e.message}", e)
|
|
961
|
+
null
|
|
924
962
|
}
|
|
925
963
|
}
|
|
926
964
|
|
|
@@ -934,6 +972,16 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
934
972
|
}
|
|
935
973
|
}
|
|
936
974
|
|
|
975
|
+
private fun extractLongValue(json: String, key: String): Long? {
|
|
976
|
+
return try {
|
|
977
|
+
val pattern = "\"$key\"\\s*:\\s*(-?\\d+)".toRegex()
|
|
978
|
+
val match = pattern.find(json)
|
|
979
|
+
match?.groupValues?.get(1)?.toLong()
|
|
980
|
+
} catch (e: Exception) {
|
|
981
|
+
null
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
|
|
937
985
|
private fun extractBooleanValue(json: String, key: String): Boolean? {
|
|
938
986
|
return try {
|
|
939
987
|
val pattern = "\"$key\"\\s*:\\s*(true|false)".toRegex()
|
|
@@ -1088,6 +1136,17 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
1088
1136
|
}
|
|
1089
1137
|
}
|
|
1090
1138
|
|
|
1139
|
+
/** Extract a nested JSON object `{ ... }` for a given key. Returns the raw JSON string or null. */
|
|
1140
|
+
private fun extractObjectJson(json: String, key: String): String? {
|
|
1141
|
+
return try {
|
|
1142
|
+
val obj = JSONObject(json)
|
|
1143
|
+
val nested = obj.optJSONObject(key) ?: return null
|
|
1144
|
+
nested.toString()
|
|
1145
|
+
} catch (e: Exception) {
|
|
1146
|
+
null
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1091
1150
|
// ==================== SMS OTP Methods ====================
|
|
1092
1151
|
|
|
1093
1152
|
@ReactMethod
|
package/dist/EKYCModule.d.ts
CHANGED
|
@@ -148,6 +148,16 @@ declare class SDKeKYC {
|
|
|
148
148
|
baseUrl?: string;
|
|
149
149
|
countMaxRetry?: number;
|
|
150
150
|
language?: string;
|
|
151
|
+
networkTimeoutMs?: number;
|
|
152
|
+
switchFrontCamera?: boolean;
|
|
153
|
+
isActiveLiveness?: boolean;
|
|
154
|
+
autoCapture?: boolean;
|
|
155
|
+
forceCaptureTimeout?: number;
|
|
156
|
+
customActions?: string[];
|
|
157
|
+
activeActionCount?: number;
|
|
158
|
+
appIDType?: string;
|
|
159
|
+
isShowBackConfirmation?: boolean;
|
|
160
|
+
backConfirmConfig?: import('./src/types/ekycLivenessType').LivenessBackConfirmConfig;
|
|
151
161
|
}, styleConfig?: {
|
|
152
162
|
textSize?: number;
|
|
153
163
|
textFont?: string;
|
package/dist/EKYCModule.js
CHANGED
|
@@ -213,7 +213,10 @@ class SDKeKYC {
|
|
|
213
213
|
try {
|
|
214
214
|
// Convert SDKFaceDetectStatus enum array to string array
|
|
215
215
|
const customActionsStrings = (_b = (_a = config.customActions) === null || _a === void 0 ? void 0 : _a.map(action => String(action))) !== null && _b !== void 0 ? _b : undefined;
|
|
216
|
-
|
|
216
|
+
const backConfirmConfigJson = config.backConfirmConfig
|
|
217
|
+
? JSON.stringify(config.backConfirmConfig)
|
|
218
|
+
: undefined;
|
|
219
|
+
return await nativeModule.startLiveness(config.appKey, config.selfieImage, (_c = config.transactionId) !== null && _c !== void 0 ? _c : '', config.isActiveLiveness, config.isShowCameraFont, customActionsStrings, config.activeActionCount, config.forceCaptureTimeout, config.isActiveLivenessColor, config.isShowBackConfirmation, backConfirmConfigJson);
|
|
217
220
|
}
|
|
218
221
|
catch (error) {
|
|
219
222
|
console.error('Liveness Error:', error);
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finos_sdk/sdk-ekyc",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.6",
|
|
4
4
|
"description": "React Native SDK for eKYC - Vietnamese CCCD NFC reading, OCR, Liveness detection, Face matching, and C06, eSign, SmsOTP residence verification",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -308,6 +308,8 @@ export declare class FinosEKYCModule {
|
|
|
308
308
|
baseUrl?: string;
|
|
309
309
|
countMaxRetry?: number;
|
|
310
310
|
language?: string;
|
|
311
|
+
/** Network timeout in milliseconds (default: 30000). callTimeout = networkTimeoutMs * 2 */
|
|
312
|
+
networkTimeoutMs?: number;
|
|
311
313
|
switchFrontCamera?: boolean;
|
|
312
314
|
/** LivenessConfig – SDKeKYCActivity (157-169) */
|
|
313
315
|
isActiveLiveness?: boolean;
|
|
@@ -318,6 +320,10 @@ export declare class FinosEKYCModule {
|
|
|
318
320
|
activeActionCount?: number;
|
|
319
321
|
/** AppIDType: NONE | HD_BANK | VIKKI (default: AppIDType.NONE) */
|
|
320
322
|
appIDType?: AppIDType;
|
|
323
|
+
/** Show confirmation bottom sheet when user presses back in liveness screen (v1.4.6+) */
|
|
324
|
+
isShowBackConfirmation?: boolean;
|
|
325
|
+
/** Text config for the back confirmation bottom sheet (v1.4.6+) */
|
|
326
|
+
backConfirmConfig?: import('../types/ekycLivenessType').LivenessBackConfirmConfig;
|
|
321
327
|
}, styleConfig?: {
|
|
322
328
|
textSize?: number;
|
|
323
329
|
textFont?: string;
|
|
@@ -286,6 +286,8 @@ export declare class FinosESignModule {
|
|
|
286
286
|
baseUrl?: string;
|
|
287
287
|
countMaxRetry?: number;
|
|
288
288
|
language?: string;
|
|
289
|
+
/** Network timeout in milliseconds (default: 30000). callTimeout = networkTimeoutMs * 2 */
|
|
290
|
+
networkTimeoutMs?: number;
|
|
289
291
|
switchFrontCamera?: boolean;
|
|
290
292
|
}, styleConfig?: {
|
|
291
293
|
textSize?: number;
|
|
@@ -20,6 +20,17 @@ export declare enum SDKFaceDetectStatus {
|
|
|
20
20
|
export declare const SDK_LIVENESS_ACTIONS: readonly SDKFaceDetectStatus[];
|
|
21
21
|
/** Chuyển customActions enum[] sang string[] khi gửi xuống native. */
|
|
22
22
|
export declare function customActionsToStrings(actions: SDKFaceDetectStatus[]): string[];
|
|
23
|
+
/** Text config for the back-press confirmation bottom sheet (v1.4.6+). All fields optional – fallback to built-in strings. */
|
|
24
|
+
export interface LivenessBackConfirmConfig {
|
|
25
|
+
titleVi?: string;
|
|
26
|
+
titleEn?: string;
|
|
27
|
+
bodyVi?: string;
|
|
28
|
+
bodyEn?: string;
|
|
29
|
+
confirmButtonVi?: string;
|
|
30
|
+
confirmButtonEn?: string;
|
|
31
|
+
cancelButtonVi?: string;
|
|
32
|
+
cancelButtonEn?: string;
|
|
33
|
+
}
|
|
23
34
|
export interface LivenessConfig {
|
|
24
35
|
appKey: string;
|
|
25
36
|
transactionId?: string;
|
|
@@ -30,6 +41,8 @@ export interface LivenessConfig {
|
|
|
30
41
|
customActions?: SDKFaceDetectStatus[];
|
|
31
42
|
activeActionCount?: number;
|
|
32
43
|
forceCaptureTimeout?: number;
|
|
44
|
+
isShowBackConfirmation?: boolean;
|
|
45
|
+
backConfirmConfig?: LivenessBackConfirmConfig;
|
|
33
46
|
}
|
|
34
47
|
export interface CheckLivenessResponse {
|
|
35
48
|
metadata?: Metadata;
|
package/ios/EKYCModule.swift
CHANGED
|
@@ -96,14 +96,14 @@ class EKYCModule: RCTEventEmitter {
|
|
|
96
96
|
callbackSuccess: { event, data in
|
|
97
97
|
switch event {
|
|
98
98
|
case .SCAN_NFC_START:
|
|
99
|
-
self?.emit("onNfcScanStart", body: ["event": event.description, "data":
|
|
99
|
+
self?.emit("onNfcScanStart", body: ["event": event.description, "data": (data as? SDKEkycResult)?.nfcResponse ?? "{}"])
|
|
100
100
|
case .SCAN_NFC_SUCCESS:
|
|
101
101
|
let nfcResponse = (data as? SDKEkycResult)?.nfcResponse ?? ""
|
|
102
102
|
let body: [String: Any] = ["event": event.description, "data": nfcResponse]
|
|
103
103
|
self?.emit("onNfcScanSuccess", body: body)
|
|
104
104
|
resolve(body)
|
|
105
105
|
default:
|
|
106
|
-
self?.emit("onNfcEvent", body: ["event": event.description, "data":
|
|
106
|
+
self?.emit("onNfcEvent", body: ["event": event.description, "data": (data as? SDKEkycResult)?.nfcResponse ?? "{}"])
|
|
107
107
|
}
|
|
108
108
|
},
|
|
109
109
|
callbackError: { event, errorResult in
|
|
@@ -123,7 +123,8 @@ class EKYCModule: RCTEventEmitter {
|
|
|
123
123
|
let ekycConfig = EKYCConfigSDK(appKey: AppKeyConfig(appKey: appKey), c06Config: c06Config)
|
|
124
124
|
SdkEkycC06.startEkyc(ekycConfigSDK: ekycConfig,
|
|
125
125
|
callbackSuccess: { [weak self] event, data in
|
|
126
|
-
let
|
|
126
|
+
let c06Response = (data as? SDKEkycResult)?.checkC06Response?.description ?? "{}"
|
|
127
|
+
let body: [String: Any] = ["event": event.description, "data": c06Response]
|
|
127
128
|
self?.emit("onC06Success", body: body)
|
|
128
129
|
resolve(body)
|
|
129
130
|
},
|
|
@@ -210,7 +211,17 @@ class EKYCModule: RCTEventEmitter {
|
|
|
210
211
|
DispatchQueue.main.async { [weak self] in
|
|
211
212
|
SdkEkycFaceService.startEkyc(ekycConfigSDK: ekycConfig,
|
|
212
213
|
callbackSuccess: { event, data in
|
|
213
|
-
let
|
|
214
|
+
let faceResponse = (data as? SDKEkycResult)?.checkFaceResponse
|
|
215
|
+
var faceDict: [String: Any] = [:]
|
|
216
|
+
if let v = faceResponse?.requestId { faceDict["requestId"] = v }
|
|
217
|
+
if let r = faceResponse?.result {
|
|
218
|
+
faceDict["result"] = ["conf": r.conf, "match": r.match, "matchScore": r.matchScore, "toBeReviewed": r.toBeReviewed]
|
|
219
|
+
}
|
|
220
|
+
if let v = faceResponse?.status { faceDict["status"] = v }
|
|
221
|
+
if let v = faceResponse?.statusCode { faceDict["statusCode"] = v }
|
|
222
|
+
if let v = faceResponse?.error { faceDict["error"] = v }
|
|
223
|
+
if let v = faceResponse?.type { faceDict["type"] = v }
|
|
224
|
+
let body: [String: Any] = ["event": event.description, "data": faceDict]
|
|
214
225
|
self?.emit("onFaceCompareSuccess", body: body)
|
|
215
226
|
resolve(body)
|
|
216
227
|
},
|
|
@@ -291,7 +302,16 @@ class EKYCModule: RCTEventEmitter {
|
|
|
291
302
|
return
|
|
292
303
|
}
|
|
293
304
|
let files = result?.ekycStateModel?.eKYCFileModel
|
|
294
|
-
var
|
|
305
|
+
var dataDict: [String: Any] = [:]
|
|
306
|
+
if let v = result?.nfcResponse { dataDict["nfcResponse"] = v }
|
|
307
|
+
if let v = result?.checkC06Response?.description { dataDict["checkC06Response"] = v }
|
|
308
|
+
if let v = result?.ocrResponse?.description { dataDict["ocrResponse"] = v }
|
|
309
|
+
if let v = result?.checkLivenessResponse?.description { dataDict["checkLivenessResponse"] = v }
|
|
310
|
+
if let v = result?.checkFaceResponse?.description { dataDict["checkFaceResponse"] = v }
|
|
311
|
+
if let v = result?.customData { dataDict["customData"] = v }
|
|
312
|
+
let dataJson = (try? JSONSerialization.data(withJSONObject: dataDict))
|
|
313
|
+
.flatMap { String(data: $0, encoding: .utf8) } ?? "{}"
|
|
314
|
+
var body: [String: Any] = ["status": "success", "event": event.description, "data": dataJson, "transactionId": result?.ekycStateModel?.transactionId ?? ""]
|
|
295
315
|
if let facePath = files?.imageFace { body["imageFacePath"] = facePath.path }
|
|
296
316
|
if let frontPath = files?.imageOcrFront { body["imageOcrFrontPath"] = frontPath.path }
|
|
297
317
|
if let backPath = files?.imageOcrBack { body["imageOcrBackPath"] = backPath.path }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finos_sdk/sdk-ekyc",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.6",
|
|
4
4
|
"description": "React Native SDK for eKYC - Vietnamese CCCD NFC reading, OCR, Liveness detection, Face matching, and C06, eSign, SmsOTP residence verification",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -764,6 +764,8 @@ export class FinosEKYCModule {
|
|
|
764
764
|
baseUrl?: string;
|
|
765
765
|
countMaxRetry?: number;
|
|
766
766
|
language?: string;
|
|
767
|
+
/** Network timeout in milliseconds (default: 30000). callTimeout = networkTimeoutMs * 2 */
|
|
768
|
+
networkTimeoutMs?: number;
|
|
767
769
|
switchFrontCamera?: boolean;
|
|
768
770
|
/** LivenessConfig – SDKeKYCActivity (157-169) */
|
|
769
771
|
isActiveLiveness?: boolean;
|
|
@@ -774,6 +776,10 @@ export class FinosEKYCModule {
|
|
|
774
776
|
activeActionCount?: number;
|
|
775
777
|
/** AppIDType: NONE | HD_BANK | VIKKI (default: AppIDType.NONE) */
|
|
776
778
|
appIDType?: AppIDType;
|
|
779
|
+
/** Show confirmation bottom sheet when user presses back in liveness screen (v1.4.6+) */
|
|
780
|
+
isShowBackConfirmation?: boolean;
|
|
781
|
+
/** Text config for the back confirmation bottom sheet (v1.4.6+) */
|
|
782
|
+
backConfirmConfig?: import('../types/ekycLivenessType').LivenessBackConfirmConfig;
|
|
777
783
|
},
|
|
778
784
|
styleConfig?: {
|
|
779
785
|
textSize?: number;
|
|
@@ -634,6 +634,8 @@ export class FinosESignModule {
|
|
|
634
634
|
baseUrl?: string;
|
|
635
635
|
countMaxRetry?: number;
|
|
636
636
|
language?: string;
|
|
637
|
+
/** Network timeout in milliseconds (default: 30000). callTimeout = networkTimeoutMs * 2 */
|
|
638
|
+
networkTimeoutMs?: number;
|
|
637
639
|
switchFrontCamera?: boolean;
|
|
638
640
|
},
|
|
639
641
|
styleConfig?: {
|
|
@@ -38,11 +38,23 @@ export function customActionsToStrings(actions: SDKFaceDetectStatus[]): string[]
|
|
|
38
38
|
return actions.map(a => a as string);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
/** Text config for the back-press confirmation bottom sheet (v1.4.6+). All fields optional – fallback to built-in strings. */
|
|
42
|
+
export interface LivenessBackConfirmConfig {
|
|
43
|
+
titleVi?: string;
|
|
44
|
+
titleEn?: string;
|
|
45
|
+
bodyVi?: string;
|
|
46
|
+
bodyEn?: string;
|
|
47
|
+
confirmButtonVi?: string;
|
|
48
|
+
confirmButtonEn?: string;
|
|
49
|
+
cancelButtonVi?: string;
|
|
50
|
+
cancelButtonEn?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
41
53
|
export interface LivenessConfig {
|
|
42
54
|
appKey: string;
|
|
43
55
|
transactionId?: string;
|
|
44
56
|
// old fields usingRandomAction and isStraight removed in 1.3.1
|
|
45
|
-
// usingRandomAction: boolean;
|
|
57
|
+
// usingRandomAction: boolean;
|
|
46
58
|
// isStraight: boolean;
|
|
47
59
|
selfieImage: string;
|
|
48
60
|
// New fields for version 1.3.0
|
|
@@ -52,6 +64,9 @@ export interface LivenessConfig {
|
|
|
52
64
|
customActions?: SDKFaceDetectStatus[];
|
|
53
65
|
activeActionCount?: number;
|
|
54
66
|
forceCaptureTimeout?: number;
|
|
67
|
+
// New fields for version 1.4.6
|
|
68
|
+
isShowBackConfirmation?: boolean;
|
|
69
|
+
backConfirmConfig?: LivenessBackConfirmConfig;
|
|
55
70
|
}
|
|
56
71
|
|
|
57
72
|
export interface CheckLivenessResponse {
|