@sanctum-key/react-native-sdk 1.0.19 → 1.0.20

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 (31) hide show
  1. package/build/package.json +1 -1
  2. package/build/src/components/KYCElements/CountrySelectionTemplate.d.ts.map +1 -1
  3. package/build/src/components/KYCElements/CountrySelectionTemplate.js +40 -128
  4. package/build/src/components/KYCElements/CountrySelectionTemplate.js.map +1 -1
  5. package/build/src/components/KYCElements/IDCardCapture.d.ts.map +1 -1
  6. package/build/src/components/KYCElements/IDCardCapture.js +166 -129
  7. package/build/src/components/KYCElements/IDCardCapture.js.map +1 -1
  8. package/build/src/components/KYCElements/VerificationProgressTemplate.d.ts.map +1 -1
  9. package/build/src/components/KYCElements/VerificationProgressTemplate.js +38 -33
  10. package/build/src/components/KYCElements/VerificationProgressTemplate.js.map +1 -1
  11. package/build/src/hooks/useTemplateKYCFlow.js +1 -1
  12. package/build/src/hooks/useTemplateKYCFlow.js.map +1 -1
  13. package/build/src/modules/api/CardAuthentification.d.ts +5 -0
  14. package/build/src/modules/api/CardAuthentification.d.ts.map +1 -1
  15. package/build/src/modules/api/CardAuthentification.js +67 -13
  16. package/build/src/modules/api/CardAuthentification.js.map +1 -1
  17. package/build/src/modules/api/KYCService.d.ts +10 -0
  18. package/build/src/modules/api/KYCService.d.ts.map +1 -1
  19. package/build/src/modules/api/KYCService.js +94 -25
  20. package/build/src/modules/api/KYCService.js.map +1 -1
  21. package/build/src/web/WebKYCEntry.d.ts.map +1 -1
  22. package/build/src/web/WebKYCEntry.js +34 -6
  23. package/build/src/web/WebKYCEntry.js.map +1 -1
  24. package/package.json +1 -1
  25. package/src/components/KYCElements/CountrySelectionTemplate.tsx +53 -133
  26. package/src/components/KYCElements/IDCardCapture.tsx +613 -556
  27. package/src/components/KYCElements/VerificationProgressTemplate.tsx +54 -66
  28. package/src/hooks/useTemplateKYCFlow.tsx +14 -14
  29. package/src/modules/api/CardAuthentification.ts +133 -66
  30. package/src/modules/api/KYCService.ts +142 -38
  31. package/src/web/WebKYCEntry.tsx +42 -7
@@ -22,7 +22,6 @@ export const VerificationProgressTemplate: React.FC<VerificationProgressTemplate
22
22
  const [timeoutId, setTimeoutId] = useState<number | null>(null);
23
23
 
24
24
  const verification = state.verification;
25
-
26
25
  const isSuccess = verification.status === 'success';
27
26
  const isFailed = verification.status === 'failed';
28
27
 
