@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
@@ -1,8 +1,9 @@
1
- import React from 'react';
2
- import { View, Text, StyleSheet, SafeAreaView, TouchableOpacity, ActivityIndicator, Dimensions, Alert } from 'react-native';
1
+ import React, { useEffect } from 'react';
2
+ import { View, Text, StyleSheet, SafeAreaView, TouchableOpacity, ActivityIndicator, Dimensions, ScrollView, Platform } from 'react-native';
3
3
  import { KYCTemplate, VerificationState } from '../types/KYC.types';
4
4
  import { TemplateKYCFlowProvider, useTemplateKYCFlowContext } from '../hooks/useTemplateKYCFlow';
5
5
  import { useI18n } from '../hooks/useI18n';
6
+ import { showAlert } from '../utils/platformAlert';
6
7
  import { IDCardCapture } from './KYCElements/IDCardCapture';
7
8
  import { SelfieCaptureTemplate } from './KYCElements/SelfieCaptureTemplate';
8
9
  import { FileUploadTemplate } from './KYCElements/FileUploadTemplate';
@@ -11,28 +12,67 @@ import { CountrySelectionTemplate } from './KYCElements/CountrySelectionTemplate
11
12
  import { InitializationStep } from './KYCElements/InitializationStep';
12
13
  import { ReviewSubmitTemplate } from './KYCElements/ReviewSubmitTemplate';
13
14
  import { VerificationProgressTemplate } from './KYCElements/VerificationProgressTemplate';
15
+ import { useTemplateLoader } from '../hooks/useTemplateLoader';
16
+ import { WelcomeTemplate } from './KYCElements/WelcomeTemplate';
17
+ import { EmailVerificationTemplate } from './KYCElements/EmailVerificationTemplate';
18
+ import { PhoneVerificationTemplate } from './KYCElements/PhoneVerificationTemplate';
19
+ import { PersonalInformationTemplate } from './KYCElements/PersonalInformationTemplate';
20
+ import { AdditionalDocumentsTemplate } from './KYCElements/AdditionalDocumentsTemplate';
21
+ import { KycEnvironment } from '../types/env.types';
14
22
 
15
23
  interface TemplateKYCFlowProps {
16
- template: KYCTemplate;
24
+ template?: KYCTemplate; // Format SDK direct (existing, now optional)
25
+ templateId?: string; // New: ID to load from API
17
26
  onComplete?: (data: VerificationState) => void;
18
27
  onError?: (error: string) => void;
19
28
  language?: string;
20
29
  onCancel?: () => void;
21
- API_KEY?: string;
30
+ API_KEY?: string; // Required if templateId is used
31
+ env?: KycEnvironment; // Environment mode: PRODUCTION or SANDBOX
32
+ existingSessionId?: string;
33
+ initialStep?: number; // Initial step index to resume verification
22
34
  }
23
35
 
