@transfergratis/react-native-sdk 0.1.24 → 0.1.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +12 -5
- package/android/build/intermediates/aar_main_jar/debug/syncDebugLibJars/classes.jar +0 -0
- package/android/build/intermediates/annotations_typedef_file/debug/extractDebugAnnotations/typedefs.txt +0 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
- package/android/build/intermediates/incremental/debug-mergeJavaRes/merge-state +0 -0
- package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +61 -59
- package/android/build/intermediates/merged_java_res/debug/mergeDebugJavaResource/feature-transfergratis-react-native-sdk.jar +0 -0
- package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +12 -5
- package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
- package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
- package/android/build/outputs/aar/transfergratis-react-native-sdk-debug.aar +0 -0
- package/android/build/outputs/logs/manifest-merger-debug-report.txt +26 -34
- package/android/src/main/AndroidManifest.xml +10 -7
- package/build/components/KYCElements/AdditionalDocumentsTemplate.d.ts +12 -0
- package/build/components/KYCElements/AdditionalDocumentsTemplate.d.ts.map +1 -0
- package/build/components/KYCElements/AdditionalDocumentsTemplate.js +283 -0
- package/build/components/KYCElements/AdditionalDocumentsTemplate.js.map +1 -0
- package/build/components/KYCElements/EmailVerificationTemplate.d.ts +12 -0
- package/build/components/KYCElements/EmailVerificationTemplate.d.ts.map +1 -0
- package/build/components/KYCElements/EmailVerificationTemplate.js +193 -0
- package/build/components/KYCElements/EmailVerificationTemplate.js.map +1 -0
- package/build/components/KYCElements/IDCardCapture.d.ts.map +1 -1
- package/build/components/KYCElements/IDCardCapture.js +180 -7
- package/build/components/KYCElements/IDCardCapture.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCapture.d.ts +2 -0
- package/build/components/KYCElements/OrientationVideoCapture.d.ts.map +1 -1
- package/build/components/KYCElements/OrientationVideoCapture.js +2 -2
- package/build/components/KYCElements/OrientationVideoCapture.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.d.ts +2 -0
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.d.ts.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js +2 -2
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureFinal.d.ts +2 -0
- package/build/components/KYCElements/OrientationVideoCaptureFinal.d.ts.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureFinal.js +2 -2
- package/build/components/KYCElements/OrientationVideoCaptureFinal.js.map +1 -1
- package/build/components/KYCElements/PersonalInformationTemplate.d.ts +12 -0
- package/build/components/KYCElements/PersonalInformationTemplate.d.ts.map +1 -0
- package/build/components/KYCElements/PersonalInformationTemplate.js +120 -0
- package/build/components/KYCElements/PersonalInformationTemplate.js.map +1 -0
- package/build/components/KYCElements/PhoneVerificationTemplate.d.ts +12 -0
- package/build/components/KYCElements/PhoneVerificationTemplate.d.ts.map +1 -0
- package/build/components/KYCElements/PhoneVerificationTemplate.js +185 -0
- package/build/components/KYCElements/PhoneVerificationTemplate.js.map +1 -0
- package/build/components/KYCElements/SelfieCaptureTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/SelfieCaptureTemplate.js +7 -3
- package/build/components/KYCElements/SelfieCaptureTemplate.js.map +1 -1
- package/build/components/TemplateKYCExample.d.ts +4 -0
- package/build/components/TemplateKYCExample.d.ts.map +1 -1
- package/build/components/TemplateKYCExample.js +7 -30
- package/build/components/TemplateKYCExample.js.map +1 -1
- package/build/components/TemplateKYCFlowRefactored.d.ts +4 -0
- package/build/components/TemplateKYCFlowRefactored.d.ts.map +1 -1
- package/build/components/TemplateKYCFlowRefactored.js +14 -2
- package/build/components/TemplateKYCFlowRefactored.js.map +1 -1
- package/build/config/KYCConfig.d.ts +14 -0
- package/build/config/KYCConfig.d.ts.map +1 -0
- package/build/config/KYCConfig.js +26 -0
- package/build/config/KYCConfig.js.map +1 -0
- package/build/config/allowedDomains.d.ts.map +1 -1
- package/build/config/allowedDomains.js +4 -19
- package/build/config/allowedDomains.js.map +1 -1
- package/build/hooks/useOrientationVideo.d.ts +2 -1
- package/build/hooks/useOrientationVideo.d.ts.map +1 -1
- package/build/hooks/useOrientationVideo.js +3 -3
- package/build/hooks/useOrientationVideo.js.map +1 -1
- package/build/hooks/useTemplateKYCFlow.d.ts +6 -1
- package/build/hooks/useTemplateKYCFlow.d.ts.map +1 -1
- package/build/hooks/useTemplateKYCFlow.js +286 -23
- package/build/hooks/useTemplateKYCFlow.js.map +1 -1
- package/build/i18n/en/index.d.ts +40 -0
- package/build/i18n/en/index.d.ts.map +1 -1
- package/build/i18n/en/index.js +41 -1
- package/build/i18n/en/index.js.map +1 -1
- package/build/i18n/fr/index.d.ts +26 -0
- package/build/i18n/fr/index.d.ts.map +1 -1
- package/build/i18n/fr/index.js +27 -1
- package/build/i18n/fr/index.js.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -0
- package/build/index.js.map +1 -1
- package/build/modules/api/CardAuthentification.d.ts +24 -3
- package/build/modules/api/CardAuthentification.d.ts.map +1 -1
- package/build/modules/api/CardAuthentification.js +68 -10
- package/build/modules/api/CardAuthentification.js.map +1 -1
- package/build/modules/api/KYCService.d.ts +7 -7
- package/build/modules/api/KYCService.d.ts.map +1 -1
- package/build/modules/api/KYCService.js +101 -37
- package/build/modules/api/KYCService.js.map +1 -1
- package/build/modules/api/SelfieVerification.d.ts +3 -1
- package/build/modules/api/SelfieVerification.d.ts.map +1 -1
- package/build/modules/api/SelfieVerification.js +17 -1
- package/build/modules/api/SelfieVerification.js.map +1 -1
- package/build/modules/api/TemplateService.d.ts +0 -1
- package/build/modules/api/TemplateService.d.ts.map +1 -1
- package/build/modules/api/TemplateService.js +3 -3
- package/build/modules/api/TemplateService.js.map +1 -1
- package/build/types/KYC.types.d.ts +124 -3
- package/build/types/KYC.types.d.ts.map +1 -1
- package/build/types/KYC.types.js.map +1 -1
- package/build/types/env.types.d.ts +13 -0
- package/build/types/env.types.d.ts.map +1 -0
- package/build/types/env.types.js +2 -0
- package/build/types/env.types.js.map +1 -0
- package/build/utils/deviceDetection.d.ts +6 -0
- package/build/utils/deviceDetection.d.ts.map +1 -0
- package/build/utils/deviceDetection.js +12 -0
- package/build/utils/deviceDetection.js.map +1 -0
- package/build/utils/platformAlert.d.ts.map +1 -1
- package/build/utils/platformAlert.js.map +1 -1
- package/build/utils/template-transformer.d.ts.map +1 -1
- package/build/utils/template-transformer.js +12 -0
- package/build/utils/template-transformer.js.map +1 -1
- package/build/web/WebKYCEntry.d.ts.map +1 -1
- package/build/web/WebKYCEntry.js +82 -38
- package/build/web/WebKYCEntry.js.map +1 -1
- package/package.json +1 -1
- package/plugin/build/withVisionCamera.js +3 -4
- package/plugin/src/withVisionCamera.js +3 -4
- package/plugin/src/withVisionCamera.ts +3 -4
- package/src/components/KYCElements/AdditionalDocumentsTemplate.tsx +346 -0
- package/src/components/KYCElements/EmailVerificationTemplate.tsx +264 -0
- package/src/components/KYCElements/IDCardCapture.tsx +216 -15
- package/src/components/KYCElements/OrientationVideoCapture.tsx +4 -1
- package/src/components/KYCElements/OrientationVideoCaptureEnhanced.tsx +4 -1
- package/src/components/KYCElements/OrientationVideoCaptureFinal.tsx +4 -1
- package/src/components/KYCElements/PersonalInformationTemplate.tsx +158 -0
- package/src/components/KYCElements/PhoneVerificationTemplate.tsx +253 -0
- package/src/components/KYCElements/SelfieCaptureTemplate.tsx +6 -3
- package/src/components/TemplateKYCExample.tsx +31 -46
- package/src/components/TemplateKYCFlowRefactored.tsx +27 -1
- package/src/config/KYCConfig.ts +34 -0
- package/src/config/allowedDomains.ts +7 -26
- package/src/hooks/useOrientationVideo.ts +5 -4
- package/src/hooks/useTemplateKYCFlow.tsx +314 -21
- package/src/i18n/en/index.ts +43 -2
- package/src/i18n/fr/index.ts +28 -1
- package/src/index.ts +3 -0
- package/src/modules/api/CardAuthentification.ts +75 -10
- package/src/modules/api/KYCService.ts +117 -37
- package/src/modules/api/SelfieVerification.ts +25 -3
- package/src/modules/api/TemplateService.ts +4 -4
- package/src/types/KYC.types.ts +146 -3
- package/src/types/env.types.ts +13 -0
- package/src/utils/deviceDetection.ts +11 -0
- package/src/utils/platformAlert.ts +1 -0
- package/src/utils/template-transformer.ts +20 -8
- package/src/web/WebKYCEntry.tsx +112 -61
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useState, useCallback, useMemo, createContext, useContext, ReactNode, useEffect } from 'react';
|
|
2
2
|
import { KYCTemplate, TemplateState, TemplateActions, UseTemplateReturn, TemplateComponent, GovernmentDocumentType, VerificationState } from '../types/KYC.types';
|
|
3
|
+
import { KycEnvironment } from '../types/env.types';
|
|
3
4
|
import kycService, { authentification, truncateFields } from '../modules/api/KYCService';
|
|
4
5
|
import useI18n from './useI18n';
|
|
5
6
|
import { logger } from '../utils/logger';
|
|
@@ -15,6 +16,7 @@ interface TemplateKYCFlowContextType {
|
|
|
15
16
|
isComplete: boolean;
|
|
16
17
|
getLocalizedText: (text: { en: string; fr: string;[key: string]: string }) => string;
|
|
17
18
|
initializeSession: () => Promise<void>;
|
|
19
|
+
env: KycEnvironment;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
const TemplateKYCFlowContext = createContext<TemplateKYCFlowContextType | undefined>(undefined);
|
|
@@ -28,6 +30,9 @@ interface TemplateKYCFlowProviderProps {
|
|
|
28
30
|
onCancel?: () => void;
|
|
29
31
|
initialLanguage?: string;
|
|
30
32
|
apiKey?: string;
|
|
33
|
+
env?: KycEnvironment;
|
|
34
|
+
existingSessionId?: string;
|
|
35
|
+
initialStep?: number;
|
|
31
36
|
}
|
|
32
37
|
|
|
33
38
|
export const TemplateKYCFlowProvider: React.FC<TemplateKYCFlowProviderProps> = ({
|
|
@@ -38,8 +43,10 @@ export const TemplateKYCFlowProvider: React.FC<TemplateKYCFlowProviderProps> = (
|
|
|
38
43
|
onCancel,
|
|
39
44
|
initialLanguage = 'en',
|
|
40
45
|
apiKey,
|
|
46
|
+
env = 'PRODUCTION',
|
|
47
|
+
existingSessionId,
|
|
41
48
|
}) => {
|
|
42
|
-
const hookResult = useTemplateKYCFlow(template, onComplete, onError, onCancel, initialLanguage, apiKey);
|
|
49
|
+
const hookResult = useTemplateKYCFlow(template, onComplete, onError, onCancel, initialLanguage, apiKey, env, existingSessionId);
|
|
43
50
|
|
|
44
51
|
return (
|
|
45
52
|
<TemplateKYCFlowContext.Provider value={hookResult}>
|
|
@@ -64,6 +71,9 @@ export const useTemplateKYCFlow = (
|
|
|
64
71
|
onCancel?: () => void,
|
|
65
72
|
initialLanguage: string = 'en',
|
|
66
73
|
apiKey?: string,
|
|
74
|
+
env: KycEnvironment = 'PRODUCTION',
|
|
75
|
+
existingSessionId?: string,
|
|
76
|
+
initialStep?: number,
|
|
67
77
|
): UseTemplateReturn => {
|
|
68
78
|
|
|
69
79
|
const { setLocale } = useI18n();
|
|
@@ -131,29 +141,286 @@ export const useTemplateKYCFlow = (
|
|
|
131
141
|
const templateWithReviewAndVerification = useMemo(() => ensureVerificationProgressStep(templateWithReview), [templateWithReview, ensureVerificationProgressStep, apiKey]);
|
|
132
142
|
|
|
133
143
|
// État initial du flux
|
|
134
|
-
const buildInitialState = (): TemplateState =>
|
|
135
|
-
template
|
|
136
|
-
|
|
137
|
-
completedComponents: []
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
const buildInitialState = (): TemplateState => {
|
|
145
|
+
// Valider initialStep pour s'assurer qu'il est dans les limites du template
|
|
146
|
+
let validInitialStep = 0;
|
|
147
|
+
let completedComponents: number[] = [];
|
|
148
|
+
|
|
149
|
+
logger.log('buildInitialState called', { initialStep, existingSessionId });
|
|
150
|
+
|
|
151
|
+
if (initialStep !== undefined && initialStep >= 0) {
|
|
152
|
+
const maxIndex = templateWithReviewAndVerification.components.length - 1;
|
|
153
|
+
const requestedStep = Math.min(initialStep, maxIndex);
|
|
154
|
+
const requestedComponent = templateWithReviewAndVerification.components[requestedStep];
|
|
155
|
+
|
|
156
|
+
logger.log('Processing initialStep', {
|
|
157
|
+
initialStep,
|
|
158
|
+
requestedStep,
|
|
159
|
+
maxIndex,
|
|
160
|
+
componentType: requestedComponent?.type,
|
|
161
|
+
componentId: requestedComponent?.id
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// Si on reprend à l'étape id_card, on peut rester à id_card si on a une session existante
|
|
165
|
+
// car les données de country_selection peuvent être chargées depuis la session
|
|
166
|
+
if (requestedComponent?.type === 'id_card') {
|
|
167
|
+
// Si on a une session existante, on peut rester à id_card et charger les données
|
|
168
|
+
if (existingSessionId) {
|
|
169
|
+
logger.log('id_card with existing session - staying at id_card');
|
|
170
|
+
validInitialStep = requestedStep;
|
|
171
|
+
// Marquer les composants précédents comme complétés
|
|
172
|
+
if (validInitialStep > 0) {
|
|
173
|
+
completedComponents = templateWithReviewAndVerification.components
|
|
174
|
+
.slice(0, validInitialStep)
|
|
175
|
+
.map(component => component.id);
|
|
176
|
+
}
|
|
177
|
+
} else {
|
|
178
|
+
// Si pas de session, revenir à country_selection pour refaire le choix
|
|
179
|
+
const countrySelectionIndex = templateWithReviewAndVerification.components.findIndex(
|
|
180
|
+
c => c.type === 'country_selection'
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
logger.log('id_card without session - going back to country_selection', { countrySelectionIndex });
|
|
184
|
+
|
|
185
|
+
if (countrySelectionIndex >= 0) {
|
|
186
|
+
validInitialStep = countrySelectionIndex;
|
|
187
|
+
// Marquer les composants avant country_selection comme complétés
|
|
188
|
+
if (countrySelectionIndex > 0) {
|
|
189
|
+
completedComponents = templateWithReviewAndVerification.components
|
|
190
|
+
.slice(0, countrySelectionIndex)
|
|
191
|
+
.map(component => component.id);
|
|
192
|
+
}
|
|
193
|
+
} else {
|
|
194
|
+
// Si pas de country_selection, commencer au début
|
|
195
|
+
validInitialStep = 0;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
} else if (requestedComponent?.type === 'review_submit') {
|
|
199
|
+
// Si on reprend au review_submit, on ne marque pas les composants précédents
|
|
200
|
+
// pour permettre à l'utilisateur de revenir en arrière et vérifier/modifier les données
|
|
201
|
+
validInitialStep = requestedStep;
|
|
202
|
+
// Ne pas marquer les composants précédents comme complétés
|
|
203
|
+
completedComponents = [];
|
|
204
|
+
} else {
|
|
205
|
+
// Pour les autres composants (selfie, etc.), commencer directement à l'étape demandée
|
|
206
|
+
validInitialStep = requestedStep;
|
|
207
|
+
|
|
208
|
+
// Marquer tous les composants précédents comme complétés
|
|
209
|
+
// Cela permet à l'utilisateur de continuer sans refaire les étapes précédentes
|
|
210
|
+
if (validInitialStep > 0) {
|
|
211
|
+
completedComponents = templateWithReviewAndVerification.components
|
|
212
|
+
.slice(0, validInitialStep)
|
|
213
|
+
.map(component => component.id);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
logger.log('Final initial state', {
|
|
218
|
+
validInitialStep,
|
|
219
|
+
completedComponentsCount: completedComponents.length,
|
|
220
|
+
componentAtStep: templateWithReviewAndVerification.components[validInitialStep]?.type
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return {
|
|
225
|
+
template: templateWithReviewAndVerification,
|
|
226
|
+
currentComponentIndex: validInitialStep,
|
|
227
|
+
completedComponents: completedComponents,
|
|
228
|
+
componentData: {},
|
|
229
|
+
errors: {},
|
|
147
230
|
isProcessing: false,
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
231
|
+
currentLanguage: initialLanguage,
|
|
232
|
+
showCustomStepper: true,
|
|
233
|
+
session: {
|
|
234
|
+
session_id: existingSessionId || '',
|
|
235
|
+
token: '',
|
|
236
|
+
isInitialized: false,
|
|
237
|
+
isProcessing: false,
|
|
238
|
+
error: null,
|
|
239
|
+
},
|
|
240
|
+
verification: {
|
|
241
|
+
status: 'idle',
|
|
242
|
+
},
|
|
243
|
+
};
|
|
244
|
+
};
|
|
154
245
|
|
|
155
246
|
// État du flux
|
|
156
247
|
const [state, setState] = useState<TemplateState>(() => buildInitialState());
|
|
248
|
+
|
|
249
|
+
// Fonction utilitaire pour convertir base64 en data URI pour l'affichage
|
|
250
|
+
const base64ToDataUri = useCallback((base64: string, mimeType: string = 'image/jpeg'): string => {
|
|
251
|
+
// Si c'est déjà une data URI, retourner tel quel
|
|
252
|
+
if (base64.startsWith('data:')) {
|
|
253
|
+
return base64;
|
|
254
|
+
}
|
|
255
|
+
// Sinon, créer une data URI
|
|
256
|
+
return `data:${mimeType};base64,${base64}`;
|
|
257
|
+
}, []);
|
|
258
|
+
|
|
259
|
+
// Charger les données de session si on reprend une session existante
|
|
260
|
+
useEffect(() => {
|
|
261
|
+
const loadSessionData = async () => {
|
|
262
|
+
// Ne charger que si on a une session existante
|
|
263
|
+
if (!existingSessionId) {
|
|
264
|
+
logger.log('No existingSessionId, skipping data load');
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Si initialStep n'est pas défini ou est 0, on ne charge pas (début de session)
|
|
269
|
+
if (initialStep === undefined || initialStep === 0) {
|
|
270
|
+
logger.log('initialStep is 0 or undefined, skipping data load');
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Attendre que la session soit initialisée
|
|
275
|
+
if (!state.session.isInitialized || !state.session.session_id) {
|
|
276
|
+
logger.log('Session not initialized yet, waiting...', {
|
|
277
|
+
isInitialized: state.session.isInitialized,
|
|
278
|
+
sessionId: state.session.session_id
|
|
279
|
+
});
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
try {
|
|
284
|
+
logger.log('Loading session data for resume:', { sessionId: existingSessionId, step: initialStep });
|
|
285
|
+
const result = await kycService.getVerificationResult(state.session.session_id);
|
|
286
|
+
const sessionData = result[state.session.session_id]?.data;
|
|
287
|
+
|
|
288
|
+
if (sessionData) {
|
|
289
|
+
// Restaurer les données des composants depuis la session
|
|
290
|
+
// Utiliser 'as any' car VerificationResult peut avoir des propriétés dynamiques
|
|
291
|
+
const data: any = sessionData;
|
|
292
|
+
const restoredComponentData: Record<number, any> = {};
|
|
293
|
+
|
|
294
|
+
// Parcourir les composants jusqu'à l'étape initiale (incluse) pour restaurer leurs données
|
|
295
|
+
// Utiliser initialStep + 1 pour inclure le composant à l'étape initialStep
|
|
296
|
+
templateWithReviewAndVerification.components
|
|
297
|
+
.slice(0, initialStep + 1)
|
|
298
|
+
.forEach((component) => {
|
|
299
|
+
// Essayer de restaurer les données selon le type de composant
|
|
300
|
+
if (component.type === 'id_card' || component.type === 'file_upload') {
|
|
301
|
+
// Les documents peuvent être dans différentes structures
|
|
302
|
+
let documents: any = null;
|
|
303
|
+
|
|
304
|
+
// Chercher dans différentes structures possibles
|
|
305
|
+
if (data.documents) {
|
|
306
|
+
documents = data.documents;
|
|
307
|
+
} else if (data.user_data?.documents) {
|
|
308
|
+
documents = data.user_data.documents;
|
|
309
|
+
} else if (data.document_images) {
|
|
310
|
+
documents = data.document_images;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (documents) {
|
|
314
|
+
// Convertir les images base64 en format utilisable
|
|
315
|
+
const restoredDocuments: Record<string, any> = {};
|
|
316
|
+
|
|
317
|
+
Object.keys(documents).forEach((key) => {
|
|
318
|
+
const doc = documents[key];
|
|
319
|
+
if (typeof doc === 'object' && doc !== null) {
|
|
320
|
+
// Si on a un fichier base64, créer une structure avec dir et file
|
|
321
|
+
if (doc.file || doc.base64) {
|
|
322
|
+
const base64Data = doc.file || doc.base64;
|
|
323
|
+
restoredDocuments[key] = {
|
|
324
|
+
dir: base64ToDataUri(base64Data), // Utiliser data URI pour l'affichage
|
|
325
|
+
file: base64Data, // Garder le base64 pour l'envoi
|
|
326
|
+
mrz: doc.mrz || '',
|
|
327
|
+
templatePath: doc.templatePath || '',
|
|
328
|
+
};
|
|
329
|
+
} else {
|
|
330
|
+
// Sinon, garder la structure originale
|
|
331
|
+
restoredDocuments[key] = doc;
|
|
332
|
+
}
|
|
333
|
+
} else if (typeof doc === 'string') {
|
|
334
|
+
// Si c'est directement une string base64
|
|
335
|
+
restoredDocuments[key] = {
|
|
336
|
+
dir: base64ToDataUri(doc),
|
|
337
|
+
file: doc,
|
|
338
|
+
mrz: '',
|
|
339
|
+
templatePath: '',
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
if (Object.keys(restoredDocuments).length > 0) {
|
|
345
|
+
restoredComponentData[component.id] = restoredDocuments;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
} else if (component.type === 'selfie') {
|
|
349
|
+
// Les selfies peuvent être dans sessionData.selfie_info
|
|
350
|
+
if (data.selfie_info) {
|
|
351
|
+
const selfieData: Record<string, any> = {};
|
|
352
|
+
const selfieInfo: any = data.selfie_info;
|
|
353
|
+
|
|
354
|
+
// Si selfie_info contient une image
|
|
355
|
+
if (selfieInfo.image) {
|
|
356
|
+
const base64Image = selfieInfo.image;
|
|
357
|
+
selfieData['front'] = {
|
|
358
|
+
dir: base64ToDataUri(base64Image),
|
|
359
|
+
file: base64Image,
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Si on a plusieurs orientations
|
|
364
|
+
if (selfieInfo.orientations) {
|
|
365
|
+
Object.keys(selfieInfo.orientations).forEach((orientation) => {
|
|
366
|
+
const img = selfieInfo.orientations[orientation];
|
|
367
|
+
if (img) {
|
|
368
|
+
selfieData[orientation] = {
|
|
369
|
+
dir: base64ToDataUri(img),
|
|
370
|
+
file: img,
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
if (Object.keys(selfieData).length > 0) {
|
|
377
|
+
restoredComponentData[component.id] = selfieData;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
} else if (component.type === 'country_selection') {
|
|
381
|
+
// Les données de sélection de pays peuvent être dans metadata
|
|
382
|
+
if (data.metadata || data.user_data) {
|
|
383
|
+
restoredComponentData[component.id] = {
|
|
384
|
+
...(data.metadata || {}),
|
|
385
|
+
...(data.user_data || {}),
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
} else if (component.type === 'location') {
|
|
389
|
+
// Les données de localisation peuvent être dans metadata
|
|
390
|
+
if (data.metadata?.location || data.user_data?.location) {
|
|
391
|
+
restoredComponentData[component.id] = {
|
|
392
|
+
...(data.metadata?.location || {}),
|
|
393
|
+
...(data.user_data?.location || {}),
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
// Mettre à jour l'état avec les données restaurées
|
|
400
|
+
if (Object.keys(restoredComponentData).length > 0) {
|
|
401
|
+
logger.log('Session data restored - components:', Object.keys(restoredComponentData));
|
|
402
|
+
logger.log('Session data restored - sample data:', truncateFields(restoredComponentData));
|
|
403
|
+
setState(prev => ({
|
|
404
|
+
...prev,
|
|
405
|
+
componentData: {
|
|
406
|
+
...prev.componentData,
|
|
407
|
+
...restoredComponentData,
|
|
408
|
+
},
|
|
409
|
+
}));
|
|
410
|
+
logger.log('Component data updated in state');
|
|
411
|
+
} else {
|
|
412
|
+
logger.log('No component data to restore from session');
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
} catch (error) {
|
|
416
|
+
logger.error('Error loading session data:', truncateFields(error));
|
|
417
|
+
// Ne pas bloquer le flux si le chargement échoue
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
loadSessionData();
|
|
422
|
+
}, [existingSessionId, initialStep, state.session.isInitialized, state.session.session_id, templateWithReviewAndVerification.components, base64ToDataUri]);
|
|
423
|
+
|
|
157
424
|
const mapComponentTypeToAction = useCallback((type: TemplateComponent['type']): string | null => {
|
|
158
425
|
switch (type) {
|
|
159
426
|
case 'id_card':
|
|
@@ -301,7 +568,18 @@ export const useTemplateKYCFlow = (
|
|
|
301
568
|
|
|
302
569
|
const token = apiKey ? undefined : await authentification();
|
|
303
570
|
console.log('token in initializeSession', { token, apiKey },);
|
|
304
|
-
|
|
571
|
+
|
|
572
|
+
// Check if we already have a session ID from URL params (passed via state or prop)
|
|
573
|
+
let session;
|
|
574
|
+
const existingSessionId = state.session.session_id; // This might be set from initial props if we add logic for it
|
|
575
|
+
|
|
576
|
+
if (existingSessionId && existingSessionId.length > 0) {
|
|
577
|
+
logger.log('Resuming existing session:', existingSessionId);
|
|
578
|
+
// Verify existence/validity if needed, for now trust the ID and just fetch/use it
|
|
579
|
+
session = { session_id: existingSessionId };
|
|
580
|
+
} else {
|
|
581
|
+
session = await kycService.newSession({ token, apiKey });
|
|
582
|
+
}
|
|
305
583
|
|
|
306
584
|
// Align backend flow from step 0 with initialize_session
|
|
307
585
|
try {
|
|
@@ -381,6 +659,20 @@ export const useTemplateKYCFlow = (
|
|
|
381
659
|
// Welcome is valid once user has given consent (componentData is set when they click Get Started)
|
|
382
660
|
return componentData && componentData.consentGiven !== false;
|
|
383
661
|
|
|
662
|
+
case 'email_verification':
|
|
663
|
+
return componentData && componentData.verified === true;
|
|
664
|
+
|
|
665
|
+
case 'phone_verification':
|
|
666
|
+
return componentData && componentData.verified === true;
|
|
667
|
+
|
|
668
|
+
case 'personal_information':
|
|
669
|
+
return componentData && Object.keys(componentData).length > 0;
|
|
670
|
+
|
|
671
|
+
case 'additional_documents':
|
|
672
|
+
// Optional by default in template config, but if required we should check based on config
|
|
673
|
+
// For now, return true or check length if present
|
|
674
|
+
return true;
|
|
675
|
+
|
|
384
676
|
case 'review_submit':
|
|
385
677
|
return true;
|
|
386
678
|
default:
|
|
@@ -660,5 +952,6 @@ export const useTemplateKYCFlow = (
|
|
|
660
952
|
isComplete,
|
|
661
953
|
getLocalizedText,
|
|
662
954
|
initializeSession,
|
|
955
|
+
env,
|
|
663
956
|
};
|
|
664
957
|
};
|
package/src/i18n/en/index.ts
CHANGED
|
@@ -15,6 +15,19 @@ export const en = {
|
|
|
15
15
|
success: 'Success',
|
|
16
16
|
warning: 'Warning',
|
|
17
17
|
info: 'Information',
|
|
18
|
+
invalidCode: 'Invalid code',
|
|
19
|
+
resendCode: 'Resend code',
|
|
20
|
+
verify: 'Verify',
|
|
21
|
+
sendCode: 'Send code',
|
|
22
|
+
resend: 'Resend',
|
|
23
|
+
email: 'Email',
|
|
24
|
+
otp: 'OTP',
|
|
25
|
+
verificationCode: 'Verification code',
|
|
26
|
+
changeEmail: 'Change Email',
|
|
27
|
+
processing: "Processing",
|
|
28
|
+
codeResent: 'Code Resent',
|
|
29
|
+
codeResentMessage: 'Code resent to %{email}',
|
|
30
|
+
phone: 'Phone number with country code',
|
|
18
31
|
},
|
|
19
32
|
|
|
20
33
|
// KYC Flow
|
|
@@ -22,7 +35,22 @@ export const en = {
|
|
|
22
35
|
title: 'Identity Verification',
|
|
23
36
|
subtitle: 'Complete your identity verification to continue',
|
|
24
37
|
step: 'Step %{current} of %{total}',
|
|
25
|
-
|
|
38
|
+
enterCodeSent: "Enter code sent",
|
|
39
|
+
|
|
40
|
+
additionalDocs: {
|
|
41
|
+
title: 'Additional Documents',
|
|
42
|
+
add: "Press to select file",
|
|
43
|
+
subtitle: 'Upload additional documents to complete your identity verification',
|
|
44
|
+
uploadButton: 'Upload',
|
|
45
|
+
uploadButtonText: 'Upload',
|
|
46
|
+
uploadSubtext: 'Upload a clear photo of your document',
|
|
47
|
+
supportedFormats: 'Supported formats: JPG, PNG, PDF',
|
|
48
|
+
maxSize: 'Max file size: 10MB',
|
|
49
|
+
processing: 'Processing file...',
|
|
50
|
+
success: 'File uploaded successfully',
|
|
51
|
+
error: 'Failed to upload file. Please try again.'
|
|
52
|
+
},
|
|
53
|
+
|
|
26
54
|
// Initialization
|
|
27
55
|
initialization: {
|
|
28
56
|
title: 'Welcome to Identity Verification',
|
|
@@ -98,6 +126,9 @@ export const en = {
|
|
|
98
126
|
success: 'ID captured successfully',
|
|
99
127
|
error: 'Failed to capture ID. Please try again.',
|
|
100
128
|
captureTitle: '%{side} side of your government document',
|
|
129
|
+
continueOnPhone: 'Continue on Phone',
|
|
130
|
+
continueOnMobile: 'Continue on Mobile',
|
|
131
|
+
scanQrCode: 'Scan this QR code with your phone to continue the verification process.',
|
|
101
132
|
},
|
|
102
133
|
|
|
103
134
|
// Selfie Capture
|
|
@@ -214,7 +245,17 @@ export const en = {
|
|
|
214
245
|
cameraError: 'Camera error. Please try again.',
|
|
215
246
|
fileError: 'File error. Please try again.',
|
|
216
247
|
timeoutError: 'Request timeout. Please try again.',
|
|
217
|
-
unknownError: 'An unknown error occurred. Please try again.'
|
|
248
|
+
unknownError: 'An unknown error occurred. Please try again.',
|
|
249
|
+
wrongCode: "Wrong code",
|
|
250
|
+
invalidCode: "Invalid code",
|
|
251
|
+
invalidEmail: "Invalid email",
|
|
252
|
+
invalidPhone: "Invalid phone",
|
|
253
|
+
invalidDate: "Invalid date",
|
|
254
|
+
minLength: "Min length",
|
|
255
|
+
maxLength: "Max length",
|
|
256
|
+
invalidFormat: "Invalid format",
|
|
257
|
+
fileTooLarge: "File too large",
|
|
258
|
+
fileTypeNotSupported: "File type not supported",
|
|
218
259
|
},
|
|
219
260
|
|
|
220
261
|
// Validation messages
|
package/src/i18n/fr/index.ts
CHANGED
|
@@ -15,6 +15,20 @@ export const fr = {
|
|
|
15
15
|
success: 'Succès',
|
|
16
16
|
warning: 'Avertissement',
|
|
17
17
|
info: 'Information',
|
|
18
|
+
invalidCode: 'Code invalide',
|
|
19
|
+
resendCode: 'Renvoyer le code',
|
|
20
|
+
verify: 'Vérifier',
|
|
21
|
+
sendCode: 'Envoyer le code',
|
|
22
|
+
resend: 'Renvoyer',
|
|
23
|
+
email: 'Email',
|
|
24
|
+
otp: 'OTP',
|
|
25
|
+
verificationCode: 'Code de vérification',
|
|
26
|
+
changeEmail: 'Changer d\'email',
|
|
27
|
+
processing: "Traitement",
|
|
28
|
+
codeResent: 'Code Renvoyé',
|
|
29
|
+
codeResentMessage: 'Code renvoyé à %{email}',
|
|
30
|
+
phone: 'Numéro de téléphone avec code pays',
|
|
31
|
+
|
|
18
32
|
},
|
|
19
33
|
|
|
20
34
|
// KYC Flow
|
|
@@ -97,6 +111,9 @@ export const fr = {
|
|
|
97
111
|
success: 'Document d\'identité capturé avec succès',
|
|
98
112
|
error: 'Échec de la capture du document. Veuillez réessayer.',
|
|
99
113
|
captureTitle: '%{side} de votre document d\'identité',
|
|
114
|
+
continueOnPhone: 'Continuer sur mobile',
|
|
115
|
+
continueOnMobile: 'Continuer sur mobile',
|
|
116
|
+
scanQrCode: 'Scannez ce code QR avec votre téléphone pour continuer la vérification.',
|
|
100
117
|
},
|
|
101
118
|
|
|
102
119
|
// Selfie Capture
|
|
@@ -213,7 +230,17 @@ export const fr = {
|
|
|
213
230
|
cameraError: 'Erreur caméra. Veuillez réessayer.',
|
|
214
231
|
fileError: 'Erreur fichier. Veuillez réessayer.',
|
|
215
232
|
timeoutError: 'Délai d\'attente dépassé. Veuillez réessayer.',
|
|
216
|
-
unknownError: 'Une erreur inconnue s\'est produite. Veuillez réessayer.'
|
|
233
|
+
unknownError: 'Une erreur inconnue s\'est produite. Veuillez réessayer.',
|
|
234
|
+
wrongCode: "Wrong code",
|
|
235
|
+
invalidCode: "Invalid code",
|
|
236
|
+
invalidEmail: "Invalid email",
|
|
237
|
+
invalidPhone: "Invalid phone",
|
|
238
|
+
invalidDate: "Invalid date",
|
|
239
|
+
minLength: "Min length",
|
|
240
|
+
maxLength: "Max length",
|
|
241
|
+
invalidFormat: "Invalid format",
|
|
242
|
+
fileTooLarge: "File too large",
|
|
243
|
+
fileTypeNotSupported: "File type not supported",
|
|
217
244
|
},
|
|
218
245
|
|
|
219
246
|
validation: {
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,9 @@ export * from './TransfergratisSdk.types';
|
|
|
4
4
|
// Export KYC types
|
|
5
5
|
export * from './types/KYC.types';
|
|
6
6
|
|
|
7
|
+
// Export Environment types
|
|
8
|
+
export * from './types/env.types';
|
|
9
|
+
|
|
7
10
|
|
|
8
11
|
export { TemplateKYCExample as LauchTransferGratisKYC } from './components/TemplateKYCExample';
|
|
9
12
|
|
|
@@ -1,14 +1,40 @@
|
|
|
1
1
|
import kycService, { authentification, errorMessage, truncateFields } from "./KYCService";
|
|
2
2
|
import { cropByObb } from "../../utils/cropByObb";
|
|
3
3
|
import { GovernmentDocumentType, IBbox } from "../../types/KYC.types";
|
|
4
|
+
import { KycEnvironment } from "../../types/env.types";
|
|
4
5
|
import { logger } from "../../utils/logger";
|
|
5
6
|
|
|
6
|
-
export async function frontVerification(result: { path?: string, regionMapping: { authMethod: string[], mrzTypes: string[] }, selectedDocumentType: string, code: string, currentSide: string, templatePath?: string, mrzType?: string }) {
|
|
7
|
+
export async function frontVerification(result: { path?: string, regionMapping: { authMethod: string[], mrzTypes: string[] }, selectedDocumentType: string, code: string, currentSide: string, templatePath?: string, mrzType?: string }, env: KycEnvironment = 'PRODUCTION') {
|
|
7
8
|
try {
|
|
8
9
|
console.log("Front verification START", JSON.stringify({ result }, null, 2));
|
|
9
10
|
logger.log("Front verification", JSON.stringify({ result }, null, 2));
|
|
11
|
+
|
|
12
|
+
// SANDBOX mode: skip AI verification and return mock response
|
|
13
|
+
if (env === 'SANDBOX') {
|
|
14
|
+
console.log("SANDBOX mode: Skipping AI verification for front document");
|
|
15
|
+
logger.log("SANDBOX mode: Returning mock front verification response");
|
|
16
|
+
const mockBbox: IBbox = { minX: 50, minY: 50, width: 200, height: 200 };
|
|
17
|
+
const mockResponse = {
|
|
18
|
+
result: true,
|
|
19
|
+
detail: [{ confidence: 0.95 }],
|
|
20
|
+
card_obb: { x: 50, y: 50, width: 200, height: 200 },
|
|
21
|
+
bbox: mockBbox,
|
|
22
|
+
...(result.regionMapping.authMethod.includes('MRZ') ? {
|
|
23
|
+
mrz: {
|
|
24
|
+
success: true,
|
|
25
|
+
parsed_data: {
|
|
26
|
+
status: 'success',
|
|
27
|
+
document_type: result.selectedDocumentType,
|
|
28
|
+
mrz_type: result.mrzType || 'TD1'
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
} : {})
|
|
32
|
+
};
|
|
33
|
+
return mockResponse;
|
|
34
|
+
}
|
|
35
|
+
|
|
10
36
|
const token = await authentification();
|
|
11
|
-
const detected = await kycService.detectFaceOnId(result?.path || '', token, result?.selectedDocumentType || '')
|
|
37
|
+
const detected = await kycService.detectFaceOnId(result?.path || '', token, result?.selectedDocumentType || '', env)
|
|
12
38
|
|
|
13
39
|
if (!detected.result) {
|
|
14
40
|
throw new Error('Aucun visage détecté sur la carte. Veuillez reprendre.');
|
|
@@ -36,7 +62,8 @@ export async function frontVerification(result: { path?: string, regionMapping:
|
|
|
36
62
|
token: token,
|
|
37
63
|
template_path: result?.templatePath || '',
|
|
38
64
|
mrz_type: result?.mrzType || ''
|
|
39
|
-
}
|
|
65
|
+
},
|
|
66
|
+
env)
|
|
40
67
|
|
|
41
68
|
}
|
|
42
69
|
|
|
@@ -47,10 +74,38 @@ export async function frontVerification(result: { path?: string, regionMapping:
|
|
|
47
74
|
}
|
|
48
75
|
}
|
|
49
76
|
|
|
50
|
-
export async function backVerification(result: { path?: string, regionMapping: { authMethod: string[], mrzTypes: string[] }, selectedDocumentType: string, code: string, currentSide: string, templatePath?: string, mrzType?: string }) {
|
|
77
|
+
export async function backVerification(result: { path?: string, regionMapping: { authMethod: string[], mrzTypes: string[] }, selectedDocumentType: string, code: string, currentSide: string, templatePath?: string, mrzType?: string }, env: KycEnvironment = 'PRODUCTION') {
|
|
51
78
|
try {
|
|
52
79
|
if (!result.path) throw new Error('No path provided');
|
|
53
80
|
logger.log("result.regionMapping", result.regionMapping, result.currentSide, result.code);
|
|
81
|
+
|
|
82
|
+
// SANDBOX mode: skip AI verification and return mock response
|
|
83
|
+
if (env === 'SANDBOX') {
|
|
84
|
+
console.log("SANDBOX mode: Skipping AI verification for back document");
|
|
85
|
+
logger.log("SANDBOX mode: Returning mock back verification response");
|
|
86
|
+
const mockBbox: IBbox = { minX: 50, minY: 50, width: 200, height: 200 };
|
|
87
|
+
|
|
88
|
+
if (result.regionMapping.authMethod.includes('MRZ')) {
|
|
89
|
+
return {
|
|
90
|
+
success: true,
|
|
91
|
+
parsed_data: {
|
|
92
|
+
status: 'success',
|
|
93
|
+
document_type: result.selectedDocumentType,
|
|
94
|
+
mrz_type: result.mrzType || 'TD1'
|
|
95
|
+
},
|
|
96
|
+
bbox: mockBbox,
|
|
97
|
+
card_obb: { x: 50, y: 50, width: 200, height: 200 }
|
|
98
|
+
};
|
|
99
|
+
} else if (result.regionMapping.authMethod.includes('2D_barcode')) {
|
|
100
|
+
return {
|
|
101
|
+
barcode_data: 'SANDBOX_MOCK_BARCODE',
|
|
102
|
+
bbox: mockBbox,
|
|
103
|
+
card_obb: { x: 50, y: 50, width: 200, height: 200 }
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
return { bbox: mockBbox };
|
|
107
|
+
}
|
|
108
|
+
|
|
54
109
|
const token = await authentification();
|
|
55
110
|
|
|
56
111
|
|
|
@@ -68,7 +123,7 @@ export async function backVerification(result: { path?: string, regionMapping: {
|
|
|
68
123
|
token: token,
|
|
69
124
|
template_path: result?.templatePath || '',
|
|
70
125
|
mrz_type: result?.mrzType || ''
|
|
71
|
-
});
|
|
126
|
+
}, env);
|
|
72
127
|
let bbox: IBbox | undefined;
|
|
73
128
|
let croppedBase64: string | undefined;
|
|
74
129
|
|
|
@@ -82,7 +137,7 @@ export async function backVerification(result: { path?: string, regionMapping: {
|
|
|
82
137
|
} catch (mrzError: any) {
|
|
83
138
|
logger.log("MRZ échoué, tentative d'extraction barcode");
|
|
84
139
|
try {
|
|
85
|
-
const barcode = await kycService.extractBarcode({ fileUri: result.path!, token: token });
|
|
140
|
+
const barcode = await kycService.extractBarcode({ fileUri: result.path!, token: token }, env);
|
|
86
141
|
return barcode;
|
|
87
142
|
} catch (barcodeError: any) {
|
|
88
143
|
throw new Error(`MRZ et barcode ont échoué. MRZ: ${mrzError?.message}, Barcode: ${barcodeError?.message}`);
|
|
@@ -108,7 +163,7 @@ export async function backVerification(result: { path?: string, regionMapping: {
|
|
|
108
163
|
token: token,
|
|
109
164
|
template_path: result?.templatePath || '',
|
|
110
165
|
mrz_type: result?.mrzType || ''
|
|
111
|
-
});
|
|
166
|
+
}, env);
|
|
112
167
|
let bbox: IBbox | undefined;
|
|
113
168
|
try {
|
|
114
169
|
const crop = await cropByObb(result?.path || '', (mrz as any).card_obb);
|
|
@@ -123,7 +178,7 @@ export async function backVerification(result: { path?: string, regionMapping: {
|
|
|
123
178
|
if (result.regionMapping.authMethod.length > 0 && result.regionMapping.authMethod.includes('2D_barcode')) {
|
|
124
179
|
try {
|
|
125
180
|
logger.log("Tentative d'extraction barcode");
|
|
126
|
-
const barcode = await kycService.extractBarcode({ fileUri: result.path!, token: token });
|
|
181
|
+
const barcode = await kycService.extractBarcode({ fileUri: result.path!, token: token }, env);
|
|
127
182
|
let bbox: IBbox | undefined;
|
|
128
183
|
try {
|
|
129
184
|
const crop = await cropByObb(result?.path || '', (barcode as any).card_obb);
|
|
@@ -145,10 +200,20 @@ export async function backVerification(result: { path?: string, regionMapping: {
|
|
|
145
200
|
* @param result
|
|
146
201
|
* @returns
|
|
147
202
|
*/
|
|
148
|
-
export async function checkTemplateType(result: { path?: string, docType: string, docRegion: string, postfix: string }) {
|
|
203
|
+
export async function checkTemplateType(result: { path?: string, docType: string, docRegion: string, postfix: string }, env: KycEnvironment = 'PRODUCTION') {
|
|
149
204
|
try {
|
|
205
|
+
// SANDBOX mode: skip AI verification and return mock response
|
|
206
|
+
if (env === 'SANDBOX') {
|
|
207
|
+
console.log("SANDBOX mode: Skipping AI template type check");
|
|
208
|
+
logger.log("SANDBOX mode: Returning mock template type response");
|
|
209
|
+
return {
|
|
210
|
+
template_path: `templates/${result.docType}_${result.docRegion}_${result.postfix}.jpg`,
|
|
211
|
+
card_obb: { x: 50, y: 50, width: 200, height: 200 }
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
150
215
|
const token = await authentification();
|
|
151
|
-
const templateType = await kycService.checkTemplateType({ fileUri: result.path || '', docType: result?.docType as GovernmentDocumentType, docRegion: result?.docRegion || "", postfix: result?.postfix, token: token });
|
|
216
|
+
const templateType = await kycService.checkTemplateType({ fileUri: result.path || '', docType: result?.docType as GovernmentDocumentType, docRegion: result?.docRegion || "", postfix: result?.postfix, token: token }, env);
|
|
152
217
|
|
|
153
218
|
logger.log("templateType result", JSON.stringify(truncateFields(templateType), null, 2));
|
|
154
219
|
return templateType;
|