@transfergratis/react-native-sdk 0.1.22 → 0.1.24
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/src/main/AndroidManifest.xml +9 -4
- package/build/components/EnhancedCameraView.d.ts.map +1 -1
- package/build/components/EnhancedCameraView.js +26 -3
- package/build/components/EnhancedCameraView.js.map +1 -1
- package/build/components/EnhancedCameraView.web.d.ts.map +1 -1
- package/build/components/EnhancedCameraView.web.js +21 -0
- package/build/components/EnhancedCameraView.web.js.map +1 -1
- package/build/components/KYCElements/CameraCapture.d.ts.map +1 -1
- package/build/components/KYCElements/CameraCapture.js +4 -3
- package/build/components/KYCElements/CameraCapture.js.map +1 -1
- package/build/components/KYCElements/CountrySelectionTemplate.d.ts +5 -2
- package/build/components/KYCElements/CountrySelectionTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/CountrySelectionTemplate.js +360 -101
- package/build/components/KYCElements/CountrySelectionTemplate.js.map +1 -1
- package/build/components/KYCElements/FileUpload.d.ts.map +1 -1
- package/build/components/KYCElements/FileUpload.js +5 -4
- package/build/components/KYCElements/FileUpload.js.map +1 -1
- package/build/components/KYCElements/FileUploadTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/FileUploadTemplate.js +5 -4
- package/build/components/KYCElements/FileUploadTemplate.js.map +1 -1
- package/build/components/KYCElements/IDCardCapture.d.ts.map +1 -1
- package/build/components/KYCElements/IDCardCapture.js +193 -237
- package/build/components/KYCElements/IDCardCapture.js.map +1 -1
- package/build/components/KYCElements/LocationCaptureTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/LocationCaptureTemplate.js +78 -37
- package/build/components/KYCElements/LocationCaptureTemplate.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCapture.js +3 -2
- package/build/components/KYCElements/OrientationVideoCapture.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js +3 -2
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureFinal.js +3 -2
- package/build/components/KYCElements/OrientationVideoCaptureFinal.js.map +1 -1
- package/build/components/KYCElements/SelfieCapture.d.ts.map +1 -1
- package/build/components/KYCElements/SelfieCapture.js +4 -3
- package/build/components/KYCElements/SelfieCapture.js.map +1 -1
- package/build/components/KYCElements/SelfieCaptureTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/SelfieCaptureTemplate.js +182 -39
- package/build/components/KYCElements/SelfieCaptureTemplate.js.map +1 -1
- package/build/components/KYCElements/WelcomeTemplate.d.ts +12 -0
- package/build/components/KYCElements/WelcomeTemplate.d.ts.map +1 -0
- package/build/components/KYCElements/WelcomeTemplate.js +243 -0
- package/build/components/KYCElements/WelcomeTemplate.js.map +1 -0
- package/build/components/TemplateKYCExample.d.ts +4 -2
- package/build/components/TemplateKYCExample.d.ts.map +1 -1
- package/build/components/TemplateKYCExample.js +5 -68
- package/build/components/TemplateKYCExample.js.map +1 -1
- package/build/components/TemplateKYCFlowRefactored.d.ts +2 -1
- package/build/components/TemplateKYCFlowRefactored.d.ts.map +1 -1
- package/build/components/TemplateKYCFlowRefactored.js +95 -9
- package/build/components/TemplateKYCFlowRefactored.js.map +1 -1
- package/build/components/example/DynamicTemplateExample.d.ts +10 -0
- package/build/components/example/DynamicTemplateExample.d.ts.map +1 -0
- package/build/components/example/DynamicTemplateExample.js +241 -0
- package/build/components/example/DynamicTemplateExample.js.map +1 -0
- package/build/config/allowedDomains.d.ts +30 -0
- package/build/config/allowedDomains.d.ts.map +1 -0
- package/build/config/allowedDomains.js +127 -0
- package/build/config/allowedDomains.js.map +1 -0
- package/build/hooks/useTemplateKYCFlow.d.ts.map +1 -1
- package/build/hooks/useTemplateKYCFlow.js +68 -43
- package/build/hooks/useTemplateKYCFlow.js.map +1 -1
- package/build/hooks/useTemplateLoader.d.ts +14 -0
- package/build/hooks/useTemplateLoader.d.ts.map +1 -0
- package/build/hooks/useTemplateLoader.js +85 -0
- package/build/hooks/useTemplateLoader.js.map +1 -0
- package/build/i18n/en/index.d.ts +9 -0
- package/build/i18n/en/index.d.ts.map +1 -1
- package/build/i18n/en/index.js +9 -0
- package/build/i18n/en/index.js.map +1 -1
- package/build/i18n/fr/index.d.ts +9 -0
- package/build/i18n/fr/index.d.ts.map +1 -1
- package/build/i18n/fr/index.js +9 -0
- package/build/i18n/fr/index.js.map +1 -1
- package/build/index.d.ts +5 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +8 -0
- package/build/index.js.map +1 -1
- package/build/modules/api/CardAuthentification.js +1 -0
- package/build/modules/api/CardAuthentification.js.map +1 -1
- package/build/modules/api/KYCService.d.ts +4 -1
- package/build/modules/api/KYCService.d.ts.map +1 -1
- package/build/modules/api/KYCService.js +17 -5
- package/build/modules/api/KYCService.js.map +1 -1
- package/build/modules/api/TemplateService.d.ts +45 -0
- package/build/modules/api/TemplateService.d.ts.map +1 -0
- package/build/modules/api/TemplateService.js +145 -0
- package/build/modules/api/TemplateService.js.map +1 -0
- package/build/modules/api/types.d.ts +1 -0
- package/build/modules/api/types.d.ts.map +1 -1
- package/build/modules/api/types.js.map +1 -1
- package/build/types/KYC.types.d.ts +144 -4
- package/build/types/KYC.types.d.ts.map +1 -1
- package/build/types/KYC.types.js +15 -0
- package/build/types/KYC.types.js.map +1 -1
- package/build/utils/cropByObb.d.ts +1 -0
- package/build/utils/cropByObb.d.ts.map +1 -1
- package/build/utils/cropByObb.js +70 -0
- package/build/utils/cropByObb.js.map +1 -1
- package/build/utils/platformAlert.d.ts +20 -0
- package/build/utils/platformAlert.d.ts.map +1 -0
- package/build/utils/platformAlert.js +67 -0
- package/build/utils/platformAlert.js.map +1 -0
- package/build/utils/template-transformer.d.ts +10 -0
- package/build/utils/template-transformer.d.ts.map +1 -0
- package/build/utils/template-transformer.js +353 -0
- package/build/utils/template-transformer.js.map +1 -0
- package/build/web/WebKYCEntry.d.ts.map +1 -1
- package/build/web/WebKYCEntry.js +102 -20
- package/build/web/WebKYCEntry.js.map +1 -1
- package/package.json +1 -1
- package/src/components/EnhancedCameraView.tsx +31 -2
- package/src/components/EnhancedCameraView.web.tsx +24 -0
- package/src/components/KYCElements/CameraCapture.tsx +4 -3
- package/src/components/KYCElements/CountrySelectionTemplate.tsx +410 -113
- package/src/components/KYCElements/FileUpload.tsx +5 -4
- package/src/components/KYCElements/FileUploadTemplate.tsx +5 -4
- package/src/components/KYCElements/IDCardCapture.tsx +196 -254
- package/src/components/KYCElements/LocationCaptureTemplate.tsx +95 -44
- 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/SelfieCapture.tsx +4 -3
- package/src/components/KYCElements/SelfieCaptureTemplate.tsx +195 -41
- package/src/components/KYCElements/WelcomeTemplate.tsx +289 -0
- package/src/components/TemplateKYCExample.tsx +16 -71
- package/src/components/TemplateKYCFlowRefactored.tsx +121 -11
- package/src/components/example/DynamicTemplateExample.tsx +289 -0
- package/src/config/allowedDomains.ts +152 -0
- package/src/hooks/useTemplateKYCFlow.tsx +71 -46
- package/src/hooks/useTemplateLoader.ts +102 -0
- package/src/i18n/en/index.ts +10 -0
- package/src/i18n/fr/index.ts +9 -0
- package/src/index.ts +11 -0
- package/src/modules/api/CardAuthentification.ts +1 -1
- package/src/modules/api/KYCService.ts +18 -8
- package/src/modules/api/TemplateService.ts +167 -0
- package/src/modules/api/types.ts +1 -0
- package/src/types/KYC.types.ts +188 -3
- package/src/utils/cropByObb.ts +83 -3
- package/src/utils/platformAlert.ts +85 -0
- package/src/utils/template-transformer.ts +433 -0
- package/src/web/WebKYCEntry.tsx +122 -24
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import { View, Text,
|
|
1
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { View, Text, StyleSheet, Image, ScrollView } from 'react-native';
|
|
3
|
+
import { showAlert } from '../../utils/platformAlert';
|
|
3
4
|
import { EnhancedCameraView } from '../EnhancedCameraView';
|
|
5
|
+
import { GovernmentDocumentTypeShorted, GovernmentDocumentTypeBackend } from '../../types/KYC.types';
|
|
4
6
|
import IdCardOverlay from '../OverLay/IdCard';
|
|
5
7
|
import { useTemplateKYCFlowContext } from '../../hooks/useTemplateKYCFlow';
|
|
6
8
|
import { useI18n } from '../../hooks/useI18n';
|
|
@@ -10,7 +12,7 @@ import { backVerification, checkTemplateType, frontVerification } from '../../mo
|
|
|
10
12
|
import { getDocumentTypeInfo } from '../../utils/get-document-type-info';
|
|
11
13
|
import pathToBase64 from '../../utils/pathToBase64';
|
|
12
14
|
import { truncateFields } from '../../modules/api/KYCService';
|
|
13
|
-
import { cropByObb, cropImageWithBBox } from '../../utils/cropByObb';
|
|
15
|
+
import { cropByObb, cropImageWithBBox, cropImageWithBBoxWithTolerance } from '../../utils/cropByObb';
|
|
14
16
|
import { logger } from '../../utils/logger';
|
|
15
17
|
export const IDCardCapture = ({ component, value = {}, onValueChange, error, language = 'en', }) => {
|
|
16
18
|
const { t, locale } = useI18n();
|
|
@@ -20,18 +22,17 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
20
22
|
const [currentSide, setCurrentSide] = useState('front');
|
|
21
23
|
// Stocker les bbox par côté pour pouvoir restaurer les images croppées
|
|
22
24
|
const [bboxBySide, setBboxBySide] = useState({});
|
|
23
|
-
const [selectedDocumentType, setSelectedDocumentType] = useState({
|
|
24
|
-
type: 'identity_card',
|
|
25
|
-
region: 'root'
|
|
26
|
-
});
|
|
27
|
-
const [showDocumentSelection, setShowDocumentSelection] = useState({
|
|
28
|
-
documentSelection: true,
|
|
29
|
-
regionSelection: false
|
|
30
|
-
});
|
|
31
25
|
const [silentCaptureResult, setSilentCaptureResult] = useState({ success: false, isAnalyzing: false });
|
|
26
|
+
// Mapping des types de documents backend vers SDK
|
|
27
|
+
const documentTypeMapping = {
|
|
28
|
+
'nationalId': 'national_id',
|
|
29
|
+
'passport': 'passport',
|
|
30
|
+
'driversLicense': 'drivers_licence',
|
|
31
|
+
'residencePermit': 'permanent_residence',
|
|
32
|
+
'healthInsuranceCard': 'health_insurance_card',
|
|
33
|
+
};
|
|
32
34
|
// const [imageNaturalSize, setImageNaturalSize] = useState<{ width: number; height: number } | null>(null);
|
|
33
|
-
const { actions, state
|
|
34
|
-
const config = component.config;
|
|
35
|
+
const { actions, state } = useTemplateKYCFlowContext();
|
|
35
36
|
const getLocalizedText = (text) => {
|
|
36
37
|
// console.log("text", text, JSON.stringify(component, null, 2));
|
|
37
38
|
if (text && typeof text[currentSide] === 'object' && text[currentSide][locale]) {
|
|
@@ -39,27 +40,27 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
39
40
|
}
|
|
40
41
|
return "";
|
|
41
42
|
};
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return
|
|
43
|
+
// Récupérer les données depuis le composant country_selection
|
|
44
|
+
const countrySelectionData = useMemo(() => {
|
|
45
|
+
const countrySelectionComponent = state.template.components.find(c => c.type === 'country_selection');
|
|
46
|
+
if (countrySelectionComponent) {
|
|
47
|
+
return state.componentData[countrySelectionComponent.id];
|
|
47
48
|
}
|
|
48
49
|
return null;
|
|
49
|
-
}, [state.componentData]);
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return
|
|
62
|
-
}, []);
|
|
50
|
+
}, [state.template.components, state.componentData]);
|
|
51
|
+
// Extraire selectedDocumentType depuis countrySelectionData
|
|
52
|
+
const selectedDocumentType = useMemo(() => {
|
|
53
|
+
if (!countrySelectionData?.documentType)
|
|
54
|
+
return null;
|
|
55
|
+
const backendDocType = countrySelectionData.documentType;
|
|
56
|
+
const mappedType = documentTypeMapping[backendDocType] || backendDocType;
|
|
57
|
+
const region = countrySelectionData.region || 'root';
|
|
58
|
+
return { type: mappedType, region };
|
|
59
|
+
}, [countrySelectionData, documentTypeMapping]);
|
|
60
|
+
// Récupérer countryData pour compatibilité avec le code existant
|
|
61
|
+
const countryData = useMemo(() => {
|
|
62
|
+
return countrySelectionData;
|
|
63
|
+
}, [countrySelectionData]);
|
|
63
64
|
useEffect(() => {
|
|
64
65
|
logger.log("cropImageUri", JSON.stringify(truncateFields({ box: silentCaptureResult }), null, 2));
|
|
65
66
|
if (capturedImages[currentSide]?.dir && silentCaptureResult?.bbox) {
|
|
@@ -68,27 +69,32 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
68
69
|
});
|
|
69
70
|
}
|
|
70
71
|
}, [capturedImages[currentSide]?.dir, silentCaptureResult?.bbox]);
|
|
71
|
-
const cameraConfig = {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
72
|
+
const cameraConfig = useMemo(() => {
|
|
73
|
+
const instructions = selectedDocumentType
|
|
74
|
+
? (locale === 'en' ? getDocumentTypeInfo(selectedDocumentType.type).instructions.en : getDocumentTypeInfo(selectedDocumentType.type).instructions.fr)
|
|
75
|
+
: getLocalizedText(component.instructions);
|
|
76
|
+
return {
|
|
77
|
+
aspectRatio: 4 / 3,
|
|
78
|
+
quality: 0.8,
|
|
79
|
+
flashMode: 'auto',
|
|
80
|
+
cameraType: 'back',
|
|
81
|
+
allowRetake: true,
|
|
82
|
+
maxRetakes: 3,
|
|
83
|
+
overlay: {
|
|
84
|
+
showGuide: true,
|
|
85
|
+
guideText: instructions,
|
|
86
|
+
bbox: {
|
|
87
|
+
xMin: 20,
|
|
88
|
+
yMin: 140,
|
|
89
|
+
xMax: 370,
|
|
90
|
+
yMax: 340,
|
|
91
|
+
borderColor: '#2DBD60',
|
|
92
|
+
borderWidth: 3,
|
|
93
|
+
cornerRadius: 8
|
|
94
|
+
}
|
|
89
95
|
}
|
|
90
|
-
}
|
|
91
|
-
};
|
|
96
|
+
};
|
|
97
|
+
}, [selectedDocumentType, locale, component.instructions]);
|
|
92
98
|
const retakePicture = (currentSide) => {
|
|
93
99
|
setShowCamera(true);
|
|
94
100
|
actions.showCustomStepper(false);
|
|
@@ -97,26 +103,14 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
97
103
|
setCropImageUri('');
|
|
98
104
|
onValueChange({ ...value, [currentSide]: { dir: '', file: '', mrz: '' } });
|
|
99
105
|
};
|
|
100
|
-
const hasRegions = useCallback((documentType) => {
|
|
101
|
-
const regionMapping = countryData?.regionMapping[documentType];
|
|
102
|
-
if (regionMapping && Object.keys(regionMapping).length > 1) {
|
|
103
|
-
return {
|
|
104
|
-
hasRegions: true,
|
|
105
|
-
regionMapping: Object.keys(regionMapping)
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
return {
|
|
109
|
-
hasRegions: false,
|
|
110
|
-
regionMapping: []
|
|
111
|
-
};
|
|
112
|
-
}, [countryData]);
|
|
113
106
|
const getCurrentSideVerification = (currentSide) => {
|
|
114
|
-
|
|
107
|
+
if (!selectedDocumentType || !countryData?.regionMapping) {
|
|
108
|
+
return { authMethod: [], mrzTypes: [], regionMapping: null, key: 'root' };
|
|
109
|
+
}
|
|
110
|
+
const regionMapping = countryData.regionMapping[selectedDocumentType.type];
|
|
115
111
|
const authMethod = [];
|
|
116
112
|
const mrzTypes = [];
|
|
117
|
-
const key = selectedDocumentType
|
|
118
|
-
// console.log("regionMapping", JSON.stringify(regionMapping, null, 2), selectedDocumentType?.region);
|
|
119
|
-
// const key = selectedDocumentType?.region as keyof typeof regionMapping;
|
|
113
|
+
const key = selectedDocumentType.region?.trim()?.length > 0 ? selectedDocumentType.region.trim() : 'root';
|
|
120
114
|
if (regionMapping?.[key] && Array.isArray(regionMapping[key])) {
|
|
121
115
|
regionMapping[key].forEach((item) => {
|
|
122
116
|
if (item[currentSide]) {
|
|
@@ -127,11 +121,11 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
127
121
|
}
|
|
128
122
|
});
|
|
129
123
|
}
|
|
130
|
-
logger.log("regionMapping", JSON.stringify(truncateFields({ regionMapping, selectedDocumentType: selectedDocumentType
|
|
124
|
+
logger.log("regionMapping", JSON.stringify(truncateFields({ regionMapping, selectedDocumentType: selectedDocumentType.region, key }), null, 2));
|
|
131
125
|
return { authMethod: removeDuplicates(authMethod), mrzTypes: removeDuplicates(mrzTypes), regionMapping: regionMapping, key: key };
|
|
132
126
|
};
|
|
133
127
|
const getCorrespondingMrzType = (templatePath, mapping, selectedDocumentType = "root") => {
|
|
134
|
-
if (!mapping[selectedDocumentType])
|
|
128
|
+
if (!mapping || !mapping[selectedDocumentType])
|
|
135
129
|
return null;
|
|
136
130
|
// Extraire le nom du fichier depuis le template_path
|
|
137
131
|
const fileName = templatePath.split("/").pop()?.replace(".jpg", "").replace(".png", "");
|
|
@@ -151,10 +145,19 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
151
145
|
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: true, success: false, error: '' }));
|
|
152
146
|
let templatePath = silentCaptureResult.templatePath || '';
|
|
153
147
|
let templateBbox;
|
|
148
|
+
if (!selectedDocumentType) {
|
|
149
|
+
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: 'Document type not selected' }));
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
154
152
|
const regionMappings = getCurrentSideVerification(currentSide);
|
|
155
153
|
// logger.log("regionMappings", JSON.stringify(truncateFields({regionMappings, templatePath}), null, 2));
|
|
156
154
|
if (templatePath.length === 0) {
|
|
157
155
|
try {
|
|
156
|
+
logger.log("checkTemplateType - BEFORE call", {
|
|
157
|
+
selectedDocumentTypeType: selectedDocumentType?.type,
|
|
158
|
+
countrySelectionDataDocumentType: countrySelectionData?.documentType,
|
|
159
|
+
docTypeToSend: selectedDocumentType?.type
|
|
160
|
+
});
|
|
158
161
|
const templateType = await checkTemplateType({ path: result.path || '', docType: selectedDocumentType?.type, docRegion: countryData?.code || "", postfix: currentSide });
|
|
159
162
|
if (templateType.template_path) {
|
|
160
163
|
templatePath = templateType.template_path;
|
|
@@ -174,49 +177,79 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
174
177
|
catch (e) {
|
|
175
178
|
logger.log("error checking template type", truncateFields(e));
|
|
176
179
|
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: e?.message || 'Erreur de vérification du template' }));
|
|
180
|
+
return; // Return early if checkTemplateType fails
|
|
177
181
|
}
|
|
178
182
|
}
|
|
179
|
-
logger.log("templatePath before
|
|
183
|
+
logger.log("templatePath before verification", templatePath, "currentSide", currentSide);
|
|
180
184
|
if (currentSide === 'front') {
|
|
181
|
-
frontVerification
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const
|
|
192
|
-
setSilentCaptureResult((prev) => ({
|
|
193
|
-
...prev,
|
|
185
|
+
logger.log("frontVerification - BEFORE call", {
|
|
186
|
+
selectedDocumentTypeType: selectedDocumentType?.type,
|
|
187
|
+
countrySelectionDataDocumentType: countrySelectionData?.documentType,
|
|
188
|
+
docTypeToSend: selectedDocumentType?.type
|
|
189
|
+
});
|
|
190
|
+
logger.log("Calling frontVerification", { templatePath, selectedDocumentType: selectedDocumentType?.type, regionMappings });
|
|
191
|
+
console.log("About to call frontVerification", typeof frontVerification);
|
|
192
|
+
try {
|
|
193
|
+
const mrzType = getCorrespondingMrzType(templatePath, regionMappings.regionMapping, regionMappings.key || '') || '';
|
|
194
|
+
console.log("mrzType calculated", mrzType);
|
|
195
|
+
const verificationParams = {
|
|
194
196
|
path: result.path,
|
|
197
|
+
regionMapping: {
|
|
198
|
+
authMethod: regionMappings.authMethod,
|
|
199
|
+
mrzTypes: regionMappings.mrzTypes,
|
|
200
|
+
},
|
|
201
|
+
selectedDocumentType: GovernmentDocumentTypeShorted[selectedDocumentType?.type] || '',
|
|
202
|
+
code: countryData?.code || '',
|
|
203
|
+
currentSide: currentSide,
|
|
195
204
|
templatePath: templatePath,
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
205
|
+
mrzType: mrzType,
|
|
206
|
+
};
|
|
207
|
+
console.log("frontVerification params", verificationParams);
|
|
208
|
+
console.log("About to call frontVerification function");
|
|
209
|
+
const promise = frontVerification(verificationParams);
|
|
210
|
+
console.log("frontVerification promise created", promise);
|
|
211
|
+
promise.then((mrz) => {
|
|
212
|
+
logger.log("front verification result", truncateFields(mrz));
|
|
213
|
+
const bbox = mrz?.bbox || templateBbox;
|
|
214
|
+
setSilentCaptureResult((prev) => ({
|
|
215
|
+
...prev,
|
|
216
|
+
path: result.path,
|
|
217
|
+
templatePath: templatePath,
|
|
218
|
+
bbox: bbox, success: true,
|
|
219
|
+
mrz: JSON.stringify(mrz), isAnalyzing: false,
|
|
220
|
+
country: countryData?.code,
|
|
221
|
+
documentType: selectedDocumentType.type,
|
|
222
|
+
}));
|
|
223
|
+
// Stocker le bbox pour ce côté
|
|
224
|
+
if (bbox && typeof bbox === 'object') {
|
|
225
|
+
setBboxBySide((prev) => ({ ...prev, [currentSide]: bbox }));
|
|
226
|
+
}
|
|
227
|
+
}).catch((e) => {
|
|
228
|
+
console.log("error front verification", e);
|
|
229
|
+
logger.log("error front verification", truncateFields(e));
|
|
230
|
+
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, templatePath: templatePath, success: false, error: e?.message || 'Erreur de détection du MRZ' }));
|
|
231
|
+
// showAlert('Erreur', e?.message || 'Erreur de détection du MRZ');
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
console.log("Error setting up frontVerification call", error);
|
|
236
|
+
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: error?.message || 'Erreur lors de la configuration de la vérification' }));
|
|
237
|
+
}
|
|
210
238
|
}
|
|
211
239
|
else {
|
|
240
|
+
const backRegionMappings = getCurrentSideVerification(currentSide);
|
|
241
|
+
logger.log("Calling backVerification", { templatePath, selectedDocumentType: selectedDocumentType.type, backRegionMappings });
|
|
212
242
|
backVerification({
|
|
213
243
|
path: result.path,
|
|
214
|
-
regionMapping:
|
|
215
|
-
|
|
244
|
+
regionMapping: {
|
|
245
|
+
authMethod: backRegionMappings.authMethod,
|
|
246
|
+
mrzTypes: backRegionMappings.mrzTypes,
|
|
247
|
+
},
|
|
248
|
+
selectedDocumentType: GovernmentDocumentTypeShorted[selectedDocumentType.type] || '',
|
|
216
249
|
code: countryData?.code || '',
|
|
217
250
|
currentSide: currentSide,
|
|
218
251
|
templatePath: templatePath,
|
|
219
|
-
mrzType: getCorrespondingMrzType(templatePath,
|
|
252
|
+
mrzType: getCorrespondingMrzType(templatePath, backRegionMappings.regionMapping, backRegionMappings.key || '') || '',
|
|
220
253
|
}).then((mrz) => {
|
|
221
254
|
logger.log("back verification result", truncateFields(mrz));
|
|
222
255
|
const bbox = mrz?.bbox || templateBbox;
|
|
@@ -224,7 +257,7 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
224
257
|
...prev, path: result.path, bbox: bbox,
|
|
225
258
|
success: true, mrz: JSON.stringify(mrz), isAnalyzing: false,
|
|
226
259
|
country: countryData?.code,
|
|
227
|
-
documentType: selectedDocumentType
|
|
260
|
+
documentType: selectedDocumentType.type,
|
|
228
261
|
}));
|
|
229
262
|
// Stocker le bbox pour ce côté
|
|
230
263
|
if (bbox && typeof bbox === 'object') {
|
|
@@ -233,109 +266,65 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
233
266
|
}).catch((e) => {
|
|
234
267
|
logger.log("error back verification", truncateFields(e));
|
|
235
268
|
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, templatePath: templatePath, success: false, error: e?.message || 'Erreur de détection du MRZ' }));
|
|
236
|
-
//
|
|
269
|
+
// showAlert('Erreur', e?.message || 'Erreur de détection du MRZ');
|
|
237
270
|
});
|
|
238
271
|
}
|
|
239
272
|
}
|
|
240
273
|
};
|
|
241
274
|
// Handle capture
|
|
242
275
|
const handleCapture = async (result) => {
|
|
276
|
+
console.log("handleCapture", JSON.stringify(truncateFields({ result, silentCaptureResult }), null, 2));
|
|
243
277
|
if (silentCaptureResult.path) {
|
|
244
|
-
|
|
278
|
+
// Créer une image rognée avec tolérance de 10% pour l'envoi
|
|
279
|
+
let imagePathForUpload = silentCaptureResult.path;
|
|
280
|
+
if (silentCaptureResult.bbox) {
|
|
281
|
+
try {
|
|
282
|
+
logger.log("Début du rognage avec tolérance, URI original:", silentCaptureResult.path);
|
|
283
|
+
imagePathForUpload = await cropImageWithBBoxWithTolerance(silentCaptureResult.path, silentCaptureResult.bbox, 0.05);
|
|
284
|
+
logger.log("Image rognée avec tolérance créée pour l'envoi, URI final:", imagePathForUpload);
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
logger.log("Erreur lors du rognage avec tolérance, utilisation de l'image originale:", truncateFields(error));
|
|
288
|
+
// En cas d'erreur, on utilise l'image originale
|
|
289
|
+
imagePathForUpload = silentCaptureResult.path;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
const base64 = await pathToBase64(imagePathForUpload);
|
|
245
293
|
logger.log("silentCaptureResult captured", JSON.stringify(truncateFields(silentCaptureResult), null, 2));
|
|
294
|
+
// Utiliser l'image originale pour l'affichage (dir) mais l'image rognée avec tolérance pour l'envoi (file)
|
|
246
295
|
const newImages = { ...capturedImages, [currentSide]: { dir: silentCaptureResult.path, file: base64, mrz: silentCaptureResult.mrz || "", templatePath: silentCaptureResult.templatePath } };
|
|
247
296
|
setCapturedImages(newImages);
|
|
248
297
|
if (silentCaptureResult.country && silentCaptureResult.documentType) {
|
|
249
298
|
onValueChange({
|
|
250
299
|
...newImages,
|
|
251
300
|
country: silentCaptureResult.country,
|
|
252
|
-
documentType: silentCaptureResult.documentType,
|
|
301
|
+
documentType: GovernmentDocumentTypeBackend[silentCaptureResult.documentType] || '',
|
|
253
302
|
});
|
|
254
303
|
}
|
|
255
304
|
setShowCamera(false);
|
|
256
305
|
actions.showCustomStepper(true);
|
|
257
306
|
}
|
|
258
307
|
else {
|
|
259
|
-
|
|
308
|
+
showAlert('Erreur', result.error || 'Impossible de prendre la photo');
|
|
260
309
|
}
|
|
261
310
|
};
|
|
262
311
|
const handleError = (event) => {
|
|
263
|
-
|
|
312
|
+
showAlert('Erreur', event.message);
|
|
264
313
|
setShowCamera(false);
|
|
265
314
|
};
|
|
266
315
|
useEffect(() => {
|
|
267
316
|
actions.showCustomStepper(!showCamera);
|
|
268
317
|
}, [showCamera]);
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
setSilentCaptureResult((prev) => ({ ...prev, templatePath: '', bbox: undefined, success: false, isAnalyzing: false, error: '', path: '', mrz: '', country: '', documentType: '' }));
|
|
272
|
-
setCapturedImages((prev) => ({ front: { dir: '', file: '', mrz: '', templatePath: '' }, back: { dir: '', file: '', mrz: '', templatePath: '' } }));
|
|
273
|
-
};
|
|
274
|
-
const handleRegionSelection = (region) => {
|
|
275
|
-
setSelectedDocumentType((prev) => ({ ...prev, region: region }));
|
|
276
|
-
};
|
|
277
|
-
// Interface de sélection du type de document
|
|
278
|
-
if (showDocumentSelection.documentSelection || showDocumentSelection.regionSelection) {
|
|
318
|
+
// Vérifier si les données sont disponibles, sinon afficher un message d'erreur
|
|
319
|
+
if (!countrySelectionData || !selectedDocumentType) {
|
|
279
320
|
return (<View style={styles.root}>
|
|
280
321
|
<View style={styles.container}>
|
|
281
|
-
|
|
282
322
|
<Text style={styles.title}>{getLocalizedText(component.labels)}</Text>
|
|
283
|
-
<Text style={styles.description}>
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
return (<TouchableOpacity key={docType} style={[styles.documentTypeButton, { backgroundColor: selectedDocumentType?.type === docType ? '#2DBD6030' : '#F8F9FA', borderColor: selectedDocumentType?.type === docType ? '#2DBD60' : '#E9ECEF', borderWidth: 2 }]} onPress={() => handleDocumentTypeSelection(docType)}>
|
|
289
|
-
<View style={[styles.documentTypeIconContainer, { backgroundColor: 'gray', }]}>
|
|
290
|
-
<Text style={styles.documentTypeIcon}>{docInfo.icon}</Text>
|
|
291
|
-
</View>
|
|
292
|
-
<Text style={styles.documentTypeName}>
|
|
293
|
-
{docInfo.name[language] || docInfo.name.en}
|
|
294
|
-
</Text>
|
|
295
|
-
<Text style={styles.documentTypeArrow}>→</Text>
|
|
296
|
-
</TouchableOpacity>);
|
|
297
|
-
}) : null}
|
|
298
|
-
{showDocumentSelection.regionSelection ?
|
|
299
|
-
hasRegions(selectedDocumentType?.type || 'identity_card').regionMapping.map((region) => {
|
|
300
|
-
return (<TouchableOpacity key={region} onPress={() => handleRegionSelection(region)} style={[styles.documentTypeButton, { backgroundColor: selectedDocumentType?.region === region ? '#2DBD6030' : '#F8F9FA', borderColor: selectedDocumentType?.region === region ? '#2DBD60' : '#E9ECEF', borderWidth: 2 }]}>
|
|
301
|
-
<Text>{region}</Text>
|
|
302
|
-
</TouchableOpacity>);
|
|
303
|
-
}) : null}
|
|
304
|
-
</ScrollView>
|
|
305
|
-
<Button title={t('common.next')} onPress={() => {
|
|
306
|
-
if (!selectedDocumentType) {
|
|
307
|
-
Alert.alert(t('common.error'), t('validation.required'));
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
if (showDocumentSelection.regionSelection) {
|
|
311
|
-
logger.log("showDocumentSelection", JSON.stringify(truncateFields(showDocumentSelection), null, 2));
|
|
312
|
-
setShowDocumentSelection({
|
|
313
|
-
documentSelection: false,
|
|
314
|
-
regionSelection: false
|
|
315
|
-
});
|
|
316
|
-
setShowCamera(true);
|
|
317
|
-
actions.showCustomStepper(false);
|
|
318
|
-
return;
|
|
319
|
-
}
|
|
320
|
-
else {
|
|
321
|
-
if (hasRegions(selectedDocumentType?.type)?.hasRegions) {
|
|
322
|
-
setShowDocumentSelection({
|
|
323
|
-
documentSelection: false,
|
|
324
|
-
regionSelection: true
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
else {
|
|
328
|
-
setShowDocumentSelection({
|
|
329
|
-
documentSelection: false,
|
|
330
|
-
regionSelection: false
|
|
331
|
-
});
|
|
332
|
-
setShowCamera(true);
|
|
333
|
-
actions.showCustomStepper(false);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
}} variant={selectedDocumentType ? 'primary' : "neutral"} size="large" fullWidth/>
|
|
337
|
-
|
|
338
|
-
|
|
323
|
+
<Text style={styles.description}>
|
|
324
|
+
{state.currentLanguage === "en"
|
|
325
|
+
? "Please complete the country and document selection first."
|
|
326
|
+
: "Veuillez d'abord compléter la sélection du pays et du document."}
|
|
327
|
+
</Text>
|
|
339
328
|
{error && (<Text style={styles.errorText}>{error}</Text>)}
|
|
340
329
|
</View>
|
|
341
330
|
</View>);
|
|
@@ -347,10 +336,6 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
347
336
|
if (currentSide === 'back') {
|
|
348
337
|
setCurrentSide('front');
|
|
349
338
|
setShowCamera(false);
|
|
350
|
-
setShowDocumentSelection({
|
|
351
|
-
documentSelection: false,
|
|
352
|
-
regionSelection: false
|
|
353
|
-
});
|
|
354
339
|
// Si une image front existe, on la restaure pour l'afficher
|
|
355
340
|
if (capturedImages['front']?.dir) {
|
|
356
341
|
// Restaurer l'état de capture du front pour afficher l'image
|
|
@@ -375,14 +360,11 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
375
360
|
}
|
|
376
361
|
}
|
|
377
362
|
else {
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
regionSelection: false
|
|
381
|
-
});
|
|
382
|
-
actions.showCustomStepper(true);
|
|
363
|
+
// Retour au composant précédent (country_selection)
|
|
364
|
+
actions.previousComponent();
|
|
383
365
|
}
|
|
384
366
|
},
|
|
385
|
-
selectedDocumentType: locale === 'en' ? getDocumentTypeInfo(selectedDocumentType
|
|
367
|
+
selectedDocumentType: selectedDocumentType ? (locale === 'en' ? getDocumentTypeInfo(selectedDocumentType.type).name.en : getDocumentTypeInfo(selectedDocumentType.type).name.fr) : '',
|
|
386
368
|
step: state.currentComponentIndex + 1,
|
|
387
369
|
totalSteps: state.template.components.length,
|
|
388
370
|
side: currentSide,
|
|
@@ -430,22 +412,33 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
430
412
|
}}/>) : null}
|
|
431
413
|
|
|
432
414
|
</View>
|
|
433
|
-
{/*
|
|
434
|
-
<Button title={
|
|
435
|
-
retakePicture(currentSide);
|
|
436
|
-
}} variant="outline" size="medium" fullWidth/>
|
|
437
|
-
<Button title={t('common.next')} onPress={() => {
|
|
438
|
-
if (currentSide === 'back' || selectedDocumentType?.type === 'passport') {
|
|
439
|
-
actions.nextComponent();
|
|
440
|
-
return;
|
|
441
|
-
}
|
|
442
|
-
else {
|
|
415
|
+
{/* Capture button si aucune image n'a été capturée */}
|
|
416
|
+
{!capturedImages[currentSide]?.dir && (<Button title={state.currentLanguage === "en" ? "Take Photo" : "Prendre une photo"} onPress={() => {
|
|
443
417
|
setShowCamera(true);
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
418
|
+
actions.showCustomStepper(false);
|
|
419
|
+
}} variant="primary" size="large" fullWidth/>)}
|
|
420
|
+
{/* retake button si une image a été capturée */}
|
|
421
|
+
{capturedImages[currentSide]?.dir && (<>
|
|
422
|
+
<Button title={t('kyc.idCardCapture.retakeButton')} onPress={() => {
|
|
423
|
+
retakePicture(currentSide);
|
|
424
|
+
}} variant="outline" size="medium" fullWidth/>
|
|
425
|
+
<Button title={t('common.next')} onPress={() => {
|
|
426
|
+
if (!selectedDocumentType) {
|
|
427
|
+
showAlert('Error', 'Document type not selected');
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
if (currentSide === 'back' || selectedDocumentType.type === 'passport') {
|
|
431
|
+
actions.nextComponent();
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
setShowCamera(true);
|
|
436
|
+
setCurrentSide('back');
|
|
437
|
+
setSilentCaptureResult((prev) => ({ path: '', success: false, isAnalyzing: false, error: '', mrz: '', templatePath: '' }));
|
|
438
|
+
setCropImageUri('');
|
|
439
|
+
}
|
|
440
|
+
}} variant="primary" size="large" fullWidth/>
|
|
441
|
+
</>)}
|
|
449
442
|
</View>
|
|
450
443
|
</View>
|
|
451
444
|
</ScrollView>
|
|
@@ -606,42 +599,5 @@ const styles = StyleSheet.create({
|
|
|
606
599
|
marginTop: 8,
|
|
607
600
|
textAlign: 'center',
|
|
608
601
|
},
|
|
609
|
-
documentTypesContainer: {
|
|
610
|
-
// flex: 1,
|
|
611
|
-
// marginBottom: 16,
|
|
612
|
-
// paddingHorizontal: 16,
|
|
613
|
-
maxHeight: Dimensions.get('window').height - 400,
|
|
614
|
-
},
|
|
615
|
-
documentTypeButton: {
|
|
616
|
-
flexDirection: 'row',
|
|
617
|
-
alignItems: 'center',
|
|
618
|
-
backgroundColor: '#F8F9FA',
|
|
619
|
-
padding: 16,
|
|
620
|
-
marginBottom: 12,
|
|
621
|
-
borderRadius: 12,
|
|
622
|
-
borderWidth: 1,
|
|
623
|
-
borderColor: '#E9ECEF',
|
|
624
|
-
},
|
|
625
|
-
documentTypeIconContainer: {
|
|
626
|
-
width: 40, height: 40,
|
|
627
|
-
borderRadius: 10,
|
|
628
|
-
alignItems: 'center',
|
|
629
|
-
justifyContent: 'center',
|
|
630
|
-
marginRight: 16,
|
|
631
|
-
},
|
|
632
|
-
documentTypeIcon: {
|
|
633
|
-
fontSize: 24,
|
|
634
|
-
},
|
|
635
|
-
documentTypeName: {
|
|
636
|
-
flex: 1,
|
|
637
|
-
fontSize: 16,
|
|
638
|
-
fontWeight: '600',
|
|
639
|
-
color: '#333',
|
|
640
|
-
},
|
|
641
|
-
documentTypeArrow: {
|
|
642
|
-
fontSize: 18,
|
|
643
|
-
color: '#666',
|
|
644
|
-
fontWeight: 'bold',
|
|
645
|
-
},
|
|
646
602
|
});
|
|
647
603
|
//# sourceMappingURL=IDCardCapture.js.map
|