@transfergratis/react-native-sdk 0.1.23 → 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.
Files changed (207) hide show
  1. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +12 -5
  2. package/android/build/intermediates/aar_main_jar/debug/syncDebugLibJars/classes.jar +0 -0
  3. package/android/build/intermediates/annotations_typedef_file/debug/extractDebugAnnotations/typedefs.txt +0 -0
  4. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
  5. package/android/build/intermediates/incremental/debug-mergeJavaRes/merge-state +0 -0
  6. package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +61 -59
  7. package/android/build/intermediates/merged_java_res/debug/mergeDebugJavaResource/feature-transfergratis-react-native-sdk.jar +0 -0
  8. package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +12 -5
  9. package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
  10. package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
  11. package/android/build/outputs/aar/transfergratis-react-native-sdk-debug.aar +0 -0
  12. package/android/build/outputs/logs/manifest-merger-debug-report.txt +26 -34
  13. package/android/src/main/AndroidManifest.xml +13 -5
  14. package/build/components/EnhancedCameraView.d.ts.map +1 -1
  15. package/build/components/EnhancedCameraView.js +26 -3
  16. package/build/components/EnhancedCameraView.js.map +1 -1
  17. package/build/components/EnhancedCameraView.web.d.ts.map +1 -1
  18. package/build/components/EnhancedCameraView.web.js +21 -0
  19. package/build/components/EnhancedCameraView.web.js.map +1 -1
  20. package/build/components/KYCElements/AdditionalDocumentsTemplate.d.ts +12 -0
  21. package/build/components/KYCElements/AdditionalDocumentsTemplate.d.ts.map +1 -0
  22. package/build/components/KYCElements/AdditionalDocumentsTemplate.js +283 -0
  23. package/build/components/KYCElements/AdditionalDocumentsTemplate.js.map +1 -0
  24. package/build/components/KYCElements/CameraCapture.d.ts.map +1 -1
  25. package/build/components/KYCElements/CameraCapture.js +4 -3
  26. package/build/components/KYCElements/CameraCapture.js.map +1 -1
  27. package/build/components/KYCElements/CountrySelectionTemplate.d.ts +5 -2
  28. package/build/components/KYCElements/CountrySelectionTemplate.d.ts.map +1 -1
  29. package/build/components/KYCElements/CountrySelectionTemplate.js +360 -101
  30. package/build/components/KYCElements/CountrySelectionTemplate.js.map +1 -1
  31. package/build/components/KYCElements/EmailVerificationTemplate.d.ts +12 -0
  32. package/build/components/KYCElements/EmailVerificationTemplate.d.ts.map +1 -0
  33. package/build/components/KYCElements/EmailVerificationTemplate.js +193 -0
  34. package/build/components/KYCElements/EmailVerificationTemplate.js.map +1 -0
  35. package/build/components/KYCElements/FileUpload.d.ts.map +1 -1
  36. package/build/components/KYCElements/FileUpload.js +5 -4
  37. package/build/components/KYCElements/FileUpload.js.map +1 -1
  38. package/build/components/KYCElements/FileUploadTemplate.d.ts.map +1 -1
  39. package/build/components/KYCElements/FileUploadTemplate.js +5 -4
  40. package/build/components/KYCElements/FileUploadTemplate.js.map +1 -1
  41. package/build/components/KYCElements/IDCardCapture.d.ts.map +1 -1
  42. package/build/components/KYCElements/IDCardCapture.js +356 -227
  43. package/build/components/KYCElements/IDCardCapture.js.map +1 -1
  44. package/build/components/KYCElements/LocationCaptureTemplate.d.ts.map +1 -1
  45. package/build/components/KYCElements/LocationCaptureTemplate.js +78 -37
  46. package/build/components/KYCElements/LocationCaptureTemplate.js.map +1 -1
  47. package/build/components/KYCElements/OrientationVideoCapture.d.ts +2 -0
  48. package/build/components/KYCElements/OrientationVideoCapture.d.ts.map +1 -1
  49. package/build/components/KYCElements/OrientationVideoCapture.js +5 -4
  50. package/build/components/KYCElements/OrientationVideoCapture.js.map +1 -1
  51. package/build/components/KYCElements/OrientationVideoCaptureEnhanced.d.ts +2 -0
  52. package/build/components/KYCElements/OrientationVideoCaptureEnhanced.d.ts.map +1 -1
  53. package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js +5 -4
  54. package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js.map +1 -1
  55. package/build/components/KYCElements/OrientationVideoCaptureFinal.d.ts +2 -0
  56. package/build/components/KYCElements/OrientationVideoCaptureFinal.d.ts.map +1 -1
  57. package/build/components/KYCElements/OrientationVideoCaptureFinal.js +5 -4
  58. package/build/components/KYCElements/OrientationVideoCaptureFinal.js.map +1 -1
  59. package/build/components/KYCElements/PersonalInformationTemplate.d.ts +12 -0
  60. package/build/components/KYCElements/PersonalInformationTemplate.d.ts.map +1 -0
  61. package/build/components/KYCElements/PersonalInformationTemplate.js +120 -0
  62. package/build/components/KYCElements/PersonalInformationTemplate.js.map +1 -0
  63. package/build/components/KYCElements/PhoneVerificationTemplate.d.ts +12 -0
  64. package/build/components/KYCElements/PhoneVerificationTemplate.d.ts.map +1 -0
  65. package/build/components/KYCElements/PhoneVerificationTemplate.js +185 -0
  66. package/build/components/KYCElements/PhoneVerificationTemplate.js.map +1 -0
  67. package/build/components/KYCElements/SelfieCapture.d.ts.map +1 -1
  68. package/build/components/KYCElements/SelfieCapture.js +4 -3
  69. package/build/components/KYCElements/SelfieCapture.js.map +1 -1
  70. package/build/components/KYCElements/SelfieCaptureTemplate.d.ts.map +1 -1
  71. package/build/components/KYCElements/SelfieCaptureTemplate.js +189 -42
  72. package/build/components/KYCElements/SelfieCaptureTemplate.js.map +1 -1
  73. package/build/components/KYCElements/WelcomeTemplate.d.ts +12 -0
  74. package/build/components/KYCElements/WelcomeTemplate.d.ts.map +1 -0
  75. package/build/components/KYCElements/WelcomeTemplate.js +243 -0
  76. package/build/components/KYCElements/WelcomeTemplate.js.map +1 -0
  77. package/build/components/TemplateKYCExample.d.ts +8 -2
  78. package/build/components/TemplateKYCExample.d.ts.map +1 -1
  79. package/build/components/TemplateKYCExample.js +10 -97
  80. package/build/components/TemplateKYCExample.js.map +1 -1
  81. package/build/components/TemplateKYCFlowRefactored.d.ts +6 -1
  82. package/build/components/TemplateKYCFlowRefactored.d.ts.map +1 -1
  83. package/build/components/TemplateKYCFlowRefactored.js +108 -11
  84. package/build/components/TemplateKYCFlowRefactored.js.map +1 -1
  85. package/build/components/example/DynamicTemplateExample.d.ts +10 -0
  86. package/build/components/example/DynamicTemplateExample.d.ts.map +1 -0
  87. package/build/components/example/DynamicTemplateExample.js +241 -0
  88. package/build/components/example/DynamicTemplateExample.js.map +1 -0
  89. package/build/config/KYCConfig.d.ts +14 -0
  90. package/build/config/KYCConfig.d.ts.map +1 -0
  91. package/build/config/KYCConfig.js +26 -0
  92. package/build/config/KYCConfig.js.map +1 -0
  93. package/build/config/allowedDomains.d.ts +30 -0
  94. package/build/config/allowedDomains.d.ts.map +1 -0
  95. package/build/config/allowedDomains.js +112 -0
  96. package/build/config/allowedDomains.js.map +1 -0
  97. package/build/hooks/useOrientationVideo.d.ts +2 -1
  98. package/build/hooks/useOrientationVideo.d.ts.map +1 -1
  99. package/build/hooks/useOrientationVideo.js +3 -3
  100. package/build/hooks/useOrientationVideo.js.map +1 -1
  101. package/build/hooks/useTemplateKYCFlow.d.ts +6 -1
  102. package/build/hooks/useTemplateKYCFlow.d.ts.map +1 -1
  103. package/build/hooks/useTemplateKYCFlow.js +317 -34
  104. package/build/hooks/useTemplateKYCFlow.js.map +1 -1
  105. package/build/hooks/useTemplateLoader.d.ts +14 -0
  106. package/build/hooks/useTemplateLoader.d.ts.map +1 -0
  107. package/build/hooks/useTemplateLoader.js +85 -0
  108. package/build/hooks/useTemplateLoader.js.map +1 -0
  109. package/build/i18n/en/index.d.ts +49 -0
  110. package/build/i18n/en/index.d.ts.map +1 -1
  111. package/build/i18n/en/index.js +50 -1
  112. package/build/i18n/en/index.js.map +1 -1
  113. package/build/i18n/fr/index.d.ts +35 -0
  114. package/build/i18n/fr/index.d.ts.map +1 -1
  115. package/build/i18n/fr/index.js +36 -1
  116. package/build/i18n/fr/index.js.map +1 -1
  117. package/build/index.d.ts +6 -0
  118. package/build/index.d.ts.map +1 -1
  119. package/build/index.js +10 -0
  120. package/build/index.js.map +1 -1
  121. package/build/modules/api/CardAuthentification.d.ts +24 -3
  122. package/build/modules/api/CardAuthentification.d.ts.map +1 -1
  123. package/build/modules/api/CardAuthentification.js +69 -10
  124. package/build/modules/api/CardAuthentification.js.map +1 -1
  125. package/build/modules/api/KYCService.d.ts +7 -7
  126. package/build/modules/api/KYCService.d.ts.map +1 -1
  127. package/build/modules/api/KYCService.js +108 -39
  128. package/build/modules/api/KYCService.js.map +1 -1
  129. package/build/modules/api/SelfieVerification.d.ts +3 -1
  130. package/build/modules/api/SelfieVerification.d.ts.map +1 -1
  131. package/build/modules/api/SelfieVerification.js +17 -1
  132. package/build/modules/api/SelfieVerification.js.map +1 -1
  133. package/build/modules/api/TemplateService.d.ts +44 -0
  134. package/build/modules/api/TemplateService.d.ts.map +1 -0
  135. package/build/modules/api/TemplateService.js +145 -0
  136. package/build/modules/api/TemplateService.js.map +1 -0
  137. package/build/types/KYC.types.d.ts +265 -4
  138. package/build/types/KYC.types.d.ts.map +1 -1
  139. package/build/types/KYC.types.js +15 -0
  140. package/build/types/KYC.types.js.map +1 -1
  141. package/build/types/env.types.d.ts +13 -0
  142. package/build/types/env.types.d.ts.map +1 -0
  143. package/build/types/env.types.js +2 -0
  144. package/build/types/env.types.js.map +1 -0
  145. package/build/utils/cropByObb.d.ts +1 -0
  146. package/build/utils/cropByObb.d.ts.map +1 -1
  147. package/build/utils/cropByObb.js +70 -0
  148. package/build/utils/cropByObb.js.map +1 -1
  149. package/build/utils/deviceDetection.d.ts +6 -0
  150. package/build/utils/deviceDetection.d.ts.map +1 -0
  151. package/build/utils/deviceDetection.js +12 -0
  152. package/build/utils/deviceDetection.js.map +1 -0
  153. package/build/utils/platformAlert.d.ts +20 -0
  154. package/build/utils/platformAlert.d.ts.map +1 -0
  155. package/build/utils/platformAlert.js +67 -0
  156. package/build/utils/platformAlert.js.map +1 -0
  157. package/build/utils/template-transformer.d.ts +10 -0
  158. package/build/utils/template-transformer.d.ts.map +1 -0
  159. package/build/utils/template-transformer.js +365 -0
  160. package/build/utils/template-transformer.js.map +1 -0
  161. package/build/web/WebKYCEntry.d.ts.map +1 -1
  162. package/build/web/WebKYCEntry.js +158 -32
  163. package/build/web/WebKYCEntry.js.map +1 -1
  164. package/package.json +1 -1
  165. package/plugin/build/withVisionCamera.js +3 -4
  166. package/plugin/src/withVisionCamera.js +3 -4
  167. package/plugin/src/withVisionCamera.ts +3 -4
  168. package/src/components/EnhancedCameraView.tsx +31 -2
  169. package/src/components/EnhancedCameraView.web.tsx +24 -0
  170. package/src/components/KYCElements/AdditionalDocumentsTemplate.tsx +346 -0
  171. package/src/components/KYCElements/CameraCapture.tsx +4 -3
  172. package/src/components/KYCElements/CountrySelectionTemplate.tsx +410 -113
  173. package/src/components/KYCElements/EmailVerificationTemplate.tsx +264 -0
  174. package/src/components/KYCElements/FileUpload.tsx +5 -4
  175. package/src/components/KYCElements/FileUploadTemplate.tsx +5 -4
  176. package/src/components/KYCElements/IDCardCapture.tsx +397 -254
  177. package/src/components/KYCElements/LocationCaptureTemplate.tsx +95 -44
  178. package/src/components/KYCElements/OrientationVideoCapture.tsx +6 -3
  179. package/src/components/KYCElements/OrientationVideoCaptureEnhanced.tsx +6 -3
  180. package/src/components/KYCElements/OrientationVideoCaptureFinal.tsx +6 -3
  181. package/src/components/KYCElements/PersonalInformationTemplate.tsx +158 -0
  182. package/src/components/KYCElements/PhoneVerificationTemplate.tsx +253 -0
  183. package/src/components/KYCElements/SelfieCapture.tsx +4 -3
  184. package/src/components/KYCElements/SelfieCaptureTemplate.tsx +201 -44
  185. package/src/components/KYCElements/WelcomeTemplate.tsx +289 -0
  186. package/src/components/TemplateKYCExample.tsx +37 -108
  187. package/src/components/TemplateKYCFlowRefactored.tsx +148 -12
  188. package/src/components/example/DynamicTemplateExample.tsx +289 -0
  189. package/src/config/KYCConfig.ts +34 -0
  190. package/src/config/allowedDomains.ts +133 -0
  191. package/src/hooks/useOrientationVideo.ts +5 -4
  192. package/src/hooks/useTemplateKYCFlow.tsx +347 -32
  193. package/src/hooks/useTemplateLoader.ts +102 -0
  194. package/src/i18n/en/index.ts +53 -2
  195. package/src/i18n/fr/index.ts +37 -1
  196. package/src/index.ts +14 -0
  197. package/src/modules/api/CardAuthentification.ts +76 -11
  198. package/src/modules/api/KYCService.ts +129 -45
  199. package/src/modules/api/SelfieVerification.ts +25 -3
  200. package/src/modules/api/TemplateService.ts +167 -0
  201. package/src/types/KYC.types.ts +331 -3
  202. package/src/types/env.types.ts +13 -0
  203. package/src/utils/cropByObb.ts +83 -3
  204. package/src/utils/deviceDetection.ts +11 -0
  205. package/src/utils/platformAlert.ts +86 -0
  206. package/src/utils/template-transformer.ts +445 -0
  207. package/src/web/WebKYCEntry.tsx +199 -50
