@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.
Files changed (142) hide show
  1. package/android/src/main/AndroidManifest.xml +9 -4
  2. package/build/components/EnhancedCameraView.d.ts.map +1 -1
  3. package/build/components/EnhancedCameraView.js +26 -3
  4. package/build/components/EnhancedCameraView.js.map +1 -1
  5. package/build/components/EnhancedCameraView.web.d.ts.map +1 -1
  6. package/build/components/EnhancedCameraView.web.js +21 -0
  7. package/build/components/EnhancedCameraView.web.js.map +1 -1
  8. package/build/components/KYCElements/CameraCapture.d.ts.map +1 -1
  9. package/build/components/KYCElements/CameraCapture.js +4 -3
  10. package/build/components/KYCElements/CameraCapture.js.map +1 -1
  11. package/build/components/KYCElements/CountrySelectionTemplate.d.ts +5 -2
  12. package/build/components/KYCElements/CountrySelectionTemplate.d.ts.map +1 -1
  13. package/build/components/KYCElements/CountrySelectionTemplate.js +360 -101
  14. package/build/components/KYCElements/CountrySelectionTemplate.js.map +1 -1
  15. package/build/components/KYCElements/FileUpload.d.ts.map +1 -1
  16. package/build/components/KYCElements/FileUpload.js +5 -4
  17. package/build/components/KYCElements/FileUpload.js.map +1 -1
  18. package/build/components/KYCElements/FileUploadTemplate.d.ts.map +1 -1
  19. package/build/components/KYCElements/FileUploadTemplate.js +5 -4
  20. package/build/components/KYCElements/FileUploadTemplate.js.map +1 -1
  21. package/build/components/KYCElements/IDCardCapture.d.ts.map +1 -1
  22. package/build/components/KYCElements/IDCardCapture.js +193 -237
  23. package/build/components/KYCElements/IDCardCapture.js.map +1 -1
  24. package/build/components/KYCElements/LocationCaptureTemplate.d.ts.map +1 -1
  25. package/build/components/KYCElements/LocationCaptureTemplate.js +78 -37
  26. package/build/components/KYCElements/LocationCaptureTemplate.js.map +1 -1
  27. package/build/components/KYCElements/OrientationVideoCapture.js +3 -2
  28. package/build/components/KYCElements/OrientationVideoCapture.js.map +1 -1
  29. package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js +3 -2
  30. package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js.map +1 -1
  31. package/build/components/KYCElements/OrientationVideoCaptureFinal.js +3 -2
  32. package/build/components/KYCElements/OrientationVideoCaptureFinal.js.map +1 -1
  33. package/build/components/KYCElements/SelfieCapture.d.ts.map +1 -1
  34. package/build/components/KYCElements/SelfieCapture.js +4 -3
  35. package/build/components/KYCElements/SelfieCapture.js.map +1 -1
  36. package/build/components/KYCElements/SelfieCaptureTemplate.d.ts.map +1 -1
  37. package/build/components/KYCElements/SelfieCaptureTemplate.js +182 -39
  38. package/build/components/KYCElements/SelfieCaptureTemplate.js.map +1 -1
  39. package/build/components/KYCElements/WelcomeTemplate.d.ts +12 -0
  40. package/build/components/KYCElements/WelcomeTemplate.d.ts.map +1 -0
  41. package/build/components/KYCElements/WelcomeTemplate.js +243 -0
  42. package/build/components/KYCElements/WelcomeTemplate.js.map +1 -0
  43. package/build/components/TemplateKYCExample.d.ts +4 -2
  44. package/build/components/TemplateKYCExample.d.ts.map +1 -1
  45. package/build/components/TemplateKYCExample.js +5 -68
  46. package/build/components/TemplateKYCExample.js.map +1 -1
  47. package/build/components/TemplateKYCFlowRefactored.d.ts +2 -1
  48. package/build/components/TemplateKYCFlowRefactored.d.ts.map +1 -1
  49. package/build/components/TemplateKYCFlowRefactored.js +95 -9
  50. package/build/components/TemplateKYCFlowRefactored.js.map +1 -1
  51. package/build/components/example/DynamicTemplateExample.d.ts +10 -0
  52. package/build/components/example/DynamicTemplateExample.d.ts.map +1 -0
  53. package/build/components/example/DynamicTemplateExample.js +241 -0
  54. package/build/components/example/DynamicTemplateExample.js.map +1 -0
  55. package/build/config/allowedDomains.d.ts +30 -0
  56. package/build/config/allowedDomains.d.ts.map +1 -0
  57. package/build/config/allowedDomains.js +127 -0
  58. package/build/config/allowedDomains.js.map +1 -0
  59. package/build/hooks/useTemplateKYCFlow.d.ts.map +1 -1
  60. package/build/hooks/useTemplateKYCFlow.js +68 -43
  61. package/build/hooks/useTemplateKYCFlow.js.map +1 -1
  62. package/build/hooks/useTemplateLoader.d.ts +14 -0
  63. package/build/hooks/useTemplateLoader.d.ts.map +1 -0
  64. package/build/hooks/useTemplateLoader.js +85 -0
  65. package/build/hooks/useTemplateLoader.js.map +1 -0
  66. package/build/i18n/en/index.d.ts +9 -0
  67. package/build/i18n/en/index.d.ts.map +1 -1
  68. package/build/i18n/en/index.js +9 -0
  69. package/build/i18n/en/index.js.map +1 -1
  70. package/build/i18n/fr/index.d.ts +9 -0
  71. package/build/i18n/fr/index.d.ts.map +1 -1
  72. package/build/i18n/fr/index.js +9 -0
  73. package/build/i18n/fr/index.js.map +1 -1
  74. package/build/index.d.ts +5 -0
  75. package/build/index.d.ts.map +1 -1
  76. package/build/index.js +8 -0
  77. package/build/index.js.map +1 -1
  78. package/build/modules/api/CardAuthentification.js +1 -0
  79. package/build/modules/api/CardAuthentification.js.map +1 -1
  80. package/build/modules/api/KYCService.d.ts +4 -1
  81. package/build/modules/api/KYCService.d.ts.map +1 -1
  82. package/build/modules/api/KYCService.js +17 -5
  83. package/build/modules/api/KYCService.js.map +1 -1
  84. package/build/modules/api/TemplateService.d.ts +45 -0
  85. package/build/modules/api/TemplateService.d.ts.map +1 -0
  86. package/build/modules/api/TemplateService.js +145 -0
  87. package/build/modules/api/TemplateService.js.map +1 -0
  88. package/build/modules/api/types.d.ts +1 -0
  89. package/build/modules/api/types.d.ts.map +1 -1
  90. package/build/modules/api/types.js.map +1 -1
  91. package/build/types/KYC.types.d.ts +144 -4
  92. package/build/types/KYC.types.d.ts.map +1 -1
  93. package/build/types/KYC.types.js +15 -0
  94. package/build/types/KYC.types.js.map +1 -1
  95. package/build/utils/cropByObb.d.ts +1 -0
  96. package/build/utils/cropByObb.d.ts.map +1 -1
  97. package/build/utils/cropByObb.js +70 -0
  98. package/build/utils/cropByObb.js.map +1 -1
  99. package/build/utils/platformAlert.d.ts +20 -0
  100. package/build/utils/platformAlert.d.ts.map +1 -0
  101. package/build/utils/platformAlert.js +67 -0
  102. package/build/utils/platformAlert.js.map +1 -0
  103. package/build/utils/template-transformer.d.ts +10 -0
  104. package/build/utils/template-transformer.d.ts.map +1 -0
  105. package/build/utils/template-transformer.js +353 -0
  106. package/build/utils/template-transformer.js.map +1 -0
  107. package/build/web/WebKYCEntry.d.ts.map +1 -1
  108. package/build/web/WebKYCEntry.js +102 -20
  109. package/build/web/WebKYCEntry.js.map +1 -1
  110. package/package.json +1 -1
  111. package/src/components/EnhancedCameraView.tsx +31 -2
  112. package/src/components/EnhancedCameraView.web.tsx +24 -0
  113. package/src/components/KYCElements/CameraCapture.tsx +4 -3
  114. package/src/components/KYCElements/CountrySelectionTemplate.tsx +410 -113
  115. package/src/components/KYCElements/FileUpload.tsx +5 -4
  116. package/src/components/KYCElements/FileUploadTemplate.tsx +5 -4
  117. package/src/components/KYCElements/IDCardCapture.tsx +196 -254
  118. package/src/components/KYCElements/LocationCaptureTemplate.tsx +95 -44
  119. package/src/components/KYCElements/OrientationVideoCapture.tsx +2 -2
  120. package/src/components/KYCElements/OrientationVideoCaptureEnhanced.tsx +2 -2
  121. package/src/components/KYCElements/OrientationVideoCaptureFinal.tsx +2 -2
  122. package/src/components/KYCElements/SelfieCapture.tsx +4 -3
  123. package/src/components/KYCElements/SelfieCaptureTemplate.tsx +195 -41
  124. package/src/components/KYCElements/WelcomeTemplate.tsx +289 -0
  125. package/src/components/TemplateKYCExample.tsx +16 -71
  126. package/src/components/TemplateKYCFlowRefactored.tsx +121 -11
  127. package/src/components/example/DynamicTemplateExample.tsx +289 -0
  128. package/src/config/allowedDomains.ts +152 -0
  129. package/src/hooks/useTemplateKYCFlow.tsx +71 -46
  130. package/src/hooks/useTemplateLoader.ts +102 -0
  131. package/src/i18n/en/index.ts +10 -0
  132. package/src/i18n/fr/index.ts +9 -0
  133. package/src/index.ts +11 -0
  134. package/src/modules/api/CardAuthentification.ts +1 -1
  135. package/src/modules/api/KYCService.ts +18 -8
  136. package/src/modules/api/TemplateService.ts +167 -0
  137. package/src/modules/api/types.ts +1 -0
  138. package/src/types/KYC.types.ts +188 -3
  139. package/src/utils/cropByObb.ts +83 -3
  140. package/src/utils/platformAlert.ts +85 -0
  141. package/src/utils/template-transformer.ts +433 -0
  142. 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
- const base = { template_id: null, step: component.order, permissionGranted: true } as any;
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
- return { ...base, documents, country: _idCardData?.country || '', documentType: _idCardData?.documentType as GovernmentDocumentType || 'identity_card' };
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
- // return { ...base, documents };
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
- setState(prev => ({
405
- ...prev,
406
- isProcessing: true,
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) return;
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: null,
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
- // console.error('Error validating component:', error);
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
+ }
@@ -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',
@@ -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, { headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` } });
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: { 'Content-Type': 'application/json', ...(this.apiKey ? { 'Authorization': `ApiKey ${this.apiKey}` } : { 'Authorization': `Bearer ${token}` }) }
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(errorMessage(error), null, 2));
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');