24
36
  export const TemplateKYCFlow: React.FC<TemplateKYCFlowProps> = ({
25
- template,
37
+ template: providedTemplate,
38
+ templateId,
26
39
  onComplete,
27
40
  onError,
28
41
  language = 'fr',
29
42
  onCancel,
30
43
  API_KEY,
44
+ env = 'PRODUCTION',
45
+ existingSessionId,
46
+ initialStep,
31
47
  }) => {
32
48
  const { t } = useI18n();
33
- // console.log('API_KEY', API_KEY);
49
+ const { template: loadedTemplate, isLoading, error, loadTemplate } = useTemplateLoader();
50
+
51
+ // Validate props
52
+ useEffect(() => {
53
+ if (!providedTemplate && !templateId) {
54
+ const errorMsg = 'Either template or templateId must be provided';
55
+ onError?.(errorMsg);
56
+ return;
57
+ }
58
+
59
+ if (templateId && !API_KEY) {
60
+ // Try to load without API key (will use token authentication)
61
+ loadTemplate(templateId);
62
+ } else if (templateId && API_KEY) {
63
+ loadTemplate(templateId, API_KEY);
64
+ }
65
+ }, [templateId, API_KEY, providedTemplate, loadTemplate, onError]);
66
+
67
+ // Handle loading errors
68
+ useEffect(() => {
69
+ if (error) {
70
+ onError?.(error);
71
+ }
72
+ }, [error, onError]);
73
+
34
74
  const OnCancel = () => {
35
- Alert.alert(
75
+ showAlert(
36
76
  t('kyc.cancelConfirmation.title'),
37
77
  t('kyc.cancelConfirmation.message'),
38
78
  [
@@ -46,6 +86,46 @@ export const TemplateKYCFlow: React.FC<TemplateKYCFlowProps> = ({
46
86
  ]
47
87
  );
48
88
  };
89
+
90
+ // Determine which template to use
91
+ const template = providedTemplate || loadedTemplate;
92
+
93
+ // Show loading state while fetching template
94
+ if (templateId && isLoading && !template) {
95
+ return (
96
+ <View style={styles.loadingContainer}>
97
+ <ActivityIndicator size="large" color="#2DBD60" />
98
+ <Text style={styles.loadingText}>{t('common.loading') || 'Loading template...'}</Text>
99
+ </View>
100
+ );
101
+ }
102
+
103
+ // Show error state if template failed to load
104
+ if (templateId && error && !template) {
105
+ return (
106
+ <View style={styles.errorContainer}>
107
+ <Text style={styles.errorText}>{error}</Text>
108
+ <TouchableOpacity
109
+ style={styles.retryButton}
110
+ onPress={() => loadTemplate(templateId, API_KEY)}
111
+ >
112
+ <Text style={styles.retryButtonText}>{t('common.retry') || 'Retry'}</Text>
113
+ </TouchableOpacity>
114
+ </View>
115
+ );
116
+ }
117
+
118
+ // Show error if no template available
119
+ if (!template) {
120
+ return (
121
+ <View style={styles.errorContainer}>
122
+ <Text style={styles.errorText}>
123
+ {t('errors.unknownError') || 'Template not available'}
124
+ </Text>
125
+ </View>
126
+ );
127
+ }
128
+
49
129
  return (
50
130
  <TemplateKYCFlowProvider
51
131
  template={template}
@@ -54,6 +134,9 @@ export const TemplateKYCFlow: React.FC<TemplateKYCFlowProps> = ({
54
134
  onCancel={OnCancel}
55
135
  initialLanguage={language}
56
136
  apiKey={API_KEY}
137
+ env={env}
138
+ existingSessionId={existingSessionId}
139
+ initialStep={initialStep}
57
140
  >
58
141
  <TemplateKYCFlowContent onCancel={OnCancel} />
59
142
  </TemplateKYCFlowProvider>
@@ -97,6 +180,9 @@ const TemplateKYCFlowContent: React.FC<{ onCancel?: () => void }> = ({ onCancel
97
180
  }
98
181
 
99
182
  switch (currentComponent.type) {
183
+ case 'welcome':
184
+ return <WelcomeTemplate {...commonProps} />;
185
+
100
186
  case 'id_card':
101
187
  return <IDCardCapture {...commonProps} />;
102
188
 
@@ -115,6 +201,18 @@ const TemplateKYCFlowContent: React.FC<{ onCancel?: () => void }> = ({ onCancel
115
201
  case 'review_submit':
116
202
  return <ReviewSubmitTemplate {...commonProps} />;
117
203
 
204
+ case 'email_verification':
205
+ return <EmailVerificationTemplate {...commonProps} />;
206
+
207
+ case 'phone_verification':
208
+ return <PhoneVerificationTemplate {...commonProps} />;
209
+
210
+ case 'personal_information':
211
+ return <PersonalInformationTemplate {...commonProps} />;
212
+
213
+ case 'additional_documents':
214
+ return <AdditionalDocumentsTemplate {...commonProps} />;
215
+
118
216
  case 'verification_progress':
119
217
  return <VerificationProgressTemplate {...commonProps} />;
120
218
 
@@ -166,9 +264,14 @@ const TemplateKYCFlowContent: React.FC<{ onCancel?: () => void }> = ({ onCancel
166
264
  ) : null}
167
265
 
168
266
  {/* Contenu principal */}
169
- <View style={styles.content}>
267
+ <ScrollView
268
+ style={styles.scrollView}
269
+ contentContainerStyle={styles.content}
270
+ showsVerticalScrollIndicator={Platform.OS === 'web'}
271
+ bounces={false}
272
+ >
170
273
  {renderCurrentComponent()}
171
- </View>
274
+ </ScrollView>
172
275
 
173
276
  {state.isProcessing && (
174
277
  <View style={styles.processingContainer}>
@@ -253,11 +356,13 @@ const styles = StyleSheet.create({
253
356
  color: '#666',
254
357
  lineHeight: 20,
255
358
  },
256
- content: {
359
+ scrollView: {
257
360
  flex: 1,
258
- // justifyContent: 'center',
361
+ },
362
+ content: {
363
+ flexGrow: 1,
259
364
  alignItems: 'center',
260
- // paddingTop: Dimensions.get('window').height > 760 ? 12 : 0,
365
+ paddingBottom: 20, // Add padding for better mobile scrolling
261
366
  },
262
367
  navigation: {
263
368
  flexDirection: 'row',
@@ -316,4 +421,35 @@ const styles = StyleSheet.create({
316
421
  fontWeight: 'bold',
317
422
  marginBottom: 10,
318
423
  },
424
+ loadingContainer: {
425
+ flex: 1,
426
+ justifyContent: 'center',
427
+ alignItems: 'center',
428
+ backgroundColor: '#f5f5f5',
429
+ },
430
+ loadingText: {
431
+ marginTop: 16,
432
+ fontSize: 16,
433
+ color: '#666',
434
+ textAlign: 'center',
435
+ },
436
+ errorContainer: {
437
+ flex: 1,
438
+ justifyContent: 'center',
439
+ alignItems: 'center',
440
+ backgroundColor: '#f5f5f5',
441
+ padding: 20,
442
+ },
443
+ retryButton: {
444
+ marginTop: 20,
445
+ paddingHorizontal: 24,
446
+ paddingVertical: 12,
447
+ backgroundColor: '#2DBD60',
448
+ borderRadius: 8,
449
+ },
450
+ retryButtonText: {
451
+ color: '#fff',
452
+ fontSize: 16,
453
+ fontWeight: '600',
454
+ },
319
455
  });
@@ -0,0 +1,289 @@
1
+ import React, { useState } from 'react';
2
+ import { View, Text, StyleSheet, SafeAreaView, TextInput, TouchableOpacity, ScrollView } from 'react-native';
3
+ import { TemplateKYCFlow } from '../TemplateKYCFlowRefactored';
4
+ import { VerificationState } from '../../types/KYC.types';
5
+
6
+ /**
7
+ * Example component demonstrating how to use dynamic template loading
8
+ *
9
+ * This example shows two ways to use templates:
10
+ * 1. With templateId - loads template dynamically from backend API
11
+ * 2. With direct template object - uses hardcoded template (backward compatibility)
12
+ */
13
+ export const DynamicTemplateExample: React.FC = () => {
14
+ const [templateId, setTemplateId] = useState<string>('');
15
+ const [apiKey, setApiKey] = useState<string>('');
16
+ const [showFlow, setShowFlow] = useState<boolean>(false);
17
+ const [language, setLanguage] = useState<'en' | 'fr'>('en');
18
+
19
+ const handleComplete = (data: VerificationState) => {
20
+ console.log('KYC Verification completed:', data);
21
+ setShowFlow(false);
22
+ alert('Verification completed successfully!');
23
+ };
24
+
25
+ const handleError = (error: string) => {
26
+ console.error('KYC Error:', error);
27
+ alert(`Error: ${error}`);
28
+ setShowFlow(false);
29
+ };
30
+
31
+ const handleCancel = () => {
32
+ console.log('KYC Flow cancelled');
33
+ setShowFlow(false);
34
+ };
35
+
36
+ const startFlow = () => {
37
+ if (!templateId.trim()) {
38
+ alert('Please enter a template ID');
39
+ return;
40
+ }
41
+ setShowFlow(true);
42
+ };
43
+
44
+ if (showFlow) {
45
+ return (
46
+ <SafeAreaView style={styles.container}>
47
+ <TemplateKYCFlow
48
+ templateId={templateId}
49
+ API_KEY={apiKey || undefined}
50
+ language={language}
51
+ onComplete={handleComplete}
52
+ onError={handleError}
53
+ onCancel={handleCancel}
54
+ />
55
+ </SafeAreaView>
56
+ );
57
+ }
58
+
59
+ return (
60
+ <SafeAreaView style={styles.container}>
61
+ <ScrollView style={styles.scrollView} contentContainerStyle={styles.content}>
62
+ <Text style={styles.title}>Dynamic Template KYC Example</Text>
63
+ <Text style={styles.subtitle}>
64
+ Load a KYC template dynamically from the backend API
65
+ </Text>
66
+
67
+ <View style={styles.section}>
68
+ <Text style={styles.label}>Template ID *</Text>
69
+ <TextInput
70
+ style={styles.input}
71
+ placeholder="e.g., free-style"
72
+ value={templateId}
73
+ onChangeText={setTemplateId}
74
+ autoCapitalize="none"
75
+ autoCorrect={false}
76
+ />
77
+ <Text style={styles.hint}>
78
+ Enter the template ID to load from the backend API
79
+ </Text>
80
+ </View>
81
+
82
+ <View style={styles.section}>
83
+ <Text style={styles.label}>API Key (Optional)</Text>
84
+ <TextInput
85
+ style={styles.input}
86
+ placeholder="Your API key"
87
+ value={apiKey}
88
+ onChangeText={setApiKey}
89
+ autoCapitalize="none"
90
+ autoCorrect={false}
91
+ secureTextEntry
92
+ />
93
+ <Text style={styles.hint}>
94
+ If not provided, the SDK will use token-based authentication
95
+ </Text>
96
+ </View>
97
+
98
+ <View style={styles.section}>
99
+ <Text style={styles.label}>Language</Text>
100
+ <View style={styles.languageContainer}>
101
+ <TouchableOpacity
102
+ style={[
103
+ styles.languageButton,
104
+ language === 'en' && styles.languageButtonActive,
105
+ ]}
106
+ onPress={() => setLanguage('en')}
107
+ >
108
+ <Text
109
+ style={[
110
+ styles.languageButtonText,
111
+ language === 'en' && styles.languageButtonTextActive,
112
+ ]}
113
+ >
114
+ English
115
+ </Text>
116
+ </TouchableOpacity>
117
+ <TouchableOpacity
118
+ style={[
119
+ styles.languageButton,
120
+ language === 'fr' && styles.languageButtonActive,
121
+ ]}
122
+ onPress={() => setLanguage('fr')}
123
+ >
124
+ <Text
125
+ style={[
126
+ styles.languageButtonText,
127
+ language === 'fr' && styles.languageButtonTextActive,
128
+ ]}
129
+ >
130
+ Français
131
+ </Text>
132
+ </TouchableOpacity>
133
+ </View>
134
+ </View>
135
+
136
+ <TouchableOpacity
137
+ style={[styles.button, !templateId.trim() && styles.buttonDisabled]}
138
+ onPress={startFlow}
139
+ disabled={!templateId.trim()}
140
+ >
141
+ <Text style={styles.buttonText}>Start KYC Verification</Text>
142
+ </TouchableOpacity>
143
+
144
+ <View style={styles.infoSection}>
145
+ <Text style={styles.infoTitle}>Usage Example:</Text>
146
+ <Text style={styles.code}>
147
+ {`<TemplateKYCFlow
148
+ templateId="free-style"
149
+ API_KEY="your-api-key"
150
+ language="fr"
151
+ onComplete={handleComplete}
152
+ onError={handleError}
153
+ onCancel={handleCancel}
154
+ />`}
155
+ </Text>
156
+ </View>
157
+
158
+ <View style={styles.infoSection}>
159
+ <Text style={styles.infoTitle}>Notes:</Text>
160
+ <Text style={styles.infoText}>
161
+ • Template ID is required to load from backend{'\n'}
162
+ • API Key is optional but recommended for production{'\n'}
163
+ • The SDK will automatically transform the backend template format to SDK format{'\n'}
164
+ • Templates are cached for 5 minutes to improve performance{'\n'}
165
+ • You can also use a direct template object for backward compatibility
166
+ </Text>
167
+ </View>
168
+ </ScrollView>
169
+ </SafeAreaView>
170
+ );
171
+ };
172
+
173
+ const styles = StyleSheet.create({
174
+ container: {
175
+ flex: 1,
176
+ backgroundColor: '#f5f5f5',
177
+ },
178
+ scrollView: {
179
+ flex: 1,
180
+ },
181
+ content: {
182
+ padding: 20,
183
+ paddingBottom: 40,
184
+ },
185
+ title: {
186
+ fontSize: 24,
187
+ fontWeight: 'bold',
188
+ color: '#333',
189
+ marginBottom: 8,
190
+ textAlign: 'center',
191
+ },
192
+ subtitle: {
193
+ fontSize: 16,
194
+ color: '#666',
195
+ marginBottom: 32,
196
+ textAlign: 'center',
197
+ },
198
+ section: {
199
+ marginBottom: 24,
200
+ },
201
+ label: {
202
+ fontSize: 16,
203
+ fontWeight: '600',
204
+ color: '#333',
205
+ marginBottom: 8,
206
+ },
207
+ input: {
208
+ backgroundColor: 'white',
209
+ borderWidth: 1,
210
+ borderColor: '#ddd',
211
+ borderRadius: 8,
212
+ padding: 12,
213
+ fontSize: 16,
214
+ color: '#333',
215
+ },
216
+ hint: {
217
+ fontSize: 12,
218
+ color: '#999',
219
+ marginTop: 4,
220
+ },
221
+ languageContainer: {
222
+ flexDirection: 'row',
223
+ gap: 12,
224
+ },
225
+ languageButton: {
226
+ flex: 1,
227
+ padding: 12,
228
+ backgroundColor: 'white',
229
+ borderWidth: 1,
230
+ borderColor: '#ddd',
231
+ borderRadius: 8,
232
+ alignItems: 'center',
233
+ },
234
+ languageButtonActive: {
235
+ backgroundColor: '#2DBD60',
236
+ borderColor: '#2DBD60',
237
+ },
238
+ languageButtonText: {
239
+ fontSize: 16,
240
+ color: '#666',
241
+ fontWeight: '500',
242
+ },
243
+ languageButtonTextActive: {
244
+ color: 'white',
245
+ fontWeight: '600',
246
+ },
247
+ button: {
248
+ backgroundColor: '#2DBD60',
249
+ padding: 16,
250
+ borderRadius: 8,
251
+ alignItems: 'center',
252
+ marginTop: 8,
253
+ marginBottom: 32,
254
+ },
255
+ buttonDisabled: {
256
+ backgroundColor: '#ccc',
257
+ },
258
+ buttonText: {
259
+ color: 'white',
260
+ fontSize: 16,
261
+ fontWeight: '600',
262
+ },
263
+ infoSection: {
264
+ backgroundColor: 'white',
265
+ padding: 16,
266
+ borderRadius: 8,
267
+ marginBottom: 16,
268
+ },
269
+ infoTitle: {
270
+ fontSize: 16,
271
+ fontWeight: '600',
272
+ color: '#333',
273
+ marginBottom: 8,
274
+ },
275
+ code: {
276
+ fontFamily: 'monospace',
277
+ fontSize: 12,
278
+ color: '#555',
279
+ backgroundColor: '#f5f5f5',
280
+ padding: 12,
281
+ borderRadius: 4,
282
+ overflow: 'hidden',
283
+ },
284
+ infoText: {
285
+ fontSize: 14,
286
+ color: '#666',
287
+ lineHeight: 20,
288
+ },
289
+ });
@@ -0,0 +1,34 @@
1
+ import { BackendEnvironment } from '../types/env.types';
2
+
3
+ class KYCConfig {
4
+ private static instance: KYCConfig;
5
+ private backendEnvironment: BackendEnvironment = 'PRODUCTION';
6
+
7
+ private backendUrls: Record<BackendEnvironment, string> = {
8
+ PRODUCTION: 'https://service.sanctumkey.com/api/v1',
9
+ TEST: 'https://test-service.sanctumkey.com/api/v1', // Placeholder URL
10
+ };
11
+
12
+ private constructor() { }
13
+
14
+ public static getInstance(): KYCConfig {
15
+ if (!KYCConfig.instance) {
16
+ KYCConfig.instance = new KYCConfig();
17
+ }
18
+ return KYCConfig.instance;
19
+ }
20
+
21
+ public setBackendEnvironment(env: BackendEnvironment) {
22
+ this.backendEnvironment = env;
23
+ }
24
+
25
+ public getBackendUrl(): string {
26
+ return this.backendUrls[this.backendEnvironment];
27
+ }
28
+
29
+ public getBackendEnvironment(): BackendEnvironment {
30
+ return this.backendEnvironment;
31
+ }
32
+ }
33
+
34
+ export default KYCConfig.getInstance();
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Allowed domains configuration for callback URL validation
3
+ * These domains are permitted to receive KYC completion callbacks
4
+ */
5
+
6
+ export interface AllowedDomainConfig {
7
+ domains: string[];
8
+ enforceHttps: boolean;
9
+ allowLocalhost: boolean;
10
+ }
11
+
12
+ // Default configuration - can be overridden via environment variables
13
+ const DEFAULT_CONFIG: AllowedDomainConfig = {
14
+ domains: [
15
+ 'transfergratis.com',
16
+ 'www.transfergratis.com',
17
+ 'admin.transfergratis.com',
18
+ 'dashboard.transfergratis.com',
19
+ 'preweb.transfergratis.net',
20
+ // Add other trusted domains here
21
+ ],
22
+ enforceHttps: true,
23
+ allowLocalhost: true, // Allow localhost for development
24
+ };
25
+
26
+ /**
27
+ * Get allowed domains from environment or use defaults
28
+ */
29
+ export const getAllowedDomainsConfig = (): AllowedDomainConfig => {
30
+ // Check for environment variable override
31
+ if (typeof window !== 'undefined' && (window as any).KYC_ALLOWED_DOMAINS) {
32
+ const envDomains = (window as any).KYC_ALLOWED_DOMAINS;
33
+ if (Array.isArray(envDomains)) {
34
+ return {
35
+ ...DEFAULT_CONFIG,
36
+ domains: envDomains,
37
+ };
38
+ }
39
+ }
40
+
41
+ return DEFAULT_CONFIG;
42
+ };
43
+
44
+ /**
45
+ * Check if a domain is in the allowed list
46
+ */
47
+ export const isDomainAllowed = (domain: string): boolean => {
48
+ const config = getAllowedDomainsConfig();
49
+
50
+ // Allow localhost in development
51
+ if (config.allowLocalhost && (domain === 'localhost' || domain.startsWith('127.0.0.1'))) {
52
+ return true;
53
+ }
54
+
55
+ // Check if domain matches any in the allowed list
56
+ return config.domains.some(allowedDomain => {
57
+ // Exact match
58
+ if (domain === allowedDomain) {
59
+ return true;
60
+ }
61
+
62
+ // Subdomain match (e.g., app.transfergratis.com matches transfergratis.com)
63
+ if (domain.endsWith('.' + allowedDomain)) {
64
+ return true;
65
+ }
66
+
67
+ return false;
68
+ });
69
+ };
70
+
71
+ /**
72
+ * Validate if a URL is allowed for callback
73
+ */
74
+ export const isCallbackUrlAllowed = (url: string): { allowed: boolean; reason?: string } => {
75
+ try {
76
+ // Check if valid URL
77
+ new URL(url);
78
+ // Allow all URLs for redirection as requested
79
+ return { allowed: true };
80
+ } catch (error) {
81
+ return {
82
+ allowed: false,
83
+ reason: 'Invalid URL format',
84
+ };
85
+ }
86
+ };
87
+
88
+ /**
89
+ * Generate a signature for the callback URL parameters
90
+ * This can be used to verify the integrity of the callback
91
+ */
92
+ export const generateCallbackSignature = async (
93
+ params: Record<string, string>,
94
+ secret?: string
95
+ ): Promise<string> => {
96
+ // Only generate signature if secret is provided
97
+ if (!secret) {
98
+ return '';
99
+ }
100
+
101
+ // Sort params for consistent signature
102
+ const sortedParams = Object.keys(params)
103
+ .sort()
104
+ .map(key => `${key}=${params[key]}`)
105
+ .join('&');
106
+
107
+ const data = `${sortedParams}:${secret}`;
108
+
109
+ // Use Web Crypto API for signature generation
110
+ if (typeof window !== 'undefined' && window.crypto && window.crypto.subtle) {
111
+ try {
112
+ const encoder = new TextEncoder();
113
+ const dataBuffer = encoder.encode(data);
114
+ const hashBuffer = await window.crypto.subtle.digest('SHA-256', dataBuffer);
115
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
116
+ const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
117
+ return hashHex;
118
+ } catch (error) {
119
+ console.error('Error generating signature:', error);
120
+ return '';
121
+ }
122
+ }
123
+
124
+ // Fallback: simple hash for environments without Web Crypto API
125
+ let hash = 0;
126
+ for (let i = 0; i < data.length; i++) {
127
+ const char = data.charCodeAt(i);
128
+ hash = ((hash << 5) - hash) + char;
129
+ hash = hash & hash;
130
+ }
131
+ return Math.abs(hash).toString(16);
132
+ };
133
+