@sanctum-key/react-native-sdk 1.0.24 → 1.0.26

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 (73) hide show
  1. package/build/package.json +5 -2
  2. package/build/src/components/EnhancedCameraView.d.ts +7 -1
  3. package/build/src/components/EnhancedCameraView.d.ts.map +1 -1
  4. package/build/src/components/EnhancedCameraView.js +88 -30
  5. package/build/src/components/EnhancedCameraView.js.map +1 -1
  6. package/build/src/components/EnhancedCameraView.web.d.ts +5 -1
  7. package/build/src/components/EnhancedCameraView.web.d.ts.map +1 -1
  8. package/build/src/components/EnhancedCameraView.web.js +80 -295
  9. package/build/src/components/EnhancedCameraView.web.js.map +1 -1
  10. package/build/src/components/KYCElements/CameraCapture.js +1 -1
  11. package/build/src/components/KYCElements/CameraCapture.js.map +1 -1
  12. package/build/src/components/KYCElements/CountrySelection.d.ts.map +1 -1
  13. package/build/src/components/KYCElements/CountrySelection.js +38 -218
  14. package/build/src/components/KYCElements/CountrySelection.js.map +1 -1
  15. package/build/src/components/KYCElements/CountrySelectionTemplate.d.ts.map +1 -1
  16. package/build/src/components/KYCElements/CountrySelectionTemplate.js +5 -17
  17. package/build/src/components/KYCElements/CountrySelectionTemplate.js.map +1 -1
  18. package/build/src/components/KYCElements/IDCardCapture.d.ts.map +1 -1
  19. package/build/src/components/KYCElements/IDCardCapture.js +509 -95
  20. package/build/src/components/KYCElements/IDCardCapture.js.map +1 -1
  21. package/build/src/components/KYCElements/VerificationProgressTemplate.d.ts.map +1 -1
  22. package/build/src/components/KYCElements/VerificationProgressTemplate.js +93 -51
  23. package/build/src/components/KYCElements/VerificationProgressTemplate.js.map +1 -1
  24. package/build/src/components/OverLay/type.d.ts +1 -0
  25. package/build/src/components/OverLay/type.d.ts.map +1 -1
  26. package/build/src/components/OverLay/type.js.map +1 -1
  27. package/build/src/components/WebBarcodeScanner.d.ts +9 -0
  28. package/build/src/components/WebBarcodeScanner.d.ts.map +1 -0
  29. package/build/src/components/WebBarcodeScanner.js +152 -0
  30. package/build/src/components/WebBarcodeScanner.js.map +1 -0
  31. package/build/src/config/KYCConfigs.js +2 -2
  32. package/build/src/config/KYCConfigs.js.map +1 -1
  33. package/build/src/config/region_mapping.json +0 -14
  34. package/build/src/modules/api/CardAuthentification.d.ts +2 -0
  35. package/build/src/modules/api/CardAuthentification.d.ts.map +1 -1
  36. package/build/src/modules/api/CardAuthentification.js +22 -39
  37. package/build/src/modules/api/CardAuthentification.js.map +1 -1
  38. package/build/src/modules/api/KYCService.d.ts +7 -2
  39. package/build/src/modules/api/KYCService.d.ts.map +1 -1
  40. package/build/src/modules/api/KYCService.js +163 -57
  41. package/build/src/modules/api/KYCService.js.map +1 -1
  42. package/build/src/types/KYC.types.d.ts +1 -0
  43. package/build/src/types/KYC.types.d.ts.map +1 -1
  44. package/build/src/types/KYC.types.js.map +1 -1
  45. package/build/src/utils/aamvaParser.d.ts +62 -0
  46. package/build/src/utils/aamvaParser.d.ts.map +1 -0
  47. package/build/src/utils/aamvaParser.js +91 -0
  48. package/build/src/utils/aamvaParser.js.map +1 -0
  49. package/build/src/utils/cropByObb.d.ts.map +1 -1
  50. package/build/src/utils/cropByObb.js +4 -3
  51. package/build/src/utils/cropByObb.js.map +1 -1
  52. package/build/src/web/WebKYCEntry.d.ts +1 -1
  53. package/build/src/web/WebKYCEntry.d.ts.map +1 -1
  54. package/build/src/web/WebKYCEntry.js +105 -239
  55. package/build/src/web/WebKYCEntry.js.map +1 -1
  56. package/package.json +5 -2
  57. package/src/components/EnhancedCameraView.tsx +116 -42
  58. package/src/components/EnhancedCameraView.web.tsx +98 -338
  59. package/src/components/KYCElements/CameraCapture.tsx +1 -1
  60. package/src/components/KYCElements/CountrySelection.tsx +60 -240
  61. package/src/components/KYCElements/CountrySelectionTemplate.tsx +7 -20
  62. package/src/components/KYCElements/IDCardCapture.tsx +672 -151
  63. package/src/components/KYCElements/VerificationProgressTemplate.tsx +112 -65
  64. package/src/components/OverLay/type.ts +1 -1
  65. package/src/components/WebBarcodeScanner.tsx +273 -0
  66. package/src/config/KYCConfigs.ts +2 -2
  67. package/src/config/region_mapping.json +0 -14
  68. package/src/modules/api/CardAuthentification.ts +41 -56
  69. package/src/modules/api/KYCService.ts +236 -82
  70. package/src/types/KYC.types.ts +1 -0
  71. package/src/utils/aamvaParser.ts +102 -0
  72. package/src/utils/cropByObb.ts +5 -3
  73. package/src/web/WebKYCEntry.tsx +125 -301