@@ -30,38 +29,47 @@ export const VerificationProgressTemplate: React.FC<VerificationProgressTemplate
30
29
  const getVerificationResult = async (currentRetryCount = 0, maxRetries = 40) => {
31
30
  try {
32
31
  logger.log(`Starting verification check (attempt ${currentRetryCount + 1}/${maxRetries + 1})`);
32
+ const result: any = await kycService.getVerificationResult(state.session.session_id);
33
+
34
+ logger.log('getVerificationResult raw result:', JSON.stringify(result, null, 2));
35
+
36
+ if (result?.status === 'Failed.' || result?.status === 'failed' || result?.status === 'rejected') {
37
+ actions.setVerificationState({
38
+ status: 'failed',
39
+ result: {
40
+ referenceId: state.session.session_id,
41
+ issues: [result?.message || 'Verification failed. Sent for manual review.']
42
+ } as any
43
+ });
44
+ setIsRetrying(false);
45
+ return; // Break out of the function so it DOES NOT RETRY
46
+ }
33
47
 
34
- const result = await kycService.getVerificationResult(state.session.session_id);
35
- const responseData = (result as any)?.data;
48
+ // Check standard nested payload format
49
+ const responseData = result?.data;
36
50
  const verificationResult = responseData?.[state.session.session_id]?.data;
37
51
 
38
52
  if (!verificationResult) {
53
+ // If we still didn't get data and the status wasn't failed, throw to trigger a retry
39
54
  throw new Error('Verification payload missing for current session');
40
55
  }
41
56
 
42
- logger.log('getVerificationResult result', JSON.stringify({result,verificationResult}, null, 2));
43
-
44
57
  // Vérifier le statut de vérification
45
58
  if (verificationResult.verification_status === null || verificationResult.verification_status === "processing" || verificationResult.verification_status === "pending") {
46
59
  if (currentRetryCount < maxRetries) {
47
60
  const nextRetryCount = currentRetryCount + 1;
48
61
  setRetryCount(nextRetryCount);
49
62
  setIsRetrying(true);
50
-
51
63
  logger.log(`Verification still processing, retrying in 10s... (${nextRetryCount}/${maxRetries})`);
52
-
53
- // Nettoyer le timeout précédent s'il existe
54
- if (timeoutId) {
55
- clearTimeout(timeoutId);
56
- }
57
-
58
- // Attendre 10 secondes avant de relancer
64
+
65
+ if (timeoutId) clearTimeout(timeoutId);
66
+
59
67
  const newTimeoutId = setTimeout(() => {
60
68
  getVerificationResult(nextRetryCount, maxRetries);
61
69
  }, 10000);
62
-
63
- setTimeoutId(newTimeoutId);
64
- return; // Sortir de la fonction pour éviter de traiter le résultat
70
+
71
+ setTimeoutId(newTimeoutId as any);
72
+ return;
65
73
  } else {
66
74
  logger.error('Max retries reached, verification still processing');
67
75
  setIsRetrying(false);
@@ -70,51 +78,39 @@ export const VerificationProgressTemplate: React.FC<VerificationProgressTemplate
70
78
  }
71
79
 
72
80
  // Traiter le résultat final (success, failed, etc.)
73
- if (verificationResult.verification_status === "completed" ||
74
- verificationResult.verification_status === "approved") {
75
- // Mettre à jour l'état avec le succès
81
+ if (verificationResult.verification_status === "completed" || verificationResult.verification_status === "approved") {
76
82
  actions.setVerificationState({
77
83
  status: 'success',
78
84
  result: result
79
85
  });
80
- } else if (verificationResult.verification_status === "failed" ||
81
- verificationResult.verification_status === "rejected") {
82
- // Mettre à jour l'état avec l'échec
86
+ } else if (verificationResult.verification_status === "failed" || verificationResult.verification_status === "rejected") {
83
87
  actions.setVerificationState({
84
88
  status: 'failed',
85
89
  result: {
86
- referenceId: verificationResult.verification_id,
87
- issues: ['Verification failed']
90
+ referenceId: verificationResult.verification_id || state.session.session_id,
91
+ issues: ['Verification failed during processing.']
88
92
  } as any
89
93
  });
90
94
  }
91
-
95
+
92
96
  setIsRetrying(false);
93
97
 
94
98
  } catch (error: any) {
95
- logger.error(
96
- 'getVerificationResult error',
97
- JSON.stringify(errorMessage(error) || { message: error?.message || 'Unknown error' }, null, 2)
98
- );
99
-
100
- // En cas d'erreur, on peut aussi retry
99
+ logger.error('getVerificationResult error', JSON.stringify(errorMessage(error) || { message: error?.message || 'Unknown error' }, null, 2));
100
+
101
101
  if (currentRetryCount < maxRetries) {
102
102
  const nextRetryCount = currentRetryCount + 1;
103
103
  setRetryCount(nextRetryCount);
104
104
  setIsRetrying(true);
105
-
106
105
  logger.log(`getVerificationResult Error occurred, retrying in 10s... (${nextRetryCount}/${maxRetries})`);
107
-
108
- // Nettoyer le timeout précédent s'il existe
109
- if (timeoutId) {
110
- clearTimeout(timeoutId);
111
- }
112
-
106
+
107
+ if (timeoutId) clearTimeout(timeoutId);
108
+
113
109
  const newTimeoutId = setTimeout(() => {
114
110
  getVerificationResult(nextRetryCount, maxRetries);
115
111
  }, 10000);
116
-
117
- setTimeoutId(newTimeoutId);
112
+
113
+ setTimeoutId(newTimeoutId as any);
118
114
  } else {
119
115
  setIsRetrying(false);
120
116
  logger.error('Max retries reached after errors');
@@ -128,12 +124,9 @@ export const VerificationProgressTemplate: React.FC<VerificationProgressTemplate
128
124
  }
129
125
  }, [state.session.session_id]);
130
126
 
131
- // Nettoyage des timeouts lors du démontage du composant
132
127
  useEffect(() => {
133
128
  return () => {
134
- if (timeoutId) {
135
- clearTimeout(timeoutId);
136
- }
129
+ if (timeoutId) clearTimeout(timeoutId);
137
130
  };
138
131
  }, [timeoutId]);
139
132
 
@@ -156,19 +149,27 @@ export const VerificationProgressTemplate: React.FC<VerificationProgressTemplate
156
149
  return (
157
150
  <View style={styles.container}>
158
151
  <Text style={styles.title}>{t('kyc.verificationProgress.status.failed')}</Text>
159
- <Text style={styles.subtitle}>{t('errors.validationError')}</Text>
152
+
160
153
  <View style={styles.issuesBox}>
161
154
  <Text style={styles.issuesTitle}>{t('common.error')}</Text>
162
155
  {Array.isArray(verification.result?.issues) && verification.result.issues.map((issue: string, idx: number) => (
163
156
  <Text key={idx} style={styles.issueItem}>• {issue}</Text>
164
157
  ))}
165
158
  </View>
166
- <TouchableOpacity style={[styles.button, styles.primary]} onPress={() => actions.resetTemplate()}>
167
- <Text style={styles.buttonText}>{t('kyc.verificationProgress.status.retry')}</Text>
159
+
160
+ {/* 🚨 FIX 2: Give the user actionable options to End or Restart */}
161
+ <TouchableOpacity style={[styles.button, styles.primary]} onPress={() => actions.submitVerification()}>
162
+ <Text style={styles.buttonText}>
163
+ {state.currentLanguage === 'en' ? 'OK / Finish' : 'Terminer'}
164
+ </Text>
168
165
  </TouchableOpacity>
169
- <TouchableOpacity style={[styles.button, styles.secondary]}>
170
- <Text style={styles.secondaryText}>{t('common.info')}</Text>
166
+
167
+ <TouchableOpacity style={[styles.button, styles.secondary]} onPress={() => actions.resetTemplate()}>
168
+ <Text style={styles.secondaryText}>
169
+ {state.currentLanguage === 'en' ? 'Start Over' : 'Recommencer'}
170
+ </Text>
171
171
  </TouchableOpacity>
172
+
172
173
  {verification.result?.referenceId ? (
173
174
  <Text style={styles.refText}>{`Reference ID: ${verification.result.referenceId}`}</Text>
174
175
  ) : null}
@@ -176,12 +177,6 @@ export const VerificationProgressTemplate: React.FC<VerificationProgressTemplate
176
177
  );
177
178
  }
178
179
 
179
-
180
-
181
-
182
-
183
-
184
-
185
180
  return (
186
181
  <View style={styles.container}>
187
182
  <Text style={styles.title}>{t('kyc.verificationProgress.title')}</Text>
@@ -191,7 +186,6 @@ export const VerificationProgressTemplate: React.FC<VerificationProgressTemplate
191
186
  : t('kyc.verificationProgress.estimatedTime')
192
187
  }
193
188
  </Text>
194
-
195
189
  <View style={styles.timeline}>
196
190
  <View style={[styles.dot, styles.done]}><Text style={styles.stepCheckmark}>✓</Text></View>
197
191
  <View style={styles.line} />
@@ -199,13 +193,11 @@ export const VerificationProgressTemplate: React.FC<VerificationProgressTemplate
199
193
  <View style={styles.line} />
200
194
  <View style={[styles.dot, styles.pending]}><Text style={styles.stepCheckmark}>3</Text></View>
201
195
  </View>
202
-
203
196
  <View style={styles.row}>
204
197
  <Text style={styles.stepLabel}>{t('kyc.verificationProgress.status.completed')}</Text>
205
198
  <Text style={styles.stepLabel}>{t('kyc.verificationProgress.steps.analyzing')}</Text>
206
199
  <Text style={styles.stepLabel}>{t('kyc.verificationProgress.steps.verifying')}</Text>
207
200
  </View>
208
-
209
201
  <View style={styles.card}>
210
202
  <Text style={styles.cardTitle}>{t('kyc.idCardCapture.title')}</Text>
211
203
  <Text style={styles.cardLine}>{t('kyc.verificationProgress.steps.extracting')}</Text>
@@ -239,17 +231,13 @@ const styles = StyleSheet.create({
239
231
  card: { backgroundColor: 'white', padding: 16, borderRadius: 16, marginTop: 24 },
240
232
  cardTitle: { fontSize: 16, color: '#6B7280', marginTop: 8 },
241
233
  cardLine: { fontSize: 18, color: '#111827', fontWeight: '600', marginTop: 2 },
242
- // Success/Failure specific
243
- button: { paddingVertical: 14, borderRadius: 10, alignItems: 'center', marginTop: 20 },
234
+ button: { paddingVertical: 14, borderRadius: 10, alignItems: 'center', marginTop: 14 },
244
235
  primary: { backgroundColor: '#2DBD60' },
245
236
  buttonText: { color: 'white', fontSize: 16, fontWeight: '600' },
246
237
  refText: { marginTop: 12, textAlign: 'center', color: '#6B7280' },
247
238
  issuesBox: { backgroundColor: '#FEF2F2', borderRadius: 16, padding: 16, marginTop: 20 },
248
239
  issuesTitle: { color: '#991B1B', fontWeight: '700', marginBottom: 8 },
249
240
  issueItem: { color: '#991B1B', marginTop: 4 },
250
- secondary: { backgroundColor: '#F3F4F6' },
251
- secondaryText: { color: '#111827', fontSize: 16, fontWeight: '600' },
252
- });
253
-
254
-
255
-
241
+ secondary: { backgroundColor: '#F3F4F6', borderWidth: 1, borderColor: '#D1D5DB' },
242
+ secondaryText: { color: '#374151', fontSize: 16, fontWeight: '600' },
243
+ });
@@ -698,21 +698,21 @@ export const useTemplateKYCFlow = (
698
698
  const templateId = chooseTemplateId(templateWithReviewAndVerification);
699
699
 
700
700
  // This is the API call that we know succeeds
701
- await kycService.verificationSession({
702
- session_id: resolvedSessionId,
703
- step: 0,
704
- data: {
705
- template_id: templateId,
706
- metadata: {
707
- language: initialLanguage,
708
- ...(referenceId ? { reference_id: referenceId } : {}),
709
- },
701
+ await kycService.verificationSession({
702
+ session_id: resolvedSessionId,
703
+ step: 0,
704
+ data: {
705
+ template_id: templateId,
706
+ ...(referenceId ? { reference_id: referenceId } : {}),
707
+ metadata: {
708
+ language: initialLanguage,
710
709
  },
711
- templateId: templateId,
712
- token: token ?? "",
713
- action: 'initialize_session',
714
- apiKey: apiKey,
715
- });
710
+ },
711
+ templateId: templateId,
712
+ token: token ?? "",
713
+ action: 'initialize_session',
714
+ apiKey: apiKey,
715
+ });
716
716
 
717
717
 
718
718
  setState(prev => ({