@transfergratis/react-native-sdk 0.1.24 → 0.1.26
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/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +12 -5
- package/android/build/intermediates/aar_main_jar/debug/syncDebugLibJars/classes.jar +0 -0
- package/android/build/intermediates/annotations_typedef_file/debug/extractDebugAnnotations/typedefs.txt +0 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
- package/android/build/intermediates/incremental/debug-mergeJavaRes/merge-state +0 -0
- package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +61 -59
- package/android/build/intermediates/merged_java_res/debug/mergeDebugJavaResource/feature-transfergratis-react-native-sdk.jar +0 -0
- package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +12 -5
- package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
- package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
- package/android/build/outputs/aar/transfergratis-react-native-sdk-debug.aar +0 -0
- package/android/build/outputs/logs/manifest-merger-debug-report.txt +26 -34
- package/android/src/main/AndroidManifest.xml +22 -7
- package/build/components/EnhancedCameraView.web.d.ts.map +1 -1
- package/build/components/EnhancedCameraView.web.js +76 -21
- package/build/components/EnhancedCameraView.web.js.map +1 -1
- package/build/components/KYCElements/AdditionalDocumentsTemplate.d.ts +12 -0
- package/build/components/KYCElements/AdditionalDocumentsTemplate.d.ts.map +1 -0
- package/build/components/KYCElements/AdditionalDocumentsTemplate.js +283 -0
- package/build/components/KYCElements/AdditionalDocumentsTemplate.js.map +1 -0
- package/build/components/KYCElements/EmailVerificationTemplate.d.ts +12 -0
- package/build/components/KYCElements/EmailVerificationTemplate.d.ts.map +1 -0
- package/build/components/KYCElements/EmailVerificationTemplate.js +212 -0
- package/build/components/KYCElements/EmailVerificationTemplate.js.map +1 -0
- package/build/components/KYCElements/IDCardCapture.d.ts.map +1 -1
- package/build/components/KYCElements/IDCardCapture.js +216 -14
- package/build/components/KYCElements/IDCardCapture.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCapture.d.ts +2 -0
- package/build/components/KYCElements/OrientationVideoCapture.d.ts.map +1 -1
- package/build/components/KYCElements/OrientationVideoCapture.js +2 -2
- package/build/components/KYCElements/OrientationVideoCapture.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.d.ts +2 -0
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.d.ts.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js +2 -2
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureFinal.d.ts +2 -0
- package/build/components/KYCElements/OrientationVideoCaptureFinal.d.ts.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureFinal.js +2 -2
- package/build/components/KYCElements/OrientationVideoCaptureFinal.js.map +1 -1
- package/build/components/KYCElements/PersonalInformationTemplate.d.ts +12 -0
- package/build/components/KYCElements/PersonalInformationTemplate.d.ts.map +1 -0
- package/build/components/KYCElements/PersonalInformationTemplate.js +120 -0
- package/build/components/KYCElements/PersonalInformationTemplate.js.map +1 -0
- package/build/components/KYCElements/PhoneVerificationTemplate.d.ts +12 -0
- package/build/components/KYCElements/PhoneVerificationTemplate.d.ts.map +1 -0
- package/build/components/KYCElements/PhoneVerificationTemplate.js +185 -0
- package/build/components/KYCElements/PhoneVerificationTemplate.js.map +1 -0
- package/build/components/KYCElements/SelfieCaptureTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/SelfieCaptureTemplate.js +7 -3
- package/build/components/KYCElements/SelfieCaptureTemplate.js.map +1 -1
- package/build/components/KYCElements/WelcomeTemplate.js +2 -1
- package/build/components/KYCElements/WelcomeTemplate.js.map +1 -1
- package/build/components/OverLay/type.d.ts +2 -0
- package/build/components/OverLay/type.d.ts.map +1 -1
- package/build/components/OverLay/type.js.map +1 -1
- package/build/components/TemplateKYCExample.d.ts +10 -0
- package/build/components/TemplateKYCExample.d.ts.map +1 -1
- package/build/components/TemplateKYCExample.js +7 -30
- package/build/components/TemplateKYCExample.js.map +1 -1
- package/build/components/TemplateKYCFlowRefactored.d.ts +12 -0
- package/build/components/TemplateKYCFlowRefactored.d.ts.map +1 -1
- package/build/components/TemplateKYCFlowRefactored.js +25 -3
- package/build/components/TemplateKYCFlowRefactored.js.map +1 -1
- package/build/config/KYCConfig.d.ts +14 -0
- package/build/config/KYCConfig.d.ts.map +1 -0
- package/build/config/KYCConfig.js +26 -0
- package/build/config/KYCConfig.js.map +1 -0
- package/build/config/allowedDomains.d.ts.map +1 -1
- package/build/config/allowedDomains.js +4 -19
- package/build/config/allowedDomains.js.map +1 -1
- package/build/hooks/useOrientationVideo.d.ts +2 -1
- package/build/hooks/useOrientationVideo.d.ts.map +1 -1
- package/build/hooks/useOrientationVideo.js +3 -3
- package/build/hooks/useOrientationVideo.js.map +1 -1
- package/build/hooks/useTemplateKYCFlow.d.ts +18 -1
- package/build/hooks/useTemplateKYCFlow.d.ts.map +1 -1
- package/build/hooks/useTemplateKYCFlow.js +410 -56
- package/build/hooks/useTemplateKYCFlow.js.map +1 -1
- package/build/i18n/en/index.d.ts +42 -0
- package/build/i18n/en/index.d.ts.map +1 -1
- package/build/i18n/en/index.js +44 -2
- package/build/i18n/en/index.js.map +1 -1
- package/build/i18n/fr/index.d.ts +28 -0
- package/build/i18n/fr/index.d.ts.map +1 -1
- package/build/i18n/fr/index.js +30 -2
- package/build/i18n/fr/index.js.map +1 -1
- package/build/i18n/types.d.ts +2 -0
- package/build/i18n/types.d.ts.map +1 -1
- package/build/i18n/types.js.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -0
- package/build/index.js.map +1 -1
- package/build/modules/api/CardAuthentification.d.ts +24 -3
- package/build/modules/api/CardAuthentification.d.ts.map +1 -1
- package/build/modules/api/CardAuthentification.js +90 -12
- package/build/modules/api/CardAuthentification.js.map +1 -1
- package/build/modules/api/KYCService.d.ts +17 -7
- package/build/modules/api/KYCService.d.ts.map +1 -1
- package/build/modules/api/KYCService.js +125 -37
- package/build/modules/api/KYCService.js.map +1 -1
- package/build/modules/api/SelfieVerification.d.ts +3 -1
- package/build/modules/api/SelfieVerification.d.ts.map +1 -1
- package/build/modules/api/SelfieVerification.js +17 -1
- package/build/modules/api/SelfieVerification.js.map +1 -1
- package/build/modules/api/TemplateService.d.ts +0 -1
- package/build/modules/api/TemplateService.d.ts.map +1 -1
- package/build/modules/api/TemplateService.js +3 -3
- package/build/modules/api/TemplateService.js.map +1 -1
- package/build/modules/camera/VisionCameraModule.web.d.ts.map +1 -1
- package/build/modules/camera/VisionCameraModule.web.js +27 -8
- package/build/modules/camera/VisionCameraModule.web.js.map +1 -1
- package/build/types/KYC.types.d.ts +130 -5
- package/build/types/KYC.types.d.ts.map +1 -1
- package/build/types/KYC.types.js.map +1 -1
- package/build/types/env.types.d.ts +13 -0
- package/build/types/env.types.d.ts.map +1 -0
- package/build/types/env.types.js +2 -0
- package/build/types/env.types.js.map +1 -0
- package/build/utils/cropByObb.d.ts +7 -0
- package/build/utils/cropByObb.d.ts.map +1 -1
- package/build/utils/cropByObb.js +20 -1
- package/build/utils/cropByObb.js.map +1 -1
- package/build/utils/deviceDetection.d.ts +6 -0
- package/build/utils/deviceDetection.d.ts.map +1 -0
- package/build/utils/deviceDetection.js +12 -0
- package/build/utils/deviceDetection.js.map +1 -0
- package/build/utils/platformAlert.d.ts.map +1 -1
- package/build/utils/platformAlert.js.map +1 -1
- package/build/utils/template-transformer.d.ts.map +1 -1
- package/build/utils/template-transformer.js +12 -0
- package/build/utils/template-transformer.js.map +1 -1
- package/build/web/WebKYCEntry.d.ts.map +1 -1
- package/build/web/WebKYCEntry.js +88 -38
- package/build/web/WebKYCEntry.js.map +1 -1
- package/package.json +1 -1
- package/plugin/build/index.d.ts +1 -0
- package/plugin/build/index.js +3 -1
- package/plugin/build/withRemovePermissions.d.ts +3 -0
- package/plugin/build/withRemovePermissions.js +67 -0
- package/plugin/build/withVisionCamera.js +3 -4
- package/plugin/src/index.ts +2 -1
- package/plugin/src/withRemovePermissions.js +85 -0
- package/plugin/src/withRemovePermissions.ts +83 -0
- package/plugin/src/withVisionCamera.js +3 -4
- package/plugin/src/withVisionCamera.ts +3 -4
- package/plugin/tsconfig.tsbuildinfo +1 -1
- package/plugin.js +6 -1
- package/src/components/EnhancedCameraView.web.tsx +76 -21
- package/src/components/KYCElements/AdditionalDocumentsTemplate.tsx +346 -0
- package/src/components/KYCElements/EmailVerificationTemplate.tsx +278 -0
- package/src/components/KYCElements/IDCardCapture.tsx +253 -21
- package/src/components/KYCElements/OrientationVideoCapture.tsx +4 -1
- package/src/components/KYCElements/OrientationVideoCaptureEnhanced.tsx +4 -1
- package/src/components/KYCElements/OrientationVideoCaptureFinal.tsx +4 -1
- package/src/components/KYCElements/PersonalInformationTemplate.tsx +158 -0
- package/src/components/KYCElements/PhoneVerificationTemplate.tsx +253 -0
- package/src/components/KYCElements/SelfieCaptureTemplate.tsx +6 -3
- package/src/components/KYCElements/WelcomeTemplate.tsx +2 -1
- package/src/components/OverLay/type.ts +2 -0
- package/src/components/TemplateKYCExample.tsx +35 -46
- package/src/components/TemplateKYCFlowRefactored.tsx +46 -2
- package/src/config/KYCConfig.ts +34 -0
- package/src/config/allowedDomains.ts +7 -26
- package/src/hooks/useOrientationVideo.ts +5 -4
- package/src/hooks/useTemplateKYCFlow.tsx +443 -56
- package/src/i18n/en/index.ts +46 -3
- package/src/i18n/fr/index.ts +31 -2
- package/src/i18n/types.ts +2 -0
- package/src/index.ts +3 -0
- package/src/modules/api/CardAuthentification.ts +98 -12
- package/src/modules/api/KYCService.ts +158 -37
- package/src/modules/api/SelfieVerification.ts +25 -3
- package/src/modules/api/TemplateService.ts +4 -4
- package/src/modules/camera/VisionCameraModule.web.ts +30 -12
- package/src/types/KYC.types.ts +153 -6
- package/src/types/env.types.ts +13 -0
- package/src/utils/cropByObb.ts +20 -1
- package/src/utils/deviceDetection.ts +11 -0
- package/src/utils/platformAlert.ts +1 -0
- package/src/utils/template-transformer.ts +20 -8
- package/src/web/WebKYCEntry.tsx +123 -61
|
@@ -1,11 +1,33 @@
|
|
|
1
|
-
import kycService, { authentification } from "./KYCService";
|
|
1
|
+
import kycService, { authentification, SelfieVideoResponse } from "./KYCService";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import { KycEnvironment } from "../../types/env.types";
|
|
4
|
+
|
|
5
|
+
const selfieVerification = async (selfieImage: string, env: KycEnvironment = 'PRODUCTION'): Promise<SelfieVideoResponse[]> => {
|
|
6
|
+
// In SANDBOX mode, skip AI verification and return a mock success response
|
|
7
|
+
if (env === 'SANDBOX') {
|
|
8
|
+
console.log("SANDBOX mode: Skipping AI verification for selfie");
|
|
9
|
+
// Return a mock response that simulates successful verification
|
|
10
|
+
// This allows the flow to continue without actual AI processing
|
|
11
|
+
|
|
12
|
+
const mockResponse: SelfieVideoResponse[] = [{
|
|
13
|
+
orientation_direction: "center",
|
|
14
|
+
turn_score: 1.0,
|
|
15
|
+
bbox: [0, 0, 100, 100],
|
|
16
|
+
capture: true,
|
|
17
|
+
instruction: "SANDBOX: AI verification skipped",
|
|
18
|
+
error: ""
|
|
19
|
+
}];
|
|
20
|
+
return mockResponse;
|
|
21
|
+
}
|
|
5
22
|
|
|
23
|
+
// PRODUCTION mode: perform actual AI verification
|
|
24
|
+
const token = await authentification();
|
|
6
25
|
const response = await kycService.processSelfieOrientationPicture(selfieImage, token);
|
|
7
26
|
console.log("selfieVerification response", JSON.stringify(response, null, 2));
|
|
8
27
|
return response;
|
|
9
28
|
}
|
|
10
29
|
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
11
33
|
export default selfieVerification;
|
|
@@ -2,9 +2,9 @@ import axios from 'axios';
|
|
|
2
2
|
import { BackendKYCTemplate, TemplateAPIResponse } from '../../types/KYC.types';
|
|
3
3
|
import { logger } from '../../utils/logger';
|
|
4
4
|
import { errorMessage } from './KYCService';
|
|
5
|
+
import KYCConfig from '../../config/KYCConfig';
|
|
5
6
|
|
|
6
7
|
export class TemplateServiceClass {
|
|
7
|
-
private backendServiceURL = 'https://service.sanctumkey.com/api/v1';
|
|
8
8
|
private cache: Map<string, { template: BackendKYCTemplate; timestamp: number }> = new Map();
|
|
9
9
|
private cacheTimeout = 5 * 60 * 1000; // 5 minutes
|
|
10
10
|
|
|
@@ -55,8 +55,8 @@ export class TemplateServiceClass {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
try {
|
|
58
|
-
const url = `${
|
|
59
|
-
logger.log(`Fetching template from: ${url} with apiKey: ${apiKey} and token: ${token}`,{
|
|
58
|
+
const url = `${KYCConfig.getBackendUrl()}/templates/kyc/template/${templateId}/`;
|
|
59
|
+
logger.log(`Fetching template from: ${url} with apiKey: ${apiKey} and token: ${token}`, {
|
|
60
60
|
headers: this.getHeaders(apiKey, token)
|
|
61
61
|
});
|
|
62
62
|
|
|
@@ -142,7 +142,7 @@ export class TemplateServiceClass {
|
|
|
142
142
|
*/
|
|
143
143
|
async fetchTemplateList(apiKey?: string, token?: string): Promise<Array<{ id: string; name: Record<string, string>; version?: string; status?: string }>> {
|
|
144
144
|
try {
|
|
145
|
-
const url = `${
|
|
145
|
+
const url = `${KYCConfig.getBackendUrl()}/templates/kyc/templates`;
|
|
146
146
|
logger.log(`Fetching template list from: ${url}`);
|
|
147
147
|
|
|
148
148
|
const response = await axios.get<Array<{ id: string; name: Record<string, string>; version?: string; status?: string }>>(url, {
|
|
@@ -151,17 +151,18 @@ export class VisionCameraModule {
|
|
|
151
151
|
return false;
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
|
|
155
|
-
|
|
154
|
+
// Use min + ideal so Android Chrome doesn't cache low resolution (e.g. 640x480)
|
|
155
|
+
const stream = await navigator.mediaDevices.getUserMedia({
|
|
156
|
+
video: {
|
|
156
157
|
facingMode: 'user',
|
|
157
|
-
width: {
|
|
158
|
-
height: {
|
|
159
|
-
}
|
|
158
|
+
width: { min: 1280, ideal: 1920 },
|
|
159
|
+
height: { min: 720, ideal: 1080 },
|
|
160
|
+
},
|
|
160
161
|
});
|
|
161
|
-
|
|
162
|
+
|
|
162
163
|
// Libérer le stream de test
|
|
163
164
|
stream.getTracks().forEach(track => track.stop());
|
|
164
|
-
|
|
165
|
+
|
|
165
166
|
return true;
|
|
166
167
|
} catch (error) {
|
|
167
168
|
console.error('Error requesting camera permission:', error);
|
|
@@ -330,13 +331,30 @@ export class VisionCameraModule {
|
|
|
330
331
|
return;
|
|
331
332
|
}
|
|
332
333
|
|
|
333
|
-
|
|
334
|
+
const constraints: MediaStreamConstraints = {
|
|
334
335
|
video: {
|
|
335
336
|
facingMode: 'user',
|
|
336
|
-
width: {
|
|
337
|
-
height: {
|
|
337
|
+
width: { min: 1280, ideal: 1920 },
|
|
338
|
+
height: { min: 720, ideal: 1080 },
|
|
339
|
+
},
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
try {
|
|
343
|
+
this.stream = await navigator.mediaDevices.getUserMedia(constraints);
|
|
344
|
+
} catch (err) {
|
|
345
|
+
const name = err instanceof Error ? err.name : '';
|
|
346
|
+
if (name === 'OverconstrainedError') {
|
|
347
|
+
this.stream = await navigator.mediaDevices.getUserMedia({
|
|
348
|
+
video: {
|
|
349
|
+
facingMode: 'user',
|
|
350
|
+
width: { ideal: 1920 },
|
|
351
|
+
height: { ideal: 1080 },
|
|
352
|
+
},
|
|
353
|
+
});
|
|
354
|
+
} else {
|
|
355
|
+
throw err;
|
|
338
356
|
}
|
|
339
|
-
}
|
|
357
|
+
}
|
|
340
358
|
|
|
341
359
|
if (this.videoElement) {
|
|
342
360
|
this.videoElement.srcObject = this.stream;
|
|
@@ -531,7 +549,7 @@ export class VisionCameraModule {
|
|
|
531
549
|
context.drawImage(this.videoElement, 0, 0);
|
|
532
550
|
|
|
533
551
|
// Convertir en base64
|
|
534
|
-
const imageDataUrl = this.canvasElement.toDataURL('image/jpeg', 0.
|
|
552
|
+
const imageDataUrl = this.canvasElement.toDataURL('image/jpeg', 0.95);
|
|
535
553
|
|
|
536
554
|
// Créer un nom de fichier unique
|
|
537
555
|
const timestamp = new Date().getTime();
|
package/src/types/KYC.types.ts
CHANGED
|
@@ -8,6 +8,7 @@ export interface Document {
|
|
|
8
8
|
uploadedAt: Date;
|
|
9
9
|
validated: boolean;
|
|
10
10
|
extractedData?: DocumentData;
|
|
11
|
+
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
export type DocumentType = 'passport' | 'id_card' | 'drivers_license';
|
|
@@ -406,12 +407,17 @@ export type ComponentConfig =
|
|
|
406
407
|
| FileUploadConfig
|
|
407
408
|
| LocationConfig
|
|
408
409
|
| CountrySelectionConfig
|
|
409
|
-
|
|
|
410
|
+
| CountrySelectionConfig
|
|
411
|
+
| WelcomeConfig
|
|
412
|
+
| EmailVerificationConfig
|
|
413
|
+
| PhoneVerificationConfig
|
|
414
|
+
| PersonalInformationConfig
|
|
415
|
+
| AdditionalDocumentsConfig;
|
|
410
416
|
|
|
411
417
|
// Nouveau type de composant basé sur le template JSON
|
|
412
418
|
export interface TemplateComponent {
|
|
413
419
|
id: number;
|
|
414
|
-
type: 'id_card' | 'selfie' | 'file_upload' | 'location' | 'country_selection' | 'initialization' | 'review_submit' | 'verification_progress' | 'welcome';
|
|
420
|
+
type: 'id_card' | 'selfie' | 'file_upload' | 'location' | 'country_selection' | 'initialization' | 'review_submit' | 'verification_progress' | 'welcome' | 'email_verification' | 'phone_verification' | 'personal_information' | 'additional_documents';
|
|
415
421
|
order: number;
|
|
416
422
|
templateId?: number;
|
|
417
423
|
labels: LocalizedText | Record<string, LocalizedText>;
|
|
@@ -449,6 +455,8 @@ export interface SessionState {
|
|
|
449
455
|
isInitialized: boolean;
|
|
450
456
|
isProcessing: boolean;
|
|
451
457
|
error: string | null;
|
|
458
|
+
/** True once loadSessionData has run (for resume flow); allows UI to show loading until country/data restored */
|
|
459
|
+
sessionDataRestored?: boolean;
|
|
452
460
|
}
|
|
453
461
|
|
|
454
462
|
export type VerificationStatus = 'idle' | 'in_progress' | 'success' | 'failed';
|
|
@@ -463,11 +471,11 @@ export interface VerificationState {
|
|
|
463
471
|
// Actions pour le template KYC
|
|
464
472
|
export interface TemplateActions {
|
|
465
473
|
initializeTemplate: (template: KYCTemplate) => void;
|
|
466
|
-
nextComponent: () => void;
|
|
474
|
+
nextComponent: (overrideData?: any) => void;
|
|
467
475
|
previousComponent: () => void;
|
|
468
476
|
goToComponent: (componentId: number) => void;
|
|
469
477
|
updateComponentData: (componentId: number, data: any) => void;
|
|
470
|
-
validateComponent: (componentId: number) => boolean;
|
|
478
|
+
validateComponent: (componentId: number, dataOverride?: any) => boolean;
|
|
471
479
|
submitTemplate: () => Promise<void>;
|
|
472
480
|
resetTemplate: () => void;
|
|
473
481
|
setLanguage: (language: string) => void;
|
|
@@ -476,7 +484,7 @@ export interface TemplateActions {
|
|
|
476
484
|
submitVerification: () => Promise<void>;
|
|
477
485
|
}
|
|
478
486
|
|
|
479
|
-
// Hook pour le template KYC
|
|
487
|
+
// Hook pour le template KYC (return type of useTemplateKYCFlow)
|
|
480
488
|
export interface UseTemplateReturn {
|
|
481
489
|
state: TemplateState;
|
|
482
490
|
actions: TemplateActions;
|
|
@@ -487,6 +495,9 @@ export interface UseTemplateReturn {
|
|
|
487
495
|
isComplete: boolean;
|
|
488
496
|
getLocalizedText: (text: LocalizedText) => string;
|
|
489
497
|
initializeSession: () => Promise<void>;
|
|
498
|
+
env: 'PRODUCTION' | 'SANDBOX';
|
|
499
|
+
/** Optional API key for backend auth (e.g. email verification endpoints). */
|
|
500
|
+
apiKey?: string;
|
|
490
501
|
}
|
|
491
502
|
|
|
492
503
|
|
|
@@ -646,7 +657,7 @@ export interface BackendComponentTranslations {
|
|
|
646
657
|
// Backend template component
|
|
647
658
|
export interface BackendTemplateComponent {
|
|
648
659
|
id: string;
|
|
649
|
-
type: 'welcome' | 'location-capture' | 'government-id' | 'selfie-capture' | 'review-submit' | 'verification-progress';
|
|
660
|
+
type: 'welcome' | 'location-capture' | 'government-id' | 'selfie-capture' | 'review-submit' | 'verification-progress' | 'email-verification' | 'phone-verification' | 'personal-information' | 'additional-documents';
|
|
650
661
|
order: number;
|
|
651
662
|
config: BackendComponentConfig;
|
|
652
663
|
required?: boolean;
|
|
@@ -671,6 +682,74 @@ export interface BackendKYCTemplate {
|
|
|
671
682
|
};
|
|
672
683
|
}
|
|
673
684
|
|
|
685
|
+
// ===== NEW CONFIG TYPES FOR INPUT VERIFICATION =====
|
|
686
|
+
|
|
687
|
+
export interface EmailVerificationConfig {
|
|
688
|
+
allowResend: boolean;
|
|
689
|
+
otpSettings: {
|
|
690
|
+
codeLength: number;
|
|
691
|
+
expiryTime: number;
|
|
692
|
+
};
|
|
693
|
+
resendCooldown: number;
|
|
694
|
+
emailValidation: {
|
|
695
|
+
corporateOnly: boolean;
|
|
696
|
+
validateFormat: boolean;
|
|
697
|
+
checkDisposable: boolean;
|
|
698
|
+
checkDeliverability: boolean;
|
|
699
|
+
};
|
|
700
|
+
verificationMethod: string;
|
|
701
|
+
required?: boolean;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
export interface PhoneVerificationConfig {
|
|
705
|
+
required: boolean;
|
|
706
|
+
codeExpiry: number;
|
|
707
|
+
codeLength: number;
|
|
708
|
+
maxAttempts: number;
|
|
709
|
+
resendDelay: number;
|
|
710
|
+
countryRestrictions: string;
|
|
711
|
+
verificationMethods: string[];
|
|
712
|
+
allowSkipForVerified: boolean;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
export interface PersonalInfoField {
|
|
716
|
+
id: string;
|
|
717
|
+
type: string;
|
|
718
|
+
label: string;
|
|
719
|
+
required: boolean;
|
|
720
|
+
placeholder?: string;
|
|
721
|
+
autoFillFromId?: boolean;
|
|
722
|
+
minAge?: number;
|
|
723
|
+
verifyAge?: boolean;
|
|
724
|
+
dateFormat?: string;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
export interface PersonalInformationConfig {
|
|
728
|
+
fields: PersonalInfoField[];
|
|
729
|
+
validationSettings: {
|
|
730
|
+
validateOnBlur: boolean;
|
|
731
|
+
showAllErrorsAtOnce: boolean;
|
|
732
|
+
preventSubmissionWithErrors: boolean;
|
|
733
|
+
};
|
|
734
|
+
required?: boolean;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
export interface DocumentCategory {
|
|
738
|
+
enabled: boolean;
|
|
739
|
+
category: string;
|
|
740
|
+
documentTypes: string[];
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
export interface AdditionalDocumentsConfig {
|
|
744
|
+
required: boolean;
|
|
745
|
+
maxSizeEach: string;
|
|
746
|
+
maxDocuments: number;
|
|
747
|
+
minDocuments: number;
|
|
748
|
+
documentCategories: DocumentCategory[];
|
|
749
|
+
customDocumentTypes: any[];
|
|
750
|
+
showBasedOnUserProfile: boolean;
|
|
751
|
+
}
|
|
752
|
+
|
|
674
753
|
// API response for template
|
|
675
754
|
export interface TemplateAPIResponse {
|
|
676
755
|
id: string;
|
|
@@ -687,4 +766,72 @@ export interface TemplateAPIResponse {
|
|
|
687
766
|
fr: string;
|
|
688
767
|
[key: string]: string;
|
|
689
768
|
};
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
// ===== NEW CONFIG TYPES FOR INPUT VERIFICATION =====
|
|
772
|
+
|
|
773
|
+
export interface EmailVerificationConfig {
|
|
774
|
+
allowResend: boolean;
|
|
775
|
+
otpSettings: {
|
|
776
|
+
codeLength: number;
|
|
777
|
+
expiryTime: number;
|
|
778
|
+
};
|
|
779
|
+
resendCooldown: number;
|
|
780
|
+
emailValidation: {
|
|
781
|
+
corporateOnly: boolean;
|
|
782
|
+
validateFormat: boolean;
|
|
783
|
+
checkDisposable: boolean;
|
|
784
|
+
checkDeliverability: boolean;
|
|
785
|
+
};
|
|
786
|
+
verificationMethod: string;
|
|
787
|
+
required?: boolean;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
export interface PhoneVerificationConfig {
|
|
791
|
+
required: boolean;
|
|
792
|
+
codeExpiry: number;
|
|
793
|
+
codeLength: number;
|
|
794
|
+
maxAttempts: number;
|
|
795
|
+
resendDelay: number;
|
|
796
|
+
countryRestrictions: string;
|
|
797
|
+
verificationMethods: string[];
|
|
798
|
+
allowSkipForVerified: boolean;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
export interface PersonalInfoField {
|
|
802
|
+
id: string;
|
|
803
|
+
type: string;
|
|
804
|
+
label: string;
|
|
805
|
+
required: boolean;
|
|
806
|
+
placeholder?: string;
|
|
807
|
+
autoFillFromId?: boolean;
|
|
808
|
+
minAge?: number;
|
|
809
|
+
verifyAge?: boolean;
|
|
810
|
+
dateFormat?: string;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
export interface PersonalInformationConfig {
|
|
814
|
+
fields: PersonalInfoField[];
|
|
815
|
+
validationSettings: {
|
|
816
|
+
validateOnBlur: boolean;
|
|
817
|
+
showAllErrorsAtOnce: boolean;
|
|
818
|
+
preventSubmissionWithErrors: boolean;
|
|
819
|
+
};
|
|
820
|
+
required?: boolean;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
export interface DocumentCategory {
|
|
824
|
+
enabled: boolean;
|
|
825
|
+
category: string;
|
|
826
|
+
documentTypes: string[];
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
export interface AdditionalDocumentsConfig {
|
|
830
|
+
required: boolean;
|
|
831
|
+
maxSizeEach: string;
|
|
832
|
+
maxDocuments: number;
|
|
833
|
+
minDocuments: number;
|
|
834
|
+
documentCategories: DocumentCategory[];
|
|
835
|
+
customDocumentTypes: any[];
|
|
836
|
+
showBasedOnUserProfile: boolean;
|
|
690
837
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KYC Environment types
|
|
3
|
+
* PRODUCTION: Full verification with AI checks
|
|
4
|
+
* SANDBOX: Skip AI verification, only save data to backend
|
|
5
|
+
*/
|
|
6
|
+
export type KycEnvironment = 'PRODUCTION' | 'SANDBOX';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Backend Environment types
|
|
10
|
+
* PRODUCTION: Production backend
|
|
11
|
+
* TEST: Test backend
|
|
12
|
+
*/
|
|
13
|
+
export type BackendEnvironment = 'PRODUCTION' | 'TEST';
|
package/src/utils/cropByObb.ts
CHANGED
|
@@ -5,6 +5,21 @@ import { logger } from './logger';
|
|
|
5
5
|
|
|
6
6
|
type Point = [number, number];
|
|
7
7
|
|
|
8
|
+
/** OBB confidence below this = card not fully in frame; don't crop, give user feedback. */
|
|
9
|
+
export const OBB_CONFIDENCE_THRESHOLD = 0.85;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* card_obb format from API: [ [ [p1,p2,p3,p4], confidence ] ]
|
|
13
|
+
* Returns confidence in [0,1] or null if not present.
|
|
14
|
+
*/
|
|
15
|
+
export function getObbConfidence(cardObb: any): number | null {
|
|
16
|
+
if (!cardObb || !Array.isArray(cardObb) || cardObb.length === 0) return null;
|
|
17
|
+
const first = cardObb[0];
|
|
18
|
+
if (!Array.isArray(first) || first.length < 2) return null;
|
|
19
|
+
const score = first[1];
|
|
20
|
+
return typeof score === 'number' ? score : null;
|
|
21
|
+
}
|
|
22
|
+
|
|
8
23
|
// Compute axis-aligned bounding box from oriented quadrilateral
|
|
9
24
|
function computeAabb(points: Point[]) {
|
|
10
25
|
const xs = points.map(p => p[0]);
|
|
@@ -49,7 +64,11 @@ async function cropWeb(uri: string, points: Point[]): Promise<string> {
|
|
|
49
64
|
// Fallback: return original for native (no dependency added); caller can still use bbox to draw overlay
|
|
50
65
|
export async function cropByObb(uri: string, cardObb: any): Promise<{ base64?: string; bbox?: { minX: number; minY: number; width: number; height: number } }> {
|
|
51
66
|
try {
|
|
52
|
-
// card_obb format: [ [ [p1,p2,p3,p4], score ] ]
|
|
67
|
+
// card_obb format: [ [ [p1,p2,p3,p4], score ] ] — if confidence too low, don't crop (send full image)
|
|
68
|
+
const confidence = getObbConfidence(cardObb);
|
|
69
|
+
if (confidence !== null && confidence < OBB_CONFIDENCE_THRESHOLD) {
|
|
70
|
+
return {};
|
|
71
|
+
}
|
|
53
72
|
const first = Array.isArray(cardObb) ? cardObb[0] : null;
|
|
54
73
|
const points = Array.isArray(first?.[0]) ? (first[0] as Point[]) : null;
|
|
55
74
|
if (!points || points.length !== 4) return {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks if the current environment is a mobile web browser based on User Agent.
|
|
3
|
+
* This can be used to distinguish between desktop web and mobile web.
|
|
4
|
+
*/
|
|
5
|
+
export const isMobileWeb = (): boolean => {
|
|
6
|
+
if (typeof window === 'undefined' || !window.navigator) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
const userAgent = window.navigator.userAgent;
|
|
10
|
+
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent);
|
|
11
|
+
};
|
|
@@ -42,6 +42,10 @@ const COMPONENT_TYPE_MAPPING: Record<string, TemplateComponent['type']> = {
|
|
|
42
42
|
'verification-progress': 'verification_progress',
|
|
43
43
|
'file-upload': 'file_upload',
|
|
44
44
|
'country-selection': 'country_selection',
|
|
45
|
+
'email-verification': 'email_verification',
|
|
46
|
+
'phone-verification': 'phone_verification',
|
|
47
|
+
'personal-information': 'personal_information',
|
|
48
|
+
'additional-documents': 'additional_documents',
|
|
45
49
|
};
|
|
46
50
|
|
|
47
51
|
/**
|
|
@@ -241,6 +245,14 @@ function transformComponentConfig(
|
|
|
241
245
|
default_country: backendConfig.default_country || '',
|
|
242
246
|
required: backendConfig.required !== false,
|
|
243
247
|
} as CountrySelectionConfig;
|
|
248
|
+
case 'email_verification':
|
|
249
|
+
return backendConfig as any;
|
|
250
|
+
case 'phone_verification':
|
|
251
|
+
return backendConfig as any;
|
|
252
|
+
case 'personal_information':
|
|
253
|
+
return backendConfig as any;
|
|
254
|
+
case 'additional_documents':
|
|
255
|
+
return backendConfig as any;
|
|
244
256
|
default:
|
|
245
257
|
return backendConfig as ComponentConfig;
|
|
246
258
|
}
|
|
@@ -328,23 +340,23 @@ export function transformBackendTemplateToSDK(
|
|
|
328
340
|
// Auto-create country_selection component before id_card if government-id has selection data
|
|
329
341
|
// Check if country_selection already exists in backend template
|
|
330
342
|
const hasCountrySelectionInBackend = sortedComponents.some(c => (c as any).type === 'country-selection');
|
|
331
|
-
|
|
343
|
+
|
|
332
344
|
if (!hasCountrySelectionInBackend) {
|
|
333
345
|
// Find the first government-id component with selection data
|
|
334
|
-
const govIdWithSelection = sortedComponents.find(backendComp =>
|
|
335
|
-
backendComp.type === 'government-id' &&
|
|
346
|
+
const govIdWithSelection = sortedComponents.find(backendComp =>
|
|
347
|
+
backendComp.type === 'government-id' &&
|
|
336
348
|
backendComp.config && (
|
|
337
349
|
(backendComp.config as any).selectedCountries ||
|
|
338
350
|
(backendComp.config as any).documentTypesByCountry
|
|
339
351
|
)
|
|
340
352
|
);
|
|
341
|
-
|
|
353
|
+
|
|
342
354
|
if (govIdWithSelection) {
|
|
343
355
|
// Find the corresponding transformed id_card component
|
|
344
|
-
const transformedIdCard = transformedComponents.find(c =>
|
|
356
|
+
const transformedIdCard = transformedComponents.find(c =>
|
|
345
357
|
hashStringToNumber(govIdWithSelection.id) === c.id
|
|
346
358
|
);
|
|
347
|
-
|
|
359
|
+
|
|
348
360
|
if (transformedIdCard) {
|
|
349
361
|
// Create a country_selection component before id_card
|
|
350
362
|
const countrySelectionComponent: TemplateComponent = {
|
|
@@ -372,14 +384,14 @@ export function transformBackendTemplateToSDK(
|
|
|
372
384
|
required: true,
|
|
373
385
|
} as CountrySelectionConfig,
|
|
374
386
|
};
|
|
375
|
-
|
|
387
|
+
|
|
376
388
|
// Insert country_selection before id_card in transformedComponents
|
|
377
389
|
const idCardIndex = transformedComponents.indexOf(transformedIdCard);
|
|
378
390
|
transformedComponents.splice(idCardIndex, 0, countrySelectionComponent);
|
|
379
391
|
}
|
|
380
392
|
}
|
|
381
393
|
}
|
|
382
|
-
|
|
394
|
+
|
|
383
395
|
// Re-assign order values sequentially after insertion
|
|
384
396
|
transformedComponents.forEach((comp, index) => {
|
|
385
397
|
comp.order = index + 1;
|