@sanctum-key/react-native-sdk 1.0.40 → 1.0.43
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/build/package.json +1 -1
- package/build/src/components/KYCElements/IDCardCapture.d.ts.map +1 -1
- package/build/src/components/KYCElements/IDCardCapture.js +68 -17
- package/build/src/components/KYCElements/IDCardCapture.js.map +1 -1
- package/build/src/modules/api/CardAuthentification.d.ts.map +1 -1
- package/build/src/modules/api/CardAuthentification.js +12 -5
- package/build/src/modules/api/CardAuthentification.js.map +1 -1
- package/build/src/modules/api/KYCService.d.ts +1 -0
- package/build/src/modules/api/KYCService.d.ts.map +1 -1
- package/build/src/modules/api/KYCService.js +3 -0
- package/build/src/modules/api/KYCService.js.map +1 -1
- package/build/src/utils/template-transformer.js +4 -4
- package/build/src/utils/template-transformer.js.map +1 -1
- package/package.json +1 -1
- package/src/components/KYCElements/IDCardCapture.tsx +84 -12
- package/src/modules/api/CardAuthentification.ts +16 -6
- package/src/modules/api/KYCService.ts +4 -0
- package/src/utils/template-transformer.ts +4 -4
package/build/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IDCardCapture.d.ts","sourceRoot":"","sources":["../../../../src/components/KYCElements/IDCardCapture.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+C,MAAM,OAAO,CAAC;AAIpE,OAAO,EAAE,iBAAiB,EAAoI,MAAM,uBAAuB,CAAC;AAqB5L,UAAU,cAAc;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,kBAAkB;IAC1B,SAAS,EAAE,iBAAiB,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACvC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAAC,KAAK,IAAI,CAAC;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAkCD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,
|
|
1
|
+
{"version":3,"file":"IDCardCapture.d.ts","sourceRoot":"","sources":["../../../../src/components/KYCElements/IDCardCapture.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+C,MAAM,OAAO,CAAC;AAIpE,OAAO,EAAE,iBAAiB,EAAoI,MAAM,uBAAuB,CAAC;AAqB5L,UAAU,cAAc;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,kBAAkB;IAC1B,SAAS,EAAE,iBAAiB,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACvC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAAC,KAAK,IAAI,CAAC;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAkCD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA0yBtD,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
-
import { View, Text, StyleSheet, Image, ScrollView, Platform, ActivityIndicator, TouchableOpacity, useWindowDimensions } from 'react-native';
|
|
2
|
+
import { View, Text, StyleSheet, Image, ScrollView, Platform, ActivityIndicator, TouchableOpacity, useWindowDimensions, Alert } from 'react-native';
|
|
3
3
|
import { showAlert } from '../../utils/platformAlert';
|
|
4
4
|
import { EnhancedCameraView } from '../EnhancedCameraView';
|
|
5
5
|
import { GovernmentDocumentTypeShorted, GovernmentDocumentTypeBackend } from '../../types/KYC.types';
|
|
@@ -15,7 +15,7 @@ import { cropByObb, getObbConfidence, OBB_CONFIDENCE_THRESHOLD } from '../../uti
|
|
|
15
15
|
import REGION_MAPPING from '../../config/region_mapping.json';
|
|
16
16
|
import QRCode from 'react-native-qrcode-svg';
|
|
17
17
|
import { cropImageWithBBoxWithTolerance } from '../../utils/cropByObb';
|
|
18
|
-
import kycService, { authentification } from '../../modules/api/KYCService';
|
|
18
|
+
import kycService, { authentification, clearAuthToken } from '../../modules/api/KYCService';
|
|
19
19
|
const ISO_TO_COUNTRY_NAME = {
|
|
20
20
|
'KE': 'Kenya', 'CM': 'Cameroon', 'NG': 'Nigeria', 'CA': 'Canada',
|
|
21
21
|
'FR': 'France', 'GH': 'Ghana', 'ZA': 'South Africa', 'GB': 'Britain',
|
|
@@ -397,6 +397,31 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
397
397
|
setSilentCaptureResult(prev => ({ ...prev, isAnalyzing: false, success: false, error: 'Failed to process barcode. Please retake the photo.' }));
|
|
398
398
|
}
|
|
399
399
|
};
|
|
400
|
+
const handleExitKYCFlow = () => {
|
|
401
|
+
clearAuthToken();
|
|
402
|
+
// 2. Clear all local camera/capture states
|
|
403
|
+
setCapturedImages({});
|
|
404
|
+
if (onValueChange)
|
|
405
|
+
onValueChange({}); // Clear the parent's form state
|
|
406
|
+
setCurrentSide('front');
|
|
407
|
+
setScanPhase('image');
|
|
408
|
+
setSilentCaptureResult({ success: false, isAnalyzing: false, path: '', error: '' });
|
|
409
|
+
scannedBarcodeRef.current = null;
|
|
410
|
+
setPendingCAImage(null);
|
|
411
|
+
setIsProcessingCapture(false);
|
|
412
|
+
setProcessingImagePath(null);
|
|
413
|
+
// 3. Restart the flow
|
|
414
|
+
if (actions.resetTemplate) {
|
|
415
|
+
// This is the best method: it wipes the context and rebuilds the initial state
|
|
416
|
+
actions.resetTemplate();
|
|
417
|
+
}
|
|
418
|
+
else if (actions.goToComponent && state.template?.components?.length > 0) {
|
|
419
|
+
actions.goToComponent(state.template.components[0].id);
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
console.warn("Could not restart flow. Check your KYC context actions.");
|
|
423
|
+
}
|
|
424
|
+
};
|
|
400
425
|
const handleSilentCapture = async (result) => {
|
|
401
426
|
if (isProcessingCaptureRef.current)
|
|
402
427
|
return;
|
|
@@ -404,7 +429,6 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
404
429
|
return;
|
|
405
430
|
if (isAnalyzingRef.current)
|
|
406
431
|
return;
|
|
407
|
-
// USE REFS TO AVOID IOS NATIVE STALE CLOSURE
|
|
408
432
|
const side = currentSideRef.current;
|
|
409
433
|
const captured = capturedImagesRef.current;
|
|
410
434
|
const docType = selectedDocTypeRef.current;
|
|
@@ -497,24 +521,51 @@ export const IDCardCapture = ({ component, value = {}, onValueChange, error, lan
|
|
|
497
521
|
}
|
|
498
522
|
catch (error) {
|
|
499
523
|
clearTimeout(watchdog);
|
|
500
|
-
const
|
|
524
|
+
const rawMessage = (typeof error === 'string' ? error : (error?.message || '')).toLowerCase();
|
|
525
|
+
const statusCode = error?.response?.status || error?.status;
|
|
526
|
+
if (statusCode === 401 ||
|
|
527
|
+
statusCode === 403 ||
|
|
528
|
+
rawMessage.includes('401') ||
|
|
529
|
+
rawMessage.includes('unauthorized') ||
|
|
530
|
+
rawMessage.includes('token') ||
|
|
531
|
+
rawMessage.includes('unauthenticated')) {
|
|
532
|
+
setShowCamera(false);
|
|
533
|
+
setIsProcessingCapture(false);
|
|
534
|
+
setSilentCaptureResult(prev => ({ ...prev, isAnalyzing: false, success: false, error: '' }));
|
|
535
|
+
// Use React Native's native Alert to wait for the user's tap
|
|
536
|
+
Alert.alert(state.currentLanguage === 'en' ? 'Session Expired' : 'Session Expirée', state.currentLanguage === 'en'
|
|
537
|
+
? 'Your secure session has expired. Please restart the process.'
|
|
538
|
+
: 'Votre session sécurisée a expiré. Veuillez recommencer.', [
|
|
539
|
+
{
|
|
540
|
+
text: state.currentLanguage === 'en' ? 'Restart' : 'Recommencer',
|
|
541
|
+
onPress: () => handleExitKYCFlow() // Redirects ONLY when they click the button
|
|
542
|
+
}
|
|
543
|
+
], { cancelable: false } // Forces them to click the button
|
|
544
|
+
);
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
501
547
|
let hintMessage = '';
|
|
502
|
-
|
|
503
|
-
|
|
548
|
+
// 2. Business Logic Errors
|
|
549
|
+
if (rawMessage.includes('pays sélectionné') || rawMessage.includes('country mismatch')) {
|
|
550
|
+
hintMessage = state.currentLanguage === 'en' ? 'Does not match the selected country.' : 'Ne correspond pas au pays sélectionné.';
|
|
551
|
+
}
|
|
552
|
+
else if (rawMessage.includes('impossible') || rawMessage.includes('unreadable')) {
|
|
553
|
+
hintMessage = state.currentLanguage === 'en' ? 'Move to better lighting and ensure card is in frame.' : 'Améliorez l\'éclairage et assurez-vous que la carte est bien cadrée.';
|
|
504
554
|
}
|
|
555
|
+
else if (rawMessage.includes('card_not_fully_in_frame') || rawMessage.includes('frame')) {
|
|
556
|
+
hintMessage = state.currentLanguage === 'en' ? 'Move closer to the document.' : 'Rapprochez-vous du document.';
|
|
557
|
+
}
|
|
558
|
+
else if (rawMessage.includes('ne correspond pas au recto')) {
|
|
559
|
+
hintMessage = state.currentLanguage === 'en' ? 'Please scan the same ID.' : 'Veuillez scanner la même pièce.';
|
|
560
|
+
}
|
|
561
|
+
// 3. Fallback to Network/API failure
|
|
505
562
|
else {
|
|
506
|
-
const
|
|
507
|
-
if (
|
|
508
|
-
hintMessage = state.currentLanguage === 'en' ? '
|
|
509
|
-
}
|
|
510
|
-
else if (rawMessage.includes('country mismatch') || rawMessage.includes('pays sélectionné')) {
|
|
511
|
-
hintMessage = state.currentLanguage === 'en' ? 'Wrong document type.' : 'Mauvais type de document.';
|
|
563
|
+
const isNetworkError = error.isAxiosError || error.message === 'Network Error' || error.code === 'ECONNABORTED' || rawMessage.includes('network') || !error.response;
|
|
564
|
+
if (isNetworkError) {
|
|
565
|
+
hintMessage = state.currentLanguage === 'en' ? 'Poor connection. Retrying...' : 'Connexion faible. Nouvelle tentative...';
|
|
512
566
|
}
|
|
513
|
-
else
|
|
514
|
-
hintMessage = state.currentLanguage === 'en' ? '
|
|
515
|
-
}
|
|
516
|
-
else if (rawMessage.includes('ne correspond pas au recto')) {
|
|
517
|
-
hintMessage = state.currentLanguage === 'en' ? 'Scan the same ID.' : 'Scannez la même pièce.';
|
|
567
|
+
else {
|
|
568
|
+
hintMessage = state.currentLanguage === 'en' ? 'Analyzing...' : 'Analyse en cours...';
|
|
518
569
|
}
|
|
519
570
|
}
|
|
520
571
|
setSilentCaptureResult(prev => ({ ...prev, isAnalyzing: false, success: false, error: hintMessage }));
|