@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
|
@@ -70,12 +70,12 @@ export const useTemplateKYCFlow = (
|
|
|
70
70
|
|
|
71
71
|
useEffect(() => {
|
|
72
72
|
setLocale(initialLanguage);
|
|
73
|
-
}, [initialLanguage]);
|
|
73
|
+
}, [initialLanguage, apiKey]);
|
|
74
74
|
|
|
75
75
|
// Helpers to align SDK steps with backend actions/templates
|
|
76
76
|
const isUiOnlyStep = useCallback((type: TemplateComponent['type']) => {
|
|
77
77
|
return type === 'verification_progress';
|
|
78
|
-
}, []);
|
|
78
|
+
}, [apiKey]);
|
|
79
79
|
|
|
80
80
|
|
|
81
81
|
|
|
@@ -101,7 +101,7 @@ export const useTemplateKYCFlow = (
|
|
|
101
101
|
...tpl,
|
|
102
102
|
components: [...tpl.components, reviewComponent],
|
|
103
103
|
};
|
|
104
|
-
}, []);
|
|
104
|
+
}, [apiKey]);
|
|
105
105
|
|
|
106
106
|
const ensureVerificationProgressStep = useCallback((tpl: KYCTemplate): KYCTemplate => {
|
|
107
107
|
const hasVerification = tpl.components.some(c => c.type === 'verification_progress');
|
|
@@ -125,10 +125,10 @@ export const useTemplateKYCFlow = (
|
|
|
125
125
|
...tpl,
|
|
126
126
|
components: [...tpl.components, verificationComponent],
|
|
127
127
|
};
|
|
128
|
-
}, []);
|
|
128
|
+
}, [apiKey]);
|
|
129
129
|
|
|
130
|
-
const templateWithReview = useMemo(() => ensureReviewSubmitStep(template), [template, ensureReviewSubmitStep]);
|
|
131
|
-
const templateWithReviewAndVerification = useMemo(() => ensureVerificationProgressStep(templateWithReview), [templateWithReview, ensureVerificationProgressStep]);
|
|
130
|
+
const templateWithReview = useMemo(() => ensureReviewSubmitStep(template), [template, ensureReviewSubmitStep, apiKey]);
|
|
131
|
+
const templateWithReviewAndVerification = useMemo(() => ensureVerificationProgressStep(templateWithReview), [templateWithReview, ensureVerificationProgressStep, apiKey]);
|
|
132
132
|
|
|
133
133
|
// État initial du flux
|
|
134
134
|
const buildInitialState = (): TemplateState => ({
|
|
@@ -168,6 +168,9 @@ export const useTemplateKYCFlow = (
|
|
|
168
168
|
case 'country_selection':
|
|
169
169
|
// No direct backend action; pack into metadata of next actionable step
|
|
170
170
|
return null;
|
|
171
|
+
case 'welcome':
|
|
172
|
+
// UI-only step, no backend action needed
|
|
173
|
+
return null;
|
|
171
174
|
case 'initialization':
|
|
172
175
|
return 'initialize_session';
|
|
173
176
|
case 'verification_progress':
|
|
@@ -186,7 +189,7 @@ export const useTemplateKYCFlow = (
|
|
|
186
189
|
if (hasLocation && hasSelfie && hasIdDoc) return 'enhanced_id';
|
|
187
190
|
if (hasSelfie && hasIdDoc) return 'standard_passport';
|
|
188
191
|
return 'standard_passport';
|
|
189
|
-
}, []);
|
|
192
|
+
}, [apiKey]);
|
|
190
193
|
|
|
191
194
|
|
|
192
195
|
const computeServerStepIndex = useCallback((tpl: KYCTemplate, upToIndex: number): number => {
|
|
@@ -195,11 +198,13 @@ export const useTemplateKYCFlow = (
|
|
|
195
198
|
.slice(0, upToIndex)
|
|
196
199
|
.filter(c => !isUiOnlyStep(c.type) && mapComponentTypeToAction(c.type) !== null);
|
|
197
200
|
return actionable.length; // 0-based
|
|
198
|
-
}, [isUiOnlyStep, mapComponentTypeToAction]);
|
|
201
|
+
}, [isUiOnlyStep, mapComponentTypeToAction, apiKey]);
|
|
199
202
|
|
|
200
203
|
// Build backend-friendly payloads per action
|
|
201
204
|
const buildPayloadForComponent = useCallback((action: string | null, component: TemplateComponent, rawData: any, templateId: string, step: number) => {
|
|
202
|
-
|
|
205
|
+
console.log('apiKey in buildPayloadForComponent', apiKey);
|
|
206
|
+
|
|
207
|
+
const base = { template_id: templateId || null, templateId: templateId || null, step: component.order, permissionGranted: true } as any;
|
|
203
208
|
if (!action) {
|
|
204
209
|
return base;
|
|
205
210
|
}
|
|
@@ -228,9 +233,12 @@ export const useTemplateKYCFlow = (
|
|
|
228
233
|
const idCardID = Object.keys(state.componentData).find((c: string) => c === "1");
|
|
229
234
|
if (idCardID) {
|
|
230
235
|
const _idCardData = state.componentData[idCardID];
|
|
231
|
-
|
|
236
|
+
const documentType = _idCardData?.documentType;
|
|
237
|
+
// Map national_id to identity_card for selfie capture
|
|
238
|
+
const mappedDocumentType = documentType === 'national_id' ? 'identity_card' : (documentType as GovernmentDocumentType || 'identity_card');
|
|
239
|
+
return { ...base, documents, country: _idCardData?.country || '', documentType: mappedDocumentType };
|
|
232
240
|
}
|
|
233
|
-
|
|
241
|
+
return { ...base, documents };
|
|
234
242
|
}
|
|
235
243
|
|
|
236
244
|
if (action === 'location_permission') {
|
|
@@ -239,45 +247,44 @@ export const useTemplateKYCFlow = (
|
|
|
239
247
|
|
|
240
248
|
// Default: wrap as metadata
|
|
241
249
|
return { ...base, metadata: { ...(rawData || {}) } };
|
|
242
|
-
}, [state.componentData]);
|
|
250
|
+
}, [state.componentData, apiKey]);
|
|
243
251
|
// Ensure the template contains a final review step
|
|
244
252
|
|
|
245
|
-
|
|
246
|
-
|
|
253
|
+
// console.log('apiKey in useTemplateKYCFlow', apiKey);
|
|
247
254
|
|
|
248
255
|
|
|
249
256
|
// Composant actuel
|
|
250
257
|
const currentComponent = useMemo(() => {
|
|
251
258
|
return state.template.components[state.currentComponentIndex] || null;
|
|
252
|
-
}, [state.template.components, state.currentComponentIndex]);
|
|
259
|
+
}, [state.template.components, state.currentComponentIndex, apiKey]);
|
|
253
260
|
|
|
254
261
|
// Progression du flux
|
|
255
262
|
const progress = useMemo(() => {
|
|
256
263
|
return state.template.components.length > 0
|
|
257
264
|
? ((state.currentComponentIndex + 1) / state.template.components.length) * 100
|
|
258
265
|
: 0;
|
|
259
|
-
}, [state.currentComponentIndex, state.template.components.length]);
|
|
266
|
+
}, [state.currentComponentIndex, state.template.components.length, apiKey]);
|
|
260
267
|
|
|
261
268
|
// Vérifications de navigation
|
|
262
269
|
const canGoNext = useMemo(() => {
|
|
263
270
|
return state.currentComponentIndex < state.template.components.length - 1;
|
|
264
|
-
}, [state.currentComponentIndex, state.template.components.length]);
|
|
271
|
+
}, [state.currentComponentIndex, state.template.components.length, apiKey]);
|
|
265
272
|
|
|
266
273
|
const canGoPrevious = useMemo(() => {
|
|
267
274
|
return state.currentComponentIndex > 0;
|
|
268
|
-
}, [state.currentComponentIndex]);
|
|
275
|
+
}, [state.currentComponentIndex, apiKey]);
|
|
269
276
|
|
|
270
277
|
const isComplete = useMemo(() => {
|
|
271
278
|
const atReview = state.template.components[state.currentComponentIndex]?.type === 'review_submit';
|
|
272
279
|
const nonReviewCount = state.template.components.filter(c => c.type !== 'review_submit').length;
|
|
273
280
|
const completedNonReview = state.completedComponents.length >= nonReviewCount;
|
|
274
281
|
return atReview && completedNonReview;
|
|
275
|
-
}, [state.currentComponentIndex, state.completedComponents.length, state.template.components]);
|
|
282
|
+
}, [state.currentComponentIndex, state.completedComponents.length, state.template.components, apiKey]);
|
|
276
283
|
|
|
277
284
|
// Fonction pour obtenir le texte localisé
|
|
278
285
|
const getLocalizedText = useCallback((text: { en: string; fr: string;[key: string]: string }): string => {
|
|
279
286
|
return text[state.currentLanguage] || text.en || '';
|
|
280
|
-
}, [state.currentLanguage]);
|
|
287
|
+
}, [state.currentLanguage, apiKey]);
|
|
281
288
|
|
|
282
289
|
const initializeSession = useCallback(async () => {
|
|
283
290
|
try {
|
|
@@ -292,9 +299,9 @@ export const useTemplateKYCFlow = (
|
|
|
292
299
|
}));
|
|
293
300
|
logger.log('Initializing session');
|
|
294
301
|
|
|
295
|
-
const token = await authentification();
|
|
296
|
-
|
|
297
|
-
const session = await kycService.newSession(token);
|
|
302
|
+
const token = apiKey ? undefined : await authentification();
|
|
303
|
+
console.log('token in initializeSession', { token, apiKey },);
|
|
304
|
+
const session = await kycService.newSession({token,apiKey});
|
|
298
305
|
|
|
299
306
|
// Align backend flow from step 0 with initialize_session
|
|
300
307
|
try {
|
|
@@ -305,7 +312,8 @@ export const useTemplateKYCFlow = (
|
|
|
305
312
|
data: { template_id: templateId, metadata: { language: initialLanguage } },
|
|
306
313
|
templateId: templateId,
|
|
307
314
|
token: token,
|
|
308
|
-
action: 'initialize_session'
|
|
315
|
+
action: 'initialize_session',
|
|
316
|
+
apiKey: apiKey,
|
|
309
317
|
});
|
|
310
318
|
} catch (e) {
|
|
311
319
|
logger.error('Error initializing session:', JSON.stringify(e, null, 2));
|
|
@@ -336,7 +344,7 @@ export const useTemplateKYCFlow = (
|
|
|
336
344
|
},
|
|
337
345
|
}));
|
|
338
346
|
}
|
|
339
|
-
}, []);
|
|
347
|
+
}, [apiKey]);
|
|
340
348
|
// Validation d'un composant
|
|
341
349
|
const validateComponent = useCallback((componentId: number): boolean => {
|
|
342
350
|
const component = state.template.components.find(c => c.id === componentId);
|
|
@@ -369,12 +377,16 @@ export const useTemplateKYCFlow = (
|
|
|
369
377
|
|
|
370
378
|
return componentData && componentData.code && componentData.regionMapping;
|
|
371
379
|
|
|
380
|
+
case 'welcome':
|
|
381
|
+
// Welcome is valid once user has given consent (componentData is set when they click Get Started)
|
|
382
|
+
return componentData && componentData.consentGiven !== false;
|
|
383
|
+
|
|
372
384
|
case 'review_submit':
|
|
373
385
|
return true;
|
|
374
386
|
default:
|
|
375
387
|
return false;
|
|
376
388
|
}
|
|
377
|
-
}, [state.template.components, state.componentData]);
|
|
389
|
+
}, [state.template.components, state.componentData, apiKey]);
|
|
378
390
|
|
|
379
391
|
// Actions du flux
|
|
380
392
|
const actions: TemplateActions = {
|
|
@@ -392,7 +404,7 @@ export const useTemplateKYCFlow = (
|
|
|
392
404
|
isProcessing: false,
|
|
393
405
|
verification: { status: 'idle', result: undefined },
|
|
394
406
|
}));
|
|
395
|
-
}, [ensureReviewSubmitStep, ensureVerificationProgressStep]),
|
|
407
|
+
}, [ensureReviewSubmitStep, ensureVerificationProgressStep, apiKey]),
|
|
396
408
|
|
|
397
409
|
// Passer au composant suivant
|
|
398
410
|
nextComponent: useCallback(async () => {
|
|
@@ -401,10 +413,16 @@ export const useTemplateKYCFlow = (
|
|
|
401
413
|
const currentComp = state.template.components[state.currentComponentIndex];
|
|
402
414
|
if (!currentComp) return;
|
|
403
415
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
isProcessing
|
|
407
|
-
|
|
416
|
+
// Prevent multiple simultaneous calls
|
|
417
|
+
setState(prev => {
|
|
418
|
+
if (prev.isProcessing) {
|
|
419
|
+
return prev;
|
|
420
|
+
}
|
|
421
|
+
return {
|
|
422
|
+
...prev,
|
|
423
|
+
isProcessing: true,
|
|
424
|
+
};
|
|
425
|
+
});
|
|
408
426
|
// Valider le composant actuel
|
|
409
427
|
if (!validateComponent(currentComp.id)) {
|
|
410
428
|
setState(prev => ({
|
|
@@ -421,7 +439,13 @@ export const useTemplateKYCFlow = (
|
|
|
421
439
|
|
|
422
440
|
try {
|
|
423
441
|
const component = state.template.components.find(c => c.id === currentComp.id);
|
|
424
|
-
if (!component)
|
|
442
|
+
if (!component) {
|
|
443
|
+
setState(prev => ({
|
|
444
|
+
...prev,
|
|
445
|
+
isProcessing: false,
|
|
446
|
+
}));
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
425
449
|
if (component.type === 'review_submit') {
|
|
426
450
|
// Move to verification screen and mark verification in progress
|
|
427
451
|
setState(prev => ({
|
|
@@ -476,15 +500,16 @@ export const useTemplateKYCFlow = (
|
|
|
476
500
|
const step = serverStep === 0 && action !== 'initialize_session' ? 1 : serverStep;
|
|
477
501
|
// Build payload data per action
|
|
478
502
|
const payloadData = buildPayloadForComponent(action, component, state.componentData[currentComp.id], templateId, step);
|
|
503
|
+
console.log('payloadData', action, apiKey);
|
|
479
504
|
|
|
480
505
|
await kycService.verificationSession({
|
|
481
506
|
session_id: state.session.session_id,
|
|
482
507
|
step: step,
|
|
483
508
|
data: payloadData,
|
|
484
|
-
templateId:
|
|
509
|
+
templateId: templateId,
|
|
485
510
|
token: state.session.token,
|
|
486
511
|
action: action,
|
|
487
|
-
apiKey: apiKey,
|
|
512
|
+
apiKey: apiKey ?? "-",
|
|
488
513
|
});
|
|
489
514
|
logger.log("currentComp state", truncateFields(state));
|
|
490
515
|
// Marquer comme complété et passer au suivant
|
|
@@ -501,7 +526,7 @@ export const useTemplateKYCFlow = (
|
|
|
501
526
|
}));
|
|
502
527
|
|
|
503
528
|
} catch (error) {
|
|
504
|
-
|
|
529
|
+
logger.error('Error in nextComponent:', error);
|
|
505
530
|
setState(prev => ({
|
|
506
531
|
...prev,
|
|
507
532
|
isProcessing: false,
|
|
@@ -512,7 +537,7 @@ export const useTemplateKYCFlow = (
|
|
|
512
537
|
}));
|
|
513
538
|
}
|
|
514
539
|
|
|
515
|
-
}, [canGoNext, state.currentComponentIndex, state.template.components, validateComponent, apiKey]),
|
|
540
|
+
}, [canGoNext, state.currentComponentIndex, state.template.components, validateComponent, apiKey, state.session.session_id, state.session.token, buildPayloadForComponent, mapComponentTypeToAction, chooseTemplateId, state.currentLanguage]),
|
|
516
541
|
|
|
517
542
|
// Retourner au composant précédent
|
|
518
543
|
previousComponent: useCallback(() => {
|
|
@@ -522,7 +547,7 @@ export const useTemplateKYCFlow = (
|
|
|
522
547
|
...prev,
|
|
523
548
|
currentComponentIndex: prev.currentComponentIndex - 1,
|
|
524
549
|
}));
|
|
525
|
-
}, [canGoPrevious]),
|
|
550
|
+
}, [canGoPrevious, apiKey]),
|
|
526
551
|
|
|
527
552
|
// Aller à un composant spécifique
|
|
528
553
|
goToComponent: useCallback((componentId: number) => {
|
|
@@ -533,7 +558,7 @@ export const useTemplateKYCFlow = (
|
|
|
533
558
|
currentComponentIndex: componentIndex,
|
|
534
559
|
}));
|
|
535
560
|
}
|
|
536
|
-
}, [state.template.components]),
|
|
561
|
+
}, [state.template.components, apiKey]),
|
|
537
562
|
|
|
538
563
|
// Mettre à jour les données d'un composant
|
|
539
564
|
updateComponentData: useCallback((componentId: number, data: any) => {
|
|
@@ -551,12 +576,12 @@ export const useTemplateKYCFlow = (
|
|
|
551
576
|
}
|
|
552
577
|
}));
|
|
553
578
|
|
|
554
|
-
}, []),
|
|
579
|
+
}, [apiKey]),
|
|
555
580
|
|
|
556
581
|
// Valider un composant
|
|
557
582
|
validateComponent: useCallback((componentId: number) => {
|
|
558
583
|
return validateComponent(componentId);
|
|
559
|
-
}, [validateComponent]),
|
|
584
|
+
}, [validateComponent, apiKey]),
|
|
560
585
|
// complet verification
|
|
561
586
|
submitVerification: useCallback(async () => {
|
|
562
587
|
setState(prev => ({ ...prev, isProcessing: true }));
|
|
@@ -566,7 +591,7 @@ export const useTemplateKYCFlow = (
|
|
|
566
591
|
} catch (error) {
|
|
567
592
|
setState(prev => ({ ...prev, isProcessing: false }));
|
|
568
593
|
}
|
|
569
|
-
}, [state.session.session_id, state.verification, onComplete]),
|
|
594
|
+
}, [state.session.session_id, state.verification, onComplete, apiKey]),
|
|
570
595
|
|
|
571
596
|
// Soumettre le template complet
|
|
572
597
|
submitTemplate: useCallback(async () => {
|
|
@@ -594,12 +619,12 @@ export const useTemplateKYCFlow = (
|
|
|
594
619
|
setState(prev => ({ ...prev, isProcessing: false }));
|
|
595
620
|
onError?.(error instanceof Error ? error.message : 'Erreur lors de la soumission');
|
|
596
621
|
}
|
|
597
|
-
}, [state.template.components, state.verification, state.currentComponentIndex, validateComponent, state.componentData, onComplete, onError]),
|
|
622
|
+
}, [state.template.components, state.verification, state.currentComponentIndex, validateComponent, state.componentData, onComplete, onError, apiKey]),
|
|
598
623
|
|
|
599
624
|
// Réinitialiser le template
|
|
600
625
|
resetTemplate: useCallback(() => {
|
|
601
626
|
setState(buildInitialState());
|
|
602
|
-
}, [buildInitialState]),
|
|
627
|
+
}, [buildInitialState, apiKey]),
|
|
603
628
|
|
|
604
629
|
// Changer la langue
|
|
605
630
|
setLanguage: useCallback((language: string) => {
|
|
@@ -607,7 +632,7 @@ export const useTemplateKYCFlow = (
|
|
|
607
632
|
...prev,
|
|
608
633
|
currentLanguage: language,
|
|
609
634
|
}));
|
|
610
|
-
}, []),
|
|
635
|
+
}, [apiKey]),
|
|
611
636
|
|
|
612
637
|
// Afficher le stepper personnalisé
|
|
613
638
|
showCustomStepper: useCallback((show: boolean) => {
|
|
@@ -615,14 +640,14 @@ export const useTemplateKYCFlow = (
|
|
|
615
640
|
...prev,
|
|
616
641
|
showCustomStepper: show,
|
|
617
642
|
}));
|
|
618
|
-
}, []),
|
|
643
|
+
}, [apiKey]),
|
|
619
644
|
|
|
620
645
|
setVerificationState: useCallback((verificationState) => {
|
|
621
646
|
setState(prev => ({
|
|
622
647
|
...prev,
|
|
623
648
|
verification: verificationState,
|
|
624
649
|
}));
|
|
625
|
-
}, []),
|
|
650
|
+
}, [apiKey]),
|
|
626
651
|
};
|
|
627
652
|
|
|
628
653
|
return {
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { useState, useCallback, useRef } from 'react';
|
|
2
|
+
import { KYCTemplate } from '../types/KYC.types';
|
|
3
|
+
import templateService from '../modules/api/TemplateService';
|
|
4
|
+
import { transformBackendTemplateToSDK, validateTransformedTemplate } from '../utils/template-transformer';
|
|
5
|
+
import { logger } from '../utils/logger';
|
|
6
|
+
import { authentification } from '../modules/api/KYCService';
|
|
7
|
+
|
|
8
|
+
export interface UseTemplateLoaderReturn {
|
|
9
|
+
template: KYCTemplate | null;
|
|
10
|
+
isLoading: boolean;
|
|
11
|
+
error: string | null;
|
|
12
|
+
loadTemplate: (templateId: string, apiKey?: string) => Promise<void>;
|
|
13
|
+
refresh: () => void;
|
|
14
|
+
clearError: () => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Hook to load and transform templates from the backend API
|
|
19
|
+
*/
|
|
20
|
+
export function useTemplateLoader(): UseTemplateLoaderReturn {
|
|
21
|
+
const [template, setTemplate] = useState<KYCTemplate | null>(null);
|
|
22
|
+
const [isLoading, setIsLoading] = useState<boolean>(false);
|
|
23
|
+
const [error, setError] = useState<string | null>(null);
|
|
24
|
+
const currentTemplateIdRef = useRef<string | null>(null);
|
|
25
|
+
const currentApiKeyRef = useRef<string | undefined>(undefined);
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Load a template by ID
|
|
29
|
+
*/
|
|
30
|
+
const loadTemplate = useCallback(async (templateId: string, apiKey?: string) => {
|
|
31
|
+
// Reset state
|
|
32
|
+
setError(null);
|
|
33
|
+
setIsLoading(true);
|
|
34
|
+
currentTemplateIdRef.current = templateId;
|
|
35
|
+
currentApiKeyRef.current = apiKey;
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
logger.log(`Loading template: ${templateId}`);
|
|
39
|
+
|
|
40
|
+
// Get token if no API key provided
|
|
41
|
+
let token: string | undefined;
|
|
42
|
+
if (!apiKey) {
|
|
43
|
+
try {
|
|
44
|
+
token = await authentification();
|
|
45
|
+
} catch (authError) {
|
|
46
|
+
logger.error('Authentication failed:', authError);
|
|
47
|
+
throw new Error('Failed to authenticate. Please provide a valid API key.');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Fetch template from backend
|
|
52
|
+
const backendTemplate = await templateService.fetchTemplate(templateId, apiKey, token);
|
|
53
|
+
|
|
54
|
+
// Transform to SDK format
|
|
55
|
+
const transformedTemplate = transformBackendTemplateToSDK(backendTemplate);
|
|
56
|
+
|
|
57
|
+
// Validate transformed template
|
|
58
|
+
if (!validateTransformedTemplate(transformedTemplate)) {
|
|
59
|
+
throw new Error('Transformed template validation failed');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Set the template
|
|
63
|
+
setTemplate(transformedTemplate);
|
|
64
|
+
logger.log(`Template loaded successfully: ${templateId}`);
|
|
65
|
+
} catch (err: any) {
|
|
66
|
+
const errorMessage = err.message || 'Failed to load template';
|
|
67
|
+
logger.error(`Error loading template ${templateId}:`, errorMessage);
|
|
68
|
+
setError(errorMessage);
|
|
69
|
+
setTemplate(null);
|
|
70
|
+
} finally {
|
|
71
|
+
setIsLoading(false);
|
|
72
|
+
}
|
|
73
|
+
}, []);
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Refresh the current template
|
|
77
|
+
*/
|
|
78
|
+
const refresh = useCallback(() => {
|
|
79
|
+
if (currentTemplateIdRef.current) {
|
|
80
|
+
// Clear cache for this template
|
|
81
|
+
templateService.clearCache(currentTemplateIdRef.current);
|
|
82
|
+
// Reload template
|
|
83
|
+
loadTemplate(currentTemplateIdRef.current, currentApiKeyRef.current);
|
|
84
|
+
}
|
|
85
|
+
}, [loadTemplate]);
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Clear error state
|
|
89
|
+
*/
|
|
90
|
+
const clearError = useCallback(() => {
|
|
91
|
+
setError(null);
|
|
92
|
+
}, []);
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
template,
|
|
96
|
+
isLoading,
|
|
97
|
+
error,
|
|
98
|
+
loadTemplate,
|
|
99
|
+
refresh,
|
|
100
|
+
clearError,
|
|
101
|
+
};
|
|
102
|
+
}
|
package/src/i18n/en/index.ts
CHANGED
|
@@ -36,6 +36,16 @@ export const en = {
|
|
|
36
36
|
]
|
|
37
37
|
},
|
|
38
38
|
|
|
39
|
+
welcome: {
|
|
40
|
+
requirements: 'What you\'ll need:',
|
|
41
|
+
estimatedTime: 'Estimated time:',
|
|
42
|
+
consent: 'Please accept the following:',
|
|
43
|
+
privacyPolicy: 'I agree to the Privacy Policy',
|
|
44
|
+
termsOfService: 'I agree to the Terms of Service',
|
|
45
|
+
marketingConsent: 'I agree to receive marketing communications',
|
|
46
|
+
readMore: 'Read more'
|
|
47
|
+
},
|
|
48
|
+
|
|
39
49
|
// Location Capture
|
|
40
50
|
locationCapture: {
|
|
41
51
|
title: 'Secure Your Verification',
|
package/src/i18n/fr/index.ts
CHANGED
|
@@ -35,6 +35,15 @@ export const fr = {
|
|
|
35
35
|
'Une connexion internet stable'
|
|
36
36
|
]
|
|
37
37
|
},
|
|
38
|
+
welcome: {
|
|
39
|
+
requirements: 'Ce dont vous aurez besoin :',
|
|
40
|
+
estimatedTime: 'Temps estimé :',
|
|
41
|
+
consent: 'Veuillez accepter les suivants :',
|
|
42
|
+
privacyPolicy: 'J\'accepte la Politique de Confidentialité',
|
|
43
|
+
termsOfService: 'J\'accepte les Conditions d\'Utilisation',
|
|
44
|
+
marketingConsent: 'J\'accepte de recevoir des communications marketing',
|
|
45
|
+
readMore: 'Lire plus'
|
|
46
|
+
},
|
|
38
47
|
|
|
39
48
|
// Location Capture
|
|
40
49
|
locationCapture: {
|
package/src/index.ts
CHANGED
|
@@ -7,5 +7,16 @@ export * from './types/KYC.types';
|
|
|
7
7
|
|
|
8
8
|
export { TemplateKYCExample as LauchTransferGratisKYC } from './components/TemplateKYCExample';
|
|
9
9
|
|
|
10
|
+
// Export Template Flow Components
|
|
11
|
+
export { TemplateKYCFlow } from './components/TemplateKYCFlowRefactored';
|
|
12
|
+
|
|
13
|
+
// Export Template Service and Utilities
|
|
14
|
+
export { default as templateService } from './modules/api/TemplateService';
|
|
15
|
+
export { transformBackendTemplateToSDK, validateTransformedTemplate } from './utils/template-transformer';
|
|
16
|
+
export { useTemplateLoader } from './hooks/useTemplateLoader';
|
|
17
|
+
|
|
18
|
+
// Export Template Components
|
|
19
|
+
export { WelcomeTemplate } from './components/KYCElements/WelcomeTemplate';
|
|
20
|
+
|
|
10
21
|
// Export Web KYC Components
|
|
11
22
|
export { WebKYCEntry } from './web';
|
|
@@ -5,7 +5,7 @@ import { logger } from "../../utils/logger";
|
|
|
5
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
7
|
try {
|
|
8
|
-
|
|
8
|
+
console.log("Front verification START", JSON.stringify({ result }, null, 2));
|
|
9
9
|
logger.log("Front verification", JSON.stringify({ result }, null, 2));
|
|
10
10
|
const token = await authentification();
|
|
11
11
|
const detected = await kycService.detectFaceOnId(result?.path || '', token, result?.selectedDocumentType || '')
|
|
@@ -200,9 +200,10 @@ export class KYCService {
|
|
|
200
200
|
const formData = new FormData();
|
|
201
201
|
const rnFile: any = { uri: idCardImageUri, type: 'image/jpeg', name: 'id_card_photo.jpg' };
|
|
202
202
|
formData.append('file', rnFile);
|
|
203
|
+
logger.log('detectFaceOnId formData', JSON.stringify(formData, null, 2));
|
|
203
204
|
|
|
204
205
|
const docTypeShorted = GovernmentDocumentTypeShorted[docType as GovernmentDocumentType];
|
|
205
|
-
|
|
206
|
+
logger.log('detectFaceOnId docTypeShorted', docTypeShorted);
|
|
206
207
|
try {
|
|
207
208
|
const res = await axios.post(`${this.faceServiceURL}/detect_face/?doc_type=${docTypeShorted}`, formData,
|
|
208
209
|
{
|
|
@@ -368,14 +369,19 @@ export class KYCService {
|
|
|
368
369
|
return res.data;
|
|
369
370
|
}
|
|
370
371
|
|
|
371
|
-
async newSession(token: string): Promise<SessionResponse> {
|
|
372
|
+
async newSession({ token, apiKey }: { token?: string, apiKey?: string }): Promise<SessionResponse> {
|
|
372
373
|
try {
|
|
373
374
|
const data = {
|
|
374
375
|
"status": "PENDING",
|
|
375
376
|
"metadata": {},
|
|
376
377
|
}
|
|
377
378
|
const res = await axios.post<SessionResponse>(`${this.backendServiceURL}/verification/sessions/`,
|
|
378
|
-
data, {
|
|
379
|
+
data, {
|
|
380
|
+
headers: {
|
|
381
|
+
'Content-Type': 'application/json',
|
|
382
|
+
...(apiKey ? { 'Authorization': `ApiKey ${apiKey}` } : { 'Authorization': `Bearer ${token}` })
|
|
383
|
+
}
|
|
384
|
+
});
|
|
379
385
|
return res.data;
|
|
380
386
|
} catch (error: any) {
|
|
381
387
|
logger.error('Error creating session:', JSON.stringify(errorMessage(error), null, 2));
|
|
@@ -393,10 +399,10 @@ export class KYCService {
|
|
|
393
399
|
}
|
|
394
400
|
|
|
395
401
|
async verificationSession(payload: VerificationSessionRequest): Promise<any> {
|
|
396
|
-
|
|
402
|
+
console.log('apiKey in verificationSession', payload.apiKey);
|
|
397
403
|
try {
|
|
398
404
|
|
|
399
|
-
|
|
405
|
+
|
|
400
406
|
// /api/v1/verification/api/kyc/sessions/{session_id}/steps/{step}/
|
|
401
407
|
const { session_id, step, data, templateId, action, apiKey } = payload;
|
|
402
408
|
|
|
@@ -418,20 +424,23 @@ export class KYCService {
|
|
|
418
424
|
|
|
419
425
|
const logPayload = truncateFields({ payloadData, session_id, step });
|
|
420
426
|
logger.log('verificationSession payload',
|
|
421
|
-
JSON.stringify(truncateFields({ logPayload, token, path: url }),
|
|
427
|
+
JSON.stringify(truncateFields({ logPayload, token: token ?? "-", path: url, apiKey }),
|
|
422
428
|
null, 2))
|
|
423
429
|
|
|
424
430
|
const res = await axios.post<SessionResponse>(url,
|
|
425
431
|
payloadData,
|
|
426
432
|
{
|
|
427
|
-
headers: {
|
|
433
|
+
headers: {
|
|
434
|
+
'Content-Type': 'application/json',
|
|
435
|
+
...(apiKey ? { 'Authorization': `ApiKey ${apiKey}` } : { 'Authorization': `Bearer ${token}` })
|
|
436
|
+
}
|
|
428
437
|
});
|
|
429
438
|
logger.log('verificationSession res', JSON.stringify(truncateFields(res.data), null, 2));
|
|
430
439
|
return res.data;
|
|
431
440
|
|
|
432
441
|
|
|
433
442
|
} catch (error) {
|
|
434
|
-
logger.error('Error validating component:', JSON.stringify(
|
|
443
|
+
logger.error('Error validating component:', JSON.stringify(error, null, 2));
|
|
435
444
|
throw new Error(errorMessage(error));
|
|
436
445
|
}
|
|
437
446
|
}
|
|
@@ -476,6 +485,7 @@ export function truncateFields(obj: any, maxLength = 420): any {
|
|
|
476
485
|
}
|
|
477
486
|
export const authentification = async () => {
|
|
478
487
|
try {
|
|
488
|
+
logger.log('authentification params', 'kyc_frontend', 'ZCW4mGaJXWR0UuI40lM1pHNQmYLw2xvX');
|
|
479
489
|
const params = new URLSearchParams();
|
|
480
490
|
params.append('client_id', 'kyc_frontend');
|
|
481
491
|
params.append('client_secret', 'ZCW4mGaJXWR0UuI40lM1pHNQmYLw2xvX');
|