@sanctum-key/react-native-sdk 1.0.23 → 1.0.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.
- package/build/package.json +3 -1
- package/build/src/components/EnhancedCameraView.d.ts +7 -1
- package/build/src/components/EnhancedCameraView.d.ts.map +1 -1
- package/build/src/components/EnhancedCameraView.js +88 -30
- package/build/src/components/EnhancedCameraView.js.map +1 -1
- package/build/src/components/EnhancedCameraView.web.d.ts +5 -1
- package/build/src/components/EnhancedCameraView.web.d.ts.map +1 -1
- package/build/src/components/EnhancedCameraView.web.js +80 -295
- package/build/src/components/EnhancedCameraView.web.js.map +1 -1
- package/build/src/components/KYCElements/CameraCapture.js +1 -1
- package/build/src/components/KYCElements/CameraCapture.js.map +1 -1
- package/build/src/components/KYCElements/CountrySelection.d.ts.map +1 -1
- package/build/src/components/KYCElements/CountrySelection.js +38 -218
- package/build/src/components/KYCElements/CountrySelection.js.map +1 -1
- package/build/src/components/KYCElements/CountrySelectionTemplate.d.ts.map +1 -1
- package/build/src/components/KYCElements/CountrySelectionTemplate.js +119 -26
- 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 +512 -87
- package/build/src/components/KYCElements/IDCardCapture.js.map +1 -1
- package/build/src/components/KYCElements/VerificationProgressTemplate.d.ts.map +1 -1
- package/build/src/components/KYCElements/VerificationProgressTemplate.js +93 -51
- package/build/src/components/KYCElements/VerificationProgressTemplate.js.map +1 -1
- package/build/src/components/OverLay/type.d.ts +1 -0
- package/build/src/components/OverLay/type.d.ts.map +1 -1
- package/build/src/components/OverLay/type.js.map +1 -1
- package/build/src/components/WebBarcodeScanner.d.ts +9 -0
- package/build/src/components/WebBarcodeScanner.d.ts.map +1 -0
- package/build/src/components/WebBarcodeScanner.js +152 -0
- package/build/src/components/WebBarcodeScanner.js.map +1 -0
- package/build/src/config/KYCConfigs.js +2 -2
- package/build/src/config/KYCConfigs.js.map +1 -1
- package/build/src/config/region_mapping.js +14 -14
- package/build/src/config/region_mapping.js.map +1 -1
- package/build/src/config/region_mapping.json +0 -14
- package/build/src/modules/api/CardAuthentification.d.ts +2 -0
- package/build/src/modules/api/CardAuthentification.d.ts.map +1 -1
- package/build/src/modules/api/CardAuthentification.js +23 -40
- package/build/src/modules/api/CardAuthentification.js.map +1 -1
- package/build/src/modules/api/KYCService.d.ts +7 -2
- package/build/src/modules/api/KYCService.d.ts.map +1 -1
- package/build/src/modules/api/KYCService.js +163 -57
- package/build/src/modules/api/KYCService.js.map +1 -1
- package/build/src/types/KYC.types.d.ts +1 -0
- package/build/src/types/KYC.types.d.ts.map +1 -1
- package/build/src/types/KYC.types.js.map +1 -1
- package/build/src/utils/aamvaParser.d.ts +62 -0
- package/build/src/utils/aamvaParser.d.ts.map +1 -0
- package/build/src/utils/aamvaParser.js +91 -0
- package/build/src/utils/aamvaParser.js.map +1 -0
- package/build/src/utils/cropByObb.d.ts.map +1 -1
- package/build/src/utils/cropByObb.js +4 -3
- package/build/src/utils/cropByObb.js.map +1 -1
- package/build/src/web/WebKYCEntry.d.ts +1 -1
- package/build/src/web/WebKYCEntry.d.ts.map +1 -1
- package/build/src/web/WebKYCEntry.js +105 -239
- package/build/src/web/WebKYCEntry.js.map +1 -1
- package/package.json +3 -1
- package/src/components/EnhancedCameraView.tsx +116 -42
- package/src/components/EnhancedCameraView.web.tsx +98 -338
- package/src/components/KYCElements/CameraCapture.tsx +1 -1
- package/src/components/KYCElements/CountrySelection.tsx +60 -240
- package/src/components/KYCElements/CountrySelectionTemplate.tsx +148 -29
- package/src/components/KYCElements/IDCardCapture.tsx +675 -142
- package/src/components/KYCElements/VerificationProgressTemplate.tsx +112 -65
- package/src/components/OverLay/type.ts +1 -1
- package/src/components/WebBarcodeScanner.tsx +273 -0
- package/src/config/KYCConfigs.ts +2 -2
- package/src/config/region_mapping.json +0 -14
- package/src/config/region_mapping.ts +14 -14
- package/src/modules/api/CardAuthentification.ts +44 -58
- package/src/modules/api/KYCService.ts +236 -82
- package/src/types/KYC.types.ts +1 -0
- package/src/utils/aamvaParser.ts +102 -0
- package/src/utils/cropByObb.ts +5 -3
- package/src/web/WebKYCEntry.tsx +125 -301
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react';
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
2
2
|
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
|
|
3
3
|
import { useTemplateKYCFlowContext } from '../../hooks/useTemplateKYCFlow';
|
|
4
4
|
import { useI18n } from '../../hooks/useI18n';
|
|
@@ -10,73 +10,118 @@ export const VerificationProgressTemplate = () => {
|
|
|
10
10
|
const [retryCount, setRetryCount] = useState(0);
|
|
11
11
|
const [isRetrying, setIsRetrying] = useState(false);
|
|
12
12
|
const [timeoutId, setTimeoutId] = useState(null);
|
|
13
|
+
const isPollingRef = useRef(false);
|
|
13
14
|
const verification = state.verification;
|
|
14
15
|
const isSuccess = verification.status === 'success';
|
|
15
16
|
const isFailed = verification.status === 'failed';
|
|
16
|
-
const getVerificationResult = async (currentRetryCount = 0, maxRetries =
|
|
17
|
+
const getVerificationResult = async (currentRetryCount = 0, maxRetries = 60) => {
|
|
17
18
|
try {
|
|
18
19
|
logger.log(`Starting verification check (attempt ${currentRetryCount + 1}/${maxRetries + 1})`);
|
|
19
20
|
const result = await kycService.getVerificationResult(state.session.session_id);
|
|
20
21
|
logger.log('getVerificationResult raw result:', JSON.stringify(result, null, 2));
|
|
21
|
-
|
|
22
|
+
const rootStatus = (result?.status || '').toLowerCase();
|
|
23
|
+
if (rootStatus === 'failed.' || rootStatus === 'failed' || rootStatus === 'rejected' || rootStatus === 'error') {
|
|
22
24
|
actions.setVerificationState({
|
|
23
25
|
status: 'failed',
|
|
24
26
|
result: {
|
|
25
27
|
referenceId: state.session.session_id,
|
|
26
|
-
issues: [result?.message || 'Verification failed. Sent for manual review.']
|
|
28
|
+
issues: [result?.message || result?.reason || 'Verification failed. Sent for manual review.']
|
|
27
29
|
}
|
|
28
30
|
});
|
|
29
31
|
setIsRetrying(false);
|
|
32
|
+
isPollingRef.current = false; // Release lock
|
|
30
33
|
return;
|
|
31
34
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
// 2. Safely Extract Nested Payload
|
|
36
|
+
let vData = result?.data || result; // Fallback to root if .data is missing
|
|
37
|
+
// Handle stringified JSON
|
|
38
|
+
if (typeof vData === 'string') {
|
|
39
|
+
try {
|
|
40
|
+
vData = JSON.parse(vData);
|
|
41
|
+
}
|
|
42
|
+
catch (e) { }
|
|
43
|
+
}
|
|
44
|
+
// Handle backend dictionaries indexed by session_id
|
|
45
|
+
if (vData && typeof vData === 'object' && vData[state.session.session_id]) {
|
|
46
|
+
let nested = vData[state.session.session_id];
|
|
47
|
+
if (nested && nested.data) {
|
|
48
|
+
nested = typeof nested.data === 'string' ? JSON.parse(nested.data) : nested.data;
|
|
49
|
+
}
|
|
50
|
+
vData = nested;
|
|
36
51
|
}
|
|
37
|
-
if (!
|
|
38
|
-
throw new Error('Verification payload missing for current session');
|
|
52
|
+
if (!vData || typeof vData !== 'object') {
|
|
53
|
+
throw new Error('Verification payload missing or invalid for current session');
|
|
39
54
|
}
|
|
40
|
-
const
|
|
41
|
-
|
|
55
|
+
const vStatus = (vData.verification_status || vData.status || vData.state || '').toLowerCase();
|
|
56
|
+
const vDecision = (vData.decision || vData.outcome || vData.result || '').toLowerCase();
|
|
57
|
+
// const processingError = vData.reason || vData.error || vData.issues || vData.error_message;
|
|
58
|
+
const selfieMatch = vData.selfie_info?.is_match; // true, false, or null
|
|
59
|
+
logger.log(`Parsed Status: [${vStatus}], Decision: [${vDecision}], Selfie Match: [${selfieMatch}]`);
|
|
60
|
+
// 4. Evaluate Failures First
|
|
61
|
+
// 5. Evaluate Definitive Success
|
|
62
|
+
if (vStatus === 'approved' || vStatus === 'verified' || vStatus === 'success' ||
|
|
63
|
+
vDecision === 'approved' || vDecision === 'passed' || vDecision === 'clear' ||
|
|
64
|
+
(vStatus === 'completed' && selfieMatch === true)) {
|
|
65
|
+
// 🚨 THE FIX: Prevent False Positives (Ghost Payloads)
|
|
66
|
+
// If it says success, but the data object is completely empty, it is actually a failure.
|
|
67
|
+
const hasActualData = vData && Object.keys(vData).length > 0;
|
|
68
|
+
if (!hasActualData) {
|
|
69
|
+
logger.warn('Backend returned success, but data payload is entirely empty.');
|
|
70
|
+
actions.setVerificationState({
|
|
71
|
+
status: 'failed',
|
|
72
|
+
result: {
|
|
73
|
+
referenceId: state.session.session_id,
|
|
74
|
+
issues: ['Document text could not be read clearly. Please retake the photo in better lighting.']
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
setIsRetrying(false);
|
|
78
|
+
isPollingRef.current = false;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
// If we have data, proceed to actual success
|
|
82
|
+
actions.setVerificationState({
|
|
83
|
+
status: 'success',
|
|
84
|
+
result: {
|
|
85
|
+
...result,
|
|
86
|
+
referenceId: vData.verification_id || vData.session_id || state.session.session_id
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
setIsRetrying(false);
|
|
90
|
+
isPollingRef.current = false;
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (vStatus === 'processing' || vStatus === 'pending' || vStatus === 'in_progress' ||
|
|
94
|
+
vStatus === 'initiated' || (vStatus === 'completed' && selfieMatch === null) || !vStatus) {
|
|
42
95
|
if (currentRetryCount < maxRetries) {
|
|
43
96
|
const nextRetryCount = currentRetryCount + 1;
|
|
44
97
|
setRetryCount(nextRetryCount);
|
|
45
98
|
setIsRetrying(true);
|
|
46
|
-
logger.log(`Verification still processing, retrying in
|
|
99
|
+
logger.log(`Verification still processing, retrying in 3s... (${nextRetryCount}/${maxRetries})`);
|
|
47
100
|
if (timeoutId)
|
|
48
101
|
clearTimeout(timeoutId);
|
|
49
102
|
const newTimeoutId = setTimeout(() => {
|
|
50
103
|
getVerificationResult(nextRetryCount, maxRetries);
|
|
51
|
-
},
|
|
104
|
+
}, 3000);
|
|
52
105
|
setTimeoutId(newTimeoutId);
|
|
53
|
-
return;
|
|
54
106
|
}
|
|
55
107
|
else {
|
|
56
108
|
logger.error('Max retries reached, verification still processing');
|
|
57
109
|
setIsRetrying(false);
|
|
58
|
-
|
|
110
|
+
isPollingRef.current = false;
|
|
111
|
+
actions.setVerificationState({
|
|
112
|
+
status: 'failed',
|
|
113
|
+
result: {
|
|
114
|
+
referenceId: state.session.session_id,
|
|
115
|
+
issues: ['Verification timed out. Please try again.']
|
|
116
|
+
}
|
|
117
|
+
});
|
|
59
118
|
}
|
|
119
|
+
return;
|
|
60
120
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
status: 'success',
|
|
64
|
-
result: {
|
|
65
|
-
...result,
|
|
66
|
-
referenceId: verificationResult.verification_id || verificationResult.session_id
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
else if (currentStatus === "failed" || currentStatus === "rejected") {
|
|
71
|
-
actions.setVerificationState({
|
|
72
|
-
status: 'failed',
|
|
73
|
-
result: {
|
|
74
|
-
referenceId: verificationResult.verification_id || state.session.session_id,
|
|
75
|
-
issues: ['Verification failed during processing.']
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
}
|
|
121
|
+
// Fallback release if status is completely unknown
|
|
122
|
+
logger.warn(`Unknown verification status received: ${vStatus}`);
|
|
79
123
|
setIsRetrying(false);
|
|
124
|
+
isPollingRef.current = false;
|
|
80
125
|
}
|
|
81
126
|
catch (error) {
|
|
82
127
|
logger.error('getVerificationResult error', JSON.stringify(errorMessage(error) || { message: error?.message || 'Unknown error' }, null, 2));
|
|
@@ -84,42 +129,42 @@ export const VerificationProgressTemplate = () => {
|
|
|
84
129
|
const nextRetryCount = currentRetryCount + 1;
|
|
85
130
|
setRetryCount(nextRetryCount);
|
|
86
131
|
setIsRetrying(true);
|
|
87
|
-
logger.log(`getVerificationResult Error occurred, retrying in
|
|
132
|
+
logger.log(`getVerificationResult Error occurred, retrying in 3s... (${nextRetryCount}/${maxRetries})`);
|
|
88
133
|
if (timeoutId)
|
|
89
134
|
clearTimeout(timeoutId);
|
|
90
135
|
const newTimeoutId = setTimeout(() => {
|
|
91
136
|
getVerificationResult(nextRetryCount, maxRetries);
|
|
92
|
-
},
|
|
137
|
+
}, 3000);
|
|
93
138
|
setTimeoutId(newTimeoutId);
|
|
94
139
|
}
|
|
95
140
|
else {
|
|
96
141
|
setIsRetrying(false);
|
|
142
|
+
isPollingRef.current = false; // Release lock
|
|
97
143
|
logger.error('Max retries reached after errors');
|
|
98
144
|
}
|
|
99
145
|
}
|
|
100
146
|
};
|
|
101
147
|
useEffect(() => {
|
|
102
|
-
if (state.session.session_id) {
|
|
148
|
+
if (state.session.session_id && !isSuccess && !isFailed && !isPollingRef.current) {
|
|
149
|
+
isPollingRef.current = true; // Lock the gate instantly
|
|
103
150
|
getVerificationResult();
|
|
104
151
|
}
|
|
105
|
-
}, [state.session.session_id]);
|
|
152
|
+
}, [state.session.session_id, isSuccess, isFailed]);
|
|
106
153
|
useEffect(() => {
|
|
107
154
|
return () => {
|
|
108
155
|
if (timeoutId)
|
|
109
156
|
clearTimeout(timeoutId);
|
|
157
|
+
isPollingRef.current = false; // Reset lock on unmount
|
|
110
158
|
};
|
|
111
159
|
}, [timeoutId]);
|
|
112
|
-
// 🚨 THE FIX: Automatically trigger the webhook/completion flow on success
|
|
113
160
|
useEffect(() => {
|
|
114
161
|
let autoSubmitTimer;
|
|
115
162
|
if (isSuccess) {
|
|
116
163
|
logger.log("Verification successful. Initiating auto-submit countdown...");
|
|
117
|
-
// Wait 3 seconds so the user can see the "Complete" screen, then automatically push the data
|
|
118
164
|
autoSubmitTimer = setTimeout(() => {
|
|
119
165
|
actions.submitVerification();
|
|
120
166
|
}, 3000);
|
|
121
167
|
}
|
|
122
|
-
// Cleanup the timer if the user clicks the button manually before 3 seconds are up
|
|
123
168
|
return () => {
|
|
124
169
|
if (autoSubmitTimer)
|
|
125
170
|
clearTimeout(autoSubmitTimer);
|
|
@@ -138,34 +183,29 @@ export const VerificationProgressTemplate = () => {
|
|
|
138
183
|
if (isFailed) {
|
|
139
184
|
return (<View style={styles.container}>
|
|
140
185
|
<Text style={styles.title}>{t('kyc.verificationProgress.status.failed')}</Text>
|
|
141
|
-
|
|
142
186
|
<View style={styles.issuesBox}>
|
|
143
187
|
<Text style={styles.issuesTitle}>{t('common.error')}</Text>
|
|
144
188
|
{Array.isArray(verification.result?.issues) && verification.result.issues.map((issue, idx) => (<Text key={idx} style={styles.issueItem}>• {issue}</Text>))}
|
|
145
189
|
</View>
|
|
146
|
-
|
|
147
190
|
<TouchableOpacity style={[styles.button, styles.primary]} onPress={() => actions.submitVerification()}>
|
|
148
191
|
<Text style={styles.buttonText}>
|
|
149
192
|
{state.currentLanguage === 'en' ? 'OK / Finish' : 'Terminer'}
|
|
150
193
|
</Text>
|
|
151
194
|
</TouchableOpacity>
|
|
152
|
-
|
|
153
195
|
<TouchableOpacity style={[styles.button, styles.secondary]} onPress={() => actions.resetTemplate()}>
|
|
154
196
|
<Text style={styles.secondaryText}>
|
|
155
197
|
{state.currentLanguage === 'en' ? 'Start Over' : 'Recommencer'}
|
|
156
198
|
</Text>
|
|
157
199
|
</TouchableOpacity>
|
|
158
|
-
|
|
159
200
|
{verification.result?.referenceId ? (<Text style={styles.refText}>{`Reference ID: ${verification.result.referenceId}`}</Text>) : null}
|
|
160
201
|
</View>);
|
|
161
202
|
}
|
|
162
203
|
return (<View style={styles.container}>
|
|
163
204
|
<Text style={styles.title}>{t('kyc.verificationProgress.title')}</Text>
|
|
164
205
|
<Text style={styles.subtitle}>
|
|
165
|
-
{isRetrying
|
|
166
|
-
? `${t('kyc.verificationProgress.retrying', { current: retryCount, max: 40 })}`
|
|
167
|
-
: t('kyc.verificationProgress.estimatedTime')}
|
|
206
|
+
{isRetrying ? `${t('kyc.verificationProgress.retrying', { current: retryCount, max: 40 })}` : t('kyc.verificationProgress.estimatedTime')}
|
|
168
207
|
</Text>
|
|
208
|
+
|
|
169
209
|
<View style={styles.timeline}>
|
|
170
210
|
<View style={[styles.dot, styles.done]}><Text style={styles.stepCheckmark}>✓</Text></View>
|
|
171
211
|
<View style={styles.line}/>
|
|
@@ -173,21 +213,23 @@ export const VerificationProgressTemplate = () => {
|
|
|
173
213
|
<View style={styles.line}/>
|
|
174
214
|
<View style={[styles.dot, styles.pending]}><Text style={styles.stepCheckmark}>3</Text></View>
|
|
175
215
|
</View>
|
|
216
|
+
|
|
176
217
|
<View style={styles.row}>
|
|
177
218
|
<Text style={styles.stepLabel}>{t('kyc.verificationProgress.status.completed')}</Text>
|
|
178
219
|
<Text style={styles.stepLabel}>{t('kyc.verificationProgress.steps.analyzing')}</Text>
|
|
179
220
|
<Text style={styles.stepLabel}>{t('kyc.verificationProgress.steps.verifying')}</Text>
|
|
180
221
|
</View>
|
|
222
|
+
|
|
181
223
|
<View style={styles.card}>
|
|
182
224
|
<Text style={styles.cardTitle}>{t('kyc.idCardCapture.title')}</Text>
|
|
183
225
|
<Text style={styles.cardLine}>{t('kyc.verificationProgress.steps.extracting')}</Text>
|
|
226
|
+
|
|
184
227
|
<Text style={styles.cardTitle}>{t('kyc.selfieCapture.title')}</Text>
|
|
185
228
|
<Text style={styles.cardLine}>{t('kyc.verificationProgress.steps.analyzing')}</Text>
|
|
229
|
+
|
|
186
230
|
<Text style={styles.cardTitle}>{t('kyc.verificationProgress.title')}</Text>
|
|
187
231
|
<Text style={styles.cardLine}>
|
|
188
|
-
{isRetrying
|
|
189
|
-
? `${t('kyc.verificationProgress.status.processing')}...`
|
|
190
|
-
: t('kyc.verificationProgress.status.pending')}
|
|
232
|
+
{isRetrying ? `${t('kyc.verificationProgress.status.processing')}...` : t('kyc.verificationProgress.status.pending')}
|
|
191
233
|
</Text>
|
|
192
234
|
</View>
|
|
193
235
|
</View>);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VerificationProgressTemplate.js","sourceRoot":"","sources":["../../../../src/components/KYCElements/VerificationProgressTemplate.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useEffect, useState } from 'react';\nimport { View, Text, StyleSheet, TouchableOpacity } from 'react-native';\nimport { TemplateComponent } from '../../types/KYC.types';\nimport { useTemplateKYCFlowContext } from '../../hooks/useTemplateKYCFlow';\nimport { useI18n } from '../../hooks/useI18n';\nimport kycService, { errorMessage } from '../../modules/api/KYCService';\nimport { logger } from '../../utils/logger';\n\ninterface VerificationProgressTemplateProps {\n component: TemplateComponent;\n value: unknown;\n onValueChange: (data: unknown) => void;\n error?: string;\n language?: string;\n}\n\nexport const VerificationProgressTemplate: React.FC<VerificationProgressTemplateProps> = () => {\n const { t } = useI18n();\n const { state, actions } = useTemplateKYCFlowContext();\n const [retryCount, setRetryCount] = useState(0);\n const [isRetrying, setIsRetrying] = useState(false);\n const [timeoutId, setTimeoutId] = useState<number | null>(null);\n\n const verification = state.verification;\n const isSuccess = verification.status === 'success';\n const isFailed = verification.status === 'failed';\n\n const getVerificationResult = async (currentRetryCount = 0, maxRetries = 40) => {\n try {\n logger.log(`Starting verification check (attempt ${currentRetryCount + 1}/${maxRetries + 1})`);\n const result: any = await kycService.getVerificationResult(state.session.session_id);\n \n logger.log('getVerificationResult raw result:', JSON.stringify(result, null, 2));\n\n if (result?.status === 'Failed.' || result?.status === 'failed' || result?.status === 'rejected') {\n actions.setVerificationState({\n status: 'failed',\n result: {\n referenceId: state.session.session_id,\n issues: [result?.message || 'Verification failed. Sent for manual review.']\n } as any\n });\n setIsRetrying(false);\n return; \n }\n\n let verificationResult = result?.data;\n \n if (verificationResult && !verificationResult.verification_status && verificationResult[state.session.session_id]) {\n const nestedData = verificationResult[state.session.session_id]?.data;\n verificationResult = typeof nestedData === 'string' ? JSON.parse(nestedData) : nestedData;\n }\n\n if (!verificationResult) {\n throw new Error('Verification payload missing for current session');\n }\n\n const currentStatus = verificationResult.verification_status;\n\n if (currentStatus === null || currentStatus === \"processing\" || currentStatus === \"pending\") {\n if (currentRetryCount < maxRetries) {\n const nextRetryCount = currentRetryCount + 1;\n setRetryCount(nextRetryCount);\n setIsRetrying(true);\n logger.log(`Verification still processing, retrying in 10s... (${nextRetryCount}/${maxRetries})`);\n \n if (timeoutId) clearTimeout(timeoutId);\n \n const newTimeoutId = setTimeout(() => {\n getVerificationResult(nextRetryCount, maxRetries);\n }, 10000);\n \n setTimeoutId(newTimeoutId as any);\n return;\n } else {\n logger.error('Max retries reached, verification still processing');\n setIsRetrying(false);\n return;\n }\n }\n\n if (currentStatus === \"completed\" || currentStatus === \"approved\") {\n actions.setVerificationState({\n status: 'success',\n result: {\n ...result,\n referenceId: verificationResult.verification_id || verificationResult.session_id\n } as any\n });\n } else if (currentStatus === \"failed\" || currentStatus === \"rejected\") {\n actions.setVerificationState({\n status: 'failed',\n result: {\n referenceId: verificationResult.verification_id || state.session.session_id,\n issues: ['Verification failed during processing.']\n } as any\n });\n }\n \n setIsRetrying(false);\n\n } catch (error: any) {\n logger.error('getVerificationResult error', JSON.stringify(errorMessage(error) || { message: error?.message || 'Unknown error' }, null, 2));\n \n if (currentRetryCount < maxRetries) {\n const nextRetryCount = currentRetryCount + 1;\n setRetryCount(nextRetryCount);\n setIsRetrying(true);\n logger.log(`getVerificationResult Error occurred, retrying in 10s... (${nextRetryCount}/${maxRetries})`);\n \n if (timeoutId) clearTimeout(timeoutId);\n \n const newTimeoutId = setTimeout(() => {\n getVerificationResult(nextRetryCount, maxRetries);\n }, 10000);\n \n setTimeoutId(newTimeoutId as any);\n } else {\n setIsRetrying(false);\n logger.error('Max retries reached after errors');\n }\n }\n };\n\n useEffect(() => {\n if (state.session.session_id) {\n getVerificationResult();\n }\n }, [state.session.session_id]);\n\n useEffect(() => {\n return () => {\n if (timeoutId) clearTimeout(timeoutId);\n };\n }, [timeoutId]);\n\n // 🚨 THE FIX: Automatically trigger the webhook/completion flow on success\n useEffect(() => {\n let autoSubmitTimer: ReturnType<typeof setTimeout>;\n \n if (isSuccess) {\n logger.log(\"Verification successful. Initiating auto-submit countdown...\");\n // Wait 3 seconds so the user can see the \"Complete\" screen, then automatically push the data\n autoSubmitTimer = setTimeout(() => {\n actions.submitVerification();\n }, 3000);\n }\n\n // Cleanup the timer if the user clicks the button manually before 3 seconds are up\n return () => {\n if (autoSubmitTimer) clearTimeout(autoSubmitTimer);\n };\n }, [isSuccess, actions]);\n\n if (isSuccess) {\n return (\n <View style={styles.container}>\n <Text style={styles.title}>{t('kyc.verificationProgress.steps.complete')}</Text>\n <Text style={styles.subtitle}>{t('kyc.verificationProgress.subtitle')}</Text>\n <TouchableOpacity style={[styles.button, styles.primary]} onPress={() => actions.submitVerification()}>\n <Text style={styles.buttonText}>{t('common.continue')}</Text>\n </TouchableOpacity>\n {verification.result?.referenceId ? (\n <Text style={styles.refText}>{`Verification ID: ${verification.result.referenceId}`}</Text>\n ) : null}\n </View>\n );\n }\n\n if (isFailed) {\n return (\n <View style={styles.container}>\n <Text style={styles.title}>{t('kyc.verificationProgress.status.failed')}</Text>\n \n <View style={styles.issuesBox}>\n <Text style={styles.issuesTitle}>{t('common.error')}</Text>\n {Array.isArray(verification.result?.issues) && verification.result.issues.map((issue: string, idx: number) => (\n <Text key={idx} style={styles.issueItem}>• {issue}</Text>\n ))}\n </View>\n\n <TouchableOpacity style={[styles.button, styles.primary]} onPress={() => actions.submitVerification()}>\n <Text style={styles.buttonText}>\n {state.currentLanguage === 'en' ? 'OK / Finish' : 'Terminer'}\n </Text>\n </TouchableOpacity>\n \n <TouchableOpacity style={[styles.button, styles.secondary]} onPress={() => actions.resetTemplate()}>\n <Text style={styles.secondaryText}>\n {state.currentLanguage === 'en' ? 'Start Over' : 'Recommencer'}\n </Text>\n </TouchableOpacity>\n\n {verification.result?.referenceId ? (\n <Text style={styles.refText}>{`Reference ID: ${verification.result.referenceId}`}</Text>\n ) : null}\n </View>\n );\n }\n\n return (\n <View style={styles.container}>\n <Text style={styles.title}>{t('kyc.verificationProgress.title')}</Text>\n <Text style={styles.subtitle}>\n {isRetrying\n ? `${t('kyc.verificationProgress.retrying', { current: retryCount, max: 40 })}`\n : t('kyc.verificationProgress.estimatedTime')\n }\n </Text>\n <View style={styles.timeline}>\n <View style={[styles.dot, styles.done]}><Text style={styles.stepCheckmark}>✓</Text></View>\n <View style={styles.line} />\n <View style={[styles.dot, styles.active]}><Text style={styles.stepCheckmark}>2</Text></View>\n <View style={styles.line} />\n <View style={[styles.dot, styles.pending]}><Text style={styles.stepCheckmark}>3</Text></View>\n </View>\n <View style={styles.row}>\n <Text style={styles.stepLabel}>{t('kyc.verificationProgress.status.completed')}</Text>\n <Text style={styles.stepLabel}>{t('kyc.verificationProgress.steps.analyzing')}</Text>\n <Text style={styles.stepLabel}>{t('kyc.verificationProgress.steps.verifying')}</Text>\n </View>\n <View style={styles.card}>\n <Text style={styles.cardTitle}>{t('kyc.idCardCapture.title')}</Text>\n <Text style={styles.cardLine}>{t('kyc.verificationProgress.steps.extracting')}</Text>\n <Text style={styles.cardTitle}>{t('kyc.selfieCapture.title')}</Text>\n <Text style={styles.cardLine}>{t('kyc.verificationProgress.steps.analyzing')}</Text>\n <Text style={styles.cardTitle}>{t('kyc.verificationProgress.title')}</Text>\n <Text style={styles.cardLine}>\n {isRetrying\n ? `${t('kyc.verificationProgress.status.processing')}...`\n : t('kyc.verificationProgress.status.pending')\n }\n </Text>\n </View>\n </View>\n );\n};\n\nconst styles = StyleSheet.create({\n container: { flex: 1, width: '100%', paddingHorizontal: 16, paddingVertical: 12 },\n title: { fontSize: 24, fontWeight: 'bold', color: '#111827', textAlign: 'center', marginTop: 12 },\n subtitle: { fontSize: 14, color: '#6B7280', textAlign: 'center', marginTop: 8 },\n timeline: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginTop: 24 },\n dot: { width: 38, height: 38, borderRadius: 34, justifyContent: 'center', alignItems: 'center' },\n stepCheckmark: { color: 'white', fontSize: 16, fontWeight: 'bold' },\n line: { flex: 1, height: 4, backgroundColor: '#E5E7EB' },\n done: { backgroundColor: '#10B981' },\n active: { backgroundColor: '#F59E0B' },\n pending: { backgroundColor: '#E5E7EB' },\n row: { flexDirection: 'row', justifyContent: 'space-between', marginTop: 8 },\n stepLabel: { fontSize: 14, color: '#111827', fontWeight: '600' },\n card: { backgroundColor: 'white', padding: 16, borderRadius: 16, marginTop: 24 },\n cardTitle: { fontSize: 16, color: '#6B7280', marginTop: 8 },\n cardLine: { fontSize: 18, color: '#111827', fontWeight: '600', marginTop: 2 },\n button: { paddingVertical: 14, borderRadius: 10, alignItems: 'center', marginTop: 14 },\n primary: { backgroundColor: '#2DBD60' },\n buttonText: { color: 'white', fontSize: 16, fontWeight: '600' },\n refText: { marginTop: 12, textAlign: 'center', color: '#6B7280' },\n issuesBox: { backgroundColor: '#FEF2F2', borderRadius: 16, padding: 16, marginTop: 20 },\n issuesTitle: { color: '#991B1B', fontWeight: '700', marginBottom: 8 },\n issueItem: { color: '#991B1B', marginTop: 4 },\n secondary: { backgroundColor: '#F3F4F6', borderWidth: 1, borderColor: '#D1D5DB' },\n secondaryText: { color: '#374151', fontSize: 16, fontWeight: '600' },\n});"]}
|
|
1
|
+
{"version":3,"file":"VerificationProgressTemplate.js","sourceRoot":"","sources":["../../../../src/components/KYCElements/VerificationProgressTemplate.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport { View, Text, StyleSheet, TouchableOpacity } from 'react-native';\nimport { TemplateComponent } from '../../types/KYC.types';\nimport { useTemplateKYCFlowContext } from '../../hooks/useTemplateKYCFlow';\nimport { useI18n } from '../../hooks/useI18n';\nimport kycService, { errorMessage } from '../../modules/api/KYCService';\nimport { logger } from '../../utils/logger';\n\ninterface VerificationProgressTemplateProps {\n component: TemplateComponent;\n value: unknown;\n onValueChange: (data: unknown) => void;\n error?: string;\n language?: string;\n}\n\nexport const VerificationProgressTemplate: React.FC<VerificationProgressTemplateProps> = () => {\n const { t } = useI18n();\n const { state, actions } = useTemplateKYCFlowContext();\n const [retryCount, setRetryCount] = useState(0);\n const [isRetrying, setIsRetrying] = useState(false);\n const [timeoutId, setTimeoutId] = useState<number | null>(null);\n const isPollingRef = useRef(false);\n\n const verification = state.verification;\n const isSuccess = verification.status === 'success';\n const isFailed = verification.status === 'failed';\n\n const getVerificationResult = async (currentRetryCount = 0, maxRetries = 60) => {\n try {\n logger.log(`Starting verification check (attempt ${currentRetryCount + 1}/${maxRetries + 1})`);\n const result: any = await kycService.getVerificationResult(state.session.session_id);\n \n logger.log('getVerificationResult raw result:', JSON.stringify(result, null, 2));\n \n const rootStatus = (result?.status || '').toLowerCase();\n if (rootStatus === 'failed.' || rootStatus === 'failed' || rootStatus === 'rejected' || rootStatus === 'error') {\n actions.setVerificationState({\n status: 'failed',\n result: {\n referenceId: state.session.session_id,\n issues: [result?.message || result?.reason || 'Verification failed. Sent for manual review.']\n } as any\n });\n setIsRetrying(false);\n isPollingRef.current = false; // Release lock\n return;\n }\n \n // 2. Safely Extract Nested Payload\n let vData = result?.data || result; // Fallback to root if .data is missing\n \n // Handle stringified JSON\n if (typeof vData === 'string') {\n try {\n vData = JSON.parse(vData);\n } catch (e) { }\n }\n \n // Handle backend dictionaries indexed by session_id\n if (vData && typeof vData === 'object' && vData[state.session.session_id]) {\n let nested = vData[state.session.session_id];\n if (nested && nested.data) {\n nested = typeof nested.data === 'string' ? JSON.parse(nested.data) : nested.data;\n }\n vData = nested;\n }\n \n if (!vData || typeof vData !== 'object') {\n throw new Error('Verification payload missing or invalid for current session');\n }\n \n const vStatus = (vData.verification_status || vData.status || vData.state || '').toLowerCase();\n const vDecision = (vData.decision || vData.outcome || vData.result || '').toLowerCase();\n // const processingError = vData.reason || vData.error || vData.issues || vData.error_message;\n const selfieMatch = vData.selfie_info?.is_match; // true, false, or null\n \n logger.log(`Parsed Status: [${vStatus}], Decision: [${vDecision}], Selfie Match: [${selfieMatch}]`);\n \n // 4. Evaluate Failures First\n // 5. Evaluate Definitive Success\n if (\n vStatus === 'approved' || vStatus === 'verified' || vStatus === 'success' ||\n vDecision === 'approved' || vDecision === 'passed' || vDecision === 'clear' ||\n (vStatus === 'completed' && selfieMatch === true)\n ) {\n \n // 🚨 THE FIX: Prevent False Positives (Ghost Payloads)\n // If it says success, but the data object is completely empty, it is actually a failure.\n const hasActualData = vData && Object.keys(vData).length > 0;\n \n if (!hasActualData) {\n logger.warn('Backend returned success, but data payload is entirely empty.');\n actions.setVerificationState({\n status: 'failed',\n result: {\n referenceId: state.session.session_id,\n issues: ['Document text could not be read clearly. Please retake the photo in better lighting.']\n } as any\n });\n setIsRetrying(false);\n isPollingRef.current = false;\n return;\n }\n\n // If we have data, proceed to actual success\n actions.setVerificationState({\n status: 'success',\n result: {\n ...result,\n referenceId: vData.verification_id || vData.session_id || state.session.session_id\n } as any\n });\n setIsRetrying(false);\n isPollingRef.current = false;\n return;\n }\n \n if (\n vStatus === 'processing' || vStatus === 'pending' || vStatus === 'in_progress' ||\n vStatus === 'initiated' || (vStatus === 'completed' && selfieMatch === null) || !vStatus\n ) {\n if (currentRetryCount < maxRetries) {\n const nextRetryCount = currentRetryCount + 1;\n setRetryCount(nextRetryCount);\n setIsRetrying(true);\n \n logger.log(`Verification still processing, retrying in 3s... (${nextRetryCount}/${maxRetries})`);\n \n if (timeoutId) clearTimeout(timeoutId);\n const newTimeoutId = setTimeout(() => {\n getVerificationResult(nextRetryCount, maxRetries);\n }, 3000); \n \n setTimeoutId(newTimeoutId as any);\n } else {\n logger.error('Max retries reached, verification still processing');\n setIsRetrying(false);\n isPollingRef.current = false;\n actions.setVerificationState({\n status: 'failed',\n result: {\n referenceId: state.session.session_id,\n issues: ['Verification timed out. Please try again.']\n } as any\n });\n }\n return;\n }\n \n // Fallback release if status is completely unknown\n logger.warn(`Unknown verification status received: ${vStatus}`);\n setIsRetrying(false);\n isPollingRef.current = false;\n \n } catch (error: any) {\n logger.error('getVerificationResult error', JSON.stringify(errorMessage(error) || { message: error?.message || 'Unknown error' }, null, 2));\n \n if (currentRetryCount < maxRetries) {\n const nextRetryCount = currentRetryCount + 1;\n setRetryCount(nextRetryCount);\n setIsRetrying(true);\n \n logger.log(`getVerificationResult Error occurred, retrying in 3s... (${nextRetryCount}/${maxRetries})`);\n \n if (timeoutId) clearTimeout(timeoutId);\n const newTimeoutId = setTimeout(() => {\n getVerificationResult(nextRetryCount, maxRetries);\n }, 3000);\n \n setTimeoutId(newTimeoutId as any);\n } else {\n setIsRetrying(false);\n isPollingRef.current = false; // Release lock\n logger.error('Max retries reached after errors');\n }\n }\n };\n\n useEffect(() => {\n if (state.session.session_id && !isSuccess && !isFailed && !isPollingRef.current) {\n isPollingRef.current = true; // Lock the gate instantly\n getVerificationResult();\n }\n }, [state.session.session_id, isSuccess, isFailed]);\n\n useEffect(() => {\n return () => {\n if (timeoutId) clearTimeout(timeoutId);\n isPollingRef.current = false; // Reset lock on unmount\n };\n }, [timeoutId]);\n\n useEffect(() => {\n let autoSubmitTimer: ReturnType<typeof setTimeout>;\n if (isSuccess) {\n logger.log(\"Verification successful. Initiating auto-submit countdown...\");\n autoSubmitTimer = setTimeout(() => {\n actions.submitVerification();\n }, 3000);\n }\n return () => {\n if (autoSubmitTimer) clearTimeout(autoSubmitTimer);\n };\n }, [isSuccess, actions]);\n\n if (isSuccess) {\n return (\n <View style={styles.container}>\n <Text style={styles.title}>{t('kyc.verificationProgress.steps.complete')}</Text>\n <Text style={styles.subtitle}>{t('kyc.verificationProgress.subtitle')}</Text>\n <TouchableOpacity style={[styles.button, styles.primary]} onPress={() => actions.submitVerification()}>\n <Text style={styles.buttonText}>{t('common.continue')}</Text>\n </TouchableOpacity>\n {verification.result?.referenceId ? (\n <Text style={styles.refText}>{`Verification ID: ${verification.result.referenceId}`}</Text>\n ) : null}\n </View>\n );\n }\n\n if (isFailed) {\n return (\n <View style={styles.container}>\n <Text style={styles.title}>{t('kyc.verificationProgress.status.failed')}</Text>\n <View style={styles.issuesBox}>\n <Text style={styles.issuesTitle}>{t('common.error')}</Text>\n {Array.isArray(verification.result?.issues) && verification.result.issues.map((issue: string, idx: number) => (\n <Text key={idx} style={styles.issueItem}>• {issue}</Text>\n ))}\n </View>\n <TouchableOpacity style={[styles.button, styles.primary]} onPress={() => actions.submitVerification()}>\n <Text style={styles.buttonText}>\n {state.currentLanguage === 'en' ? 'OK / Finish' : 'Terminer'}\n </Text>\n </TouchableOpacity>\n <TouchableOpacity style={[styles.button, styles.secondary]} onPress={() => actions.resetTemplate()}>\n <Text style={styles.secondaryText}>\n {state.currentLanguage === 'en' ? 'Start Over' : 'Recommencer'}\n </Text>\n </TouchableOpacity>\n {verification.result?.referenceId ? (\n <Text style={styles.refText}>{`Reference ID: ${verification.result.referenceId}`}</Text>\n ) : null}\n </View>\n );\n }\n\n return (\n <View style={styles.container}>\n <Text style={styles.title}>{t('kyc.verificationProgress.title')}</Text>\n <Text style={styles.subtitle}>\n {isRetrying ? `${t('kyc.verificationProgress.retrying', { current: retryCount, max: 40 })}` : t('kyc.verificationProgress.estimatedTime')}\n </Text>\n\n <View style={styles.timeline}>\n <View style={[styles.dot, styles.done]}><Text style={styles.stepCheckmark}>✓</Text></View>\n <View style={styles.line} />\n <View style={[styles.dot, styles.active]}><Text style={styles.stepCheckmark}>2</Text></View>\n <View style={styles.line} />\n <View style={[styles.dot, styles.pending]}><Text style={styles.stepCheckmark}>3</Text></View>\n </View>\n\n <View style={styles.row}>\n <Text style={styles.stepLabel}>{t('kyc.verificationProgress.status.completed')}</Text>\n <Text style={styles.stepLabel}>{t('kyc.verificationProgress.steps.analyzing')}</Text>\n <Text style={styles.stepLabel}>{t('kyc.verificationProgress.steps.verifying')}</Text>\n </View>\n\n <View style={styles.card}>\n <Text style={styles.cardTitle}>{t('kyc.idCardCapture.title')}</Text>\n <Text style={styles.cardLine}>{t('kyc.verificationProgress.steps.extracting')}</Text>\n\n <Text style={styles.cardTitle}>{t('kyc.selfieCapture.title')}</Text>\n <Text style={styles.cardLine}>{t('kyc.verificationProgress.steps.analyzing')}</Text>\n\n <Text style={styles.cardTitle}>{t('kyc.verificationProgress.title')}</Text>\n <Text style={styles.cardLine}>\n {isRetrying ? `${t('kyc.verificationProgress.status.processing')}...` : t('kyc.verificationProgress.status.pending')}\n </Text>\n </View>\n </View>\n );\n};\n\nconst styles = StyleSheet.create({\n container: { flex: 1, width: '100%', paddingHorizontal: 16, paddingVertical: 12 },\n title: { fontSize: 24, fontWeight: 'bold', color: '#111827', textAlign: 'center', marginTop: 12 },\n subtitle: { fontSize: 14, color: '#6B7280', textAlign: 'center', marginTop: 8 },\n timeline: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginTop: 24 },\n dot: { width: 38, height: 38, borderRadius: 34, justifyContent: 'center', alignItems: 'center' },\n stepCheckmark: { color: 'white', fontSize: 16, fontWeight: 'bold' },\n line: { flex: 1, height: 4, backgroundColor: '#E5E7EB' },\n done: { backgroundColor: '#10B981' },\n active: { backgroundColor: '#F59E0B' },\n pending: { backgroundColor: '#E5E7EB' },\n row: { flexDirection: 'row', justifyContent: 'space-between', marginTop: 8 },\n stepLabel: { fontSize: 14, color: '#111827', fontWeight: '600' },\n card: { backgroundColor: 'white', padding: 16, borderRadius: 16, marginTop: 24 },\n cardTitle: { fontSize: 16, color: '#6B7280', marginTop: 8 },\n cardLine: { fontSize: 18, color: '#111827', fontWeight: '600', marginTop: 2 },\n button: { paddingVertical: 14, borderRadius: 10, alignItems: 'center', marginTop: 14 },\n primary: { backgroundColor: '#2DBD60' },\n buttonText: { color: 'white', fontSize: 16, fontWeight: '600' },\n refText: { marginTop: 12, textAlign: 'center', color: '#6B7280' },\n issuesBox: { backgroundColor: '#FEF2F2', borderRadius: 16, padding: 16, marginTop: 20 },\n issuesTitle: { color: '#991B1B', fontWeight: '700', marginBottom: 8 },\n issueItem: { color: '#991B1B', marginTop: 4 },\n secondary: { backgroundColor: '#F3F4F6', borderWidth: 1, borderColor: '#D1D5DB' },\n secondaryText: { color: '#374151', fontSize: 16, fontWeight: '600' },\n});"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../../../../src/components/OverLay/type.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,WAAW,kBAAkB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,WAAW,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IAC1C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAA;CACnB;AAGD,UAAU,YAAY;IAClB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACnC,WAAW,EAAE;QACT,QAAQ,EAAE,MAAM,CAAC;QACjB,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,eAAe,EAAE,MAAM,CAAC;QACxB,0BAA0B,EAAE,MAAM,CAAC;QACnC,gBAAgB,EAAE,MAAM,CAAC;QACzB,UAAU,EAAE,MAAM,CAAC;QACnB,GAAG,EAAE,MAAM,CAAC;QACZ,WAAW,EAAE,MAAM,CAAC;QACpB,aAAa,EAAE,MAAM,CAAC;QACtB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,OAAO,EAAE,OAAO,CAAC;CACpB;AAID,MAAM,WAAW,uBAAuB;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC9B,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAClF,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../../../../src/components/OverLay/type.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type.js","sourceRoot":"","sources":["../../../../src/components/OverLay/type.ts"],"names":[],"mappings":"","sourcesContent":["import { ViewStyle } from \"react-native\";\nimport { ISilentCaptureResult } from \"../../types/KYC.types\";\n\nexport interface IdCardOverlayProps {\n xMin: number;\n yMin: number;\n xMax: number;\n yMax: number;\n cornerOpacity: number;\n instructions: string;\n cornerColor?: string;\n stepperProps?: StepperProps;\n instructionsTile?: string;\n instructionsSubtitle?: string;\n orientation?: 'center' | 'left' | 'right';\n isAnalyzing?: boolean;\n isSuccess?: boolean;\n language: string\n}\n\n\ninterface StepperProps {\n back: () => void;\n selectedDocumentType: string;\n step: number;\n totalSteps: number;\n side: string;\n}\n\nexport interface ExtractMrzTextResponse {\n parsed_data: {\n mrz_type: string;\n document_code: string;\n issuer_code: string;\n surname: string;\n given_name: string;\n document_number: string;\n document_number_checkdigit: string;\n nationality_code: string;\n birth_date: string;\n sex: string;\n expiry_date: string;\n optional_data: string;\n mrz_text: string;\n status: string;\n },\n success: boolean;\n}\n\n\n\nexport interface EnhancedCameraViewProps {\n instructions?: string;\n showCamera: boolean;\n cameraType?: 'front' | 'back';\n style?: ViewStyle;\n onCapture?: (result: { success: boolean; path?: string; error?: string }) => void;\n onSilentCapture?: (result: { success: boolean; path?: string; error?: string }) => void;\n silentCaptureResult?: ISilentCaptureResult;\n onError?: (event: { message: string }) => void;\n onClose?: () => void;\n enableFlash?: boolean;\n enableHdr?: boolean;\n quality?: 'low' | 'medium' | 'high';\n showCaptureButton?: boolean;\n showSwitchCamera?: boolean;\n overlayComponent?: React.ReactNode;\n isProcessing?: boolean; \n bbox?: {\n xMin: number;\n yMin: number;\n xMax: number;\n yMax: number;\n borderColor?: string;\n borderWidth?: number;\n cornerRadius?: number;\n };\n canFlip?: boolean;\n // Video recording props\n enableVideo?: boolean;\n isRecording?: boolean;\n onVideoRecordingStart?: () => void;\n onVideoRecordingStop?: (result: { success: boolean; path?: string; error?: string }) => void;\n videoDuration?: number;\n /** Delay in ms before first auto-capture (lets camera focus and user position document). Recommended 2500–3000 for ID/document capture. */\n captureStabilizationDelayMs?: number;\n}\n\nexport interface CheckTemplateTypeResponse {\n template_path: string;\n lpips_score: number;\n}"]}
|
|
1
|
+
{"version":3,"file":"type.js","sourceRoot":"","sources":["../../../../src/components/OverLay/type.ts"],"names":[],"mappings":"","sourcesContent":["import { ViewStyle } from \"react-native\";\nimport { ISilentCaptureResult } from \"../../types/KYC.types\";\n\nexport interface IdCardOverlayProps {\n xMin: number;\n yMin: number;\n xMax: number;\n yMax: number;\n cornerOpacity: number;\n instructions: string;\n cornerColor?: string;\n stepperProps?: StepperProps;\n instructionsTile?: string;\n instructionsSubtitle?: string;\n orientation?: 'center' | 'left' | 'right';\n isAnalyzing?: boolean;\n isSuccess?: boolean;\n language: string\n}\n\n\ninterface StepperProps {\n back: () => void;\n selectedDocumentType: string;\n step: number;\n totalSteps: number;\n side: string;\n}\n\nexport interface ExtractMrzTextResponse {\n parsed_data: {\n mrz_type: string;\n document_code: string;\n issuer_code: string;\n surname: string;\n given_name: string;\n document_number: string;\n document_number_checkdigit: string;\n nationality_code: string;\n birth_date: string;\n sex: string;\n expiry_date: string;\n optional_data: string;\n mrz_text: string;\n status: string;\n },\n success: boolean;\n}\n\n\n\nexport interface EnhancedCameraViewProps {\n instructions?: string;\n showCamera: boolean;\n cameraType?: 'front' | 'back';\n style?: ViewStyle;\n onCapture?: (result: { success: boolean; path?: string; error?: string }) => void;\n onSilentCapture?: (result: { success: boolean; path?: string; error?: string; barcode:unknown }) => void;\n silentCaptureResult?: ISilentCaptureResult;\n onError?: (event: { message: string }) => void;\n onClose?: () => void;\n enableFlash?: boolean;\n enableHdr?: boolean;\n quality?: 'low' | 'medium' | 'high';\n showCaptureButton?: boolean;\n showSwitchCamera?: boolean;\n overlayComponent?: React.ReactNode;\n isProcessing?: boolean; \n bbox?: {\n xMin: number;\n yMin: number;\n xMax: number;\n yMax: number;\n borderColor?: string;\n borderWidth?: number;\n cornerRadius?: number;\n };\n canFlip?: boolean;\n // Video recording props\n enableVideo?: boolean;\n isRecording?: boolean;\n onVideoRecordingStart?: () => void;\n onVideoRecordingStop?: (result: { success: boolean; path?: string; error?: string }) => void;\n videoDuration?: number;\n /** Delay in ms before first auto-capture (lets camera focus and user position document). Recommended 2500–3000 for ID/document capture. */\n captureStabilizationDelayMs?: number;\n}\n\nexport interface CheckTemplateTypeResponse {\n template_path: string;\n lpips_score: number;\n}"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface WebBarcodeScannerProps {
|
|
3
|
+
videoRef: React.RefObject<HTMLVideoElement | null>;
|
|
4
|
+
active: boolean;
|
|
5
|
+
onBarcodeScanned: (value: string) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare const WebBarcodeScanner: React.FC<WebBarcodeScannerProps>;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=WebBarcodeScanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebBarcodeScanner.d.ts","sourceRoot":"","sources":["../../../src/components/WebBarcodeScanner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyC,MAAM,OAAO,CAAC;AAW9D,UAAU,sBAAsB;IAC9B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACnD,MAAM,EAAE,OAAO,CAAC;IAChB,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AAED,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CA+P9D,CAAC"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
2
|
+
import { MultiFormatReader, BarcodeFormat, DecodeHintType, HTMLCanvasElementLuminanceSource, BinaryBitmap, HybridBinarizer, GlobalHistogramBinarizer, } from '@zxing/library';
|
|
3
|
+
export const WebBarcodeScanner = ({ videoRef, active, onBarcodeScanned, }) => {
|
|
4
|
+
const readerRef = useRef(null);
|
|
5
|
+
const canvasRef = useRef(null);
|
|
6
|
+
const lastValueRef = useRef(null);
|
|
7
|
+
const stoppedRef = useRef(false);
|
|
8
|
+
const callbackRef = useRef(onBarcodeScanned);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
callbackRef.current = onBarcodeScanned;
|
|
11
|
+
}, [onBarcodeScanned]);
|
|
12
|
+
const decodeBitmap = useCallback((canvas) => {
|
|
13
|
+
if (!readerRef.current) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
const source = new HTMLCanvasElementLuminanceSource(canvas);
|
|
17
|
+
const attempts = [
|
|
18
|
+
new BinaryBitmap(new HybridBinarizer(source)),
|
|
19
|
+
new BinaryBitmap(new GlobalHistogramBinarizer(source)),
|
|
20
|
+
];
|
|
21
|
+
for (const bitmap of attempts) {
|
|
22
|
+
try {
|
|
23
|
+
const result = readerRef.current.decodeWithState(bitmap);
|
|
24
|
+
if (result?.getText()) {
|
|
25
|
+
return result.getText();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// continue
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}, []);
|
|
34
|
+
const drawROI = useCallback((video, canvas) => {
|
|
35
|
+
const ctx = canvas.getContext('2d', {
|
|
36
|
+
willReadFrequently: true,
|
|
37
|
+
});
|
|
38
|
+
if (!ctx) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
const roi = 0.8;
|
|
42
|
+
const sw = Math.floor(video.videoWidth * roi);
|
|
43
|
+
const sh = Math.floor(video.videoHeight * roi);
|
|
44
|
+
const sx = Math.floor((video.videoWidth - sw) / 2);
|
|
45
|
+
const sy = Math.floor((video.videoHeight - sh) / 2);
|
|
46
|
+
if (canvas.width !== sw ||
|
|
47
|
+
canvas.height !== sh) {
|
|
48
|
+
canvas.width = sw;
|
|
49
|
+
canvas.height = sh;
|
|
50
|
+
}
|
|
51
|
+
ctx.drawImage(video, sx, sy, sw, sh, 0, 0, sw, sh);
|
|
52
|
+
return true;
|
|
53
|
+
}, []);
|
|
54
|
+
// Add a persistent rotation canvas ref at the top
|
|
55
|
+
const rotationCanvasRef = useRef(null);
|
|
56
|
+
// Update rotateCanvas to re-use the persistent canvas
|
|
57
|
+
const rotateCanvas = useCallback((sourceCanvas, degrees) => {
|
|
58
|
+
if (!rotationCanvasRef.current) {
|
|
59
|
+
rotationCanvasRef.current = document.createElement('canvas');
|
|
60
|
+
}
|
|
61
|
+
const rotated = rotationCanvasRef.current;
|
|
62
|
+
const ctx = rotated.getContext('2d');
|
|
63
|
+
if (!ctx)
|
|
64
|
+
return null;
|
|
65
|
+
const radians = (degrees * Math.PI) / 180;
|
|
66
|
+
if (degrees === 90 || degrees === -90) {
|
|
67
|
+
rotated.width = sourceCanvas.height;
|
|
68
|
+
rotated.height = sourceCanvas.width;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
rotated.width = sourceCanvas.width;
|
|
72
|
+
rotated.height = sourceCanvas.height;
|
|
73
|
+
}
|
|
74
|
+
ctx.clearRect(0, 0, rotated.width, rotated.height);
|
|
75
|
+
ctx.translate(rotated.width / 2, rotated.height / 2);
|
|
76
|
+
ctx.rotate(radians);
|
|
77
|
+
ctx.drawImage(sourceCanvas, -sourceCanvas.width / 2, -sourceCanvas.height / 2);
|
|
78
|
+
return rotated;
|
|
79
|
+
}, []);
|
|
80
|
+
const tryDecode = useCallback(() => {
|
|
81
|
+
const video = videoRef.current;
|
|
82
|
+
const canvas = canvasRef.current;
|
|
83
|
+
if (!video ||
|
|
84
|
+
!canvas ||
|
|
85
|
+
video.readyState < 2) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
const ok = drawROI(video, canvas);
|
|
89
|
+
if (!ok) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
let value = decodeBitmap(canvas);
|
|
93
|
+
if (value) {
|
|
94
|
+
return value;
|
|
95
|
+
}
|
|
96
|
+
const rotations = [90, -90, 180];
|
|
97
|
+
for (const rotation of rotations) {
|
|
98
|
+
const rotated = rotateCanvas(canvas, rotation);
|
|
99
|
+
if (!rotated) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
value = decodeBitmap(rotated);
|
|
103
|
+
if (value) {
|
|
104
|
+
return value;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}, [
|
|
109
|
+
videoRef,
|
|
110
|
+
drawROI,
|
|
111
|
+
decodeBitmap,
|
|
112
|
+
rotateCanvas,
|
|
113
|
+
]);
|
|
114
|
+
const tick = useCallback(() => {
|
|
115
|
+
if (stoppedRef.current)
|
|
116
|
+
return;
|
|
117
|
+
const value = tryDecode();
|
|
118
|
+
if (value && value !== lastValueRef.current) {
|
|
119
|
+
lastValueRef.current = value;
|
|
120
|
+
callbackRef.current(value);
|
|
121
|
+
// If you want it to stop scanning on success, leave 'return;'
|
|
122
|
+
// but ensure your parent component handles unmounting the scanner!
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
setTimeout(tick, 100);
|
|
126
|
+
}, [tryDecode]);
|
|
127
|
+
useEffect(() => {
|
|
128
|
+
if (!active) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
stoppedRef.current = false;
|
|
132
|
+
lastValueRef.current = null;
|
|
133
|
+
if (!canvasRef.current) {
|
|
134
|
+
canvasRef.current =
|
|
135
|
+
document.createElement('canvas');
|
|
136
|
+
}
|
|
137
|
+
const hints = new Map();
|
|
138
|
+
hints.set(DecodeHintType.POSSIBLE_FORMATS, [BarcodeFormat.PDF_417]);
|
|
139
|
+
hints.set(DecodeHintType.TRY_HARDER, true);
|
|
140
|
+
const reader = new MultiFormatReader();
|
|
141
|
+
reader.setHints(hints);
|
|
142
|
+
readerRef.current = reader;
|
|
143
|
+
tick();
|
|
144
|
+
return () => {
|
|
145
|
+
stoppedRef.current = true;
|
|
146
|
+
readerRef.current?.reset();
|
|
147
|
+
readerRef.current = null;
|
|
148
|
+
};
|
|
149
|
+
}, [active, tick]);
|
|
150
|
+
return null;
|
|
151
|
+
};
|
|
152
|
+
//# sourceMappingURL=WebBarcodeScanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebBarcodeScanner.js","sourceRoot":"","sources":["../../../src/components/WebBarcodeScanner.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useCallback, useEffect, useRef } from 'react';\nimport {\n MultiFormatReader,\n BarcodeFormat,\n DecodeHintType,\n HTMLCanvasElementLuminanceSource,\n BinaryBitmap,\n HybridBinarizer,\n GlobalHistogramBinarizer,\n} from '@zxing/library';\n\ninterface WebBarcodeScannerProps {\n videoRef: React.RefObject<HTMLVideoElement | null>;\n active: boolean;\n onBarcodeScanned: (value: string) => void;\n}\n\nexport const WebBarcodeScanner: React.FC<WebBarcodeScannerProps> = ({\n videoRef,\n active,\n onBarcodeScanned,\n}) => {\n const readerRef = useRef<MultiFormatReader | null>(null);\n\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n\n const lastValueRef = useRef<string | null>(null);\n\n const stoppedRef = useRef(false);\n\n const callbackRef = useRef(onBarcodeScanned);\n\n useEffect(() => {\n callbackRef.current = onBarcodeScanned;\n }, [onBarcodeScanned]);\n\n const decodeBitmap = useCallback(\n (canvas: HTMLCanvasElement) => {\n if (!readerRef.current) {\n return null;\n }\n\n const source = new HTMLCanvasElementLuminanceSource(canvas);\n\n const attempts = [\n new BinaryBitmap(\n new HybridBinarizer(source)\n ),\n new BinaryBitmap(\n new GlobalHistogramBinarizer(source)\n ),\n ];\n\n for (const bitmap of attempts) {\n try {\n const result =\n readerRef.current.decodeWithState(bitmap);\n\n if (result?.getText()) {\n return result.getText();\n }\n } catch {\n // continue\n }\n }\n\n return null;\n },\n []\n );\n\n const drawROI = useCallback(\n (\n video: HTMLVideoElement,\n canvas: HTMLCanvasElement\n ) => {\n const ctx = canvas.getContext('2d', {\n willReadFrequently: true,\n });\n\n if (!ctx) {\n return false;\n }\n\n const roi = 0.8;\n\n const sw = Math.floor(\n video.videoWidth * roi\n );\n\n const sh = Math.floor(\n video.videoHeight * roi\n );\n\n const sx = Math.floor(\n (video.videoWidth - sw) / 2\n );\n\n const sy = Math.floor(\n (video.videoHeight - sh) / 2\n );\n\n if (\n canvas.width !== sw ||\n canvas.height !== sh\n ) {\n canvas.width = sw;\n canvas.height = sh;\n }\n\n ctx.drawImage(\n video,\n sx,\n sy,\n sw,\n sh,\n 0,\n 0,\n sw,\n sh\n );\n\n return true;\n },\n []\n );\n\n // Add a persistent rotation canvas ref at the top\nconst rotationCanvasRef = useRef<HTMLCanvasElement | null>(null);\n\n// Update rotateCanvas to re-use the persistent canvas\nconst rotateCanvas = useCallback(\n (sourceCanvas: HTMLCanvasElement, degrees: number) => {\n if (!rotationCanvasRef.current) {\n rotationCanvasRef.current = document.createElement('canvas');\n }\n const rotated = rotationCanvasRef.current;\n const ctx = rotated.getContext('2d');\n if (!ctx) return null;\n\n const radians = (degrees * Math.PI) / 180;\n if (degrees === 90 || degrees === -90) {\n rotated.width = sourceCanvas.height;\n rotated.height = sourceCanvas.width;\n } else {\n rotated.width = sourceCanvas.width;\n rotated.height = sourceCanvas.height;\n }\n\n ctx.clearRect(0, 0, rotated.width, rotated.height);\n ctx.translate(rotated.width / 2, rotated.height / 2);\n ctx.rotate(radians);\n ctx.drawImage(sourceCanvas, -sourceCanvas.width / 2, -sourceCanvas.height / 2);\n return rotated;\n },\n []\n);\n\n\n\n const tryDecode = useCallback(() => {\n const video = videoRef.current;\n\n const canvas = canvasRef.current;\n\n if (\n !video ||\n !canvas ||\n video.readyState < 2\n ) {\n return null;\n }\n\n const ok = drawROI(video, canvas);\n\n if (!ok) {\n return null;\n }\n\n let value = decodeBitmap(canvas);\n\n if (value) {\n return value;\n }\n\n const rotations = [90, -90, 180];\n\n for (const rotation of rotations) {\n const rotated = rotateCanvas(\n canvas,\n rotation\n );\n\n if (!rotated) {\n continue;\n }\n\n value = decodeBitmap(rotated);\n\n if (value) {\n return value;\n }\n }\n\n return null;\n }, [\n videoRef,\n drawROI,\n decodeBitmap,\n rotateCanvas,\n ]);\n\nconst tick = useCallback(() => {\n if (stoppedRef.current) return;\n \n const value = tryDecode();\n if (value && value !== lastValueRef.current) {\n lastValueRef.current = value;\n callbackRef.current(value);\n // If you want it to stop scanning on success, leave 'return;' \n // but ensure your parent component handles unmounting the scanner!\n return; \n }\n \n setTimeout(tick, 100);\n }, [tryDecode]);\n\n useEffect(() => {\n if (!active) {\n return;\n }\n\n stoppedRef.current = false;\n\n lastValueRef.current = null;\n\n if (!canvasRef.current) {\n canvasRef.current =\n document.createElement('canvas');\n }\n\n const hints = new Map();\n\n hints.set(\n DecodeHintType.POSSIBLE_FORMATS,\n [BarcodeFormat.PDF_417]\n );\n\n hints.set(\n DecodeHintType.TRY_HARDER,\n true\n );\n\n const reader =\n new MultiFormatReader();\n\n reader.setHints(hints);\n\n readerRef.current = reader;\n\n tick();\n\n return () => {\n stoppedRef.current = true;\n\n readerRef.current?.reset();\n\n readerRef.current = null;\n };\n }, [active, tick]);\n\n return null;\n};"]}
|