@transfergratis/react-native-sdk 0.1.4 → 0.1.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/build/api/axios.d.ts +30 -0
- package/build/api/axios.d.ts.map +1 -0
- package/build/api/axios.js +92 -0
- package/build/api/axios.js.map +1 -0
- package/build/components/EnhancedCameraView.d.ts +1 -41
- package/build/components/EnhancedCameraView.d.ts.map +1 -1
- package/build/components/EnhancedCameraView.js +75 -34
- package/build/components/EnhancedCameraView.js.map +1 -1
- package/build/components/EnhancedCameraView.web.d.ts +1 -41
- package/build/components/EnhancedCameraView.web.d.ts.map +1 -1
- package/build/components/EnhancedCameraView.web.js +28 -4
- package/build/components/EnhancedCameraView.web.js.map +1 -1
- package/build/components/KYCElements/CountrySelectionTemplate.d.ts +2 -2
- package/build/components/KYCElements/CountrySelectionTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/CountrySelectionTemplate.js +77 -114
- package/build/components/KYCElements/CountrySelectionTemplate.js.map +1 -1
- package/build/components/KYCElements/FileUploadTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/FileUploadTemplate.js +7 -3
- package/build/components/KYCElements/FileUploadTemplate.js.map +1 -1
- package/build/components/KYCElements/IDCardCapture.d.ts +7 -2
- package/build/components/KYCElements/IDCardCapture.d.ts.map +1 -1
- package/build/components/KYCElements/IDCardCapture.js +253 -104
- package/build/components/KYCElements/IDCardCapture.js.map +1 -1
- package/build/components/KYCElements/InitializationStep.d.ts +5 -0
- package/build/components/KYCElements/InitializationStep.d.ts.map +1 -0
- package/build/components/KYCElements/InitializationStep.js +41 -0
- package/build/components/KYCElements/InitializationStep.js.map +1 -0
- package/build/components/KYCElements/LocationCaptureTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/LocationCaptureTemplate.js +15 -13
- package/build/components/KYCElements/LocationCaptureTemplate.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCapture.d.ts +2 -2
- package/build/components/KYCElements/OrientationVideoCapture.d.ts.map +1 -1
- package/build/components/KYCElements/OrientationVideoCapture.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.d.ts +2 -2
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.d.ts.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureFinal.d.ts +2 -2
- package/build/components/KYCElements/OrientationVideoCaptureFinal.d.ts.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureFinal.js.map +1 -1
- package/build/components/KYCElements/ReviewSubmitTemplate.d.ts +12 -0
- package/build/components/KYCElements/ReviewSubmitTemplate.d.ts.map +1 -0
- package/build/components/KYCElements/ReviewSubmitTemplate.js +171 -0
- package/build/components/KYCElements/ReviewSubmitTemplate.js.map +1 -0
- package/build/components/KYCElements/SelfieCaptureTemplate.d.ts +6 -2
- package/build/components/KYCElements/SelfieCaptureTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/SelfieCaptureTemplate.js +137 -38
- package/build/components/KYCElements/SelfieCaptureTemplate.js.map +1 -1
- package/build/components/KYCElements/VerificationProgressTemplate.d.ts +12 -0
- package/build/components/KYCElements/VerificationProgressTemplate.d.ts.map +1 -0
- package/build/components/KYCElements/VerificationProgressTemplate.js +194 -0
- package/build/components/KYCElements/VerificationProgressTemplate.js.map +1 -0
- package/build/components/OverLay/IdCard.d.ts +1 -1
- package/build/components/OverLay/IdCard.d.ts.map +1 -1
- package/build/components/OverLay/IdCard.js +10 -6
- package/build/components/OverLay/IdCard.js.map +1 -1
- package/build/components/OverLay/SelfieOverlay.d.ts +1 -1
- package/build/components/OverLay/SelfieOverlay.d.ts.map +1 -1
- package/build/components/OverLay/SelfieOverlay.js +5 -4
- package/build/components/OverLay/SelfieOverlay.js.map +1 -1
- package/build/components/OverLay/type.d.ts +71 -1
- 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 +4 -1
- package/build/components/TemplateKYCExample.d.ts.map +1 -1
- package/build/components/TemplateKYCExample.js +74 -199
- package/build/components/TemplateKYCExample.js.map +1 -1
- package/build/components/TemplateKYCFlowRefactored.d.ts +3 -2
- package/build/components/TemplateKYCFlowRefactored.d.ts.map +1 -1
- package/build/components/TemplateKYCFlowRefactored.js +64 -40
- package/build/components/TemplateKYCFlowRefactored.js.map +1 -1
- package/build/components/example/OrientationVideoExample.d.ts.map +1 -1
- package/build/components/example/OrientationVideoExample.js +1 -5
- package/build/components/example/OrientationVideoExample.js.map +1 -1
- package/build/config/countriesData.d.ts +3 -0
- package/build/config/countriesData.d.ts.map +1 -0
- package/build/config/countriesData.js +79 -0
- package/build/config/countriesData.js.map +1 -0
- package/build/config/region_mapping.d.ts +3 -0
- package/build/config/region_mapping.d.ts.map +1 -0
- package/build/config/region_mapping.js +687 -0
- package/build/config/region_mapping.js.map +1 -0
- package/build/hooks/useI18n.d.ts +11 -0
- package/build/hooks/useI18n.d.ts.map +1 -0
- package/build/hooks/useI18n.js +37 -0
- package/build/hooks/useI18n.js.map +1 -0
- package/build/hooks/useOrientationVideo.d.ts +1 -2
- package/build/hooks/useOrientationVideo.d.ts.map +1 -1
- package/build/hooks/useOrientationVideo.js +2 -1
- package/build/hooks/useOrientationVideo.js.map +1 -1
- package/build/hooks/useRealtimeVerifier.d.ts +28 -0
- package/build/hooks/useRealtimeVerifier.d.ts.map +1 -0
- package/build/hooks/useRealtimeVerifier.js +91 -0
- package/build/hooks/useRealtimeVerifier.js.map +1 -0
- package/build/hooks/useTemplateKYCFlow.d.ts +6 -3
- package/build/hooks/useTemplateKYCFlow.d.ts.map +1 -1
- package/build/hooks/useTemplateKYCFlow.js +356 -42
- package/build/hooks/useTemplateKYCFlow.js.map +1 -1
- package/build/i18n/en/index.d.ts +168 -0
- package/build/i18n/en/index.d.ts.map +1 -0
- package/build/i18n/en/index.js +195 -0
- package/build/i18n/en/index.js.map +1 -0
- package/build/i18n/fr/index.d.ts +168 -0
- package/build/i18n/fr/index.d.ts.map +1 -0
- package/build/i18n/fr/index.js +194 -0
- package/build/i18n/fr/index.js.map +1 -0
- package/build/i18n/index.d.ts +10 -0
- package/build/i18n/index.d.ts.map +1 -0
- package/build/i18n/index.js +56 -0
- package/build/i18n/index.js.map +1 -0
- package/build/i18n/types.d.ts +153 -0
- package/build/i18n/types.d.ts.map +1 -0
- package/build/i18n/types.js +3 -0
- package/build/i18n/types.js.map +1 -0
- package/build/i18n/usage-example.d.ts +4 -0
- package/build/i18n/usage-example.d.ts.map +1 -0
- package/build/i18n/usage-example.js +189 -0
- package/build/i18n/usage-example.js.map +1 -0
- 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 +22 -0
- package/build/modules/api/CardAuthentification.d.ts.map +1 -0
- package/build/modules/api/CardAuthentification.js +107 -0
- package/build/modules/api/CardAuthentification.js.map +1 -0
- package/build/modules/api/KYCService.d.ts +58 -1
- package/build/modules/api/KYCService.d.ts.map +1 -1
- package/build/modules/api/KYCService.js +304 -27
- package/build/modules/api/KYCService.js.map +1 -1
- package/build/modules/api/SelfieVerification.d.ts +3 -0
- package/build/modules/api/SelfieVerification.d.ts.map +1 -0
- package/build/modules/api/SelfieVerification.js +9 -0
- package/build/modules/api/SelfieVerification.js.map +1 -0
- package/build/modules/api/backendApi.d.ts +2 -0
- package/build/modules/api/backendApi.d.ts.map +1 -0
- package/build/modules/api/backendApi.js +6 -0
- package/build/modules/api/backendApi.js.map +1 -0
- package/build/modules/api/types.d.ts +45 -0
- package/build/modules/api/types.d.ts.map +1 -0
- package/build/modules/api/types.js +2 -0
- package/build/modules/api/types.js.map +1 -0
- package/build/types/KYC.types.d.ts +56 -7
- package/build/types/KYC.types.d.ts.map +1 -1
- package/build/types/KYC.types.js +9 -1
- package/build/types/KYC.types.js.map +1 -1
- package/build/utils/cropByObb.d.ts +11 -0
- package/build/utils/cropByObb.d.ts.map +1 -0
- package/build/utils/cropByObb.js +78 -0
- package/build/utils/cropByObb.js.map +1 -0
- package/build/utils/get-document-type-info.d.ts +13 -0
- package/build/utils/get-document-type-info.d.ts.map +1 -0
- package/build/utils/get-document-type-info.js +59 -0
- package/build/utils/get-document-type-info.js.map +1 -0
- package/build/utils/pathToBase64.d.ts +3 -0
- package/build/utils/pathToBase64.d.ts.map +1 -0
- package/build/utils/pathToBase64.js +47 -0
- package/build/utils/pathToBase64.js.map +1 -0
- package/build/utils/remove-duplicate.d.ts +2 -0
- package/build/utils/remove-duplicate.d.ts.map +1 -0
- package/build/utils/remove-duplicate.js +4 -0
- package/build/utils/remove-duplicate.js.map +1 -0
- package/build/web/WebKYCEntry.d.ts +9 -0
- package/build/web/WebKYCEntry.d.ts.map +1 -0
- package/build/web/WebKYCEntry.js +156 -0
- package/build/web/WebKYCEntry.js.map +1 -0
- package/build/web/index.d.ts +2 -0
- package/build/web/index.d.ts.map +1 -0
- package/build/web/index.js +2 -0
- package/build/web/index.js.map +1 -0
- package/package.json +3 -1
- package/src/api/axios.ts +144 -0
- package/src/components/EnhancedCameraView.tsx +96 -78
- package/src/components/EnhancedCameraView.web.tsx +41 -40
- package/src/components/KYCElements/CountrySelectionTemplate.tsx +111 -136
- package/src/components/KYCElements/FileUploadTemplate.tsx +14 -8
- package/src/components/KYCElements/IDCardCapture.tsx +311 -115
- package/src/components/KYCElements/InitializationStep.tsx +53 -0
- package/src/components/KYCElements/LocationCaptureTemplate.tsx +17 -15
- package/src/components/KYCElements/OrientationVideoCapture.tsx +2 -2
- package/src/components/KYCElements/OrientationVideoCaptureEnhanced.tsx +2 -2
- package/src/components/KYCElements/OrientationVideoCaptureFinal.tsx +2 -2
- package/src/components/KYCElements/ReviewSubmitTemplate.tsx +201 -0
- package/src/components/KYCElements/SelfieCaptureTemplate.tsx +174 -57
- package/src/components/KYCElements/VerificationProgressTemplate.tsx +246 -0
- package/src/components/OverLay/IdCard.tsx +17 -9
- package/src/components/OverLay/SelfieOverlay.tsx +6 -5
- package/src/components/OverLay/type.ts +64 -2
- package/src/components/TemplateKYCExample.tsx +80 -200
- package/src/components/TemplateKYCFlowRefactored.tsx +80 -48
- package/src/components/example/OrientationVideoExample.tsx +3 -7
- package/src/config/countriesData.ts +84 -0
- package/src/config/region_mapping.ts +688 -0
- package/src/hooks/useI18n.ts +53 -0
- package/src/hooks/useOrientationVideo.ts +2 -2
- package/src/hooks/useRealtimeVerifier.ts +128 -0
- package/src/hooks/useTemplateKYCFlow.tsx +407 -57
- package/src/i18n/README.md +288 -0
- package/src/i18n/en/index.ts +206 -0
- package/src/i18n/fr/index.ts +205 -0
- package/src/i18n/index.ts +65 -0
- package/src/i18n/types.ts +172 -0
- package/src/i18n/usage-example.tsx +202 -0
- package/src/index.ts +3 -0
- package/src/modules/api/CardAuthentification.ts +114 -0
- package/src/modules/api/KYCService.ts +350 -30
- package/src/modules/api/SelfieVerification.ts +11 -0
- package/src/modules/api/backendApi.ts +8 -0
- package/src/modules/api/types.ts +51 -0
- package/src/types/KYC.types.ts +82 -14
- package/src/utils/cropByObb.ts +99 -0
- package/src/utils/get-document-type-info.ts +62 -0
- package/src/utils/pathToBase64.ts +47 -0
- package/src/utils/remove-duplicate.ts +3 -0
- package/src/web/WebKYCEntry.tsx +215 -0
- package/src/web/index.ts +1 -0
- package/src/types/nativewind.d.ts +0 -2
package/src/types/KYC.types.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { VerificationResult } from "../modules/api/types";
|
|
2
|
+
|
|
1
3
|
// Types pour les documents
|
|
2
4
|
export interface Document {
|
|
3
5
|
id: string;
|
|
@@ -111,6 +113,8 @@ export type KYCElementType =
|
|
|
111
113
|
| 'selfie_capture'
|
|
112
114
|
| 'verification'
|
|
113
115
|
| 'completion';
|
|
116
|
+
//KYCElementType shorted
|
|
117
|
+
|
|
114
118
|
|
|
115
119
|
// Configuration d'un élément KYC
|
|
116
120
|
export interface KYCElement {
|
|
@@ -306,7 +310,7 @@ export interface LocalizedText {
|
|
|
306
310
|
export interface ComponentUI {
|
|
307
311
|
icon?: string;
|
|
308
312
|
themeColor?: string;
|
|
309
|
-
buttonText: LocalizedText
|
|
313
|
+
buttonText: LocalizedText | Record<string, LocalizedText>;
|
|
310
314
|
backgroundColor?: string;
|
|
311
315
|
textColor?: string;
|
|
312
316
|
borderRadius?: number;
|
|
@@ -314,16 +318,23 @@ export interface ComponentUI {
|
|
|
314
318
|
|
|
315
319
|
// Types de documents gouvernementaux supportés
|
|
316
320
|
export type GovernmentDocumentType =
|
|
317
|
-
| '
|
|
321
|
+
| 'identity_card'
|
|
318
322
|
| 'passport'
|
|
319
|
-
| '
|
|
320
|
-
| '
|
|
323
|
+
| 'drivers_licence'
|
|
324
|
+
| 'health_insurance_card'
|
|
325
|
+
| 'permanent_residence'
|
|
321
326
|
| 'national_id'
|
|
322
|
-
| 'voter_id'
|
|
323
|
-
| 'military_id'
|
|
324
|
-
| 'student_id'
|
|
325
327
|
| 'work_permit'
|
|
326
|
-
|
|
328
|
+
|
|
329
|
+
export const GovernmentDocumentTypeShorted: Record<GovernmentDocumentType, string> = {
|
|
330
|
+
identity_card: 'id',
|
|
331
|
+
passport: 'pp',
|
|
332
|
+
drivers_licence: 'dl',
|
|
333
|
+
health_insurance_card: 'hic',
|
|
334
|
+
permanent_residence: 'pr',
|
|
335
|
+
national_id: 'id',
|
|
336
|
+
work_permit: 'wp',
|
|
337
|
+
}
|
|
327
338
|
|
|
328
339
|
// Configuration spécifique pour chaque type de composant
|
|
329
340
|
export interface IDCardConfig {
|
|
@@ -346,7 +357,7 @@ export interface IDCardConfig {
|
|
|
346
357
|
export interface SelfieConfig {
|
|
347
358
|
liveness_check: boolean;
|
|
348
359
|
max_attempts: number;
|
|
349
|
-
orientations: ('
|
|
360
|
+
orientations: ('center' | 'left' | 'right')[]; // Tableau d'orientations à capturer
|
|
350
361
|
}
|
|
351
362
|
|
|
352
363
|
export interface FileUploadConfig {
|
|
@@ -377,12 +388,12 @@ export type ComponentConfig =
|
|
|
377
388
|
// Nouveau type de composant basé sur le template JSON
|
|
378
389
|
export interface TemplateComponent {
|
|
379
390
|
id: number;
|
|
380
|
-
type: 'id_card' | 'selfie' | 'file_upload' | 'location' | 'country_selection';
|
|
391
|
+
type: 'id_card' | 'selfie' | 'file_upload' | 'location' | 'country_selection' | 'initialization' | 'review_submit' | 'verification_progress';
|
|
381
392
|
order: number;
|
|
382
393
|
templateId?: number;
|
|
383
|
-
labels: LocalizedText
|
|
384
|
-
instructions: LocalizedText
|
|
385
|
-
ui: ComponentUI
|
|
394
|
+
labels: LocalizedText | Record<string, LocalizedText>;
|
|
395
|
+
instructions: LocalizedText | Record<string, LocalizedText>;
|
|
396
|
+
ui: ComponentUI | Record<string, ComponentUI>;
|
|
386
397
|
config: ComponentConfig;
|
|
387
398
|
}
|
|
388
399
|
|
|
@@ -405,6 +416,25 @@ export interface TemplateState {
|
|
|
405
416
|
isProcessing: boolean;
|
|
406
417
|
currentLanguage: string;
|
|
407
418
|
showCustomStepper: boolean;
|
|
419
|
+
session: SessionState;
|
|
420
|
+
verification: VerificationState;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
export interface SessionState {
|
|
424
|
+
session_id: string;
|
|
425
|
+
token: string;
|
|
426
|
+
isInitialized: boolean;
|
|
427
|
+
isProcessing: boolean;
|
|
428
|
+
error: string | null;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
export type VerificationStatus = 'idle' | 'in_progress' | 'success' | 'failed';
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
export interface VerificationState {
|
|
436
|
+
status: VerificationStatus;
|
|
437
|
+
result?: VerificationResult;
|
|
408
438
|
}
|
|
409
439
|
|
|
410
440
|
// Actions pour le template KYC
|
|
@@ -419,6 +449,8 @@ export interface TemplateActions {
|
|
|
419
449
|
resetTemplate: () => void;
|
|
420
450
|
setLanguage: (language: string) => void;
|
|
421
451
|
showCustomStepper: (show: boolean) => void;
|
|
452
|
+
setVerificationState: (state: VerificationState) => void;
|
|
453
|
+
submitVerification: () => Promise<void>;
|
|
422
454
|
}
|
|
423
455
|
|
|
424
456
|
// Hook pour le template KYC
|
|
@@ -431,4 +463,40 @@ export interface UseTemplateReturn {
|
|
|
431
463
|
canGoPrevious: boolean;
|
|
432
464
|
isComplete: boolean;
|
|
433
465
|
getLocalizedText: (text: LocalizedText) => string;
|
|
434
|
-
|
|
466
|
+
initializeSession: () => Promise<void>;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
export interface ISilentCaptureResult {
|
|
471
|
+
success: boolean;
|
|
472
|
+
path?: string;
|
|
473
|
+
mrz?: string;
|
|
474
|
+
error?: string;
|
|
475
|
+
isAnalyzing?: boolean;
|
|
476
|
+
bbox?: IBbox;
|
|
477
|
+
country?: string;
|
|
478
|
+
documentType?: string;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
export interface IBbox {
|
|
482
|
+
minX: number;
|
|
483
|
+
minY: number;
|
|
484
|
+
width: number;
|
|
485
|
+
height: number;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
export interface ICountryMapping {
|
|
489
|
+
py_file?: string;
|
|
490
|
+
front?: string;
|
|
491
|
+
back?: string;
|
|
492
|
+
keys_found?: string | null;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
export interface Country {
|
|
496
|
+
code?: string; // ISO 3166-1 alpha-2
|
|
497
|
+
name: string;
|
|
498
|
+
name_en: string;
|
|
499
|
+
flag: string;
|
|
500
|
+
regionMapping?: ICountryMapping;
|
|
501
|
+
hasRegions?: boolean;
|
|
502
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Image as RNImage, Platform } from 'react-native';
|
|
2
|
+
import * as ImageManipulator from "expo-image-manipulator";
|
|
3
|
+
|
|
4
|
+
type Point = [number, number];
|
|
5
|
+
|
|
6
|
+
// Compute axis-aligned bounding box from oriented quadrilateral
|
|
7
|
+
function computeAabb(points: Point[]) {
|
|
8
|
+
const xs = points.map(p => p[0]);
|
|
9
|
+
const ys = points.map(p => p[1]);
|
|
10
|
+
const minX = Math.min(...xs);
|
|
11
|
+
const minY = Math.min(...ys);
|
|
12
|
+
const maxX = Math.max(...xs);
|
|
13
|
+
const maxY = Math.max(...ys);
|
|
14
|
+
return { minX, minY, maxX, maxY, width: maxX - minX, height: maxY - minY };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Web-only crop using Canvas; returns dataURL (base64)
|
|
18
|
+
async function cropWeb(uri: string, points: Point[]): Promise<string> {
|
|
19
|
+
return new Promise((resolve, reject) => {
|
|
20
|
+
const img = new Image();
|
|
21
|
+
img.crossOrigin = 'anonymous';
|
|
22
|
+
img.onload = () => {
|
|
23
|
+
const { minX, minY, width, height } = computeAabb(points);
|
|
24
|
+
const canvas = document.createElement('canvas');
|
|
25
|
+
canvas.width = Math.max(1, Math.round(width));
|
|
26
|
+
canvas.height = Math.max(1, Math.round(height));
|
|
27
|
+
const ctx = canvas.getContext('2d');
|
|
28
|
+
if (!ctx) return reject(new Error('Canvas context not available'));
|
|
29
|
+
ctx.drawImage(
|
|
30
|
+
img,
|
|
31
|
+
minX, // sx
|
|
32
|
+
minY, // sy
|
|
33
|
+
width, // sw
|
|
34
|
+
height, // sh
|
|
35
|
+
0,
|
|
36
|
+
0,
|
|
37
|
+
canvas.width,
|
|
38
|
+
canvas.height
|
|
39
|
+
);
|
|
40
|
+
resolve(canvas.toDataURL('image/jpeg', 0.92));
|
|
41
|
+
};
|
|
42
|
+
img.onerror = (e) => reject(e);
|
|
43
|
+
img.src = uri;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Fallback: return original for native (no dependency added); caller can still use bbox to draw overlay
|
|
48
|
+
export async function cropByObb(uri: string, cardObb: any): Promise<{ base64?: string; bbox?: { minX: number; minY: number; width: number; height: number } }> {
|
|
49
|
+
try {
|
|
50
|
+
// card_obb format: [ [ [p1,p2,p3,p4], score ] ]
|
|
51
|
+
const first = Array.isArray(cardObb) ? cardObb[0] : null;
|
|
52
|
+
const points = Array.isArray(first?.[0]) ? (first[0] as Point[]) : null;
|
|
53
|
+
if (!points || points.length !== 4) return {};
|
|
54
|
+
|
|
55
|
+
const { minX, minY, width, height } = computeAabb(points);
|
|
56
|
+
|
|
57
|
+
if (Platform.OS === 'web') {
|
|
58
|
+
const base64 = await cropWeb(uri, points);
|
|
59
|
+
return { base64, bbox: { minX, minY, width, height } };
|
|
60
|
+
}
|
|
61
|
+
// Native: return bbox only; keep base64 undefined
|
|
62
|
+
return { bbox: { minX, minY, width, height } };
|
|
63
|
+
} catch (e) {
|
|
64
|
+
return {};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
// exemple d'appel :
|
|
72
|
+
export async function cropImageWithBBox(uri: string, bbox: any) {
|
|
73
|
+
// 1️⃣ Récupère la taille originale de l'image
|
|
74
|
+
await RNImage.getSize(uri, (width, height) => {
|
|
75
|
+
console.log("Image originale:", width, height);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// // 2️⃣ Suppose que ton bbox vient d'une image affichée dans `displayedSize`
|
|
79
|
+
// const scaleX = originalWidth / displayedSize.width;
|
|
80
|
+
// const scaleY = originalHeight / displayedSize.height;
|
|
81
|
+
|
|
82
|
+
// 3️⃣ Convertir le bbox à la taille réelle scale 0.10 = 10%
|
|
83
|
+
const crop = {
|
|
84
|
+
originX: bbox.minX ,
|
|
85
|
+
originY: bbox.minY - 80,
|
|
86
|
+
width: bbox.width + 100,
|
|
87
|
+
height: bbox.height + 150,
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// 4️⃣ Appliquer le crop
|
|
91
|
+
const result = await ImageManipulator.manipulateAsync(
|
|
92
|
+
uri,
|
|
93
|
+
[{ crop }],
|
|
94
|
+
{ compress: 1, format: ImageManipulator.SaveFormat.PNG }
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
console.log("Image recadrée:", result.uri);
|
|
98
|
+
return result.uri;
|
|
99
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { GovernmentDocumentType } from "../types/KYC.types";
|
|
2
|
+
|
|
3
|
+
export const getDocumentTypeInfo = (docType: GovernmentDocumentType) => {
|
|
4
|
+
switch (docType) {
|
|
5
|
+
case 'identity_card':
|
|
6
|
+
return {
|
|
7
|
+
name: { en: 'ID Card', fr: 'Carte d\'identité' },
|
|
8
|
+
icon: '🆔',
|
|
9
|
+
instructions: { en: 'Position your ID card within the frame', fr: 'Positionnez votre carte d\'identité dans le cadre' }
|
|
10
|
+
};
|
|
11
|
+
case 'passport':
|
|
12
|
+
return {
|
|
13
|
+
name: { en: 'Passport', fr: 'Passeport' },
|
|
14
|
+
icon: '📘',
|
|
15
|
+
instructions: { en: 'Position your passport within the frame', fr: 'Positionnez votre passeport dans le cadre' }
|
|
16
|
+
};
|
|
17
|
+
case 'drivers_licence':
|
|
18
|
+
return {
|
|
19
|
+
name: { en: 'Driver\'s License', fr: 'Permis de conduire' },
|
|
20
|
+
icon: '🚗',
|
|
21
|
+
instructions: { en: 'Position your driver\'s license within the frame', fr: 'Positionnez votre permis de conduire dans le cadre' }
|
|
22
|
+
};
|
|
23
|
+
case 'permanent_residence':
|
|
24
|
+
return {
|
|
25
|
+
name: { en: 'Residence Permit', fr: 'Permis de séjour' },
|
|
26
|
+
icon: '🏠',
|
|
27
|
+
instructions: { en: 'Position your residence permit within the frame', fr: 'Positionnez votre permis de séjour dans le cadre' }
|
|
28
|
+
};
|
|
29
|
+
case 'national_id':
|
|
30
|
+
return {
|
|
31
|
+
name: { en: 'National ID', fr: 'Carte nationale d\'identité' },
|
|
32
|
+
icon: '🏛️',
|
|
33
|
+
instructions: { en: 'Position your national ID within the frame', fr: 'Positionnez votre carte nationale d\'identité dans le cadre' }
|
|
34
|
+
};
|
|
35
|
+
case 'health_insurance_card':
|
|
36
|
+
return {
|
|
37
|
+
name: { en: 'Health Insurance Card', fr: 'Carte d\'assurance santé' },
|
|
38
|
+
icon: '🗳️',
|
|
39
|
+
instructions: { en: 'Position your health insurance card within the frame', fr: 'Positionnez votre carte d\'assurance santé dans le cadre' }
|
|
40
|
+
};
|
|
41
|
+
case 'work_permit':
|
|
42
|
+
return {
|
|
43
|
+
name: { en: 'Work Permit', fr: 'Permis de travail' },
|
|
44
|
+
icon: '🎖️',
|
|
45
|
+
instructions: { en: 'Position your work permit within the frame', fr: 'Positionnez votre permis de travail dans le cadre' }
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
case 'passport':
|
|
49
|
+
return {
|
|
50
|
+
name: { en: 'Passport', fr: 'Passeport' },
|
|
51
|
+
icon: '💼',
|
|
52
|
+
instructions: { en: 'Position your passport within the frame', fr: 'Positionnez votre passeport dans le cadre' }
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
default:
|
|
56
|
+
return {
|
|
57
|
+
name: { en: 'Government Document', fr: 'Document gouvernemental' },
|
|
58
|
+
icon: '📄',
|
|
59
|
+
instructions: { en: 'Position your document within the frame', fr: 'Positionnez votre document dans le cadre' }
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export async function pathToBase64(uri: string): Promise<string> {
|
|
2
|
+
if (!uri) throw new Error('pathToBase64: uri is required');
|
|
3
|
+
|
|
4
|
+
// If already a data URI, return the base64 part
|
|
5
|
+
if (uri.startsWith('data:')) {
|
|
6
|
+
const commaIndex = uri.indexOf(',');
|
|
7
|
+
return commaIndex !== -1 ? uri.substring(commaIndex + 1) : uri;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Try Expo FileSystem if available (React Native + Expo)
|
|
11
|
+
try {
|
|
12
|
+
// Dynamically import to avoid hard dependency when not available
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
14
|
+
const FileSystem = require('expo-file-system');
|
|
15
|
+
if (FileSystem?.readAsStringAsync) {
|
|
16
|
+
const base64 = await FileSystem.readAsStringAsync(uri, { encoding: FileSystem.EncodingType.Base64 });
|
|
17
|
+
if (base64) return base64;
|
|
18
|
+
}
|
|
19
|
+
} catch (_) {
|
|
20
|
+
// ignore - fall back to other strategies
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Generic fetch + FileReader strategy (works on web; often works on RN for file:// URIs)
|
|
24
|
+
try {
|
|
25
|
+
const response = await fetch(uri);
|
|
26
|
+
const blob = await response.blob();
|
|
27
|
+
const dataUrl = await new Promise<string>((resolve, reject) => {
|
|
28
|
+
const reader = new FileReader();
|
|
29
|
+
reader.onloadend = () => {
|
|
30
|
+
if (typeof reader.result === 'string') resolve(reader.result);
|
|
31
|
+
else reject(new Error('Failed to convert blob to data URL'));
|
|
32
|
+
};
|
|
33
|
+
reader.onerror = reject;
|
|
34
|
+
reader.readAsDataURL(blob);
|
|
35
|
+
});
|
|
36
|
+
const commaIndex = dataUrl.indexOf(',');
|
|
37
|
+
return commaIndex !== -1 ? dataUrl.substring(commaIndex + 1) : dataUrl;
|
|
38
|
+
} catch (err) {
|
|
39
|
+
// continue to final error
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
throw new Error('pathToBase64: unable to convert uri to base64');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export default pathToBase64;
|
|
46
|
+
|
|
47
|
+
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import React, { useEffect, useState, useCallback } from 'react';
|
|
2
|
+
import { View, Text, StyleSheet, SafeAreaView } from 'react-native';
|
|
3
|
+
// import { TemplateKYCFlow } from '../components/TemplateKYCFlowRefactored';
|
|
4
|
+
// import { KYCTemplate } from '../types/KYC.types';
|
|
5
|
+
import { useI18n } from '../hooks/useI18n';
|
|
6
|
+
import { TemplateKYCExample } from '../components/TemplateKYCExample';
|
|
7
|
+
|
|
8
|
+
interface WebKYCEntryProps {
|
|
9
|
+
onComplete?: (data: any) => void;
|
|
10
|
+
onError?: (error: string) => void;
|
|
11
|
+
onCancel?: () => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface URLParams {
|
|
15
|
+
token?: string;
|
|
16
|
+
return_url?: string;
|
|
17
|
+
lang?: string;
|
|
18
|
+
theme?: string;
|
|
19
|
+
kyc_id?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const WebKYCEntry: React.FC<WebKYCEntryProps> = ({
|
|
23
|
+
onComplete,
|
|
24
|
+
onError,
|
|
25
|
+
onCancel,
|
|
26
|
+
}) => {
|
|
27
|
+
const { setLocale } = useI18n();
|
|
28
|
+
const [urlParams, setUrlParams] = useState<URLParams>({});
|
|
29
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
30
|
+
const [error, setError] = useState<string | null>(null);
|
|
31
|
+
|
|
32
|
+
// Parse URL parameters
|
|
33
|
+
const parseUrlParams = useCallback((): URLParams => {
|
|
34
|
+
if (typeof window === 'undefined') return {};
|
|
35
|
+
|
|
36
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
37
|
+
return {
|
|
38
|
+
token: urlParams.get('token') || undefined,
|
|
39
|
+
return_url: urlParams.get('return_url') || undefined,
|
|
40
|
+
lang: urlParams.get('lang') || 'en',
|
|
41
|
+
theme: urlParams.get('theme') || 'light',
|
|
42
|
+
kyc_id: urlParams.get('kyc_id') || undefined,
|
|
43
|
+
};
|
|
44
|
+
}, []);
|
|
45
|
+
|
|
46
|
+
// Safe redirect function with validation
|
|
47
|
+
const redirectToReturnUrl = useCallback((params: {
|
|
48
|
+
status: 'completed' | 'cancelled' | 'error';
|
|
49
|
+
kyc_id?: string;
|
|
50
|
+
message?: string;
|
|
51
|
+
sig?: string;
|
|
52
|
+
}) => {
|
|
53
|
+
const { return_url } = urlParams;
|
|
54
|
+
|
|
55
|
+
if (!return_url) {
|
|
56
|
+
console.warn('No return_url provided');
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Basic URL validation - ensure it's a valid URL
|
|
61
|
+
try {
|
|
62
|
+
const returnUrl = new URL(return_url);
|
|
63
|
+
|
|
64
|
+
// Optional: Add domain allowlist validation here
|
|
65
|
+
// const allowedDomains = ['example.com', 'trusted-site.com'];
|
|
66
|
+
// if (!allowedDomains.some(domain => returnUrl.hostname.endsWith(domain))) {
|
|
67
|
+
// console.error('Return URL not in allowlist');
|
|
68
|
+
// return;
|
|
69
|
+
// }
|
|
70
|
+
|
|
71
|
+
// Build redirect URL with parameters
|
|
72
|
+
const redirectUrl = new URL(returnUrl);
|
|
73
|
+
redirectUrl.searchParams.set('status', params.status);
|
|
74
|
+
|
|
75
|
+
if (params.kyc_id) {
|
|
76
|
+
redirectUrl.searchParams.set('kyc_id', params.kyc_id);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (params.message) {
|
|
80
|
+
redirectUrl.searchParams.set('message', params.message);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (params.sig) {
|
|
84
|
+
redirectUrl.searchParams.set('sig', params.sig);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Optional: Send postMessage to parent if in iframe
|
|
88
|
+
if (window.parent !== window) {
|
|
89
|
+
window.parent.postMessage({
|
|
90
|
+
type: 'kyc_result',
|
|
91
|
+
status: params.status,
|
|
92
|
+
kyc_id: params.kyc_id,
|
|
93
|
+
message: params.message,
|
|
94
|
+
}, '*');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Redirect to return URL
|
|
98
|
+
window.location.href = redirectUrl.toString();
|
|
99
|
+
} catch (error) {
|
|
100
|
+
console.error('Invalid return URL:', error);
|
|
101
|
+
setError('Invalid return URL provided');
|
|
102
|
+
}
|
|
103
|
+
}, [urlParams]);
|
|
104
|
+
|
|
105
|
+
// Handle KYC completion
|
|
106
|
+
const handleComplete = useCallback((data: any) => {
|
|
107
|
+
console.log('KYC completed:', data);
|
|
108
|
+
redirectToReturnUrl({
|
|
109
|
+
status: 'completed',
|
|
110
|
+
kyc_id: data.session_id || urlParams.kyc_id,
|
|
111
|
+
message: 'KYC process completed successfully',
|
|
112
|
+
});
|
|
113
|
+
onComplete?.(data);
|
|
114
|
+
}, [redirectToReturnUrl, urlParams.kyc_id, onComplete]);
|
|
115
|
+
|
|
116
|
+
// Handle KYC error
|
|
117
|
+
const handleError = useCallback((error: string) => {
|
|
118
|
+
console.error('KYC error:', error);
|
|
119
|
+
redirectToReturnUrl({
|
|
120
|
+
status: 'error',
|
|
121
|
+
kyc_id: urlParams.kyc_id,
|
|
122
|
+
message: error,
|
|
123
|
+
});
|
|
124
|
+
onError?.(error);
|
|
125
|
+
}, [redirectToReturnUrl, urlParams.kyc_id, onError]);
|
|
126
|
+
|
|
127
|
+
// Handle KYC cancellation
|
|
128
|
+
const handleCancel = useCallback(() => {
|
|
129
|
+
console.log('KYC cancelled');
|
|
130
|
+
redirectToReturnUrl({
|
|
131
|
+
status: 'cancelled',
|
|
132
|
+
kyc_id: urlParams.kyc_id,
|
|
133
|
+
message: 'KYC process was cancelled',
|
|
134
|
+
});
|
|
135
|
+
onCancel?.();
|
|
136
|
+
}, [redirectToReturnUrl, urlParams.kyc_id, onCancel]);
|
|
137
|
+
|
|
138
|
+
// Initialize component
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
try {
|
|
141
|
+
const params = parseUrlParams();
|
|
142
|
+
setUrlParams(params);
|
|
143
|
+
|
|
144
|
+
// Set language if provided
|
|
145
|
+
if (params.lang) {
|
|
146
|
+
setLocale(params.lang);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
setIsLoading(false);
|
|
150
|
+
} catch (error) {
|
|
151
|
+
console.error('Error parsing URL parameters:', error);
|
|
152
|
+
setError('Error parsing URL parameters');
|
|
153
|
+
setIsLoading(false);
|
|
154
|
+
}
|
|
155
|
+
}, [parseUrlParams, setLocale]);
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
if (isLoading) {
|
|
159
|
+
return (
|
|
160
|
+
<View style={styles.container}>
|
|
161
|
+
<Text style={styles.loadingText}>Loading KYC process...</Text>
|
|
162
|
+
</View>
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (error) {
|
|
167
|
+
return (
|
|
168
|
+
<View style={styles.container}>
|
|
169
|
+
<Text style={styles.errorText}>Error: {error}</Text>
|
|
170
|
+
</View>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (!urlParams.token) {
|
|
175
|
+
return (
|
|
176
|
+
<View style={styles.container}>
|
|
177
|
+
<Text style={styles.errorText}>No token provided in URL parameters</Text>
|
|
178
|
+
</View>
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return (
|
|
183
|
+
<SafeAreaView style={styles.container}>
|
|
184
|
+
<TemplateKYCExample
|
|
185
|
+
onComplete={handleComplete}
|
|
186
|
+
onCancel={handleCancel}
|
|
187
|
+
onError={handleError}
|
|
188
|
+
language={urlParams.lang || 'en'}
|
|
189
|
+
API_KEY={urlParams.token}
|
|
190
|
+
/>
|
|
191
|
+
</SafeAreaView>
|
|
192
|
+
);
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
const styles = StyleSheet.create({
|
|
196
|
+
container: {
|
|
197
|
+
flex: 1,
|
|
198
|
+
backgroundColor: '#f5f5f5',
|
|
199
|
+
},
|
|
200
|
+
loadingText: {
|
|
201
|
+
fontSize: 18,
|
|
202
|
+
textAlign: 'center',
|
|
203
|
+
marginTop: 50,
|
|
204
|
+
color: '#666',
|
|
205
|
+
},
|
|
206
|
+
errorText: {
|
|
207
|
+
fontSize: 16,
|
|
208
|
+
textAlign: 'center',
|
|
209
|
+
marginTop: 50,
|
|
210
|
+
color: '#dc2626',
|
|
211
|
+
paddingHorizontal: 20,
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
export default WebKYCEntry;
|
package/src/web/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as WebKYCEntry } from './WebKYCEntry';
|