@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,7 +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';
|
|
4
|
-
import { TemplateComponent,
|
|
5
|
+
import { TemplateComponent, LocalizedText, GovernmentDocumentType, ISilentCaptureResult, IBbox, GovernmentDocumentTypeShorted, GovernmentDocumentTypeBackend } from '../../types/KYC.types';
|
|
5
6
|
import IdCardOverlay from '../OverLay/IdCard';
|
|
6
7
|
import { useTemplateKYCFlowContext } from '../../hooks/useTemplateKYCFlow';
|
|
7
8
|
import { useI18n } from '../../hooks/useI18n';
|
|
@@ -11,7 +12,7 @@ import { backVerification, checkTemplateType, frontVerification } from '../../mo
|
|
|
11
12
|
import { getDocumentTypeInfo } from '../../utils/get-document-type-info';
|
|
12
13
|
import pathToBase64 from '../../utils/pathToBase64';
|
|
13
14
|
import { truncateFields } from '../../modules/api/KYCService';
|
|
14
|
-
import { cropByObb, cropImageWithBBox } from '../../utils/cropByObb';
|
|
15
|
+
import { cropByObb, cropImageWithBBox, cropImageWithBBoxWithTolerance } from '../../utils/cropByObb';
|
|
15
16
|
import { logger } from '../../utils/logger';
|
|
16
17
|
|
|
17
18
|
|
|
@@ -45,24 +46,19 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
|
|
|
45
46
|
const [currentSide, setCurrentSide] = useState<string>('front');
|
|
46
47
|
// Stocker les bbox par côté pour pouvoir restaurer les images croppées
|
|
47
48
|
const [bboxBySide, setBboxBySide] = useState<Record<string, IBbox>>({});
|
|
48
|
-
const [selectedDocumentType, setSelectedDocumentType] = useState<{
|
|
49
|
-
type: GovernmentDocumentType;
|
|
50
|
-
region: string;
|
|
51
|
-
}>({
|
|
52
|
-
type: 'identity_card',
|
|
53
|
-
region: 'root'
|
|
54
|
-
});
|
|
55
|
-
const [showDocumentSelection, setShowDocumentSelection] = useState(
|
|
56
|
-
{
|
|
57
|
-
documentSelection: true,
|
|
58
|
-
regionSelection: false
|
|
59
|
-
}
|
|
60
|
-
);
|
|
61
49
|
const [silentCaptureResult, setSilentCaptureResult] = useState<ISilentCaptureResult>({ success: false, isAnalyzing: false });
|
|
50
|
+
|
|
51
|
+
// Mapping des types de documents backend vers SDK
|
|
52
|
+
const documentTypeMapping: Record<string, GovernmentDocumentType> = {
|
|
53
|
+
'nationalId': 'national_id',
|
|
54
|
+
'passport': 'passport',
|
|
55
|
+
'driversLicense': 'drivers_licence',
|
|
56
|
+
'residencePermit': 'permanent_residence',
|
|
57
|
+
'healthInsuranceCard': 'health_insurance_card',
|
|
58
|
+
};
|
|
62
59
|
// const [imageNaturalSize, setImageNaturalSize] = useState<{ width: number; height: number } | null>(null);
|
|
63
60
|
|
|
64
|
-
const { actions, state
|
|
65
|
-
const config = component.config as IDCardConfig;
|
|
61
|
+
const { actions, state } = useTemplateKYCFlowContext();
|
|
66
62
|
|
|
67
63
|
|
|
68
64
|
|
|
@@ -74,31 +70,30 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
|
|
|
74
70
|
return "";
|
|
75
71
|
};
|
|
76
72
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (
|
|
81
|
-
|
|
82
|
-
return countryMapping;
|
|
73
|
+
// Récupérer les données depuis le composant country_selection
|
|
74
|
+
const countrySelectionData = useMemo(() => {
|
|
75
|
+
const countrySelectionComponent = state.template.components.find(c => c.type === 'country_selection');
|
|
76
|
+
if (countrySelectionComponent) {
|
|
77
|
+
return state.componentData[countrySelectionComponent.id];
|
|
83
78
|
}
|
|
84
79
|
return null;
|
|
85
|
-
}, [state.componentData]);
|
|
80
|
+
}, [state.template.components, state.componentData]);
|
|
86
81
|
|
|
82
|
+
// Extraire selectedDocumentType depuis countrySelectionData
|
|
83
|
+
const selectedDocumentType = useMemo<{ type: GovernmentDocumentType; region: string } | null>(() => {
|
|
84
|
+
if (!countrySelectionData?.documentType) return null;
|
|
87
85
|
|
|
88
|
-
|
|
89
|
-
const
|
|
86
|
+
const backendDocType = countrySelectionData.documentType;
|
|
87
|
+
const mappedType = documentTypeMapping[backendDocType] || backendDocType as GovernmentDocumentType;
|
|
88
|
+
const region = countrySelectionData.region || 'root';
|
|
90
89
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
logger.log("newconfig", truncateFields(newconfig));
|
|
100
|
-
return newconfig;
|
|
101
|
-
}, []);
|
|
90
|
+
return { type: mappedType, region };
|
|
91
|
+
}, [countrySelectionData, documentTypeMapping]);
|
|
92
|
+
|
|
93
|
+
// Récupérer countryData pour compatibilité avec le code existant
|
|
94
|
+
const countryData = useMemo(() => {
|
|
95
|
+
return countrySelectionData;
|
|
96
|
+
}, [countrySelectionData]);
|
|
102
97
|
|
|
103
98
|
|
|
104
99
|
useEffect(() => {
|
|
@@ -112,28 +107,33 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
|
|
|
112
107
|
|
|
113
108
|
|
|
114
109
|
|
|
115
|
-
const cameraConfig = {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
cameraType: 'back' as const,
|
|
120
|
-
allowRetake: true,
|
|
121
|
-
maxRetakes: 3,
|
|
122
|
-
overlay: {
|
|
123
|
-
showGuide: true,
|
|
124
|
-
guideText: selectedDocumentType ? (locale === 'en' ? getDocumentTypeInfo(selectedDocumentType.type).instructions.en : getDocumentTypeInfo(selectedDocumentType.type).instructions.fr) : getLocalizedText(component.instructions as Record<string, LocalizedText>),
|
|
125
|
-
bbox: selectedDocumentType && config.bbox_configs[selectedDocumentType.type] ? config.bbox_configs[selectedDocumentType.type] : {
|
|
126
|
-
xMin: 20,
|
|
127
|
-
yMin: 140,
|
|
128
|
-
xMax: 370,
|
|
129
|
-
yMax: 340,
|
|
130
|
-
borderColor: '#2DBD60',
|
|
131
|
-
borderWidth: 3,
|
|
132
|
-
cornerRadius: 8
|
|
133
|
-
}
|
|
110
|
+
const cameraConfig = useMemo(() => {
|
|
111
|
+
const instructions = selectedDocumentType
|
|
112
|
+
? (locale === 'en' ? getDocumentTypeInfo(selectedDocumentType.type).instructions.en : getDocumentTypeInfo(selectedDocumentType.type).instructions.fr)
|
|
113
|
+
: getLocalizedText(component.instructions as Record<string, LocalizedText>);
|
|
134
114
|
|
|
135
|
-
|
|
136
|
-
|
|
115
|
+
return {
|
|
116
|
+
aspectRatio: 4 / 3,
|
|
117
|
+
quality: 0.8,
|
|
118
|
+
flashMode: 'auto' as const,
|
|
119
|
+
cameraType: 'back' as const,
|
|
120
|
+
allowRetake: true,
|
|
121
|
+
maxRetakes: 3,
|
|
122
|
+
overlay: {
|
|
123
|
+
showGuide: true,
|
|
124
|
+
guideText: instructions,
|
|
125
|
+
bbox: {
|
|
126
|
+
xMin: 20,
|
|
127
|
+
yMin: 140,
|
|
128
|
+
xMax: 370,
|
|
129
|
+
yMax: 340,
|
|
130
|
+
borderColor: '#2DBD60',
|
|
131
|
+
borderWidth: 3,
|
|
132
|
+
cornerRadius: 8
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
}, [selectedDocumentType, locale, component.instructions]);
|
|
137
137
|
|
|
138
138
|
const retakePicture = (currentSide: string) => {
|
|
139
139
|
setShowCamera(true);
|
|
@@ -144,29 +144,18 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
|
|
|
144
144
|
onValueChange({ ...value, [currentSide]: { dir: '', file: '', mrz: '' } });
|
|
145
145
|
};
|
|
146
146
|
|
|
147
|
-
const hasRegions = useCallback((documentType: GovernmentDocumentType): { hasRegions: boolean, regionMapping: string[] } => {
|
|
148
|
-
const regionMapping = countryData?.regionMapping[documentType as GovernmentDocumentType];
|
|
149
|
-
if (regionMapping && Object.keys(regionMapping).length > 1) {
|
|
150
|
-
return {
|
|
151
|
-
hasRegions: true,
|
|
152
|
-
regionMapping: Object.keys(regionMapping)
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
return {
|
|
156
|
-
hasRegions: false,
|
|
157
|
-
regionMapping: []
|
|
158
|
-
};
|
|
159
|
-
}, [countryData]);
|
|
160
147
|
|
|
161
148
|
|
|
162
149
|
const getCurrentSideVerification = (currentSide: string) => {
|
|
163
|
-
|
|
150
|
+
if (!selectedDocumentType || !countryData?.regionMapping) {
|
|
151
|
+
return { authMethod: [], mrzTypes: [], regionMapping: null, key: 'root' };
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const regionMapping = countryData.regionMapping[selectedDocumentType.type as GovernmentDocumentType];
|
|
164
155
|
const authMethod: string[] = [];
|
|
165
156
|
const mrzTypes: string[] = [];
|
|
166
157
|
|
|
167
|
-
const key = selectedDocumentType
|
|
168
|
-
// console.log("regionMapping", JSON.stringify(regionMapping, null, 2), selectedDocumentType?.region);
|
|
169
|
-
// const key = selectedDocumentType?.region as keyof typeof regionMapping;
|
|
158
|
+
const key = selectedDocumentType.region?.trim()?.length > 0 ? selectedDocumentType.region.trim() : 'root';
|
|
170
159
|
|
|
171
160
|
if (regionMapping?.[key] && Array.isArray(regionMapping[key])) {
|
|
172
161
|
regionMapping[key].forEach((item: any) => {
|
|
@@ -179,13 +168,13 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
|
|
|
179
168
|
});
|
|
180
169
|
}
|
|
181
170
|
|
|
182
|
-
logger.log("regionMapping", JSON.stringify(truncateFields({ regionMapping, selectedDocumentType: selectedDocumentType
|
|
171
|
+
logger.log("regionMapping", JSON.stringify(truncateFields({ regionMapping, selectedDocumentType: selectedDocumentType.region, key }), null, 2));
|
|
183
172
|
|
|
184
173
|
return { authMethod: removeDuplicates(authMethod), mrzTypes: removeDuplicates(mrzTypes), regionMapping: regionMapping, key: key };
|
|
185
174
|
}
|
|
186
175
|
|
|
187
176
|
const getCorrespondingMrzType = (templatePath: string, mapping: any, selectedDocumentType: string = "root") => {
|
|
188
|
-
if (!mapping[selectedDocumentType]) return null;
|
|
177
|
+
if (!mapping || !mapping[selectedDocumentType]) return null;
|
|
189
178
|
|
|
190
179
|
// Extraire le nom du fichier depuis le template_path
|
|
191
180
|
const fileName = templatePath.split("/").pop()?.replace(".jpg", "").replace(".png", "");
|
|
@@ -210,10 +199,20 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
|
|
|
210
199
|
let templatePath = silentCaptureResult.templatePath || '';
|
|
211
200
|
let templateBbox: IBbox | undefined;
|
|
212
201
|
|
|
202
|
+
if (!selectedDocumentType) {
|
|
203
|
+
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: 'Document type not selected' }));
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
|
|
213
207
|
const regionMappings = getCurrentSideVerification(currentSide)
|
|
214
208
|
// logger.log("regionMappings", JSON.stringify(truncateFields({regionMappings, templatePath}), null, 2));
|
|
215
209
|
if (templatePath.length === 0) {
|
|
216
210
|
try {
|
|
211
|
+
logger.log("checkTemplateType - BEFORE call", {
|
|
212
|
+
selectedDocumentTypeType: selectedDocumentType?.type,
|
|
213
|
+
countrySelectionDataDocumentType: countrySelectionData?.documentType,
|
|
214
|
+
docTypeToSend: selectedDocumentType?.type
|
|
215
|
+
});
|
|
217
216
|
const templateType = await checkTemplateType({ path: result.path || '', docType: selectedDocumentType?.type as GovernmentDocumentType, docRegion: countryData?.code || "", postfix: currentSide });
|
|
218
217
|
|
|
219
218
|
if (templateType.template_path) {
|
|
@@ -232,21 +231,38 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
|
|
|
232
231
|
} catch (e: any) {
|
|
233
232
|
logger.log("error checking template type", truncateFields(e));
|
|
234
233
|
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: e?.message || 'Erreur de vérification du template' }));
|
|
234
|
+
return; // Return early if checkTemplateType fails
|
|
235
235
|
}
|
|
236
236
|
}
|
|
237
|
-
logger.log("templatePath before
|
|
237
|
+
logger.log("templatePath before verification", templatePath, "currentSide", currentSide);
|
|
238
238
|
if (currentSide === 'front') {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
239
|
+
logger.log("frontVerification - BEFORE call", {
|
|
240
|
+
selectedDocumentTypeType: selectedDocumentType?.type,
|
|
241
|
+
countrySelectionDataDocumentType: countrySelectionData?.documentType,
|
|
242
|
+
docTypeToSend: selectedDocumentType?.type
|
|
243
|
+
});
|
|
244
|
+
logger.log("Calling frontVerification", { templatePath, selectedDocumentType: selectedDocumentType?.type, regionMappings });
|
|
245
|
+
console.log("About to call frontVerification", typeof frontVerification);
|
|
246
|
+
try {
|
|
247
|
+
const mrzType = getCorrespondingMrzType(templatePath, regionMappings.regionMapping, regionMappings.key || '') || '';
|
|
248
|
+
console.log("mrzType calculated", mrzType);
|
|
249
|
+
const verificationParams = {
|
|
242
250
|
path: result.path,
|
|
243
|
-
regionMapping:
|
|
244
|
-
|
|
251
|
+
regionMapping: {
|
|
252
|
+
authMethod: regionMappings.authMethod,
|
|
253
|
+
mrzTypes: regionMappings.mrzTypes,
|
|
254
|
+
},
|
|
255
|
+
selectedDocumentType: GovernmentDocumentTypeShorted[selectedDocumentType?.type as keyof typeof GovernmentDocumentTypeShorted] || '',
|
|
245
256
|
code: countryData?.code || '',
|
|
246
257
|
currentSide: currentSide,
|
|
247
258
|
templatePath: templatePath,
|
|
248
|
-
mrzType:
|
|
249
|
-
}
|
|
259
|
+
mrzType: mrzType,
|
|
260
|
+
};
|
|
261
|
+
console.log("frontVerification params", verificationParams);
|
|
262
|
+
console.log("About to call frontVerification function");
|
|
263
|
+
const promise = frontVerification(verificationParams);
|
|
264
|
+
console.log("frontVerification promise created", promise);
|
|
265
|
+
promise.then((mrz) => {
|
|
250
266
|
logger.log("front verification result", truncateFields(mrz));
|
|
251
267
|
const bbox = (mrz as any)?.bbox || templateBbox;
|
|
252
268
|
setSilentCaptureResult((prev) => ({
|
|
@@ -256,7 +272,7 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
|
|
|
256
272
|
bbox: bbox, success: true,
|
|
257
273
|
mrz: JSON.stringify(mrz), isAnalyzing: false,
|
|
258
274
|
country: countryData?.code,
|
|
259
|
-
documentType: selectedDocumentType
|
|
275
|
+
documentType: selectedDocumentType.type,
|
|
260
276
|
}),
|
|
261
277
|
);
|
|
262
278
|
// Stocker le bbox pour ce côté
|
|
@@ -265,19 +281,29 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
|
|
|
265
281
|
}
|
|
266
282
|
|
|
267
283
|
}).catch((e: any) => {
|
|
284
|
+
console.log("error front verification", e);
|
|
268
285
|
logger.log("error front verification", truncateFields(e));
|
|
269
286
|
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, templatePath: templatePath, success: false, error: e?.message || 'Erreur de détection du MRZ' }));
|
|
270
|
-
//
|
|
271
|
-
})
|
|
287
|
+
// showAlert('Erreur', e?.message || 'Erreur de détection du MRZ');
|
|
288
|
+
});
|
|
289
|
+
} catch (error: any) {
|
|
290
|
+
console.log("Error setting up frontVerification call", error);
|
|
291
|
+
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: error?.message || 'Erreur lors de la configuration de la vérification' }));
|
|
292
|
+
}
|
|
272
293
|
} else {
|
|
294
|
+
const backRegionMappings = getCurrentSideVerification(currentSide);
|
|
295
|
+
logger.log("Calling backVerification", { templatePath, selectedDocumentType: selectedDocumentType.type, backRegionMappings });
|
|
273
296
|
backVerification({
|
|
274
297
|
path: result.path,
|
|
275
|
-
regionMapping:
|
|
276
|
-
|
|
298
|
+
regionMapping: {
|
|
299
|
+
authMethod: backRegionMappings.authMethod,
|
|
300
|
+
mrzTypes: backRegionMappings.mrzTypes,
|
|
301
|
+
},
|
|
302
|
+
selectedDocumentType: GovernmentDocumentTypeShorted[selectedDocumentType.type as keyof typeof GovernmentDocumentTypeShorted] || '',
|
|
277
303
|
code: countryData?.code || '',
|
|
278
304
|
currentSide: currentSide,
|
|
279
305
|
templatePath: templatePath,
|
|
280
|
-
mrzType: getCorrespondingMrzType(templatePath,
|
|
306
|
+
mrzType: getCorrespondingMrzType(templatePath, backRegionMappings.regionMapping, backRegionMappings.key || '') || '',
|
|
281
307
|
}).then((mrz) => {
|
|
282
308
|
logger.log("back verification result", truncateFields(mrz));
|
|
283
309
|
const bbox = (mrz as any)?.bbox || templateBbox;
|
|
@@ -285,7 +311,7 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
|
|
|
285
311
|
...prev, path: result.path, bbox: bbox,
|
|
286
312
|
success: true, mrz: JSON.stringify(mrz), isAnalyzing: false,
|
|
287
313
|
country: countryData?.code,
|
|
288
|
-
documentType: selectedDocumentType
|
|
314
|
+
documentType: selectedDocumentType.type,
|
|
289
315
|
|
|
290
316
|
}));
|
|
291
317
|
// Stocker le bbox pour ce côté
|
|
@@ -295,7 +321,7 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
|
|
|
295
321
|
}).catch((e: any) => {
|
|
296
322
|
logger.log("error back verification", truncateFields(e));
|
|
297
323
|
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, templatePath: templatePath, success: false, error: e?.message || 'Erreur de détection du MRZ' }));
|
|
298
|
-
//
|
|
324
|
+
// showAlert('Erreur', e?.message || 'Erreur de détection du MRZ');
|
|
299
325
|
})
|
|
300
326
|
}
|
|
301
327
|
|
|
@@ -304,28 +330,45 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
|
|
|
304
330
|
|
|
305
331
|
// Handle capture
|
|
306
332
|
const handleCapture = async (result: { success: boolean; path?: string; error?: string }) => {
|
|
333
|
+
console.log("handleCapture", JSON.stringify(truncateFields({ result, silentCaptureResult }), null, 2));
|
|
334
|
+
|
|
307
335
|
if (silentCaptureResult.path) {
|
|
308
|
-
|
|
336
|
+
// Créer une image rognée avec tolérance de 10% pour l'envoi
|
|
337
|
+
let imagePathForUpload = silentCaptureResult.path;
|
|
338
|
+
if (silentCaptureResult.bbox) {
|
|
339
|
+
try {
|
|
340
|
+
logger.log("Début du rognage avec tolérance, URI original:", silentCaptureResult.path);
|
|
341
|
+
imagePathForUpload = await cropImageWithBBoxWithTolerance(silentCaptureResult.path, silentCaptureResult.bbox, 0.05);
|
|
342
|
+
logger.log("Image rognée avec tolérance créée pour l'envoi, URI final:", imagePathForUpload);
|
|
343
|
+
} catch (error) {
|
|
344
|
+
logger.log("Erreur lors du rognage avec tolérance, utilisation de l'image originale:", truncateFields(error));
|
|
345
|
+
// En cas d'erreur, on utilise l'image originale
|
|
346
|
+
imagePathForUpload = silentCaptureResult.path;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
const base64 = await pathToBase64(imagePathForUpload);
|
|
309
351
|
|
|
310
352
|
logger.log("silentCaptureResult captured", JSON.stringify(truncateFields(silentCaptureResult), null, 2));
|
|
353
|
+
// Utiliser l'image originale pour l'affichage (dir) mais l'image rognée avec tolérance pour l'envoi (file)
|
|
311
354
|
const newImages = { ...capturedImages, [currentSide]: { dir: silentCaptureResult.path, file: base64, mrz: silentCaptureResult.mrz || "", templatePath: silentCaptureResult.templatePath } };
|
|
312
355
|
setCapturedImages(newImages);
|
|
313
356
|
if (silentCaptureResult.country && silentCaptureResult.documentType) {
|
|
314
357
|
onValueChange({
|
|
315
358
|
...newImages,
|
|
316
359
|
country: silentCaptureResult.country,
|
|
317
|
-
documentType: silentCaptureResult.documentType,
|
|
360
|
+
documentType: GovernmentDocumentTypeBackend[silentCaptureResult.documentType as keyof typeof GovernmentDocumentTypeBackend] || '',
|
|
318
361
|
});
|
|
319
362
|
}
|
|
320
363
|
setShowCamera(false);
|
|
321
364
|
actions.showCustomStepper(true);
|
|
322
365
|
} else {
|
|
323
|
-
|
|
366
|
+
showAlert('Erreur', result.error || 'Impossible de prendre la photo');
|
|
324
367
|
}
|
|
325
368
|
};
|
|
326
369
|
|
|
327
370
|
const handleError = (event: { message: string }) => {
|
|
328
|
-
|
|
371
|
+
showAlert('Erreur', event.message);
|
|
329
372
|
setShowCamera(false);
|
|
330
373
|
};
|
|
331
374
|
|
|
@@ -342,93 +385,18 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
|
|
|
342
385
|
|
|
343
386
|
|
|
344
387
|
|
|
345
|
-
const handleDocumentTypeSelection = (docType: GovernmentDocumentType) => {
|
|
346
|
-
setSelectedDocumentType({ type: docType, region: hasRegions(docType) ? '' : 'root' });
|
|
347
|
-
setSilentCaptureResult((prev) => ({ ...prev, templatePath: '', bbox: undefined, success: false, isAnalyzing: false, error: '', path: '', mrz: '', country: '', documentType: '' }));
|
|
348
|
-
setCapturedImages((prev) => ({ front: { dir: '', file: '', mrz: '', templatePath: '' }, back: { dir: '', file: '', mrz: '', templatePath: '' } }));
|
|
349
|
-
};
|
|
350
|
-
const handleRegionSelection = (region: string) => {
|
|
351
|
-
setSelectedDocumentType((prev) => ({ ...prev, region: region }));
|
|
352
|
-
};
|
|
353
388
|
|
|
354
|
-
//
|
|
355
|
-
if (
|
|
389
|
+
// Vérifier si les données sont disponibles, sinon afficher un message d'erreur
|
|
390
|
+
if (!countrySelectionData || !selectedDocumentType) {
|
|
356
391
|
return (
|
|
357
392
|
<View style={styles.root}>
|
|
358
393
|
<View style={styles.container}>
|
|
359
|
-
|
|
360
394
|
<Text style={styles.title}>{getLocalizedText(component.labels)}</Text>
|
|
361
|
-
<Text style={styles.description}>
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
return (
|
|
367
|
-
<TouchableOpacity
|
|
368
|
-
key={docType}
|
|
369
|
-
style={[styles.documentTypeButton, { backgroundColor: selectedDocumentType?.type === docType ? '#2DBD6030' : '#F8F9FA', borderColor: selectedDocumentType?.type === docType ? '#2DBD60' : '#E9ECEF', borderWidth: 2 }]}
|
|
370
|
-
onPress={() => handleDocumentTypeSelection(docType)}
|
|
371
|
-
>
|
|
372
|
-
<View style={[styles.documentTypeIconContainer, { backgroundColor: 'gray', }]}>
|
|
373
|
-
<Text style={styles.documentTypeIcon}>{docInfo.icon}</Text>
|
|
374
|
-
</View>
|
|
375
|
-
<Text style={styles.documentTypeName}>
|
|
376
|
-
{docInfo.name[language as keyof typeof docInfo.name] || docInfo.name.en}
|
|
377
|
-
</Text>
|
|
378
|
-
<Text style={styles.documentTypeArrow}>→</Text>
|
|
379
|
-
</TouchableOpacity>
|
|
380
|
-
);
|
|
381
|
-
}) : null}
|
|
382
|
-
{showDocumentSelection.regionSelection ?
|
|
383
|
-
hasRegions(selectedDocumentType?.type || 'identity_card').regionMapping.map((region) => {
|
|
384
|
-
return (
|
|
385
|
-
<TouchableOpacity key={region} onPress={() => handleRegionSelection(region)}
|
|
386
|
-
style={[styles.documentTypeButton, { backgroundColor: selectedDocumentType?.region === region ? '#2DBD6030' : '#F8F9FA', borderColor: selectedDocumentType?.region === region ? '#2DBD60' : '#E9ECEF', borderWidth: 2 }]}
|
|
387
|
-
|
|
388
|
-
>
|
|
389
|
-
<Text>{region}</Text>
|
|
390
|
-
</TouchableOpacity>
|
|
391
|
-
);
|
|
392
|
-
}) : null}
|
|
393
|
-
</ScrollView>
|
|
394
|
-
<Button title={t('common.next')} onPress={() => {
|
|
395
|
-
if (!selectedDocumentType) {
|
|
396
|
-
Alert.alert(t('common.error'), t('validation.required'));
|
|
397
|
-
return;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
if (showDocumentSelection.regionSelection) {
|
|
401
|
-
logger.log("showDocumentSelection", JSON.stringify(truncateFields(showDocumentSelection), null, 2));
|
|
402
|
-
setShowDocumentSelection({
|
|
403
|
-
documentSelection: false,
|
|
404
|
-
regionSelection: false
|
|
405
|
-
});
|
|
406
|
-
setShowCamera(true);
|
|
407
|
-
actions.showCustomStepper(false);
|
|
408
|
-
return;
|
|
409
|
-
} else {
|
|
410
|
-
if (hasRegions(selectedDocumentType?.type)?.hasRegions) {
|
|
411
|
-
setShowDocumentSelection({
|
|
412
|
-
documentSelection: false,
|
|
413
|
-
regionSelection: true
|
|
414
|
-
});
|
|
415
|
-
} else {
|
|
416
|
-
setShowDocumentSelection({
|
|
417
|
-
documentSelection: false,
|
|
418
|
-
regionSelection: false
|
|
419
|
-
});
|
|
420
|
-
setShowCamera(true);
|
|
421
|
-
actions.showCustomStepper(false);
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
}}
|
|
426
|
-
variant={selectedDocumentType ? 'primary' : "neutral"}
|
|
427
|
-
size="large"
|
|
428
|
-
fullWidth
|
|
429
|
-
/>
|
|
430
|
-
|
|
431
|
-
|
|
395
|
+
<Text style={styles.description}>
|
|
396
|
+
{state.currentLanguage === "en"
|
|
397
|
+
? "Please complete the country and document selection first."
|
|
398
|
+
: "Veuillez d'abord compléter la sélection du pays et du document."}
|
|
399
|
+
</Text>
|
|
432
400
|
{error && (
|
|
433
401
|
<Text style={styles.errorText}>{error}</Text>
|
|
434
402
|
)}
|
|
@@ -470,10 +438,6 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
|
|
|
470
438
|
if (currentSide === 'back') {
|
|
471
439
|
setCurrentSide('front');
|
|
472
440
|
setShowCamera(false);
|
|
473
|
-
setShowDocumentSelection({
|
|
474
|
-
documentSelection: false,
|
|
475
|
-
regionSelection: false
|
|
476
|
-
});
|
|
477
441
|
// Si une image front existe, on la restaure pour l'afficher
|
|
478
442
|
if (capturedImages['front']?.dir) {
|
|
479
443
|
// Restaurer l'état de capture du front pour afficher l'image
|
|
@@ -496,14 +460,11 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
|
|
|
496
460
|
setSilentCaptureResult((prev) => ({ path: '', success: false, isAnalyzing: false, error: '', templatePath: '' }));
|
|
497
461
|
}
|
|
498
462
|
} else {
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
regionSelection: false
|
|
502
|
-
});
|
|
503
|
-
actions.showCustomStepper(true);
|
|
463
|
+
// Retour au composant précédent (country_selection)
|
|
464
|
+
actions.previousComponent();
|
|
504
465
|
}
|
|
505
466
|
},
|
|
506
|
-
selectedDocumentType: locale === 'en' ? getDocumentTypeInfo(selectedDocumentType
|
|
467
|
+
selectedDocumentType: selectedDocumentType ? (locale === 'en' ? getDocumentTypeInfo(selectedDocumentType.type).name.en : getDocumentTypeInfo(selectedDocumentType.type).name.fr) : '',
|
|
507
468
|
step: state.currentComponentIndex + 1,
|
|
508
469
|
totalSteps: state.template.components.length,
|
|
509
470
|
side: currentSide,
|
|
@@ -568,30 +529,50 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({
|
|
|
568
529
|
/>) : null}
|
|
569
530
|
|
|
570
531
|
</View>
|
|
571
|
-
{/*
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
532
|
+
{/* Capture button si aucune image n'a été capturée */}
|
|
533
|
+
{!capturedImages[currentSide]?.dir && (
|
|
534
|
+
<Button
|
|
535
|
+
title={state.currentLanguage === "en" ? "Take Photo" : "Prendre une photo"}
|
|
536
|
+
onPress={() => {
|
|
537
|
+
setShowCamera(true);
|
|
538
|
+
actions.showCustomStepper(false);
|
|
539
|
+
}}
|
|
540
|
+
variant="primary"
|
|
541
|
+
size="large"
|
|
542
|
+
fullWidth
|
|
543
|
+
/>
|
|
544
|
+
)}
|
|
545
|
+
{/* retake button si une image a été capturée */}
|
|
546
|
+
{capturedImages[currentSide]?.dir && (
|
|
547
|
+
<>
|
|
548
|
+
<Button title={t('kyc.idCardCapture.retakeButton')} onPress={() => {
|
|
549
|
+
retakePicture(currentSide);
|
|
550
|
+
}}
|
|
551
|
+
variant="outline"
|
|
552
|
+
size="medium"
|
|
553
|
+
fullWidth
|
|
554
|
+
/>
|
|
555
|
+
<Button title={t('common.next')} onPress={() => {
|
|
556
|
+
if (!selectedDocumentType) {
|
|
557
|
+
showAlert('Error', 'Document type not selected');
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
if (currentSide === 'back' || selectedDocumentType.type === 'passport') {
|
|
561
|
+
actions.nextComponent();
|
|
562
|
+
return;
|
|
563
|
+
} else {
|
|
564
|
+
setShowCamera(true);
|
|
565
|
+
setCurrentSide('back');
|
|
566
|
+
setSilentCaptureResult((prev) => ({ path: '', success: false, isAnalyzing: false, error: '', mrz: '', templatePath: '' }));
|
|
567
|
+
setCropImageUri('');
|
|
568
|
+
}
|
|
569
|
+
}}
|
|
570
|
+
variant="primary"
|
|
571
|
+
size="large"
|
|
572
|
+
fullWidth
|
|
573
|
+
/>
|
|
574
|
+
</>
|
|
575
|
+
)}
|
|
595
576
|
</View>
|
|
596
577
|
</View>
|
|
597
578
|
</ScrollView>
|
|
@@ -757,43 +738,4 @@ const styles = StyleSheet.create({
|
|
|
757
738
|
marginTop: 8,
|
|
758
739
|
textAlign: 'center',
|
|
759
740
|
},
|
|
760
|
-
documentTypesContainer: {
|
|
761
|
-
// flex: 1,
|
|
762
|
-
// marginBottom: 16,
|
|
763
|
-
// paddingHorizontal: 16,
|
|
764
|
-
maxHeight: Dimensions.get('window').height - 400,
|
|
765
|
-
},
|
|
766
|
-
documentTypeButton: {
|
|
767
|
-
flexDirection: 'row',
|
|
768
|
-
alignItems: 'center',
|
|
769
|
-
backgroundColor: '#F8F9FA',
|
|
770
|
-
padding: 16,
|
|
771
|
-
marginBottom: 12,
|
|
772
|
-
borderRadius: 12,
|
|
773
|
-
borderWidth: 1,
|
|
774
|
-
borderColor: '#E9ECEF',
|
|
775
|
-
},
|
|
776
|
-
documentTypeIconContainer: {
|
|
777
|
-
|
|
778
|
-
width: 40, height: 40,
|
|
779
|
-
borderRadius: 10,
|
|
780
|
-
alignItems: 'center',
|
|
781
|
-
justifyContent: 'center',
|
|
782
|
-
marginRight: 16,
|
|
783
|
-
},
|
|
784
|
-
documentTypeIcon: {
|
|
785
|
-
fontSize: 24,
|
|
786
|
-
|
|
787
|
-
},
|
|
788
|
-
documentTypeName: {
|
|
789
|
-
flex: 1,
|
|
790
|
-
fontSize: 16,
|
|
791
|
-
fontWeight: '600',
|
|
792
|
-
color: '#333',
|
|
793
|
-
},
|
|
794
|
-
documentTypeArrow: {
|
|
795
|
-
fontSize: 18,
|
|
796
|
-
color: '#666',
|
|
797
|
-
fontWeight: 'bold',
|
|
798
|
-
},
|
|
799
741
|
});
|