@@ -1,7 +1,5 @@
1
1
  import React, { useEffect, useState, useCallback, JSX } from 'react';
2
2
  import { View, Text, StyleSheet, SafeAreaView, ActivityIndicator } from 'react-native';
3
- // import { TemplateKYCFlow } from '../components/TemplateKYCFlowRefactored';
4
- // import { KYCTemplate } from '../types/KYC.types';
5
3
  import { useI18n } from '../hooks/useI18n';
6
4
  import { TemplateKYCExample } from '../components/TemplateKYCExample';
7
5
  import { isCallbackUrlAllowed } from '../config/allowedDomains';
@@ -24,15 +22,18 @@ interface URLParams {
24
22
  lang?: string;
25
23
  theme?: string;
26
24
  kyc_id?: string;
27
- secret?: string; // Optional secret for signature generation
28
- env?: 'PRODUCTION' | 'SANDBOX'; // Environment mode
29
- template_id?: string; // Template ID for dynamic template loading
30
- server_env?: BackendEnvironment; // Backend environment mode
31
- step?: string; // Deprecated: use component_index.
32
- component_index?: string; // Index in template.components (0-based) to resume at
33
- country?: string; // Code pays pour restaurer la sélection (reprise multi-appareil)
34
- document_type?: string; // Type de document (national_id, passport, etc.)
35
- region?: string; // Région si applicable
25
+ secret?: string;
26
+ env?: 'PRODUCTION' | 'SANDBOX';
27
+ template_id?: string;
28
+ server_env?: BackendEnvironment;
29
+ step?: string;
30
+ component_index?: string;
31
+ country?: string;
32
+ document_type?: string;
33
+ region?: string;
34
+ // 🚨 NEW: Added explicitly for the mobile handoff
35
+ session_id?: string;
36
+ resume?: boolean;
36
37
  }
37
38
 
