@sanctum-key/react-native-sdk 1.0.18 → 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.
- package/README.md +1 -1
- package/build/package.json +3 -2
- package/build/src/components/EnhancedCameraView.d.ts.map +1 -1
- package/build/src/components/EnhancedCameraView.js +19 -182
- package/build/src/components/EnhancedCameraView.js.map +1 -1
- package/build/src/components/KYCElements/CountrySelectionTemplate.d.ts.map +1 -1
- package/build/src/components/KYCElements/CountrySelectionTemplate.js +40 -128
- package/build/src/components/KYCElements/CountrySelectionTemplate.js.map +1 -1
- package/build/src/components/KYCElements/IDCardCapture.d.ts.map +1 -1
- package/build/src/components/KYCElements/IDCardCapture.js +224 -189
- package/build/src/components/KYCElements/IDCardCapture.js.map +1 -1
- package/build/src/components/KYCElements/PhoneVerificationTemplate.d.ts.map +1 -1
- package/build/src/components/KYCElements/PhoneVerificationTemplate.js +0 -2
- package/build/src/components/KYCElements/PhoneVerificationTemplate.js.map +1 -1
- package/build/src/components/KYCElements/VerificationProgressTemplate.d.ts.map +1 -1
- package/build/src/components/KYCElements/VerificationProgressTemplate.js +38 -33
- package/build/src/components/KYCElements/VerificationProgressTemplate.js.map +1 -1
- package/build/src/components/OverLay/IdCard.d.ts +6 -1
- package/build/src/components/OverLay/IdCard.d.ts.map +1 -1
- package/build/src/components/OverLay/IdCard.js +36 -34
- package/build/src/components/OverLay/IdCard.js.map +1 -1
- package/build/src/config/countriesData.d.ts.map +1 -1
- package/build/src/config/countriesData.js.map +1 -1
- package/build/src/hooks/useTemplateKYCFlow.js +1 -1
- package/build/src/hooks/useTemplateKYCFlow.js.map +1 -1
- package/build/src/modules/api/CardAuthentification.d.ts +5 -0
- package/build/src/modules/api/CardAuthentification.d.ts.map +1 -1
- package/build/src/modules/api/CardAuthentification.js +67 -14
- package/build/src/modules/api/CardAuthentification.js.map +1 -1
- package/build/src/modules/api/KYCService.d.ts +10 -0
- package/build/src/modules/api/KYCService.d.ts.map +1 -1
- package/build/src/modules/api/KYCService.js +135 -49
- package/build/src/modules/api/KYCService.js.map +1 -1
- package/build/src/web/WebKYCEntry.d.ts.map +1 -1
- package/build/src/web/WebKYCEntry.js +34 -6
- package/build/src/web/WebKYCEntry.js.map +1 -1
- package/package.json +3 -2
- package/src/components/EnhancedCameraView.tsx +28 -219
- package/src/components/KYCElements/CountrySelectionTemplate.tsx +53 -133
- package/src/components/KYCElements/IDCardCapture.tsx +606 -570
- package/src/components/KYCElements/PhoneVerificationTemplate.tsx +0 -2
- package/src/components/KYCElements/VerificationProgressTemplate.tsx +54 -66
- package/src/components/OverLay/IdCard.tsx +48 -36
- package/src/config/countriesData.ts +0 -4
- package/src/hooks/useTemplateKYCFlow.tsx +14 -14
- package/src/modules/api/CardAuthentification.ts +133 -67
- package/src/modules/api/KYCService.ts +189 -66
- package/src/web/WebKYCEntry.tsx +42 -7
|
@@ -281,7 +281,7 @@ export class KYCService {
|
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
//check templatetemplate_type
|
|
284
|
-
async checkTemplateType(params: { fileUri: string; docType: string; docRegion: string; token: string; postfix: string
|
|
284
|
+
async checkTemplateType(params: { fileUri: string; docType: string; docRegion: string; token: string; postfix: string}, env: KycEnvironment = 'PRODUCTION'): Promise<any> {
|
|
285
285
|
// SANDBOX mode
|
|
286
286
|
if (env === 'SANDBOX') {
|
|
287
287
|
console.log("SANDBOX mode: Skipping AI template type check");
|
|
@@ -296,7 +296,6 @@ export class KYCService {
|
|
|
296
296
|
const { fileUri, docType, docRegion, token, postfix } = params;
|
|
297
297
|
const formData = new FormData();
|
|
298
298
|
|
|
299
|
-
// ✅ FIX: Dynamically assign the postfix to the filename
|
|
300
299
|
await appendFileToFormData(formData, 'file', fileUri, `id_card_${postfix}.jpg`, 'image/jpeg');
|
|
301
300
|
|
|
302
301
|
const docTypeShorted = GovernmentDocumentTypeShorted[docType as GovernmentDocumentType];
|
|
@@ -317,29 +316,75 @@ export class KYCService {
|
|
|
317
316
|
|
|
318
317
|
}
|
|
319
318
|
|
|
320
|
-
async extractDocumentInformation(params: {
|
|
321
|
-
|
|
322
|
-
|
|
319
|
+
async extractDocumentInformation(params: {
|
|
320
|
+
fileUri: string;
|
|
321
|
+
docType: string;
|
|
322
|
+
docRegion: string;
|
|
323
|
+
templatePath: string; // 🚨 Required by API
|
|
324
|
+
issuingSubdivision?: string; // 🚨 Required for non-passports
|
|
325
|
+
token: string;
|
|
326
|
+
postfix?: string
|
|
327
|
+
}): Promise<any> {
|
|
328
|
+
const { fileUri, docType, docRegion, templatePath, issuingSubdivision, token, postfix = 'front' } = params;
|
|
323
329
|
|
|
324
|
-
//
|
|
330
|
+
// 1. Prepare Form Data
|
|
331
|
+
const formData = new FormData();
|
|
332
|
+
// Prefixing with 'front' or 'back' as strictly required by the docs
|
|
325
333
|
await appendFileToFormData(formData, 'file', fileUri, `id_card_${postfix}.jpg`, 'image/jpeg');
|
|
326
334
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
335
|
+
// 2. Build the URL with ALL required parameters
|
|
336
|
+
let queryParams = `doc_type=${encodeURIComponent(docType)}&doc_region=${encodeURIComponent(docRegion)}&template_path=${encodeURIComponent(templatePath)}`;
|
|
337
|
+
if (issuingSubdivision) {
|
|
338
|
+
queryParams += `&issuing_subdivision=${encodeURIComponent(issuingSubdivision)}`;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const url = `${this.textExtractionServiceURL}/extract_doc_information/?${queryParams}`;
|
|
342
|
+
|
|
343
|
+
try {
|
|
344
|
+
// 3. Start the Job
|
|
345
|
+
const startRes = await axios.post(url, formData, {
|
|
346
|
+
headers: { 'Content-Type': 'multipart/form-data', 'Authorization': `Bearer ${token}` },
|
|
331
347
|
timeout: 60000,
|
|
332
348
|
});
|
|
333
|
-
|
|
349
|
+
|
|
350
|
+
const jobId = startRes.data?.job_id;
|
|
351
|
+
if (!jobId) throw new Error("Backend did not return a job_id");
|
|
334
352
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
353
|
+
logger.log(`Extraction job started: ${jobId}. Polling for results...`);
|
|
354
|
+
|
|
355
|
+
// 4. Poll the Status Endpoint
|
|
356
|
+
const statusUrl = `${this.textExtractionServiceURL}/extract_doc_information/status/${jobId}`;
|
|
357
|
+
|
|
358
|
+
// Poll every 2 seconds, up to 15 times (30 seconds max)
|
|
359
|
+
const maxRetries = 15;
|
|
360
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
361
|
+
// Wait 2 seconds before checking
|
|
362
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
363
|
+
|
|
364
|
+
const statusRes = await axios.get(statusUrl, {
|
|
365
|
+
headers: { 'Authorization': `Bearer ${token}` }
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
const statusData = statusRes.data;
|
|
369
|
+
|
|
370
|
+
if (statusData.status === 'completed') {
|
|
371
|
+
logger.log('Extraction completed successfully', JSON.stringify(truncateFields(statusData.result)));
|
|
372
|
+
return statusData.result; // 👈 Returns the actual extracted data
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (statusData.status === 'failed') {
|
|
376
|
+
throw new Error(statusData.error || "Document extraction failed during processing.");
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// If 'processing', loop continues...
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
throw new Error("Document extraction timed out waiting for results.");
|
|
383
|
+
|
|
384
|
+
} catch (e: any) {
|
|
385
|
+
const errorMsg = e.response?.data?.detail || e.message;
|
|
386
|
+
logger.error('Error extracting document information:', errorMsg);
|
|
387
|
+
throw new Error(errorMsg);
|
|
343
388
|
}
|
|
344
389
|
}
|
|
345
390
|
|
|
@@ -412,24 +457,14 @@ export class KYCService {
|
|
|
412
457
|
card_obb: { x: 50, y: 50, width: 200, height: 200 }
|
|
413
458
|
};
|
|
414
459
|
}
|
|
415
|
-
|
|
416
460
|
const { fileUri, docType, docRegion, postfix = 'back', token, template_path, mrz_type } = params;
|
|
417
|
-
|
|
418
|
-
// 1. Build the FormData ONLY for the file
|
|
419
|
-
const formData = new FormData();
|
|
420
|
-
const filePayload = {
|
|
421
|
-
uri: fileUri,
|
|
422
|
-
type: 'image/jpeg',
|
|
423
|
-
name: `id_card_${postfix}.jpg`,
|
|
424
|
-
};
|
|
425
|
-
formData.append('file', filePayload as any);
|
|
426
461
|
|
|
462
|
+
// ... top of extractMrzText (params extraction, etc) ...
|
|
427
463
|
const docTypeShorted = GovernmentDocumentTypeShorted[docType as GovernmentDocumentType] || docType;
|
|
428
464
|
const safeMrzType = mrz_type && mrz_type.trim() !== '' ? mrz_type : 'TD1';
|
|
429
465
|
|
|
430
466
|
logger.log("docTypeShorted", docTypeShorted, docRegion, postfix);
|
|
431
467
|
|
|
432
|
-
// 🚨 THE FIX: Pass all required text parameters in the URL query string for FastAPI
|
|
433
468
|
const queryParams = new URLSearchParams({
|
|
434
469
|
doc_type: docTypeShorted,
|
|
435
470
|
doc_region: docRegion,
|
|
@@ -443,14 +478,52 @@ export class KYCService {
|
|
|
443
478
|
logger.log("url", url);
|
|
444
479
|
|
|
445
480
|
try {
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
481
|
+
let response;
|
|
482
|
+
|
|
483
|
+
if (Platform.OS === 'web') {
|
|
484
|
+
// 🚨 THE FIX: Completely bypass React Native Web's networking polyfills.
|
|
485
|
+
// We explicitly grab the browser's native APIs so the bundler cannot interfere.
|
|
486
|
+
const nativeFetch = window.fetch;
|
|
487
|
+
const NativeFormData = window.FormData;
|
|
488
|
+
|
|
489
|
+
const formData = new NativeFormData();
|
|
490
|
+
|
|
491
|
+
// Fetch the Blob natively
|
|
492
|
+
const fileReq = await nativeFetch(fileUri);
|
|
493
|
+
const blob = await fileReq.blob();
|
|
494
|
+
|
|
495
|
+
// Append the Blob. The native browser will perfectly handle the multipart boundary.
|
|
496
|
+
formData.append('file', blob, `id_card_${postfix}.jpg`);
|
|
497
|
+
|
|
498
|
+
// Execute using Native Fetch!
|
|
499
|
+
response = await nativeFetch(url, {
|
|
500
|
+
method: 'POST',
|
|
501
|
+
headers: {
|
|
502
|
+
'Authorization': `Bearer ${token}`,
|
|
503
|
+
'Accept': 'application/json'
|
|
504
|
+
},
|
|
505
|
+
body: formData,
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
} else {
|
|
509
|
+
// 📱 MOBILE NATIVE: React Native's Native Bridge expects this exact object
|
|
510
|
+
const formData = new FormData();
|
|
511
|
+
const filePayload = {
|
|
512
|
+
uri: fileUri,
|
|
513
|
+
type: 'image/jpeg',
|
|
514
|
+
name: `id_card_${postfix}.jpg`,
|
|
515
|
+
};
|
|
516
|
+
formData.append('file', filePayload as any);
|
|
517
|
+
|
|
518
|
+
response = await fetch(url, {
|
|
519
|
+
method: 'POST',
|
|
520
|
+
headers: {
|
|
521
|
+
'Authorization': `Bearer ${token}`,
|
|
522
|
+
'Accept': 'application/json'
|
|
523
|
+
},
|
|
524
|
+
body: formData,
|
|
525
|
+
});
|
|
526
|
+
}
|
|
454
527
|
|
|
455
528
|
if (!response.ok) {
|
|
456
529
|
const errorText = await response.text();
|
|
@@ -458,19 +531,11 @@ export class KYCService {
|
|
|
458
531
|
throw new Error(`Erreur serveur: ${response.status}`);
|
|
459
532
|
}
|
|
460
533
|
|
|
461
|
-
|
|
462
|
-
// logger.log('extractMrzText res', JSON.stringify(data, null, 2));
|
|
463
|
-
|
|
464
|
-
// if (Object.keys(data).length === 0) throw new Error('No data found');
|
|
465
|
-
// if (data?.success === false) throw new Error(data.parsed_data?.status || 'Échec de l\'extraction MRZ');
|
|
466
|
-
|
|
467
|
-
// return data;
|
|
468
|
-
const data = await response.json();
|
|
534
|
+
const data = await response.json();
|
|
469
535
|
logger.log('extractMrzText res', JSON.stringify(data, null, 2));
|
|
470
536
|
|
|
471
537
|
if (Object.keys(data).length === 0) throw new Error('No data found');
|
|
472
538
|
|
|
473
|
-
// 🚨 UPDATE THIS LINE to grab the actual status_message:
|
|
474
539
|
if (data?.success === false) {
|
|
475
540
|
const serverMessage = data.parsed_data?.status_message || data.parsed_data?.status || 'Échec de l\'extraction MRZ';
|
|
476
541
|
throw new Error(`Lecture MRZ refusée: ${serverMessage}`);
|
|
@@ -559,41 +624,53 @@ export class KYCService {
|
|
|
559
624
|
}
|
|
560
625
|
|
|
561
626
|
async verificationSession(payload: VerificationSessionRequest): Promise<any> {
|
|
562
|
-
console.log('apiKey in verificationSession', payload.apiKey);
|
|
563
627
|
try {
|
|
564
628
|
const { session_id, step, data, templateId, action, apiKey } = payload;
|
|
629
|
+
|
|
630
|
+
// 1. Safe Auth Resolution
|
|
565
631
|
const token = apiKey ? undefined : await authentification();
|
|
632
|
+
|
|
633
|
+
if (!apiKey && !token) {
|
|
634
|
+
throw new Error("Authentication failed: No API key or Token available.");
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
|
|
566
638
|
const payloadData = {
|
|
567
639
|
action: action,
|
|
568
640
|
data: {
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
...
|
|
641
|
+
...data,
|
|
642
|
+
step: step,
|
|
643
|
+
templateId: templateId,
|
|
644
|
+
...(action === "location_permission" ? { permissionGranted: true } : {}),
|
|
573
645
|
},
|
|
574
|
-
|
|
575
|
-
timestamp: new Date().toISOString()
|
|
576
|
-
}
|
|
646
|
+
session_id: session_id,
|
|
647
|
+
timestamp: new Date().toISOString(),
|
|
648
|
+
};
|
|
649
|
+
|
|
577
650
|
const url = `${KYCConfig.getBackendUrl()}/verification/api/kyc/sessions/${session_id}/steps/${step}/`;
|
|
578
651
|
|
|
652
|
+
// 3. Clean Logging
|
|
579
653
|
const logPayload = truncateFields({ payloadData, session_id, step });
|
|
580
|
-
logger.log('verificationSession payload',
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
654
|
+
logger.log('verificationSession payload', JSON.stringify({
|
|
655
|
+
url,
|
|
656
|
+
apiKey: apiKey ? '***HIDDEN***' : 'None', // Don't log the raw API key!
|
|
657
|
+
token: token ? '***HIDDEN***' : 'None',
|
|
658
|
+
payload: logPayload
|
|
659
|
+
}, null, 2));
|
|
660
|
+
|
|
661
|
+
// 4. API Execution
|
|
662
|
+
const res = await axios.post<SessionResponse>(url, payloadData, {
|
|
587
663
|
headers: {
|
|
588
664
|
'Content-Type': 'application/json',
|
|
589
665
|
...(apiKey ? { 'Authorization': `ApiKey ${apiKey}` } : { 'Authorization': `Bearer ${token}` })
|
|
590
666
|
}
|
|
591
|
-
|
|
667
|
+
});
|
|
668
|
+
|
|
592
669
|
logger.log('verificationSession res', JSON.stringify(truncateFields(res.data), null, 2));
|
|
593
670
|
return res.data;
|
|
594
671
|
|
|
595
672
|
} catch (error) {
|
|
596
|
-
logger.error('Error validating component:', JSON.stringify(error, null, 2));
|
|
673
|
+
logger.error('Error validating component:', JSON.stringify(errorMessage(error), null, 2));
|
|
597
674
|
throw new Error(errorMessage(error));
|
|
598
675
|
}
|
|
599
676
|
}
|
|
@@ -738,6 +815,54 @@ export class KYCService {
|
|
|
738
815
|
throw error;
|
|
739
816
|
}
|
|
740
817
|
}
|
|
818
|
+
|
|
819
|
+
// Inside KYCService.ts
|
|
820
|
+
|
|
821
|
+
async validateBackTemplate(params: {
|
|
822
|
+
region: string;
|
|
823
|
+
docType: string;
|
|
824
|
+
frontTemplateName: string;
|
|
825
|
+
backTemplateName: string;
|
|
826
|
+
subRegion: string;
|
|
827
|
+
token: string;
|
|
828
|
+
}, env: KycEnvironment = 'PRODUCTION'): Promise<any> {
|
|
829
|
+
if (env === 'SANDBOX') {
|
|
830
|
+
logger.log("SANDBOX mode: Skipping back template validation");
|
|
831
|
+
return { is_match: true, status_message: "SANDBOX: Valid Match" };
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
const { region, docType, frontTemplateName, backTemplateName, subRegion, token } = params;
|
|
835
|
+
|
|
836
|
+
// 🚨 THE FIX: Format the payload as URL Query Parameters
|
|
837
|
+
const queryParams = new URLSearchParams({
|
|
838
|
+
region: region,
|
|
839
|
+
doc_type: docType,
|
|
840
|
+
front_template_name: frontTemplateName,
|
|
841
|
+
back_template_name: backTemplateName,
|
|
842
|
+
sub_region: subRegion || ""
|
|
843
|
+
}).toString();
|
|
844
|
+
|
|
845
|
+
const url = `${this.mrzServiceURL}/validate_back_template/?${queryParams}`;
|
|
846
|
+
|
|
847
|
+
logger.log('validateBackTemplate URL', url);
|
|
848
|
+
|
|
849
|
+
try {
|
|
850
|
+
// Pass `null` for the body since the data is now in the URL
|
|
851
|
+
const res = await axios.post(url, null, {
|
|
852
|
+
headers: {
|
|
853
|
+
'Accept': 'application/json',
|
|
854
|
+
'Authorization': `Bearer ${token}`
|
|
855
|
+
},
|
|
856
|
+
timeout: 20000,
|
|
857
|
+
});
|
|
858
|
+
logger.log('validateBackTemplate res', JSON.stringify(res.data, null, 2));
|
|
859
|
+
return res.data;
|
|
860
|
+
} catch (e: any) {
|
|
861
|
+
const errorMsg = e.response?.data?.detail || e.response?.data?.Error || e.message;
|
|
862
|
+
logger.error('Error validating back template:', JSON.stringify(errorMsg));
|
|
863
|
+
throw new Error(typeof errorMsg === 'string' ? errorMsg : 'Template validation failed');
|
|
864
|
+
}
|
|
865
|
+
}
|
|
741
866
|
}
|
|
742
867
|
|
|
743
868
|
const kycService = new KYCService("", "");
|
|
@@ -782,8 +907,6 @@ export const authentification = async (): Promise<string> => {
|
|
|
782
907
|
activeAuthRequest = (async () => {
|
|
783
908
|
logger.log('Authenticating: Fetching new Keycloak token...');
|
|
784
909
|
|
|
785
|
-
// 🚨 FIX: Do NOT use URLSearchParams in React Native with Axios.
|
|
786
|
-
// Use a raw URL-encoded string to guarantee Keycloak understands the payload.
|
|
787
910
|
const params = 'client_id=kyc_frontend&client_secret=QhgAmvKgmwODzsEp98dnA4PeUEMMaFHd&grant_type=client_credentials';
|
|
788
911
|
|
|
789
912
|
const res = await axios.post(
|
package/src/web/WebKYCEntry.tsx
CHANGED
|
@@ -111,6 +111,7 @@ export function WebKYCEntry({
|
|
|
111
111
|
onCancel,
|
|
112
112
|
onSessionSave,
|
|
113
113
|
}: WebKYCEntryProps): JSX.Element {
|
|
114
|
+
console.log('first')
|
|
114
115
|
const { setLocale } = useI18n();
|
|
115
116
|
const [urlParams, setUrlParams] = useState<URLParams>({});
|
|
116
117
|
const [isLoading, setIsLoading] = useState(true);
|
|
@@ -204,7 +205,6 @@ export function WebKYCEntry({
|
|
|
204
205
|
}
|
|
205
206
|
}, [urlParams]);
|
|
206
207
|
|
|
207
|
-
// Handle KYC completion
|
|
208
208
|
const handleComplete = useCallback(async (data: any) => {
|
|
209
209
|
console.log('KYC completed:', data);
|
|
210
210
|
|
|
@@ -214,15 +214,48 @@ export function WebKYCEntry({
|
|
|
214
214
|
// Handle Push URL webhook if provided
|
|
215
215
|
if (urlParams.push_url) {
|
|
216
216
|
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
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const finalSessionId = kycSessionId || parsedKycData?.session_id || urlParams.kyc_id || 'unknown';
|
|
247
|
+
|
|
248
|
+
// 3. Build your exact un-nested payload signature
|
|
217
249
|
const verificationState = {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
250
|
+
session_id: finalSessionId,
|
|
251
|
+
status: 'success',
|
|
252
|
+
message: innerResult?.message || 'Verification data retrieved successfully.',
|
|
253
|
+
data: parsedKycData || {}
|
|
221
254
|
};
|
|
255
|
+
|
|
222
256
|
await postWebhook(urlParams.push_url, verificationState, 5000);
|
|
223
|
-
console.log('Successfully pushed KYC data to webhook');
|
|
257
|
+
console.log('Successfully pushed beautifully clean KYC data payload to webhook');
|
|
224
258
|
} catch (err) {
|
|
225
|
-
// Fail open - redirect anyway even if webhook fails
|
|
226
259
|
console.warn('Failed to push data to webhook URL:', err);
|
|
227
260
|
}
|
|
228
261
|
}
|
|
@@ -238,6 +271,7 @@ export function WebKYCEntry({
|
|
|
238
271
|
liveness_checked: data.livenessCheckComplete || false,
|
|
239
272
|
},
|
|
240
273
|
});
|
|
274
|
+
|
|
241
275
|
onComplete?.(data);
|
|
242
276
|
}, [redirectToReturnUrl, urlParams, onComplete]);
|
|
243
277
|
|
|
@@ -311,6 +345,7 @@ export function WebKYCEntry({
|
|
|
311
345
|
useEffect(() => {
|
|
312
346
|
try {
|
|
313
347
|
const params = parseUrlParams();
|
|
348
|
+
|
|
314
349
|
setUrlParams(params);
|
|
315
350
|
|
|
316
351
|
// Set language if provided
|
|
@@ -447,4 +482,4 @@ const styles = StyleSheet.create({
|
|
|
447
482
|
},
|
|
448
483
|
});
|
|
449
484
|
|
|
450
|
-
export default WebKYCEntry;
|
|
485
|
+
export default WebKYCEntry;
|