@finos_sdk/sdk-ekyc 1.4.1 → 1.4.4
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/README.md +745 -156
- package/android/build.gradle +1 -1
- package/android/src/main/java/finos/sdk/ekyc/EKYCModule.kt +118 -127
- package/dist/EKYCModule.d.ts +2 -0
- package/dist/EKYCModule.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +22 -10
- package/dist/package.json +4 -4
- package/dist/src/modules/FinosEKYCModule.d.ts +6 -2
- package/dist/src/modules/FinosEKYCModule.js +19 -11
- package/dist/src/modules/FinosESignModule.js +17 -7
- package/dist/src/services/sharingService.js +2 -2
- package/dist/src/types/EKYCErrorResult.d.ts +35 -0
- package/dist/src/types/EKYCErrorResult.js +62 -7
- package/dist/src/types/ekycESignType.js +1 -1
- package/dist/src/types/ekycFlowType.js +3 -3
- package/dist/src/types/ekycLivenessType.d.ts +1 -2
- package/dist/src/types/ekycLivenessType.js +3 -3
- package/dist/src/types/ekycType.d.ts +10 -0
- package/dist/src/types/ekycType.js +13 -2
- package/dist/src/utils/utils.js +1 -2
- package/ios/EKYCModule.swift +87 -15
- package/ios/EKYCModuleBridge.m +8 -8
- package/package.json +4 -4
- package/src/modules/FinosEKYCModule.ts +6 -7
- package/src/types/EKYCErrorResult.ts +57 -0
- package/src/types/ekycLivenessType.ts +1 -2
- package/src/types/ekycType.ts +11 -0
- package/dist/dist/package.json +0 -86
package/README.md
CHANGED
|
@@ -5,31 +5,30 @@
|
|
|
5
5
|
|
|
6
6
|
React Native SDK for eKYC (electronic Know Your Customer) and eSign. Features include Vietnamese CCCD NFC reading, OCR, Liveness detection, Face matching, C06 residence verification, SMS OTP verification, and Electronic Signature (eSign) capabilities.
|
|
7
7
|
|
|
8
|
-
**Version**: 1.4.
|
|
8
|
+
**Version**: 1.4.2
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Features
|
|
11
11
|
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
12
|
+
- **Unified eKYC Flow** - Complete verification flow with single method call
|
|
13
|
+
- **NFC Reading** - Read Vietnamese CCCD cards with NFC chips
|
|
14
|
+
- **OCR Processing** - Extract data from ID card images
|
|
15
|
+
- **Liveness Detection** - Verify user presence with selfie (Active/Passive modes)
|
|
16
|
+
- **Face Matching** - Compare selfie with ID card photo
|
|
17
|
+
- **C06 Verification** - Residence information verification
|
|
18
|
+
- **eSign** - Electronic signature support (PDF signing, Remote signing)
|
|
19
|
+
- **SMS OTP** - Integrated SMS OTP verification
|
|
20
|
+
- **Flexible Configuration** - Custom styling, capture button colors, and retry options
|
|
21
|
+
- **TypeScript Support** - Full type definitions included
|
|
22
22
|
|
|
23
|
+
## Requirements
|
|
23
24
|
|
|
25
|
+
- React Native 0.70.0+
|
|
26
|
+
- Android 24+ / API Level 24+
|
|
27
|
+
- iOS 14.0+ (Swift 5.7+)
|
|
28
|
+
- NFC and/or Camera hardware depending on modules used
|
|
29
|
+
- Runtime permissions for Camera and/or NFC
|
|
24
30
|
|
|
25
|
-
##
|
|
26
|
-
|
|
27
|
-
- React Native 0.77.0+
|
|
28
|
-
- Android 24+ / API Level 24+ (Android platform only)
|
|
29
|
-
- NFC and/or Camera hardware depending on modules used
|
|
30
|
-
- Runtime permissions for Camera and/or NFC
|
|
31
|
-
|
|
32
|
-
## �🛠️ Installation
|
|
31
|
+
## Installation
|
|
33
32
|
|
|
34
33
|
```bash
|
|
35
34
|
npm install @finos_sdk/sdk-ekyc
|
|
@@ -37,12 +36,22 @@ npm install @finos_sdk/sdk-ekyc
|
|
|
37
36
|
yarn add @finos_sdk/sdk-ekyc
|
|
38
37
|
```
|
|
39
38
|
|
|
40
|
-
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
41
42
|
|
|
42
43
|
### 1. Import the SDK
|
|
43
44
|
|
|
44
45
|
```typescript
|
|
45
|
-
import {
|
|
46
|
+
import {
|
|
47
|
+
FinosEKYC,
|
|
48
|
+
FinosESign,
|
|
49
|
+
getEkycError,
|
|
50
|
+
SDKFaceDetectStatus,
|
|
51
|
+
SDKFlowType,
|
|
52
|
+
AppIDType,
|
|
53
|
+
} from '@finos_sdk/sdk-ekyc';
|
|
54
|
+
|
|
46
55
|
import type {
|
|
47
56
|
NfcConfig,
|
|
48
57
|
C06Config,
|
|
@@ -50,108 +59,600 @@ import type {
|
|
|
50
59
|
LivenessConfig,
|
|
51
60
|
FaceServiceConfig,
|
|
52
61
|
SmsOtpConfig,
|
|
53
|
-
|
|
62
|
+
StartEkycUIResult,
|
|
63
|
+
EKYCError,
|
|
54
64
|
} from '@finos_sdk/sdk-ekyc';
|
|
55
65
|
```
|
|
56
66
|
|
|
57
|
-
### 2.
|
|
67
|
+
### 2. Initialize SDK
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// Initialize the SDK (required before using any method)
|
|
71
|
+
await FinosEKYC.initialize();
|
|
72
|
+
|
|
73
|
+
// Check SDK info
|
|
74
|
+
const info = await FinosEKYC.getSDKInfo();
|
|
75
|
+
console.log(info); // { name, version, buildNumber, platform, isInitialized }
|
|
76
|
+
|
|
77
|
+
// Set transaction ID (optional)
|
|
78
|
+
await FinosEKYC.setTransactionId('your-transaction-id');
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Complete eKYC Flow (startEkycUI)
|
|
84
|
+
|
|
85
|
+
The recommended way to use the SDK. Handles the complete verification flow with a single method call.
|
|
86
|
+
|
|
87
|
+
### Method Signature
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
FinosEKYC.startEkycUI(
|
|
91
|
+
appKey: string,
|
|
92
|
+
flowSDK: SDKFlowType[],
|
|
93
|
+
language: string,
|
|
94
|
+
transactionId: string,
|
|
95
|
+
appKeyConfig: AppKeyConfig,
|
|
96
|
+
optionConfig?: OptionConfig,
|
|
97
|
+
styleConfig?: StyleConfig,
|
|
98
|
+
): Promise<StartEkycUIResult>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Full Example with All Configs
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
const result = await FinosEKYC.startEkycUI(
|
|
105
|
+
'your-main-app-key',
|
|
106
|
+
|
|
107
|
+
// --- flowSDK: verification steps to execute in order ---
|
|
108
|
+
['OCR', 'NFC', 'LIVENESS'],
|
|
109
|
+
|
|
110
|
+
// --- language ---
|
|
111
|
+
'vi', // 'vi' | 'en'
|
|
112
|
+
|
|
113
|
+
// --- transactionId ---
|
|
114
|
+
'txn-20260319-001',
|
|
115
|
+
|
|
116
|
+
// --- appKeyConfig: API keys for each module ---
|
|
117
|
+
{
|
|
118
|
+
appKey: 'your-main-app-key',
|
|
119
|
+
appKeyNfc: 'your-nfc-key',
|
|
120
|
+
appKeyOcr: 'your-ocr-key',
|
|
121
|
+
appKeyLiveness: 'your-liveness-key',
|
|
122
|
+
appKeyC06: 'your-c06-key',
|
|
123
|
+
appKeyFaceService: 'your-face-key',
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
// --- optionConfig: SDK behavior settings ---
|
|
127
|
+
{
|
|
128
|
+
baseUrl: 'https://api.example.com', // Custom API base URL
|
|
129
|
+
countMaxRetry: 3, // Max retry attempts (default: 3)
|
|
130
|
+
language: 'vi', // Override language
|
|
131
|
+
switchFrontCamera: true, // Use front camera (default: false)
|
|
132
|
+
isActiveLiveness: true, // Active liveness mode (default: true)
|
|
133
|
+
autoCapture: true, // Auto capture (default: true)
|
|
134
|
+
forceCaptureTimeout: 30, // Force capture timeout in seconds
|
|
135
|
+
isShowCameraFont: true, // Show camera guide text
|
|
136
|
+
customActions: [ // Custom liveness actions
|
|
137
|
+
SDKFaceDetectStatus.LEFT,
|
|
138
|
+
SDKFaceDetectStatus.RIGHT,
|
|
139
|
+
SDKFaceDetectStatus.STRAIGHT,
|
|
140
|
+
],
|
|
141
|
+
activeActionCount: 3, // Random action count 1-10 (if customActions is null)
|
|
142
|
+
appIDType: AppIDType.VIKKI, // App ID type: NONE | HD_BANK | VIKKI
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
// --- styleConfig: UI customization ---
|
|
146
|
+
{
|
|
147
|
+
// Global defaults
|
|
148
|
+
textSize: 14, // Default text size (sp)
|
|
149
|
+
textFont: '', // Font resource name (e.g. 'roboto_medium')
|
|
150
|
+
textColor: 0xFF333333, // Default text color (ARGB int)
|
|
151
|
+
statusBarBackground: undefined, // Status bar drawable resource ID
|
|
152
|
+
backIcon: undefined, // Back button drawable resource ID
|
|
153
|
+
|
|
154
|
+
// Per-element text styles (override global defaults)
|
|
155
|
+
titleStyle: { // Screen title ("CHUP MAT TRUOC", "Chup chan dung")
|
|
156
|
+
textSize: 20,
|
|
157
|
+
textFont: 'roboto_bold',
|
|
158
|
+
textColor: 0xFF142630,
|
|
159
|
+
},
|
|
160
|
+
toolbarStyle: { // Toolbar/navigation bar title
|
|
161
|
+
textSize: 18,
|
|
162
|
+
textFont: '',
|
|
163
|
+
textColor: 0xFF007AFF,
|
|
164
|
+
},
|
|
165
|
+
instructionStyle: { // User instruction text
|
|
166
|
+
textSize: 16,
|
|
167
|
+
textFont: '',
|
|
168
|
+
textColor: 0xFF666666,
|
|
169
|
+
},
|
|
170
|
+
errorStyle: { // Error message text
|
|
171
|
+
textSize: 14,
|
|
172
|
+
textFont: '',
|
|
173
|
+
textColor: 0xFFFF3B30,
|
|
174
|
+
},
|
|
175
|
+
successStyle: { // Success message text
|
|
176
|
+
textSize: 14,
|
|
177
|
+
textFont: '',
|
|
178
|
+
textColor: 0xFF34C759,
|
|
179
|
+
},
|
|
180
|
+
warningStyle: { // Warning message text
|
|
181
|
+
textSize: 14,
|
|
182
|
+
textFont: '',
|
|
183
|
+
textColor: 0xFFFF9500,
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
// Capture button colors (direct color int, ARGB)
|
|
187
|
+
captureButtonColor: 0xFF00A86F, // Capture button color when enabled
|
|
188
|
+
captureButtonDisabledColor: 0xFFCCCCCC, // Capture button color when disabled
|
|
189
|
+
},
|
|
190
|
+
);
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Result
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
interface StartEkycUIResult {
|
|
197
|
+
status: 'success';
|
|
198
|
+
event: string;
|
|
199
|
+
data?: string;
|
|
200
|
+
transactionId?: string;
|
|
201
|
+
imageFace?: string; // Base64 selfie/liveness image
|
|
202
|
+
imageOcrFront?: string; // Base64 OCR front image
|
|
203
|
+
imageOcrBack?: string; // Base64 OCR back image
|
|
204
|
+
imageFacePath?: string; // Absolute path to selfie file
|
|
205
|
+
imageOcrFrontPath?: string; // Absolute path to OCR front file
|
|
206
|
+
imageOcrBackPath?: string; // Absolute path to OCR back file
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Configuration Reference
|
|
213
|
+
|
|
214
|
+
### AppKeyConfig
|
|
58
215
|
|
|
59
|
-
|
|
216
|
+
API keys for each eKYC module.
|
|
217
|
+
|
|
218
|
+
| Field | Type | Required | Description |
|
|
219
|
+
|-------|------|----------|-------------|
|
|
220
|
+
| `appKey` | `string` | Yes | Main app key |
|
|
221
|
+
| `appKeyNfc` | `string` | Yes | NFC module key |
|
|
222
|
+
| `appKeyOcr` | `string` | Yes | OCR module key |
|
|
223
|
+
| `appKeyLiveness` | `string` | Yes | Liveness module key |
|
|
224
|
+
| `appKeyC06` | `string` | Yes | C06 module key |
|
|
225
|
+
| `appKeyFaceService` | `string` | Yes | Face service module key |
|
|
60
226
|
|
|
61
227
|
```typescript
|
|
62
|
-
|
|
63
|
-
const AppKey = {
|
|
228
|
+
const appKeyConfig = {
|
|
64
229
|
appKey: 'your-main-app-key',
|
|
65
|
-
appKeyNfc: 'your-nfc-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
appKeyFaceService: 'your-face-
|
|
230
|
+
appKeyNfc: 'your-nfc-key',
|
|
231
|
+
appKeyOcr: 'your-ocr-key',
|
|
232
|
+
appKeyLiveness: 'your-liveness-key',
|
|
233
|
+
appKeyC06: 'your-c06-key',
|
|
234
|
+
appKeyFaceService: 'your-face-key',
|
|
70
235
|
};
|
|
236
|
+
```
|
|
71
237
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
238
|
+
### OptionConfig
|
|
239
|
+
|
|
240
|
+
SDK behavior and runtime settings.
|
|
241
|
+
|
|
242
|
+
| Field | Type | Default | Description |
|
|
243
|
+
|-------|------|---------|-------------|
|
|
244
|
+
| `baseUrl` | `string` | `undefined` | Custom API base URL |
|
|
245
|
+
| `countMaxRetry` | `number` | `3` | Max retry attempts on failure |
|
|
246
|
+
| `language` | `string` | `undefined` | Override language (`'vi'` or `'en'`) |
|
|
247
|
+
| `switchFrontCamera` | `boolean` | `false` | Use front camera for liveness/face |
|
|
248
|
+
| `isActiveLiveness` | `boolean` | `true` | Enable active liveness detection |
|
|
249
|
+
| `autoCapture` | `boolean` | `true` | Auto capture when conditions met |
|
|
250
|
+
| `forceCaptureTimeout` | `number` | `0` | Force capture timeout in seconds (0 = disabled) |
|
|
251
|
+
| `isShowCameraFont` | `boolean` | `true` | Show instruction text on camera screen |
|
|
252
|
+
| `customActions` | `SDKFaceDetectStatus[]` | `undefined` | Custom liveness action sequence |
|
|
253
|
+
| `activeActionCount` | `number` | `2` | Number of random actions (1-10, used when `customActions` is null) |
|
|
254
|
+
| `appIDType` | `AppIDType` | `NONE` | App ID type for branding: `NONE`, `HD_BANK`, or `VIKKI` |
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
// Minimal
|
|
258
|
+
const optionConfig = { countMaxRetry: 3 };
|
|
259
|
+
|
|
260
|
+
// Full
|
|
261
|
+
const optionConfig = {
|
|
262
|
+
baseUrl: 'https://api.example.com',
|
|
263
|
+
countMaxRetry: 3,
|
|
264
|
+
language: 'vi',
|
|
265
|
+
switchFrontCamera: true,
|
|
266
|
+
isActiveLiveness: true,
|
|
267
|
+
autoCapture: true,
|
|
268
|
+
forceCaptureTimeout: 30,
|
|
269
|
+
isShowCameraFont: true,
|
|
270
|
+
customActions: [
|
|
271
|
+
SDKFaceDetectStatus.LEFT,
|
|
272
|
+
SDKFaceDetectStatus.RIGHT,
|
|
273
|
+
SDKFaceDetectStatus.STRAIGHT,
|
|
274
|
+
],
|
|
275
|
+
activeActionCount: 3,
|
|
276
|
+
appIDType: AppIDType.VIKKI,
|
|
277
|
+
};
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### AppIDType
|
|
281
|
+
|
|
282
|
+
Determines the branding/skin of SDK screens.
|
|
283
|
+
|
|
284
|
+
| Value | Description |
|
|
285
|
+
|-------|-------------|
|
|
286
|
+
| `NONE` | Default, no branding |
|
|
287
|
+
| `HD_BANK` | HD Bank branding |
|
|
288
|
+
| `VIKKI` | Vikki branding |
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
import { AppIDType } from '@finos_sdk/sdk-ekyc';
|
|
292
|
+
|
|
293
|
+
// In optionConfig
|
|
294
|
+
{ appIDType: AppIDType.VIKKI }
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### StyleConfig
|
|
298
|
+
|
|
299
|
+
UI appearance customization. All color values use ARGB integer format (e.g., `0xFFRRGGBB`).
|
|
300
|
+
|
|
301
|
+
| Field | Type | Default | Description |
|
|
302
|
+
|-------|------|---------|-------------|
|
|
303
|
+
| `textSize` | `number` | `14` | Default text size (sp) |
|
|
304
|
+
| `textFont` | `string` | `''` | Default font resource name (e.g., `'roboto_medium'`) |
|
|
305
|
+
| `textColor` | `number` | `0xFF000000` | Default text color (ARGB) |
|
|
306
|
+
| `statusBarBackground` | `number` | `undefined` | Status bar background drawable resource ID |
|
|
307
|
+
| `backIcon` | `number` | `undefined` | Back button icon drawable resource ID |
|
|
308
|
+
| `titleStyle` | `TextStyle` | `undefined` | Style for screen titles |
|
|
309
|
+
| `toolbarStyle` | `TextStyle` | `undefined` | Style for toolbar/navigation title |
|
|
310
|
+
| `instructionStyle` | `TextStyle` | `undefined` | Style for instruction text |
|
|
311
|
+
| `errorStyle` | `TextStyle` | `undefined` | Style for error messages |
|
|
312
|
+
| `successStyle` | `TextStyle` | `undefined` | Style for success messages |
|
|
313
|
+
| `warningStyle` | `TextStyle` | `undefined` | Style for warning messages |
|
|
314
|
+
| `captureButtonColor` | `number` | `undefined` | Capture button color when enabled (ARGB) |
|
|
315
|
+
| `captureButtonDisabledColor` | `number` | `undefined` | Capture button color when disabled (ARGB) |
|
|
316
|
+
|
|
317
|
+
#### TextStyle (sub-config)
|
|
318
|
+
|
|
319
|
+
Each text style can override the global defaults. `null`/`undefined` fields fall back to the parent `StyleConfig` defaults.
|
|
320
|
+
|
|
321
|
+
| Field | Type | Default | Description |
|
|
322
|
+
|-------|------|---------|-------------|
|
|
323
|
+
| `textSize` | `number` | Parent `textSize` | Text size (sp) |
|
|
324
|
+
| `textFont` | `string` | Parent `textFont` | Font resource name |
|
|
325
|
+
| `textColor` | `number` | Parent `textColor` | Text color (ARGB) |
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
// Minimal - just change capture button color
|
|
329
|
+
const styleConfig = {
|
|
330
|
+
captureButtonColor: 0xFF00A86F,
|
|
331
|
+
captureButtonDisabledColor: 0xFFCCCCCC,
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
// Custom theme with all styles
|
|
335
|
+
const styleConfig = {
|
|
336
|
+
textSize: 14,
|
|
337
|
+
textFont: 'roboto_regular',
|
|
338
|
+
textColor: 0xFF333333,
|
|
339
|
+
titleStyle: {
|
|
340
|
+
textSize: 20,
|
|
341
|
+
textFont: 'roboto_bold',
|
|
342
|
+
textColor: 0xFF142630,
|
|
343
|
+
},
|
|
344
|
+
toolbarStyle: {
|
|
345
|
+
textSize: 18,
|
|
346
|
+
textColor: 0xFF007AFF,
|
|
347
|
+
},
|
|
348
|
+
instructionStyle: {
|
|
349
|
+
textSize: 16,
|
|
350
|
+
textColor: 0xFF666666,
|
|
351
|
+
},
|
|
352
|
+
errorStyle: {
|
|
353
|
+
textColor: 0xFFFF3B30,
|
|
354
|
+
},
|
|
355
|
+
successStyle: {
|
|
356
|
+
textColor: 0xFF34C759,
|
|
357
|
+
},
|
|
358
|
+
warningStyle: {
|
|
359
|
+
textColor: 0xFFFF9500,
|
|
360
|
+
},
|
|
361
|
+
captureButtonColor: 0xFF142630,
|
|
362
|
+
captureButtonDisabledColor: 0xFFDDDDDD,
|
|
363
|
+
};
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### SDKFlowType
|
|
367
|
+
|
|
368
|
+
Available flow step types for `startEkycUI`.
|
|
369
|
+
|
|
370
|
+
| Value | Description |
|
|
371
|
+
|-------|-------------|
|
|
372
|
+
| `'OCR'` | Scan ID card with camera (front/back) |
|
|
373
|
+
| `'NFC'` | Read NFC chip on CCCD |
|
|
374
|
+
| `'LIVENESS'` | Liveness detection (selfie) |
|
|
375
|
+
|
|
376
|
+
```typescript
|
|
377
|
+
// Common flows
|
|
378
|
+
const flow1 = ['OCR', 'NFC', 'LIVENESS']; // Full eKYC
|
|
379
|
+
const flow2 = ['OCR', 'LIVENESS']; // Without NFC
|
|
380
|
+
const flow3 = ['LIVENESS']; // Liveness only
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### SDKFaceDetectStatus
|
|
384
|
+
|
|
385
|
+
Available liveness actions for `customActions`.
|
|
386
|
+
|
|
387
|
+
| Value | Description |
|
|
388
|
+
|-------|-------------|
|
|
389
|
+
| `LEFT` | Turn head left |
|
|
390
|
+
| `RIGHT` | Turn head right |
|
|
391
|
+
| `UP` | Look up |
|
|
392
|
+
| `DOWN` | Look down |
|
|
393
|
+
| `STRAIGHT` | Look straight |
|
|
394
|
+
| `SMILE` | Smile |
|
|
395
|
+
| `BLINK` | Blink eyes |
|
|
396
|
+
| `TILT_LEFT` | Tilt head left |
|
|
397
|
+
| `TILT_RIGHT` | Tilt head right |
|
|
398
|
+
| `WINK_LEFT` | Wink left eye |
|
|
399
|
+
| `WINK_RIGHT` | Wink right eye |
|
|
400
|
+
|
|
401
|
+
```typescript
|
|
402
|
+
import { SDKFaceDetectStatus } from '@finos_sdk/sdk-ekyc';
|
|
403
|
+
|
|
404
|
+
const customActions = [
|
|
405
|
+
SDKFaceDetectStatus.LEFT,
|
|
406
|
+
SDKFaceDetectStatus.RIGHT,
|
|
407
|
+
SDKFaceDetectStatus.SMILE,
|
|
408
|
+
];
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
## Individual Module APIs
|
|
414
|
+
|
|
415
|
+
### NFC Scanning
|
|
416
|
+
|
|
417
|
+
```typescript
|
|
418
|
+
const config: NfcConfig = {
|
|
419
|
+
appKey: 'your-nfc-key', // Required
|
|
420
|
+
documentNumber: '012345678012', // Required: CCCD number
|
|
421
|
+
birthDate: '01011990', // Required: format DDMMYYYY
|
|
422
|
+
expireDate: '01012030', // Required: format DDMMYYYY
|
|
423
|
+
transactionId: 'txn-001', // Optional
|
|
424
|
+
facePathStorage: '/path/to/face', // Optional: path to save face image
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
const result = await FinosEKYC.startNfcScan(config);
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
**NfcConfig**
|
|
431
|
+
|
|
432
|
+
| Field | Type | Required | Description |
|
|
433
|
+
|-------|------|----------|-------------|
|
|
434
|
+
| `appKey` | `string` | Yes | NFC module API key |
|
|
435
|
+
| `documentNumber` | `string` | Yes | CCCD/CMND number |
|
|
436
|
+
| `birthDate` | `string` | Yes | Date of birth (DDMMYYYY) |
|
|
437
|
+
| `expireDate` | `string` | Yes | Expiry date (DDMMYYYY) |
|
|
438
|
+
| `transactionId` | `string` | No | Transaction ID |
|
|
439
|
+
| `facePathStorage` | `string` | No | File path to store extracted face image |
|
|
440
|
+
|
|
441
|
+
### OCR Processing
|
|
442
|
+
|
|
443
|
+
```typescript
|
|
444
|
+
const config: OcrConfig = {
|
|
445
|
+
appKey: 'your-ocr-key', // Required
|
|
446
|
+
transactionId: 'txn-001', // Required
|
|
447
|
+
idImagePath: 'base64_image_data', // Required: Base64 encoded image
|
|
448
|
+
expectedDocumentSide: 'front', // Required: 'front' or 'back'
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
const result = await FinosEKYC.startOcr(config);
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
**OcrConfig**
|
|
455
|
+
|
|
456
|
+
| Field | Type | Required | Description |
|
|
457
|
+
|-------|------|----------|-------------|
|
|
458
|
+
| `appKey` | `string` | Yes | OCR module API key |
|
|
459
|
+
| `transactionId` | `string` | Yes | Transaction ID |
|
|
460
|
+
| `idImagePath` | `string` | Yes | Base64 encoded ID card image |
|
|
461
|
+
| `expectedDocumentSide` | `string` | Yes | `'front'` or `'back'` |
|
|
462
|
+
|
|
463
|
+
### Liveness Detection
|
|
464
|
+
|
|
465
|
+
```typescript
|
|
466
|
+
const config: LivenessConfig = {
|
|
467
|
+
appKey: 'your-liveness-key', // Required
|
|
468
|
+
selfieImage: 'base64_image', // Required: Base64 encoded selfie
|
|
469
|
+
transactionId: 'txn-001', // Optional
|
|
470
|
+
switchFrontCamera: true, // Optional: use front camera
|
|
471
|
+
isActiveLiveness: true, // Optional: active liveness mode
|
|
472
|
+
autoCapture: true, // Optional: auto capture
|
|
473
|
+
isShowCameraFont: true, // Optional: show guide text
|
|
474
|
+
forceCaptureTimeout: 30, // Optional: force capture timeout (seconds)
|
|
475
|
+
customActions: [ // Optional: custom action sequence
|
|
476
|
+
SDKFaceDetectStatus.LEFT,
|
|
477
|
+
SDKFaceDetectStatus.RIGHT,
|
|
478
|
+
SDKFaceDetectStatus.SMILE,
|
|
479
|
+
],
|
|
480
|
+
activeActionCount: 3, // Optional: random action count (1-10)
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
const result = await FinosEKYC.startLiveness(config);
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
**LivenessConfig**
|
|
487
|
+
|
|
488
|
+
| Field | Type | Default | Description |
|
|
489
|
+
|-------|------|---------|-------------|
|
|
490
|
+
| `appKey` | `string` | - | Liveness module API key (required) |
|
|
491
|
+
| `selfieImage` | `string` | - | Base64 encoded selfie image (required) |
|
|
492
|
+
| `transactionId` | `string` | `undefined` | Transaction ID |
|
|
493
|
+
| `switchFrontCamera` | `boolean` | `false` | Use front camera |
|
|
494
|
+
| `isActiveLiveness` | `boolean` | `false` | Enable active liveness mode |
|
|
495
|
+
| `autoCapture` | `boolean` | `true` | Auto capture when conditions met |
|
|
496
|
+
| `isShowCameraFont` | `boolean` | `true` | Show camera guide text |
|
|
497
|
+
| `forceCaptureTimeout` | `number` | `0` | Force capture timeout in seconds |
|
|
498
|
+
| `customActions` | `SDKFaceDetectStatus[]` | `undefined` | Custom action sequence (overrides random) |
|
|
499
|
+
| `activeActionCount` | `number` | `2` | Random actions count 1-10 (when `customActions` is null) |
|
|
500
|
+
|
|
501
|
+
### Face Comparison
|
|
502
|
+
|
|
503
|
+
```typescript
|
|
504
|
+
const config: FaceServiceConfig = {
|
|
505
|
+
appKey: 'your-face-key', // Required
|
|
506
|
+
selfieImage: 'base64_selfie', // Required: Base64 selfie image
|
|
507
|
+
idImage: 'base64_id_image', // Required: Base64 ID card image
|
|
508
|
+
transactionId: 'txn-001', // Optional
|
|
509
|
+
appKeyFaceService: 'alt-key', // Optional: alternative key
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
const result = await FinosEKYC.startFaceCompare(config);
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
**FaceServiceConfig**
|
|
516
|
+
|
|
517
|
+
| Field | Type | Required | Description |
|
|
518
|
+
|-------|------|----------|-------------|
|
|
519
|
+
| `appKey` | `string` | Yes | Face service API key |
|
|
520
|
+
| `selfieImage` | `string` | Yes | Base64 encoded selfie image |
|
|
521
|
+
| `idImage` | `string` | Yes | Base64 encoded ID card portrait |
|
|
522
|
+
| `transactionId` | `string` | No | Transaction ID |
|
|
523
|
+
| `appKeyFaceService` | `string` | No | Alternative face service key |
|
|
524
|
+
|
|
525
|
+
### C06 Verification
|
|
526
|
+
|
|
527
|
+
```typescript
|
|
528
|
+
const config: C06Config = {
|
|
529
|
+
appKey: 'your-c06-key', // Required
|
|
530
|
+
sod: 'nfc_sod_data', // Required: SOD data from NFC
|
|
531
|
+
idCardNumber: '012345678012', // Required: CCCD number
|
|
532
|
+
recentLocation: 'Ha Noi', // Optional: recent location
|
|
533
|
+
transactionId: 'txn-001', // Optional
|
|
534
|
+
deviceType: 'android', // Optional
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
const result = await FinosEKYC.checkC06(config);
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
**C06Config**
|
|
541
|
+
|
|
542
|
+
| Field | Type | Required | Description |
|
|
543
|
+
|-------|------|----------|-------------|
|
|
544
|
+
| `appKey` | `string` | Yes | C06 module API key |
|
|
545
|
+
| `sod` | `string` | Yes | SOD data from NFC scan |
|
|
546
|
+
| `idCardNumber` | `string` | Yes | CCCD/CMND number |
|
|
547
|
+
| `recentLocation` | `string` | No | Recent location for verification |
|
|
548
|
+
| `transactionId` | `string` | No | Transaction ID |
|
|
549
|
+
| `deviceType` | `string` | No | Device type identifier |
|
|
550
|
+
|
|
551
|
+
---
|
|
552
|
+
|
|
553
|
+
## SMS OTP Integration
|
|
554
|
+
|
|
555
|
+
```typescript
|
|
556
|
+
const otpConfig: SmsOtpConfig = {
|
|
557
|
+
appKey: 'your-api-key', // Required: X-FinOS-Api-Key
|
|
558
|
+
phoneNumber: '+84901234567', // Required: with country code
|
|
559
|
+
referenceId: 'ref-001', // Required: unique reference
|
|
560
|
+
purpose: 'transaction', // Optional (default: 'transaction')
|
|
561
|
+
requestId: undefined, // Required for verify/resend (from send response)
|
|
100
562
|
};
|
|
563
|
+
|
|
564
|
+
// 1. Send OTP
|
|
565
|
+
const sendResult = await FinosEKYC.sendOtp(otpConfig);
|
|
566
|
+
console.log('Request ID:', sendResult.requestId);
|
|
567
|
+
|
|
568
|
+
// 2. Verify OTP (use requestId from send response)
|
|
569
|
+
otpConfig.requestId = sendResult.requestId;
|
|
570
|
+
const verifyResult = await FinosEKYC.verifyOtp(otpConfig, '123456');
|
|
571
|
+
|
|
572
|
+
// 3. Resend OTP
|
|
573
|
+
const resendResult = await FinosEKYC.resendOtp(otpConfig);
|
|
101
574
|
```
|
|
102
575
|
|
|
576
|
+
**SmsOtpConfig**
|
|
103
577
|
|
|
578
|
+
| Field | Type | Required | Description |
|
|
579
|
+
|-------|------|----------|-------------|
|
|
580
|
+
| `appKey` | `string` | Yes | SMS OTP API key (X-FinOS-Api-Key) |
|
|
581
|
+
| `phoneNumber` | `string` | Yes | Phone number with country code (e.g., `+84901234567`) |
|
|
582
|
+
| `referenceId` | `string` | Yes | Unique reference ID |
|
|
583
|
+
| `purpose` | `string` | No | Purpose of OTP (default: `'transaction'`) |
|
|
584
|
+
| `requestId` | `string` | For verify/resend | Request ID from send response |
|
|
104
585
|
|
|
105
|
-
|
|
586
|
+
---
|
|
106
587
|
|
|
107
|
-
|
|
588
|
+
## eSign Integration
|
|
108
589
|
|
|
109
|
-
###
|
|
590
|
+
### Initialize
|
|
110
591
|
|
|
111
592
|
```typescript
|
|
112
|
-
// Initialize eSign
|
|
113
|
-
await FinosESign.initializeESign(
|
|
593
|
+
// Initialize eSign SDK
|
|
594
|
+
await FinosESign.initializeESign('your-finos-token', false); // token, isProd
|
|
595
|
+
|
|
596
|
+
// Get SDK token
|
|
597
|
+
const token = await FinosESign.getSdkToken(
|
|
598
|
+
'012345678012', // CCCD number
|
|
599
|
+
'Nguyen Van A', // Full name
|
|
600
|
+
'device-id-123', // Device ID
|
|
601
|
+
);
|
|
114
602
|
```
|
|
115
603
|
|
|
116
|
-
###
|
|
604
|
+
### Open Session
|
|
605
|
+
|
|
606
|
+
```typescript
|
|
607
|
+
const session = await FinosESign.openSessionId(
|
|
608
|
+
'access-token', // Access token (or null)
|
|
609
|
+
'username', // Username (or null)
|
|
610
|
+
true, // Remember me (or null)
|
|
611
|
+
);
|
|
612
|
+
console.log(session.deviceState, session.code, session.message);
|
|
613
|
+
```
|
|
117
614
|
|
|
118
|
-
|
|
615
|
+
### Device Registration
|
|
119
616
|
|
|
120
617
|
```typescript
|
|
121
618
|
const result = await FinosESign.registerDevice(
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
619
|
+
'12345678', // 8-digit recovery code
|
|
620
|
+
'123456', // 6-digit PIN code
|
|
621
|
+
'fcm-token', // Optional FCM token
|
|
125
622
|
);
|
|
126
|
-
console.log(result.message);
|
|
127
623
|
```
|
|
128
624
|
|
|
129
|
-
###
|
|
625
|
+
### Certificate Management
|
|
130
626
|
|
|
131
627
|
```typescript
|
|
132
628
|
// List certificates
|
|
133
|
-
const certs = await FinosESign.listCerts(1, 10);
|
|
629
|
+
const { certs } = await FinosESign.listCerts(1, 10);
|
|
630
|
+
// certs: [{ serial, subject, validFrom, validTo }]
|
|
134
631
|
|
|
135
|
-
// Verify
|
|
136
|
-
const verifyResult = await FinosESign.verifyCert(
|
|
632
|
+
// Verify certificate
|
|
633
|
+
const verifyResult = await FinosESign.verifyCert('cert-serial');
|
|
137
634
|
```
|
|
138
635
|
|
|
139
|
-
###
|
|
636
|
+
### Sign Documents
|
|
140
637
|
|
|
141
638
|
```typescript
|
|
142
|
-
// Sign a PDF
|
|
639
|
+
// Sign a PDF
|
|
143
640
|
const signResult = await FinosESign.signPdf(JSON.stringify(signRequest));
|
|
144
641
|
|
|
145
|
-
// Sign
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
642
|
+
// Sign PDF at multiple positions
|
|
643
|
+
const multiResult = await FinosESign.signPdfMultiplePositions(JSON.stringify(signRequest));
|
|
644
|
+
|
|
645
|
+
// Confirm signature
|
|
646
|
+
const confirmResult = await FinosESign.confirmSign(
|
|
647
|
+
'sign-request-id', // Sign request ID
|
|
648
|
+
'123456', // PIN code
|
|
649
|
+
'auth-id', // Optional auth ID
|
|
650
|
+
'auth-data', // Optional auth data
|
|
651
|
+
true, // Confirm (default: true)
|
|
149
652
|
);
|
|
150
653
|
```
|
|
151
654
|
|
|
152
|
-
###
|
|
153
|
-
|
|
154
|
-
Supported flows for remote signing:
|
|
655
|
+
### Remote Signing
|
|
155
656
|
|
|
156
657
|
```typescript
|
|
157
658
|
// Register for remote signing
|
|
@@ -159,111 +660,199 @@ const regResult = await FinosESign.registerRemoteSigning(JSON.stringify(requestB
|
|
|
159
660
|
|
|
160
661
|
// Register and Confirm in one step
|
|
161
662
|
const compositeResult = await FinosESign.registerAndConfirm(
|
|
162
|
-
|
|
163
|
-
|
|
663
|
+
JSON.stringify(requestBody),
|
|
664
|
+
'base64-confirmation-doc',
|
|
665
|
+
);
|
|
666
|
+
|
|
667
|
+
// Send confirmation document
|
|
668
|
+
const docResult = await FinosESign.sendConfirmationDocument(JSON.stringify(requestBody));
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
### Authorization Management
|
|
672
|
+
|
|
673
|
+
```typescript
|
|
674
|
+
// Initialize authorize request
|
|
675
|
+
await FinosESign.initAuthorize(
|
|
676
|
+
'cert-serial', // Certificate serial
|
|
677
|
+
10, // Quantity (signing count)
|
|
678
|
+
3600, // Time (seconds until expiry)
|
|
679
|
+
'Authorization msg',// Message
|
|
680
|
+
);
|
|
681
|
+
|
|
682
|
+
// List authorize requests
|
|
683
|
+
const { requests } = await FinosESign.listAuthorize(1, 10, 'ACTIVE');
|
|
684
|
+
|
|
685
|
+
// Register/Confirm authorize
|
|
686
|
+
await FinosESign.registerAuthorize(
|
|
687
|
+
'auth-id',
|
|
688
|
+
'auth-data',
|
|
689
|
+
'authorize-request-id',
|
|
690
|
+
'123456', // PIN code
|
|
691
|
+
true, // Confirm
|
|
164
692
|
);
|
|
165
693
|
```
|
|
166
694
|
|
|
167
|
-
|
|
695
|
+
---
|
|
696
|
+
|
|
697
|
+
## Event Listeners
|
|
168
698
|
|
|
169
|
-
|
|
699
|
+
### NFC Events
|
|
170
700
|
|
|
171
701
|
```typescript
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
702
|
+
FinosEKYC.onNfcScanStart((data) => console.log('NFC scan started', data));
|
|
703
|
+
FinosEKYC.onNfcScanSuccess((data) => console.log('NFC data:', data));
|
|
704
|
+
FinosEKYC.onNfcError((error) => console.error('NFC error:', error.code, error.message));
|
|
705
|
+
```
|
|
176
706
|
|
|
177
|
-
|
|
178
|
-
const sendResult = await FinosEKYC.sendOtp(otpConfig);
|
|
707
|
+
### OCR Events
|
|
179
708
|
|
|
180
|
-
|
|
181
|
-
|
|
709
|
+
```typescript
|
|
710
|
+
FinosEKYC.onOcrSuccess((data) => console.log('OCR result:', data));
|
|
711
|
+
FinosEKYC.onOcrError((error) => console.error('OCR error:', error.code, error.message));
|
|
712
|
+
```
|
|
182
713
|
|
|
183
|
-
|
|
184
|
-
|
|
714
|
+
### Liveness Events
|
|
715
|
+
|
|
716
|
+
```typescript
|
|
717
|
+
FinosEKYC.onLivenessSuccess((data) => console.log('Liveness result:', data));
|
|
718
|
+
FinosEKYC.onLivenessError((error) => console.error('Liveness error:', error.code, error.message));
|
|
185
719
|
```
|
|
186
720
|
|
|
187
|
-
|
|
721
|
+
### Face Compare Events
|
|
188
722
|
|
|
189
|
-
|
|
723
|
+
```typescript
|
|
724
|
+
FinosEKYC.onFaceCompareSuccess((data) => console.log('Face match:', data));
|
|
725
|
+
FinosEKYC.onFaceCompareError((error) => console.error('Face error:', error.code, error.message));
|
|
726
|
+
```
|
|
190
727
|
|
|
191
|
-
|
|
728
|
+
### C06 Events
|
|
192
729
|
|
|
193
730
|
```typescript
|
|
194
|
-
|
|
731
|
+
FinosEKYC.onC06Success((data) => console.log('C06 result:', data));
|
|
732
|
+
FinosEKYC.onC06Error((error) => console.error('C06 error:', error.code, error.message));
|
|
733
|
+
```
|
|
195
734
|
|
|
196
|
-
|
|
197
|
-
appKey: 'your_app_key',
|
|
198
|
-
isActiveLiveness: true, // Enable active liveness
|
|
199
|
-
autoCapture: true, // Auto capture when conditions met
|
|
200
|
-
isShowCameraFont: true, // Show instructions on camera
|
|
201
|
-
customActions: [ // Custom action sequence using Enum
|
|
202
|
-
SDKFaceDetectStatus.LEFT,
|
|
203
|
-
SDKFaceDetectStatus.RIGHT,
|
|
204
|
-
SDKFaceDetectStatus.SMILE
|
|
205
|
-
],
|
|
206
|
-
// activeActionCount: 2, // Or specify number of random actions
|
|
207
|
-
switchFrontCamera: true // Use front camera
|
|
208
|
-
};
|
|
735
|
+
### SMS OTP Events
|
|
209
736
|
|
|
210
|
-
|
|
737
|
+
```typescript
|
|
738
|
+
FinosEKYC.onSmsOtpSendSuccess((data) => console.log('OTP sent:', data));
|
|
739
|
+
FinosEKYC.onSmsOtpResendSuccess((data) => console.log('OTP resent:', data));
|
|
740
|
+
FinosEKYC.onSmsOtpError((error) => console.error('OTP error:', error.code, error.message));
|
|
211
741
|
```
|
|
212
742
|
|
|
213
|
-
###
|
|
743
|
+
### eSign Events
|
|
744
|
+
|
|
214
745
|
```typescript
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
746
|
+
FinosESign.onESignInitSuccess((data) => console.log('eSign init:', data));
|
|
747
|
+
FinosESign.onESignOpenSessionSuccess((data) => console.log('Session:', data));
|
|
748
|
+
FinosESign.onESignRegisterDeviceSuccess((data) => console.log('Device registered:', data));
|
|
749
|
+
FinosESign.onESignListCertsSuccess((data) => console.log('Certs:', data));
|
|
750
|
+
FinosESign.onESignSignPdfSuccess((data) => console.log('PDF signed:', data));
|
|
751
|
+
FinosESign.onESignError((error) => console.error('eSign error:', error.code, error.message));
|
|
752
|
+
```
|
|
220
753
|
|
|
221
|
-
|
|
754
|
+
### Cleanup
|
|
755
|
+
|
|
756
|
+
```typescript
|
|
757
|
+
// Remove all event listeners when done
|
|
758
|
+
FinosEKYC.removeAllListeners();
|
|
759
|
+
FinosESign.removeAllListeners();
|
|
222
760
|
```
|
|
223
761
|
|
|
224
|
-
|
|
762
|
+
---
|
|
763
|
+
|
|
764
|
+
## Error Handling
|
|
765
|
+
|
|
766
|
+
All errors follow a unified `EKYCError` format:
|
|
767
|
+
|
|
225
768
|
```typescript
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
769
|
+
interface EKYCError {
|
|
770
|
+
event: string; // Error event name (e.g., 'FACE_ERROR', 'NFC_ERROR')
|
|
771
|
+
code: string; // Error code (e.g., '110', '200', '999')
|
|
772
|
+
message: string; // Human-readable message
|
|
773
|
+
}
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
### Usage
|
|
232
777
|
|
|
233
|
-
|
|
778
|
+
```typescript
|
|
779
|
+
import { getEkycError, fromCode, getLocalizedMessage, USER_CANCEL } from '@finos_sdk/sdk-ekyc';
|
|
780
|
+
|
|
781
|
+
try {
|
|
782
|
+
const result = await FinosEKYC.startEkycUI(/* ... */);
|
|
783
|
+
} catch (error) {
|
|
784
|
+
const err = getEkycError(error);
|
|
785
|
+
console.error(`[${err.event}] Code: ${err.code}, Message: ${err.message}`);
|
|
786
|
+
|
|
787
|
+
// Check for user cancellation
|
|
788
|
+
if (err.code === '999' || err.code === USER_CANCEL.code) {
|
|
789
|
+
console.log('User cancelled the flow');
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// Lookup error details by code
|
|
794
|
+
const errorInfo = fromCode(err.code);
|
|
795
|
+
if (errorInfo) {
|
|
796
|
+
console.log('VI:', getLocalizedMessage(errorInfo, 'vi'));
|
|
797
|
+
console.log('EN:', getLocalizedMessage(errorInfo, 'en'));
|
|
798
|
+
}
|
|
799
|
+
}
|
|
234
800
|
```
|
|
235
801
|
|
|
236
|
-
|
|
802
|
+
### Common Error Codes
|
|
237
803
|
|
|
238
|
-
|
|
804
|
+
| Code | Constant | Description |
|
|
805
|
+
|------|----------|-------------|
|
|
806
|
+
| `999` | `USER_CANCEL` | User cancelled the flow |
|
|
807
|
+
| `000` | `ERROR_UNKNOWN` | Unknown error |
|
|
808
|
+
| `0` | `SDK_START_ERROR` | Failed to start SDK (check key) |
|
|
809
|
+
| `001` | `OCR_UNRECOGNIZED_ID_CARD` | Cannot recognize ID card |
|
|
810
|
+
| `110` | `LIVENESS_ERROR` | Liveness detection error |
|
|
811
|
+
| `109` | `FACE_ERROR` | Face comparison failed |
|
|
812
|
+
| `200` | `SCAN_NFC_ERROR` | NFC scan failed |
|
|
813
|
+
| `203` | `C06_ERROR` | C06 verification error |
|
|
814
|
+
| `209` | `NFC_USER_CANCEL` | User cancelled NFC scan |
|
|
815
|
+
| `300` | `SMS_OTP_ERROR` | SMS OTP error |
|
|
239
816
|
|
|
240
|
-
|
|
817
|
+
---
|
|
818
|
+
|
|
819
|
+
## Lifecycle Management
|
|
820
|
+
|
|
821
|
+
Handle app lifecycle events for NFC:
|
|
241
822
|
|
|
242
823
|
```typescript
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
};
|
|
824
|
+
import { AppState } from 'react-native';
|
|
825
|
+
|
|
826
|
+
useEffect(() => {
|
|
827
|
+
const subscription = AppState.addEventListener('change', (state) => {
|
|
828
|
+
if (state === 'active') {
|
|
829
|
+
FinosEKYC.onResume();
|
|
830
|
+
} else if (state === 'background') {
|
|
831
|
+
FinosEKYC.onPause();
|
|
832
|
+
}
|
|
833
|
+
});
|
|
834
|
+
|
|
835
|
+
return () => {
|
|
836
|
+
subscription.remove();
|
|
837
|
+
FinosEKYC.removeAllListeners();
|
|
838
|
+
};
|
|
839
|
+
}, []);
|
|
259
840
|
```
|
|
260
841
|
|
|
842
|
+
---
|
|
261
843
|
|
|
844
|
+
## What's New
|
|
262
845
|
|
|
263
|
-
|
|
846
|
+
### v1.4.2
|
|
847
|
+
- `AppIDType` enum (NONE, HD_BANK, VIKKI) for branding/skin selection
|
|
848
|
+
- `captureButtonColor` and `captureButtonDisabledColor` in StyleConfig
|
|
849
|
+
- `USER_CANCEL` error code (999) for user cancellation detection
|
|
850
|
+
- User cancellation callback support across all modules
|
|
851
|
+
- Android responsive layouts for camera preview screens
|
|
852
|
+
- Refactored StyleConfig JSON parsing with proper JSONObject
|
|
264
853
|
|
|
265
|
-
|
|
266
|
-
-
|
|
267
|
-
-
|
|
268
|
-
-
|
|
269
|
-
-
|
|
854
|
+
### v1.4.1
|
|
855
|
+
- Full iOS native bridge support
|
|
856
|
+
- eSign module with PDF signing, remote signing, authorization
|
|
857
|
+
- SMS OTP integration
|
|
858
|
+
- Active Liveness with custom actions
|