@@ -0,0 +1,167 @@
1
+ import axios from 'axios';
2
+ import { BackendKYCTemplate, TemplateAPIResponse } from '../../types/KYC.types';
3
+ import { logger } from '../../utils/logger';
4
+ import { errorMessage } from './KYCService';
5
+ import KYCConfig from '../../config/KYCConfig';
6
+
7
+ export class TemplateServiceClass {
8
+ private cache: Map<string, { template: BackendKYCTemplate; timestamp: number }> = new Map();
9
+ private cacheTimeout = 5 * 60 * 1000; // 5 minutes
10
+
11
+ /**
12
+ * Get headers for API requests
13
+ */
14
+ private getHeaders(apiKey?: string, token?: string) {
15
+ const headers: Record<string, string> = {
16
+ 'Content-Type': 'application/json',
17
+ };
18
+
19
+ if (apiKey) {
20
+ headers['Authorization'] = `ApiKey ${apiKey}`;
21
+ } else if (token) {
22
+ headers['Authorization'] = `Bearer ${token}`;
23
+ }
24
+
25
+ return headers;
26
+ }
27
+
28
+ /**
29
+ * Fetch a template from the backend API
30
+ * @param templateId - The ID of the template to fetch
31
+ * @param apiKey - Optional API key for authentication
32
+ * @param token - Optional Bearer token for authentication
33
+ * @param useCache - Whether to use cached version if available (default: true)
34
+ * @returns The backend template
35
+ */
36
+ async fetchTemplate(
37
+ templateId: string,
38
+ apiKey?: string,
39
+ token?: string,
40
+ useCache: boolean = true
41
+ ): Promise<BackendKYCTemplate> {
42
+ // Check cache first
43
+ if (useCache) {
44
+ const cached = this.cache.get(templateId);
45
+ if (cached) {
46
+ const age = Date.now() - cached.timestamp;
47
+ if (age < this.cacheTimeout) {
48
+ logger.log(`Template ${templateId} loaded from cache`);
49
+ return cached.template;
50
+ } else {
51
+ // Cache expired, remove it
52
+ this.cache.delete(templateId);
53
+ }
54
+ }
55
+ }
56
+
57
+ try {
58
+ const url = `${KYCConfig.getBackendUrl()}/templates/kyc/template/${templateId}/`;
59
+ logger.log(`Fetching template from: ${url} with apiKey: ${apiKey} and token: ${token}`, {
60
+ headers: this.getHeaders(apiKey, token)
61
+ });
62
+
63
+ const response = await axios.get<TemplateAPIResponse>(url, {
64
+ headers: this.getHeaders(apiKey, token),
65
+ timeout: 30000, // 30 seconds timeout
66
+ });
67
+
68
+ const template: BackendKYCTemplate = response.data;
69
+
70
+ // Validate template structure
71
+ if (!template.id || !template.name || !Array.isArray(template.components)) {
72
+ throw new Error('Invalid template structure received from API');
73
+ }
74
+
75
+ // Store in cache
76
+ this.cache.set(templateId, {
77
+ template,
78
+ timestamp: Date.now(),
79
+ });
80
+
81
+ logger.log(`Template ${templateId} fetched successfully`);
82
+ return template;
83
+ } catch (error: any) {
84
+ logger.error(`Error fetching template ${templateId}:`, JSON.stringify(errorMessage(error), null, 2));
85
+
86
+ // Extract backend error message if available
87
+ const backendMessage = errorMessage(error);
88
+
89
+ if (error.response?.status === 404) {
90
+ throw new Error(`Template not found: ${templateId}`);
91
+ }
92
+
93
+ if (error.response?.status === 401 || error.response?.status === 403) {
94
+ throw new Error(`Unauthorized: Invalid API key or token`);
95
+ }
96
+
97
+ if (backendMessage) {
98
+ throw new Error(`Failed to fetch template: ${JSON.stringify(backendMessage)}`);
99
+ }
100
+
101
+ throw new Error(`Failed to fetch template: ${error.message || 'Unknown error'}`);
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Clear the template cache
107
+ * @param templateId - Optional template ID to clear. If not provided, clears all cache.
108
+ */
109
+ clearCache(templateId?: string): void {
110
+ if (templateId) {
111
+ this.cache.delete(templateId);
112
+ logger.log(`Cache cleared for template: ${templateId}`);
113
+ } else {
114
+ this.cache.clear();
115
+ logger.log('All template cache cleared');
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Get cached template if available
121
+ * @param templateId - The template ID
122
+ * @returns The cached template or null if not found/expired
123
+ */
124
+ getCachedTemplate(templateId: string): BackendKYCTemplate | null {
125
+ const cached = this.cache.get(templateId);
126
+ if (cached) {
127
+ const age = Date.now() - cached.timestamp;
128
+ if (age < this.cacheTimeout) {
129
+ return cached.template;
130
+ } else {
131
+ this.cache.delete(templateId);
132
+ }
133
+ }
134
+ return null;
135
+ }
136
+
137
+ /**
138
+ * Fetch list of available templates (optional feature)
139
+ * @param apiKey - Optional API key for authentication
140
+ * @param token - Optional Bearer token for authentication
141
+ * @returns Array of template metadata
142
+ */
143
+ async fetchTemplateList(apiKey?: string, token?: string): Promise<Array<{ id: string; name: Record<string, string>; version?: string; status?: string }>> {
144
+ try {
145
+ const url = `${KYCConfig.getBackendUrl()}/templates/kyc/templates`;
146
+ logger.log(`Fetching template list from: ${url}`);
147
+
148
+ const response = await axios.get<Array<{ id: string; name: Record<string, string>; version?: string; status?: string }>>(url, {
149
+ headers: this.getHeaders(apiKey, token),
150
+ timeout: 30000,
151
+ });
152
+
153
+ logger.log(`Fetched ${response.data.length} templates`);
154
+ return response.data;
155
+ } catch (error: any) {
156
+ logger.error('Error fetching template list:', JSON.stringify(errorMessage(error), null, 2));
157
+ throw new Error(`Failed to fetch template list: ${error.message || 'Unknown error'}`);
158
+ }
159
+ }
160
+ }
161
+
162
+ // Export singleton instance as default
163
+ const templateService = new TemplateServiceClass();
164
+ export default templateService;
165
+
166
+ // Also export the class for advanced usage
167
+ // export { TemplateServiceClass };
@@ -8,6 +8,7 @@ export interface Document {
8
8
  uploadedAt: Date;
9
9
  validated: boolean;
10
10
  extractedData?: DocumentData;
11
+
11
12
  }
12
13
 
13
14
  export type DocumentType = 'passport' | 'id_card' | 'drivers_license';
@@ -325,6 +326,12 @@ export type GovernmentDocumentType =
325
326
  | 'permanent_residence'
326
327
  | 'national_id'
327
328
  | 'work_permit'
329
+ | 'id'
330
+ | 'pp'
331
+ | 'dl'
332
+ | 'hic'
333
+ | 'pr'
334
+ | 'wp'
328
335
 
329
336
  export const GovernmentDocumentTypeShorted: Record<GovernmentDocumentType, string> = {
330
337
  identity_card: 'id',
@@ -334,6 +341,22 @@ export const GovernmentDocumentTypeShorted: Record<GovernmentDocumentType, strin
334
341
  permanent_residence: 'pr',
335
342
  national_id: 'id',
336
343
  work_permit: 'wp',
344
+ id: 'id',
345
+ pp: 'pp',
346
+ dl: 'dl',
347
+ hic: 'hic',
348
+ pr: 'pr',
349
+ wp: 'wp',
350
+ }
351
+
352
+ export const GovernmentDocumentTypeBackend: Record<string, GovernmentDocumentType> = {
353
+ national_id: 'identity_card',
354
+ passport: 'passport',
355
+ driversLicense: 'drivers_licence',
356
+ healthInsuranceCard: 'health_insurance_card',
357
+ permanentResidence: 'permanent_residence',
358
+ workPermit: 'work_permit',
359
+ residencePermit: 'permanent_residence',
337
360
  }
338
361
 
339
362
  // Configuration spécifique pour chaque type de composant
@@ -342,7 +365,7 @@ export interface IDCardConfig {
342
365
  allowed_formats: string[];
343
366
  max_size_mb: number;
344
367
  document_types: GovernmentDocumentType[]; // Types de documents disponibles
345
- bbox_configs: Record<GovernmentDocumentType, {
368
+ bbox_configs?: Record<GovernmentDocumentType, {
346
369
  xMin: number;
347
370
  yMin: number;
348
371
  xMax: number;
@@ -383,12 +406,18 @@ export type ComponentConfig =
383
406
  | SelfieConfig
384
407
  | FileUploadConfig
385
408
  | LocationConfig
386
- | CountrySelectionConfig;
409
+ | CountrySelectionConfig
410
+ | CountrySelectionConfig
411
+ | WelcomeConfig
412
+ | EmailVerificationConfig
413
+ | PhoneVerificationConfig
414
+ | PersonalInformationConfig
415
+ | AdditionalDocumentsConfig;
387
416
 
388
417
  // Nouveau type de composant basé sur le template JSON
389
418
  export interface TemplateComponent {
390
419
  id: number;
391
- type: 'id_card' | 'selfie' | 'file_upload' | 'location' | 'country_selection' | 'initialization' | 'review_submit' | 'verification_progress';
420
+ type: 'id_card' | 'selfie' | 'file_upload' | 'location' | 'country_selection' | 'initialization' | 'review_submit' | 'verification_progress' | 'welcome' | 'email_verification' | 'phone_verification' | 'personal_information' | 'additional_documents';
392
421
  order: number;
393
422
  templateId?: number;
394
423
  labels: LocalizedText | Record<string, LocalizedText>;
@@ -464,6 +493,7 @@ export interface UseTemplateReturn {
464
493
  isComplete: boolean;
465
494
  getLocalizedText: (text: LocalizedText) => string;
466
495
  initializeSession: () => Promise<void>;
496
+ env: 'PRODUCTION' | 'SANDBOX';
467
497
  }
468
498
 
469
499
 
@@ -502,4 +532,302 @@ export interface Country {
502
532
  flag: string;
503
533
  regionMapping?: ICountryMapping;
504
534
  hasRegions?: boolean;
535
+ }
536
+
537
+ // ===== TYPES FOR BACKEND TEMPLATE FORMAT =====
538
+
539
+ // Backend component configuration types
540
+ export interface WelcomeConfig {
541
+ subtitle?: string;
542
+ buttonText?: string;
543
+ requirements?: string[];
544
+ estimatedTime?: string;
545
+ consentOptions?: {
546
+ showPrivacyPolicy?: boolean;
547
+ showTermsOfService?: boolean;
548
+ showMarketingConsent?: boolean;
549
+ };
550
+ welcomeMessage?: string;
551
+ showEstimatedTime?: boolean;
552
+ }
553
+
554
+ export interface LocationCaptureConfig {
555
+ showMap?: boolean;
556
+ accuracy?: string;
557
+ required?: boolean;
558
+ maxDistance?: number;
559
+ captureMethod?: string;
560
+ allowManualEntry?: boolean;
561
+ countryRestrictions?: string[];
562
+ }
563
+
564
+ export interface GovernmentIdConfig {
565
+ required?: boolean;
566
+ allowSkip?: boolean;
567
+ cameraOverlay?: {
568
+ bbox?: {
569
+ xMax?: number;
570
+ xMin?: number;
571
+ yMax?: number;
572
+ yMin?: number;
573
+ borderColor?: string;
574
+ borderWidth?: number;
575
+ cornerRadius?: number;
576
+ };
577
+ };
578
+ documentTypes?: string[];
579
+ requiredSides?: string;
580
+ cameraSettings?: {
581
+ quality?: number;
582
+ flashMode?: string;
583
+ maxRetakes?: number;
584
+ allowRetake?: boolean;
585
+ aspectRatio?: number;
586
+ };
587
+ validationRules?: string[];
588
+ regionsByCountry?: Record<string, any>;
589
+ selectedCountries?: string[];
590
+ authenticationMethods?: Record<string, Record<string, {
591
+ back?: string[];
592
+ front?: string[];
593
+ mrzTypes?: string[];
594
+ }>>;
595
+ documentTypesByCountry?: Record<string, string[]>;
596
+ instructionsByDocumentType?: Record<string, LocalizedText>;
597
+ }
598
+
599
+ export interface SelfieCaptureConfig {
600
+ timeout?: number;
601
+ maxAttempts?: number;
602
+ faceMatching?: boolean;
603
+ captureMethod?: string;
604
+ qualityChecks?: string[];
605
+ livenessChecks?: string[];
606
+ matchThreshold?: string;
607
+ livenessEnabled?: boolean;
608
+ }
609
+
610
+ export interface ReviewSubmitConfig {
611
+ allowEditing?: boolean;
612
+ displayOptions?: string[];
613
+ requireConsent?: boolean;
614
+ postSubmitActions?: string[];
615
+ }
616
+
617
+ export type BackendComponentConfig =
618
+ | WelcomeConfig
619
+ | LocationCaptureConfig
620
+ | GovernmentIdConfig
621
+ | SelfieCaptureConfig
622
+ | ReviewSubmitConfig
623
+ | Record<string, any>;
624
+
625
+ // Backend component translation structure
626
+ export interface BackendComponentTranslations {
627
+ en?: {
628
+ title?: string;
629
+ description?: string;
630
+ instructions?: string;
631
+ buttonText?: string;
632
+ consentText?: string;
633
+ successMessage?: string;
634
+ };
635
+ fr?: {
636
+ title?: string;
637
+ description?: string;
638
+ instructions?: string;
639
+ buttonText?: string;
640
+ consentText?: string;
641
+ successMessage?: string;
642
+ };
643
+ [key: string]: {
644
+ title?: string;
645
+ description?: string;
646
+ instructions?: string;
647
+ buttonText?: string;
648
+ consentText?: string;
649
+ successMessage?: string;
650
+ } | undefined;
651
+ }
652
+
653
+ // Backend template component
654
+ export interface BackendTemplateComponent {
655
+ id: string;
656
+ type: 'welcome' | 'location-capture' | 'government-id' | 'selfie-capture' | 'review-submit' | 'verification-progress' | 'email-verification' | 'phone-verification' | 'personal-information' | 'additional-documents';
657
+ order: number;
658
+ config: BackendComponentConfig;
659
+ required?: boolean;
660
+ translations: BackendComponentTranslations;
661
+ }
662
+
663
+ // Backend template structure
664
+ export interface BackendKYCTemplate {
665
+ id: string;
666
+ name: {
667
+ en: string;
668
+ fr: string;
669
+ [key: string]: string;
670
+ };
671
+ status?: string;
672
+ version?: string;
673
+ components: BackendTemplateComponent[];
674
+ description?: {
675
+ en: string;
676
+ fr: string;
677
+ [key: string]: string;
678
+ };
679
+ }
680
+
681
+ // ===== NEW CONFIG TYPES FOR INPUT VERIFICATION =====
682
+
683
+ export interface EmailVerificationConfig {
684
+ allowResend: boolean;
685
+ otpSettings: {
686
+ codeLength: number;
687
+ expiryTime: number;
688
+ };
689
+ resendCooldown: number;
690
+ emailValidation: {
691
+ corporateOnly: boolean;
692
+ validateFormat: boolean;
693
+ checkDisposable: boolean;
694
+ checkDeliverability: boolean;
695
+ };
696
+ verificationMethod: string;
697
+ required?: boolean;
698
+ }
699
+
700
+ export interface PhoneVerificationConfig {
701
+ required: boolean;
702
+ codeExpiry: number;
703
+ codeLength: number;
704
+ maxAttempts: number;
705
+ resendDelay: number;
706
+ countryRestrictions: string;
707
+ verificationMethods: string[];
708
+ allowSkipForVerified: boolean;
709
+ }
710
+
711
+ export interface PersonalInfoField {
712
+ id: string;
713
+ type: string;
714
+ label: string;
715
+ required: boolean;
716
+ placeholder?: string;
717
+ autoFillFromId?: boolean;
718
+ minAge?: number;
719
+ verifyAge?: boolean;
720
+ dateFormat?: string;
721
+ }
722
+
723
+ export interface PersonalInformationConfig {
724
+ fields: PersonalInfoField[];
725
+ validationSettings: {
726
+ validateOnBlur: boolean;
727
+ showAllErrorsAtOnce: boolean;
728
+ preventSubmissionWithErrors: boolean;
729
+ };
730
+ required?: boolean;
731
+ }
732
+
733
+ export interface DocumentCategory {
734
+ enabled: boolean;
735
+ category: string;
736
+ documentTypes: string[];
737
+ }
738
+
739
+ export interface AdditionalDocumentsConfig {
740
+ required: boolean;
741
+ maxSizeEach: string;
742
+ maxDocuments: number;
743
+ minDocuments: number;
744
+ documentCategories: DocumentCategory[];
745
+ customDocumentTypes: any[];
746
+ showBasedOnUserProfile: boolean;
747
+ }
748
+
749
+ // API response for template
750
+ export interface TemplateAPIResponse {
751
+ id: string;
752
+ name: {
753
+ en: string;
754
+ fr: string;
755
+ [key: string]: string;
756
+ };
757
+ status?: string;
758
+ version?: string;
759
+ components: BackendTemplateComponent[];
760
+ description?: {
761
+ en: string;
762
+ fr: string;
763
+ [key: string]: string;
764
+ };
765
+ }
766
+
767
+ // ===== NEW CONFIG TYPES FOR INPUT VERIFICATION =====
768
+
769
+ export interface EmailVerificationConfig {
770
+ allowResend: boolean;
771
+ otpSettings: {
772
+ codeLength: number;
773
+ expiryTime: number;
774
+ };
775
+ resendCooldown: number;
776
+ emailValidation: {
777
+ corporateOnly: boolean;
778
+ validateFormat: boolean;
779
+ checkDisposable: boolean;
780
+ checkDeliverability: boolean;
781
+ };
782
+ verificationMethod: string;
783
+ required?: boolean;
784
+ }
785
+
786
+ export interface PhoneVerificationConfig {
787
+ required: boolean;
788
+ codeExpiry: number;
789
+ codeLength: number;
790
+ maxAttempts: number;
791
+ resendDelay: number;
792
+ countryRestrictions: string;
793
+ verificationMethods: string[];
794
+ allowSkipForVerified: boolean;
795
+ }
796
+
797
+ export interface PersonalInfoField {
798
+ id: string;
799
+ type: string;
800
+ label: string;
801
+ required: boolean;
802
+ placeholder?: string;
803
+ autoFillFromId?: boolean;
804
+ minAge?: number;
805
+ verifyAge?: boolean;
806
+ dateFormat?: string;
807
+ }
808
+
809
+ export interface PersonalInformationConfig {
810
+ fields: PersonalInfoField[];
811
+ validationSettings: {
812
+ validateOnBlur: boolean;
813
+ showAllErrorsAtOnce: boolean;
814
+ preventSubmissionWithErrors: boolean;
815
+ };
816
+ required?: boolean;
817
+ }
818
+
819
+ export interface DocumentCategory {
820
+ enabled: boolean;
821
+ category: string;
822
+ documentTypes: string[];
823
+ }
824
+
825
+ export interface AdditionalDocumentsConfig {
826
+ required: boolean;
827
+ maxSizeEach: string;
828
+ maxDocuments: number;
829
+ minDocuments: number;
830
+ documentCategories: DocumentCategory[];
831
+ customDocumentTypes: any[];
832
+ showBasedOnUserProfile: boolean;
505
833
  }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * KYC Environment types
3
+ * PRODUCTION: Full verification with AI checks
4
+ * SANDBOX: Skip AI verification, only save data to backend
5
+ */
6
+ export type KycEnvironment = 'PRODUCTION' | 'SANDBOX';
7
+
8
+ /**
9
+ * Backend Environment types
10
+ * PRODUCTION: Production backend
11
+ * TEST: Test backend
12
+ */
13
+ export type BackendEnvironment = 'PRODUCTION' | 'TEST';
@@ -1,5 +1,7 @@
1
1
  import { Image as RNImage, Platform } from 'react-native';
2
2
  import * as ImageManipulator from "expo-image-manipulator";
3
+ import { truncateFields } from '../modules/api/KYCService';
4
+ import { logger } from './logger';
3
5
 
4
6
  type Point = [number, number];
5
7
 
@@ -81,13 +83,14 @@ export async function cropImageWithBBox(uri: string, bbox: any) {
81
83
 
82
84
  // 3️⃣ Convertir le bbox à la taille réelle scale 0.10 = 10%
83
85
  const crop = {
84
- originX: bbox.minX ,
85
- originY: bbox.minY ,
86
- width: bbox.width ,
86
+ originX: bbox.minX,
87
+ originY: bbox.minY,
88
+ width: bbox.width,
87
89
  height: bbox.height,
88
90
  };
89
91
 
90
92
  // 4️⃣ Appliquer le crop
93
+ // @ts-ignore - manipulateAsync is deprecated but still functional, new API (useImageManipulator) is a React hook and not suitable for utility functions
91
94
  const result = await ImageManipulator.manipulateAsync(
92
95
  uri,
93
96
  [{ crop }],
@@ -97,3 +100,80 @@ export async function cropImageWithBBox(uri: string, bbox: any) {
97
100
  console.log("Image recadrée:", result.uri);
98
101
  return result.uri;
99
102
  }
103
+
104
+ // Fonction pour rogner avec une tolérance de 10% autour du bbox
105
+ export async function cropImageWithBBoxWithTolerance(uri: string, bbox: any, tolerance: number = 0.1): Promise<string> {
106
+ console.log("cropImageWithBBoxWithTolerance", JSON.stringify(truncateFields({ uri, bbox, tolerance }), null, 2));
107
+
108
+ return new Promise<string>((resolve, reject) => {
109
+ let isResolved = false;
110
+
111
+ // Timeout de sécurité (15 secondes)
112
+ const timeout = setTimeout(() => {
113
+ if (!isResolved) {
114
+ isResolved = true;
115
+ console.warn("Timeout lors du rognage avec tolérance, utilisation de l'image originale");
116
+ resolve(uri); // Retourner l'URI original en cas de timeout
117
+ }
118
+ }, 15000);
119
+
120
+ // 1️⃣ Récupère la taille originale de l'image
121
+ RNImage.getSize(uri, (imageWidth, imageHeight) => {
122
+ if (isResolved) return;
123
+
124
+ // 2️⃣ Calculer la tolérance en pixels (10% de chaque côté)
125
+ const toleranceX = bbox.width * tolerance;
126
+ const toleranceY = bbox.height * tolerance;
127
+
128
+ // 3️⃣ Ajuster le bbox avec la tolérance
129
+ // Calculer les nouvelles coordonnées avec tolérance
130
+ const newMinX = Math.max(0, bbox.minX - toleranceX);
131
+ const newMinY = Math.max(0, bbox.minY - toleranceY);
132
+ const newMaxX = Math.min(imageWidth, bbox.minX + bbox.width + toleranceX);
133
+ const newMaxY = Math.min(imageHeight, bbox.minY + bbox.height + toleranceY);
134
+
135
+ // Calculer la largeur et hauteur finales
136
+ const finalWidth = newMaxX - newMinX;
137
+ const finalHeight = newMaxY - newMinY;
138
+
139
+ const crop = {
140
+ originX: newMinX,
141
+ originY: newMinY,
142
+ width: finalWidth,
143
+ height: finalHeight,
144
+ };
145
+
146
+ logger.log("cropImageWithBBoxWithTolerance - crop params", JSON.stringify(truncateFields({ uri, crop, tolerance, imageWidth, imageHeight }), null, 2));
147
+
148
+ // 4️⃣ Appliquer le crop avec tolérance
149
+ // @ts-ignore - manipulateAsync is deprecated but still functional, new API (useImageManipulator) is a React hook and not suitable for utility functions
150
+ ImageManipulator.manipulateAsync(
151
+ uri,
152
+ [{ crop }],
153
+ { compress: 0.95, format: ImageManipulator.SaveFormat.JPEG }
154
+ )
155
+ .then((result) => {
156
+ if (isResolved) return;
157
+ isResolved = true;
158
+ clearTimeout(timeout);
159
+ console.log("Image recadrée avec tolérance:", result.uri);
160
+ resolve(result.uri);
161
+ })
162
+ .catch((error) => {
163
+ if (isResolved) return;
164
+ isResolved = true;
165
+ clearTimeout(timeout);
166
+ console.error("Erreur lors du rognage avec tolérance:", error);
167
+ // En cas d'erreur, retourner l'URI original au lieu de rejeter
168
+ resolve(uri);
169
+ });
170
+ }, (error) => {
171
+ if (isResolved) return;
172
+ isResolved = true;
173
+ clearTimeout(timeout);
174
+ console.error("Erreur lors de la récupération de la taille de l'image:", error);
175
+ // En cas d'erreur, retourner l'URI original au lieu de rejeter
176
+ resolve(uri);
177
+ });
178
+ });
179
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Checks if the current environment is a mobile web browser based on User Agent.
3
+ * This can be used to distinguish between desktop web and mobile web.
4
+ */
5
+ export const isMobileWeb = (): boolean => {
6
+ if (typeof window === 'undefined' || !window.navigator) {
7
+ return false;
8
+ }
9
+ const userAgent = window.navigator.userAgent;
10
+ return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent);
11
+ };