38
39
  interface VerificationSteps {
@@ -43,159 +44,91 @@ interface VerificationSteps {
43
44
 
44
45
  const postWebhook = async (url: string, payload: unknown, timeoutMs: number = 5000) => {
45
46
  const body = JSON.stringify(payload);
46
-
47
47
  const postWithTimeout = async (init: RequestInit) => {
48
48
  const controller = new AbortController();
49
49
  const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
50
50
  try {
51
- return await fetch(url, {
52
- method: 'POST',
53
- ...init,
54
- signal: controller.signal,
55
- });
51
+ return await fetch(url, { method: 'POST', ...init, signal: controller.signal });
56
52
  } finally {
57
53
  clearTimeout(timeoutId);
58
54
  }
59
55
  };
60
56
 
61
- // In browser, first try a regular JSON POST so servers validating Content-Type
62
- // behave the same as Postman/cURL.
63
57
  if (typeof window !== 'undefined') {
64
58
  try {
65
- const response = await postWithTimeout({
66
- headers: {
67
- 'Content-Type': 'application/json',
68
- },
69
- body,
70
- keepalive: true,
71
- });
72
-
73
- if (!response.ok) {
74
- throw new Error(`Webhook failed with status ${response.status}`);
75
- }
59
+ const response = await postWithTimeout({ headers: { 'Content-Type': 'application/json' }, body, keepalive: true });
60
+ if (!response.ok) throw new Error(`Webhook failed with status ${response.status}`);
76
61
  return;
77
62
  } catch (error) {
78
- // If the request is blocked by browser CORS policy or a network error occurs,
79
- // fallback to no-cors + text/plain for best-effort delivery.
80
- if (error instanceof Error && error.name === 'AbortError') {
81
- throw error;
82
- }
83
-
84
- await postWithTimeout({
85
- mode: 'no-cors',
86
- headers: {
87
- 'Content-Type': 'text/plain;charset=UTF-8',
88
- },
89
- body,
90
- keepalive: true,
91
- });
63
+ if (error instanceof Error && error.name === 'AbortError') throw error;
64
+ await postWithTimeout({ mode: 'no-cors', headers: { 'Content-Type': 'text/plain;charset=UTF-8' }, body, keepalive: true });
92
65
  return;
93
66
  }
94
67
  }
95
68
 
96
- const response = await postWithTimeout({
97
- headers: {
98
- 'Content-Type': 'application/json',
99
- },
100
- body,
101
- });
102
-
103
- if (!response.ok) {
104
- throw new Error(`Webhook failed with status ${response.status}`);
105
- }
69
+ const response = await postWithTimeout({ headers: { 'Content-Type': 'application/json' }, body });
70
+ if (!response.ok) throw new Error(`Webhook failed with status ${response.status}`);
106
71
  };
107
72
 
108
- export function WebKYCEntry({
109
- onComplete,
110
- onError,
111
- onCancel,
112
- onSessionSave,
113
- }: WebKYCEntryProps): JSX.Element {
114
- console.log('first')
73
+ export function WebKYCEntry({ onComplete, onError, onCancel, onSessionSave }: WebKYCEntryProps): JSX.Element {
115
74
  const { setLocale } = useI18n();
116
75
  const [urlParams, setUrlParams] = useState<URLParams>({});
117
76
  const [isLoading, setIsLoading] = useState(true);
118
77
  const [error, setError] = useState<string | null>(null);
119
78
  const [isAnalyzing, setIsAnalyzing] = useState(false);
120
79
 
121
- // Parse URL parameters
122
80
  const parseUrlParams = useCallback((): URLParams => {
123
81
  if (typeof window === 'undefined') return {};
124
82
 
125
- const urlParams = new URLSearchParams(window.location.search);
126
- const envParam = urlParams.get('env');
127
- const validEnv = envParam === 'SANDBOX' || envParam === 'PRODUCTION' ? envParam : 'PRODUCTION';
83
+ const rawUrl = window.location.href;
84
+ console.log("Raw URL intercepted:", rawUrl);
85
+
86
+ const paramsString = rawUrl.replace(/^[^?#]*[?#]/, '').replace(/[?#]/g, '&');
128
87
 
129
- const serverEnvParam = urlParams.get('server_env');
130
- const validServerEnv: BackendEnvironment = serverEnvParam === 'TEST' || serverEnvParam === 'PRODUCTION'
131
- ? (serverEnvParam as BackendEnvironment)
132
- : 'PRODUCTION';
88
+ const urlParams = new URLSearchParams(paramsString);
89
+
90
+ const getParam = (key: string) => urlParams.get(key) || undefined;
91
+
92
+ const envParam = getParam('env');
93
+ const validEnv = envParam === 'SANDBOX' || envParam === 'PRODUCTION' ? envParam : 'PRODUCTION';
94
+ const serverEnvParam = getParam('server_env');
95
+ const validServerEnv: BackendEnvironment = serverEnvParam === 'TEST' || serverEnvParam === 'PRODUCTION' ? (serverEnvParam as BackendEnvironment) : 'PRODUCTION';
133
96
 
134
97
  return {
135
- token: urlParams.get('token') || undefined,
136
- return_url: urlParams.get('return_url') || undefined,
137
- push_url: urlParams.get('push_url') || undefined,
138
- save_session_url:
139
- urlParams.get('save_session_url') ||
140
- urlParams.get('saveSessionUrl') ||
141
- undefined,
142
- reference_id: urlParams.get('reference_id') || undefined,
143
- lang: urlParams.get('lang') || 'en',
144
- theme: urlParams.get('theme') || 'light',
145
- kyc_id: urlParams.get('kyc_id') || undefined,
146
- secret: urlParams.get('secret') || undefined,
98
+ token: getParam('token'),
99
+ return_url: getParam('return_url'),
100
+ push_url: getParam('push_url'),
101
+ save_session_url: getParam('save_session_url') || getParam('saveSessionUrl'),
102
+ reference_id: getParam('reference_id'),
103
+ lang: getParam('lang') || 'en',
104
+ theme: getParam('theme') || 'light',
105
+ kyc_id: getParam('kyc_id') || getParam('session_id'),
106
+ secret: getParam('secret'),
147
107
  env: validEnv,
148
- template_id: urlParams.get('template_id') || undefined,
108
+ template_id: getParam('template_id'),
149
109
  server_env: validServerEnv,
150
- step: urlParams.get('step') || undefined,
151
- component_index: urlParams.get('component_index') || undefined,
152
- country: urlParams.get('country') || undefined,
153
- document_type: urlParams.get('document_type') || undefined,
154
- region: urlParams.get('region') || undefined,
110
+ step: getParam('step'),
111
+ component_index: getParam('component_index'),
112
+ country: getParam('country'),
113
+ document_type: getParam('document_type'),
114
+ region: getParam('region'),
115
+ resume: getParam('resume') === 'true',
155
116
  };
156
117
  }, []);
157
118
 
158
- // Safe redirect function with enhanced validation
159
- const redirectToReturnUrl = useCallback(async (params: {
160
- status: 'completed' | 'cancelled' | 'error';
161
- kyc_id?: string;
162
- message?: string;
163
- processing_state?: 'analyzing' | 'completed' | 'pending';
164
- verification_steps?: VerificationSteps;
165
- }) => {
119
+ const redirectToReturnUrl = useCallback(async (params: { status: 'completed' | 'cancelled' | 'error'; kyc_id?: string; message?: string; processing_state?: 'analyzing' | 'completed' | 'pending'; verification_steps?: VerificationSteps; }) => {
166
120
  const { return_url } = urlParams;
167
-
168
- if (!return_url) {
169
- console.warn('No return_url provided');
170
- return;
171
- }
172
-
121
+ if (!return_url) { console.warn('No return_url provided'); return; }
173
122
  try {
174
- // Enhanced URL validation with domain whitelist
175
123
  const validation = isCallbackUrlAllowed(return_url);
176
124
  if (!validation.allowed) {
177
125
  console.error('Callback URL validation failed:', validation.reason);
178
126
  setError(`Security Error: ${validation.reason}`);
179
-
180
- // Log suspicious redirect attempt
181
- console.warn('Suspicious redirect attempt blocked:', {
182
- url: return_url,
183
- reason: validation.reason,
184
- timestamp: new Date().toISOString(),
185
- });
186
127
  return;
187
128
  }
188
- // Send postMessage to parent if in iframe
189
129
  if (window.parent !== window) {
190
130
  const targetOrigin = new URL(return_url).origin;
191
- window.parent.postMessage({
192
- type: 'kyc_result',
193
- status: params.status,
194
- kyc_id: params.kyc_id,
195
- message: params.message,
196
- processing_state: params.processing_state,
197
- verification_steps: params.verification_steps,
198
- }, targetOrigin);
131
+ window.parent.postMessage({ type: 'kyc_result', status: params.status, kyc_id: params.kyc_id, message: params.message, processing_state: params.processing_state, verification_steps: params.verification_steps }, targetOrigin);
199
132
  } else {
200
133
  window.location.href = return_url;
201
134
  }
@@ -206,190 +139,127 @@ export function WebKYCEntry({
206
139
  }, [urlParams]);
207
140
 
208
141
  const handleComplete = useCallback(async (data: any) => {
209
- console.log('KYC completed:', data);
210
-
211
- // Check if still processing/analyzing
212
- const isStillProcessing = data.isProcessing || data.session?.isProcessing;
142
+ console.log('KYC completed, raw state:', data);
143
+ const isStillProcessing = data?.isProcessing || data?.session?.isProcessing;
213
144
 
214
- // Handle Push URL webhook if provided
215
145
  if (urlParams.push_url) {
216
146
  try {
217
- const innerResult = data?.result?.result || data?.result || data;
218
- const nestedDataMap = innerResult?.data;
219
-
220
- let kycSessionId = data?.session_id || urlParams.kyc_id || '';
221
- let parsedKycData: any = null;
222
-
223
- if (nestedDataMap) {
224
- const mapKeys = Object.keys(nestedDataMap);
225
- if (mapKeys.length > 0) {
226
- const detectedSessionId = mapKeys.find(key => key.startsWith('kyc-')) || mapKeys[0];
227
- if (detectedSessionId) {
228
- kycSessionId = detectedSessionId;
229
- }
230
-
231
- const rawData = nestedDataMap[kycSessionId]?.data;
232
-
233
- if (typeof rawData === 'string') {
234
- try {
235
- parsedKycData = JSON.parse(rawData);
236
- } catch (parseErr) {
237
- console.warn('Failed parsing inner stringified JSON string:', parseErr);
238
- parsedKycData = rawData;
239
- }
240
- } else {
241
- parsedKycData = rawData;
242
- }
147
+ // 1. Locate the actual backend payload from the Context state
148
+ const backendResult = data?.verification?.result || data?.result?.result || data?.result || data;
149
+
150
+ // 2. Safely extract session ID
151
+ const finalSessionId =
152
+ data?.session?.session_id ||
153
+ backendResult?.session_id ||
154
+ backendResult?.data?.session_id ||
155
+ urlParams.kyc_id ||
156
+ 'unknown';
157
+
158
+ // 3. Extract the core data payload
159
+ let parsedKycData: any = {};
160
+ if (backendResult?.data) {
161
+ try {
162
+ parsedKycData = typeof backendResult.data === 'string'
163
+ ? JSON.parse(backendResult.data)
164
+ : backendResult.data;
165
+ } catch (e) {
166
+ console.warn("Could not parse backendResult.data JSON");
243
167
  }
244
168
  }
245
169
 
246
- const finalSessionId = kycSessionId || parsedKycData?.session_id || urlParams.kyc_id || 'unknown';
170
+ if (parsedKycData && typeof parsedKycData === 'object' && parsedKycData[finalSessionId]) {
171
+ const nested = parsedKycData[finalSessionId];
172
+ if (nested?.data) {
173
+ parsedKycData = typeof nested.data === 'string' ? JSON.parse(nested.data) : nested.data;
174
+ } else {
175
+ parsedKycData = nested;
176
+ }
177
+ }
247
178
 
248
- // 3. Build your exact un-nested payload signature
249
179
  const verificationState = {
250
180
  session_id: finalSessionId,
251
- status: 'success',
252
- message: innerResult?.message || 'Verification data retrieved successfully.',
181
+ reference_id: urlParams.reference_id || backendResult?.referenceId || null,
182
+ status: backendResult?.status || data?.verification?.status || 'completed',
183
+ message: backendResult?.message || backendResult?.reason || backendResult?.issues?.[0] || 'Verification finished.',
253
184
  data: parsedKycData || {}
254
185
  };
255
186
 
256
- await postWebhook(urlParams.push_url, verificationState, 5000);
257
- console.log('Successfully pushed beautifully clean KYC data payload to webhook');
187
+ const hasValidSessionId = finalSessionId && finalSessionId !== 'unknown';
188
+ const hasValidData = parsedKycData && Object.keys(parsedKycData).length > 0;
189
+
190
+ if (!hasValidSessionId || !hasValidData) {
191
+ console.log("Webhook Blocked: Payload contains no data or session_id is unknown.", JSON.stringify(verificationState));
192
+ } else {
193
+ console.log("Pushing Webhook Payload:", JSON.stringify(verificationState, null, 2));
194
+ await postWebhook(urlParams.push_url, verificationState, 5000);
195
+ }
196
+
258
197
  } catch (err) {
259
- console.warn('Failed to push data to webhook URL:', err);
198
+ console.warn('Failed to construct or push data to webhook URL:', err);
260
199
  }
261
200
  }
262
201
 
202
+ setIsAnalyzing(false);
203
+
204
+ // Always redirect the user back to your main app/website, regardless of webhook success/block
263
205
  redirectToReturnUrl({
264
- status: 'completed',
265
- kyc_id: data.session_id || urlParams.kyc_id,
266
- message: 'KYC process completed successfully',
206
+ status: data?.verification?.status === 'failed' ? 'error' : 'completed',
207
+ kyc_id: data?.session?.session_id || urlParams.kyc_id,
208
+ message: 'KYC process concluded',
267
209
  processing_state: isStillProcessing ? 'analyzing' : 'completed',
268
210
  verification_steps: {
269
- document_analyzed: data.documentAnalysisComplete || false,
270
- selfie_analyzed: data.selfieAnalysisComplete || false,
271
- liveness_checked: data.livenessCheckComplete || false,
211
+ document_analyzed: true,
212
+ selfie_analyzed: true,
213
+ liveness_checked: true
272
214
  },
273
215
  });
274
-
216
+
275
217
  onComplete?.(data);
276
218
  }, [redirectToReturnUrl, urlParams, onComplete]);
277
219
 
278
- // Handle KYC error
279
220
  const handleError = useCallback((error: string) => {
280
221
  console.error('KYC error:', error);
281
222
  setIsAnalyzing(false);
282
- redirectToReturnUrl({
283
- status: 'error',
284
- kyc_id: urlParams.kyc_id,
285
- message: error,
286
- processing_state: 'pending',
287
- });
223
+ redirectToReturnUrl({ status: 'error', kyc_id: urlParams.kyc_id, message: error, processing_state: 'pending' });
288
224
  onError?.(error);
289
225
  }, [redirectToReturnUrl, urlParams.kyc_id, onError]);
290
226
 
291
- // Handle KYC cancellation
292
227
  const handleCancel = useCallback(async () => {
293
- console.log('KYC cancelled', urlParams.push_url, urlParams);
294
228
  setIsAnalyzing(false);
295
229
  if (urlParams.push_url) {
296
230
  try {
297
- const verificationState = {
298
- status: 'cancelled', // verification cancelled
299
- result: null, // pass null as result
300
- reference_id: urlParams.reference_id,
301
- };
302
- await postWebhook(urlParams.push_url, verificationState, 5000);
303
- console.log('Successfully pushed KYC cancellation data to webhook');
304
- } catch (err) {
305
- // Fail open - redirect anyway even if webhook fails
306
- console.warn('Failed to push data to webhook URL:', err);
307
- }
231
+ await postWebhook(urlParams.push_url, { status: 'cancelled', result: null, reference_id: urlParams.reference_id }, 5000);
232
+ } catch (err) { console.warn('Failed to push data to webhook URL:', err); }
308
233
  }
309
- redirectToReturnUrl({
310
- status: 'cancelled',
311
- kyc_id: urlParams.kyc_id,
312
- message: 'KYC process was cancelled',
313
- processing_state: 'pending',
314
- });
234
+ redirectToReturnUrl({ status: 'cancelled', kyc_id: urlParams.kyc_id, message: 'KYC process was cancelled', processing_state: 'pending' });
315
235
  onCancel?.();
316
236
  }, [redirectToReturnUrl, urlParams.kyc_id, urlParams.push_url, urlParams.reference_id, onCancel]);
317
237
 
318
238
  const handleSessionSave = useCallback(async (sessionId: string) => {
319
- console.log('KYC session created:', sessionId);
320
-
321
239
  if (urlParams.save_session_url) {
322
240
  try {
323
- const payload = {
324
- status: 'session_created',
325
- reference_id: urlParams.reference_id,
326
- result: {
327
- session_id: sessionId,
328
- kyc_id: sessionId,
329
- },
330
- };
331
- await postWebhook(urlParams.save_session_url, payload, 5000);
332
- console.log('Successfully pushed session data to save_session_url');
333
- } catch (err) {
334
- // Fail open - do not block the KYC flow if save_session webhook fails
335
- console.warn('Failed to push session data to save_session_url:', err);
336
- }
337
- } else {
338
- console.warn('save_session_url is missing in URL params, webhook not called');
241
+ await postWebhook(urlParams.save_session_url, { status: 'session_created', reference_id: urlParams.reference_id, result: { session_id: sessionId, kyc_id: sessionId } }, 5000);
242
+ } catch (err) { console.warn('Failed to push session data:', err); }
339
243
  }
340
-
341
244
  onSessionSave?.(sessionId);
342
245
  }, [urlParams.save_session_url, urlParams.reference_id, onSessionSave]);
343
246
 
344
- // Initialize component
345
247
  useEffect(() => {
346
248
  try {
347
249
  const params = parseUrlParams();
348
-
349
250
  setUrlParams(params);
350
-
351
- // Set language if provided
352
- if (params.lang) {
353
- setLocale(params.lang);
354
- }
355
-
356
- // Configure backend environment
357
- if (params.server_env) {
358
- KYCConfig.setBackendEnvironment(params.server_env);
359
- }
360
-
251
+ if (params.lang) setLocale(params.lang);
252
+ if (params.server_env) KYCConfig.setBackendEnvironment(params.server_env);
361
253
  setIsLoading(false);
362
254
  } catch (error) {
363
- console.error('Error parsing URL parameters:', error);
364
255
  setError('Error parsing URL parameters');
365
256
  setIsLoading(false);
366
257
  }
367
258
  }, [parseUrlParams, setLocale]);
368
259
 
369
-
370
- if (isLoading) {
371
- return (
372
- <View style={styles.container}>
373
- <Text style={styles.loadingText}>Loading KYC process...</Text>
374
- </View>
375
- );
376
- }
377
-
378
- if (error) {
379
- return (
380
- <View style={styles.container}>
381
- <Text style={styles.errorText}>Error: {error}</Text>
382
- </View>
383
- );
384
- }
385
-
386
- if (!urlParams.token) {
387
- return (
388
- <View style={styles.container}>
389
- <Text style={styles.errorText}>No token provided in URL parameters</Text>
390
- </View>
391
- );
392
- }
260
+ if (isLoading) return <View style={styles.container}><Text style={styles.loadingText}>Loading KYC process...</Text></View>;
261
+ if (error) return <View style={styles.container}><Text style={styles.errorText}>Error: {error}</Text></View>;
262
+ if (!urlParams.token) return <View style={styles.container}><Text style={styles.errorText}>No token provided in URL parameters</Text></View>;
393
263
 
394
264
  return (
395
265
  <SafeAreaView style={styles.container}>
@@ -411,7 +281,7 @@ export function WebKYCEntry({
411
281
  templateId={urlParams.template_id}
412
282
  env={urlParams.env || 'PRODUCTION'}
413
283
  serverEnv={urlParams.server_env}
414
- existingSessionId={urlParams.kyc_id}
284
+ existingSessionId={urlParams.kyc_id} // Successfully passes session_id down
415
285
  initialComponentIndex={(() => {
416
286
  const raw = urlParams.component_index ?? urlParams.step;
417
287
  if (raw == null || raw === '') return undefined;
@@ -424,62 +294,16 @@ export function WebKYCEntry({
424
294
  />
425
295
  </SafeAreaView>
426
296
  );
427
- };
297
+ }
428
298
 
429
299
  const styles = StyleSheet.create({
430
- container: {
431
- flex: 1,
432
- backgroundColor: '#f5f5f5',
433
- overflow: 'visible' as any, // Allow scrolling on web
434
- },
435
- loadingText: {
436
- fontSize: 18,
437
- textAlign: 'center',
438
- marginTop: 50,
439
- color: '#666',
440
- },
441
- errorText: {
442
- fontSize: 16,
443
- textAlign: 'center',
444
- marginTop: 50,
445
- color: '#dc2626',
446
- paddingHorizontal: 20,
447
- },
448
- analyzingOverlay: {
449
- position: 'absolute',
450
- top: 0,
451
- left: 0,
452
- right: 0,
453
- bottom: 0,
454
- backgroundColor: 'rgba(0, 0, 0, 0.7)',
455
- justifyContent: 'center',
456
- alignItems: 'center',
457
- zIndex: 9999,
458
- },
459
- analyzingContainer: {
460
- backgroundColor: 'white',
461
- borderRadius: 12,
462
- padding: 32,
463
- alignItems: 'center',
464
- shadowColor: '#000',
465
- shadowOffset: { width: 0, height: 4 },
466
- shadowOpacity: 0.3,
467
- shadowRadius: 8,
468
- elevation: 8,
469
- },
470
- analyzingText: {
471
- fontSize: 18,
472
- fontWeight: '600',
473
- color: '#333',
474
- marginTop: 16,
475
- textAlign: 'center',
476
- },
477
- analyzingSubtext: {
478
- fontSize: 14,
479
- color: '#666',
480
- marginTop: 8,
481
- textAlign: 'center',
482
- },
300
+ container: { flex: 1, backgroundColor: '#f5f5f5', overflow: 'visible' as any },
301
+ loadingText: { fontSize: 18, textAlign: 'center', marginTop: 50, color: '#666' },
302
+ errorText: { fontSize: 16, textAlign: 'center', marginTop: 50, color: '#dc2626', paddingHorizontal: 20 },
303
+ analyzingOverlay: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'rgba(0, 0, 0, 0.7)', justifyContent: 'center', alignItems: 'center', zIndex: 9999 },
304
+ analyzingContainer: { backgroundColor: 'white', borderRadius: 12, padding: 32, alignItems: 'center', shadowColor: '#000', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.3, shadowRadius: 8, elevation: 8 },
305
+ analyzingText: { fontSize: 18, fontWeight: '600', color: '#333', marginTop: 16, textAlign: 'center' },
306
+ analyzingSubtext: { fontSize: 14, color: '#666', marginTop: 8, textAlign: 'center' },
483
307
  });
484
308
 
485
309
  export default WebKYCEntry;