@sanctum-key/react-native-sdk 1.0.44 → 1.0.46
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/VerificationProgressTemplate.d.ts.map +1 -1
- package/build/src/components/KYCElements/VerificationProgressTemplate.js +81 -56
- package/build/src/components/KYCElements/VerificationProgressTemplate.js.map +1 -1
- package/package.json +1 -1
- package/src/components/KYCElements/VerificationProgressTemplate.tsx +107 -93
package/build/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VerificationProgressTemplate.d.ts","sourceRoot":"","sources":["../../../../src/components/KYCElements/VerificationProgressTemplate.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAE3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAM1D,UAAU,iCAAiC;IACzC,SAAS,EAAE,iBAAiB,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;
|
|
1
|
+
{"version":3,"file":"VerificationProgressTemplate.d.ts","sourceRoot":"","sources":["../../../../src/components/KYCElements/VerificationProgressTemplate.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAE3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAM1D,UAAU,iCAAiC;IACzC,SAAS,EAAE,iBAAiB,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAID,eAAO,MAAM,4BAA4B,EAAE,KAAK,CAAC,EAAE,CAAC,iCAAiC,CAuRpF,CAAC"}
|
|
@@ -4,19 +4,25 @@ import { useTemplateKYCFlowContext } from '../../hooks/useTemplateKYCFlow';
|
|
|
4
4
|
import { useI18n } from '../../hooks/useI18n';
|
|
5
5
|
import kycService, { errorMessage } from '../../modules/api/KYCService';
|
|
6
6
|
import { logger } from '../../utils/logger';
|
|
7
|
+
const MAX_RETRIES = 40; // 40 attempts * 3 seconds = exactly 2 minutes of polling
|
|
7
8
|
export const VerificationProgressTemplate = () => {
|
|
8
9
|
const { t } = useI18n();
|
|
9
10
|
const { state, actions } = useTemplateKYCFlowContext();
|
|
10
11
|
const [retryCount, setRetryCount] = useState(0);
|
|
11
12
|
const [isRetrying, setIsRetrying] = useState(false);
|
|
12
|
-
|
|
13
|
+
// 🚨 BULLETPROOF REFS: Prevents memory leaks and duplicate polling loops
|
|
14
|
+
const timeoutIdRef = useRef(null);
|
|
13
15
|
const isPollingRef = useRef(false);
|
|
16
|
+
const isMountedRef = useRef(true);
|
|
14
17
|
const verification = state.verification;
|
|
15
18
|
const isSuccess = verification.status === 'success';
|
|
16
19
|
const isFailed = verification.status === 'failed';
|
|
17
|
-
const getVerificationResult = async (currentRetryCount = 0
|
|
20
|
+
const getVerificationResult = async (currentRetryCount = 0) => {
|
|
21
|
+
// If component unmounted while waiting, stop everything
|
|
22
|
+
if (!isMountedRef.current)
|
|
23
|
+
return;
|
|
18
24
|
try {
|
|
19
|
-
logger.log(`Starting verification check (attempt ${currentRetryCount + 1}/${
|
|
25
|
+
logger.log(`Starting verification check (attempt ${currentRetryCount + 1}/${MAX_RETRIES})`);
|
|
20
26
|
const result = await kycService.getVerificationResult(state.session.session_id);
|
|
21
27
|
logger.log('getVerificationResult raw result:', JSON.stringify(result, null, 2));
|
|
22
28
|
const rootStatus = (result?.status || '').toLowerCase();
|
|
@@ -28,20 +34,19 @@ export const VerificationProgressTemplate = () => {
|
|
|
28
34
|
issues: [result?.message || result?.reason || 'Verification failed. Sent for manual review.']
|
|
29
35
|
}
|
|
30
36
|
});
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
if (isMountedRef.current)
|
|
38
|
+
setIsRetrying(false);
|
|
39
|
+
isPollingRef.current = false;
|
|
33
40
|
return;
|
|
34
41
|
}
|
|
35
42
|
// 2. Safely Extract Nested Payload
|
|
36
|
-
let vData = result?.data || result;
|
|
37
|
-
// Handle stringified JSON
|
|
43
|
+
let vData = result?.data || result;
|
|
38
44
|
if (typeof vData === 'string') {
|
|
39
45
|
try {
|
|
40
46
|
vData = JSON.parse(vData);
|
|
41
47
|
}
|
|
42
48
|
catch (e) { }
|
|
43
49
|
}
|
|
44
|
-
// Handle backend dictionaries indexed by session_id
|
|
45
50
|
if (vData && typeof vData === 'object' && vData[state.session.session_id]) {
|
|
46
51
|
let nested = vData[state.session.session_id];
|
|
47
52
|
if (nested && nested.data) {
|
|
@@ -54,19 +59,14 @@ export const VerificationProgressTemplate = () => {
|
|
|
54
59
|
}
|
|
55
60
|
const vStatus = (vData.verification_status || vData.status || vData.state || '').toLowerCase();
|
|
56
61
|
const vDecision = (vData.decision || vData.outcome || vData.result || '').toLowerCase();
|
|
57
|
-
|
|
58
|
-
const selfieMatch = vData.selfie_info?.is_match; // true, false, or null
|
|
62
|
+
const selfieMatch = vData.selfie_info?.is_match;
|
|
59
63
|
logger.log(`Parsed Status: [${vStatus}], Decision: [${vDecision}], Selfie Match: [${selfieMatch}]`);
|
|
60
|
-
//
|
|
61
|
-
// 5. Evaluate Definitive Success
|
|
64
|
+
// SUCCESS CONDITION
|
|
62
65
|
if (vStatus === 'approved' || vStatus === 'verified' || vStatus === 'success' ||
|
|
63
66
|
vDecision === 'approved' || vDecision === 'passed' || vDecision === 'clear' ||
|
|
64
67
|
(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
68
|
const hasActualData = vData && Object.keys(vData).length > 0;
|
|
68
69
|
if (!hasActualData) {
|
|
69
|
-
logger.warn('Backend returned success, but data payload is entirely empty.');
|
|
70
70
|
actions.setVerificationState({
|
|
71
71
|
status: 'failed',
|
|
72
72
|
result: {
|
|
@@ -74,89 +74,105 @@ export const VerificationProgressTemplate = () => {
|
|
|
74
74
|
issues: ['Document text could not be read clearly. Please retake the photo in better lighting.']
|
|
75
75
|
}
|
|
76
76
|
});
|
|
77
|
-
|
|
77
|
+
if (isMountedRef.current)
|
|
78
|
+
setIsRetrying(false);
|
|
78
79
|
isPollingRef.current = false;
|
|
79
80
|
return;
|
|
80
81
|
}
|
|
81
|
-
// If we have data, proceed to actual success
|
|
82
82
|
actions.setVerificationState({
|
|
83
83
|
status: 'success',
|
|
84
|
-
result: {
|
|
85
|
-
...result,
|
|
86
|
-
referenceId: vData.verification_id || vData.session_id || state.session.session_id
|
|
87
|
-
}
|
|
84
|
+
result: { ...result, referenceId: vData.verification_id || vData.session_id || state.session.session_id }
|
|
88
85
|
});
|
|
89
|
-
|
|
86
|
+
if (isMountedRef.current)
|
|
87
|
+
setIsRetrying(false);
|
|
90
88
|
isPollingRef.current = false;
|
|
91
89
|
return;
|
|
92
90
|
}
|
|
91
|
+
// PENDING/PROCESSING CONDITION
|
|
93
92
|
if (vStatus === 'processing' || vStatus === 'pending' || vStatus === 'in_progress' ||
|
|
94
93
|
vStatus === 'initiated' || (vStatus === 'completed' && selfieMatch === null) || !vStatus) {
|
|
95
|
-
if (currentRetryCount <
|
|
94
|
+
if (currentRetryCount < MAX_RETRIES) {
|
|
96
95
|
const nextRetryCount = currentRetryCount + 1;
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
96
|
+
if (isMountedRef.current) {
|
|
97
|
+
setRetryCount(nextRetryCount);
|
|
98
|
+
setIsRetrying(true);
|
|
99
|
+
}
|
|
100
|
+
logger.log(`Verification still processing, retrying in 3s... (${nextRetryCount}/${MAX_RETRIES})`);
|
|
101
|
+
if (timeoutIdRef.current)
|
|
102
|
+
clearTimeout(timeoutIdRef.current);
|
|
103
|
+
timeoutIdRef.current = setTimeout(() => {
|
|
104
|
+
getVerificationResult(nextRetryCount);
|
|
104
105
|
}, 3000);
|
|
105
|
-
setTimeoutId(newTimeoutId);
|
|
106
106
|
}
|
|
107
107
|
else {
|
|
108
108
|
logger.error('Max retries reached, verification still processing');
|
|
109
|
-
setIsRetrying(false);
|
|
110
|
-
isPollingRef.current = false;
|
|
111
109
|
actions.setVerificationState({
|
|
112
110
|
status: 'failed',
|
|
113
111
|
result: {
|
|
114
112
|
referenceId: state.session.session_id,
|
|
115
|
-
issues: ['Verification timed out. Please try again.']
|
|
113
|
+
issues: ['Verification timed out after maximum attempts. Please try again.']
|
|
116
114
|
}
|
|
117
115
|
});
|
|
116
|
+
if (isMountedRef.current)
|
|
117
|
+
setIsRetrying(false);
|
|
118
|
+
isPollingRef.current = false;
|
|
118
119
|
}
|
|
119
120
|
return;
|
|
120
121
|
}
|
|
121
|
-
//
|
|
122
|
+
// UNKNOWN FALLBACK
|
|
122
123
|
logger.warn(`Unknown verification status received: ${vStatus}`);
|
|
123
|
-
|
|
124
|
+
if (isMountedRef.current)
|
|
125
|
+
setIsRetrying(false);
|
|
124
126
|
isPollingRef.current = false;
|
|
125
127
|
}
|
|
126
128
|
catch (error) {
|
|
127
129
|
logger.error('getVerificationResult error', JSON.stringify(errorMessage(error) || { message: error?.message || 'Unknown error' }, null, 2));
|
|
128
|
-
if (currentRetryCount <
|
|
130
|
+
if (currentRetryCount < MAX_RETRIES) {
|
|
129
131
|
const nextRetryCount = currentRetryCount + 1;
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
132
|
+
if (isMountedRef.current) {
|
|
133
|
+
setRetryCount(nextRetryCount);
|
|
134
|
+
setIsRetrying(true);
|
|
135
|
+
}
|
|
136
|
+
logger.log(`Error occurred, retrying in 3s... (${nextRetryCount}/${MAX_RETRIES})`);
|
|
137
|
+
if (timeoutIdRef.current)
|
|
138
|
+
clearTimeout(timeoutIdRef.current);
|
|
139
|
+
timeoutIdRef.current = setTimeout(() => {
|
|
140
|
+
getVerificationResult(nextRetryCount);
|
|
137
141
|
}, 3000);
|
|
138
|
-
setTimeoutId(newTimeoutId);
|
|
139
142
|
}
|
|
140
143
|
else {
|
|
141
|
-
setIsRetrying(false);
|
|
142
|
-
isPollingRef.current = false; // Release lock
|
|
143
144
|
logger.error('Max retries reached after errors');
|
|
145
|
+
actions.setVerificationState({
|
|
146
|
+
status: 'failed',
|
|
147
|
+
result: {
|
|
148
|
+
referenceId: state.session.session_id,
|
|
149
|
+
issues: ['Connection failed multiple times. Please check your network and try again.']
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
if (isMountedRef.current)
|
|
153
|
+
setIsRetrying(false);
|
|
154
|
+
isPollingRef.current = false;
|
|
144
155
|
}
|
|
145
156
|
}
|
|
146
157
|
};
|
|
158
|
+
// 1. Kick off polling when component mounts
|
|
147
159
|
useEffect(() => {
|
|
160
|
+
isMountedRef.current = true;
|
|
148
161
|
if (state.session.session_id && !isSuccess && !isFailed && !isPollingRef.current) {
|
|
149
|
-
isPollingRef.current = true;
|
|
150
|
-
getVerificationResult();
|
|
162
|
+
isPollingRef.current = true;
|
|
163
|
+
getVerificationResult(0); // Always start explicitly at 0
|
|
151
164
|
}
|
|
152
165
|
}, [state.session.session_id, isSuccess, isFailed]);
|
|
166
|
+
// 2. Strict cleanup on unmount ONLY
|
|
153
167
|
useEffect(() => {
|
|
154
168
|
return () => {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
169
|
+
isMountedRef.current = false;
|
|
170
|
+
if (timeoutIdRef.current)
|
|
171
|
+
clearTimeout(timeoutIdRef.current);
|
|
172
|
+
isPollingRef.current = false;
|
|
158
173
|
};
|
|
159
|
-
}, [
|
|
174
|
+
}, []);
|
|
175
|
+
// 3. Auto-submit on success
|
|
160
176
|
useEffect(() => {
|
|
161
177
|
let autoSubmitTimer;
|
|
162
178
|
if (isSuccess) {
|
|
@@ -170,40 +186,49 @@ export const VerificationProgressTemplate = () => {
|
|
|
170
186
|
clearTimeout(autoSubmitTimer);
|
|
171
187
|
};
|
|
172
188
|
}, [isSuccess, actions]);
|
|
189
|
+
// --- RENDER LOGIC ---
|
|
173
190
|
if (isSuccess) {
|
|
174
191
|
return (<View style={styles.container}>
|
|
175
192
|
<Text style={styles.title}>{t('kyc.verificationProgress.steps.complete')}</Text>
|
|
176
193
|
<Text style={styles.subtitle}>{t('kyc.verificationProgress.subtitle')}</Text>
|
|
194
|
+
|
|
177
195
|
<TouchableOpacity style={[styles.button, styles.primary]} onPress={() => actions.submitVerification()}>
|
|
178
196
|
<Text style={styles.buttonText}>{t('common.continue')}</Text>
|
|
179
197
|
</TouchableOpacity>
|
|
198
|
+
|
|
180
199
|
{verification.result?.referenceId ? (<Text style={styles.refText}>{`Verification ID: ${verification.result.referenceId}`}</Text>) : null}
|
|
181
200
|
</View>);
|
|
182
201
|
}
|
|
183
202
|
if (isFailed) {
|
|
184
203
|
return (<View style={styles.container}>
|
|
185
204
|
<Text style={styles.title}>{t('kyc.verificationProgress.status.failed')}</Text>
|
|
205
|
+
|
|
186
206
|
<View style={styles.issuesBox}>
|
|
187
207
|
<Text style={styles.issuesTitle}>{t('common.error')}</Text>
|
|
188
208
|
{Array.isArray(verification.result?.issues) && verification.result.issues.map((issue, idx) => (<Text key={idx} style={styles.issueItem}>• {issue}</Text>))}
|
|
189
209
|
</View>
|
|
210
|
+
|
|
190
211
|
<TouchableOpacity style={[styles.button, styles.primary]} onPress={() => actions.submitVerification()}>
|
|
191
212
|
<Text style={styles.buttonText}>
|
|
192
213
|
{state.currentLanguage === 'en' ? 'OK / Finish' : 'Terminer'}
|
|
193
214
|
</Text>
|
|
194
215
|
</TouchableOpacity>
|
|
216
|
+
|
|
195
217
|
<TouchableOpacity style={[styles.button, styles.secondary]} onPress={() => actions.resetTemplate()}>
|
|
196
218
|
<Text style={styles.secondaryText}>
|
|
197
219
|
{state.currentLanguage === 'en' ? 'Start Over' : 'Recommencer'}
|
|
198
220
|
</Text>
|
|
199
221
|
</TouchableOpacity>
|
|
222
|
+
|
|
200
223
|
{verification.result?.referenceId ? (<Text style={styles.refText}>{`Reference ID: ${verification.result.referenceId}`}</Text>) : null}
|
|
201
224
|
</View>);
|
|
202
225
|
}
|
|
203
226
|
return (<View style={styles.container}>
|
|
204
227
|
<Text style={styles.title}>{t('kyc.verificationProgress.title')}</Text>
|
|
205
228
|
<Text style={styles.subtitle}>
|
|
206
|
-
{isRetrying
|
|
229
|
+
{isRetrying
|
|
230
|
+
? `${t('kyc.verificationProgress.retrying', { current: retryCount, max: MAX_RETRIES })}`
|
|
231
|
+
: t('kyc.verificationProgress.estimatedTime')}
|
|
207
232
|
</Text>
|
|
208
233
|
|
|
209
234
|
<View style={styles.timeline}>
|
|
@@ -223,10 +248,10 @@ export const VerificationProgressTemplate = () => {
|
|
|
223
248
|
<View style={styles.card}>
|
|
224
249
|
<Text style={styles.cardTitle}>{t('kyc.idCardCapture.title')}</Text>
|
|
225
250
|
<Text style={styles.cardLine}>{t('kyc.verificationProgress.steps.extracting')}</Text>
|
|
226
|
-
|
|
251
|
+
|
|
227
252
|
<Text style={styles.cardTitle}>{t('kyc.selfieCapture.title')}</Text>
|
|
228
253
|
<Text style={styles.cardLine}>{t('kyc.verificationProgress.steps.analyzing')}</Text>
|
|
229
|
-
|
|
254
|
+
|
|
230
255
|
<Text style={styles.cardTitle}>{t('kyc.verificationProgress.title')}</Text>
|
|
231
256
|
<Text style={styles.cardLine}>
|
|
232
257
|
{isRetrying ? `${t('kyc.verificationProgress.status.processing')}...` : t('kyc.verificationProgress.status.pending')}
|
|
@@ -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, 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
|
+
{"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\nconst MAX_RETRIES = 40; // 40 attempts * 3 seconds = exactly 2 minutes of polling\n\nexport const VerificationProgressTemplate: React.FC<VerificationProgressTemplateProps> = () => {\n const { t } = useI18n();\n const { state, actions } = useTemplateKYCFlowContext();\n \n const [retryCount, setRetryCount] = useState(0);\n const [isRetrying, setIsRetrying] = useState(false);\n \n // 🚨 BULLETPROOF REFS: Prevents memory leaks and duplicate polling loops\n const timeoutIdRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const isPollingRef = useRef(false);\n const isMountedRef = useRef(true); \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) => {\n // If component unmounted while waiting, stop everything\n if (!isMountedRef.current) return;\n\n try {\n logger.log(`Starting verification check (attempt ${currentRetryCount + 1}/${MAX_RETRIES})`);\n const result: any = await kycService.getVerificationResult(state.session.session_id);\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 if (isMountedRef.current) setIsRetrying(false);\n isPollingRef.current = false;\n return;\n }\n\n // 2. Safely Extract Nested Payload\n let vData = result?.data || result;\n \n if (typeof vData === 'string') {\n try { vData = JSON.parse(vData); } catch (e) { }\n }\n\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 selfieMatch = vData.selfie_info?.is_match;\n\n logger.log(`Parsed Status: [${vStatus}], Decision: [${vDecision}], Selfie Match: [${selfieMatch}]`);\n\n // SUCCESS CONDITION\n if (\n vStatus === 'approved' || vStatus === 'verified' || vStatus === 'success' ||\n vDecision === 'approved' || vDecision === 'passed' || vDecision === 'clear' ||\n (vStatus === 'completed' && selfieMatch === true)\n ) {\n const hasActualData = vData && Object.keys(vData).length > 0;\n if (!hasActualData) {\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 if (isMountedRef.current) setIsRetrying(false);\n isPollingRef.current = false;\n return;\n }\n\n actions.setVerificationState({\n status: 'success',\n result: { ...result, referenceId: vData.verification_id || vData.session_id || state.session.session_id } as any\n });\n if (isMountedRef.current) setIsRetrying(false);\n isPollingRef.current = false;\n return;\n }\n\n // PENDING/PROCESSING CONDITION\n if (\n vStatus === 'processing' || vStatus === 'pending' || vStatus === 'in_progress' ||\n vStatus === 'initiated' || (vStatus === 'completed' && selfieMatch === null) || !vStatus\n ) {\n if (currentRetryCount < MAX_RETRIES) {\n const nextRetryCount = currentRetryCount + 1;\n if (isMountedRef.current) {\n setRetryCount(nextRetryCount);\n setIsRetrying(true);\n }\n logger.log(`Verification still processing, retrying in 3s... (${nextRetryCount}/${MAX_RETRIES})`);\n \n if (timeoutIdRef.current) clearTimeout(timeoutIdRef.current);\n timeoutIdRef.current = setTimeout(() => {\n getVerificationResult(nextRetryCount);\n }, 3000);\n } else {\n logger.error('Max retries reached, verification still processing');\n actions.setVerificationState({\n status: 'failed',\n result: {\n referenceId: state.session.session_id,\n issues: ['Verification timed out after maximum attempts. Please try again.']\n } as any\n });\n if (isMountedRef.current) setIsRetrying(false);\n isPollingRef.current = false;\n }\n return;\n }\n\n // UNKNOWN FALLBACK\n logger.warn(`Unknown verification status received: ${vStatus}`);\n if (isMountedRef.current) 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 < MAX_RETRIES) {\n const nextRetryCount = currentRetryCount + 1;\n if (isMountedRef.current) {\n setRetryCount(nextRetryCount);\n setIsRetrying(true);\n }\n logger.log(`Error occurred, retrying in 3s... (${nextRetryCount}/${MAX_RETRIES})`);\n \n if (timeoutIdRef.current) clearTimeout(timeoutIdRef.current);\n timeoutIdRef.current = setTimeout(() => {\n getVerificationResult(nextRetryCount);\n }, 3000);\n } else {\n logger.error('Max retries reached after errors');\n actions.setVerificationState({\n status: 'failed',\n result: {\n referenceId: state.session.session_id,\n issues: ['Connection failed multiple times. Please check your network and try again.']\n } as any\n });\n if (isMountedRef.current) setIsRetrying(false);\n isPollingRef.current = false;\n }\n }\n };\n\n // 1. Kick off polling when component mounts\n useEffect(() => {\n isMountedRef.current = true;\n if (state.session.session_id && !isSuccess && !isFailed && !isPollingRef.current) {\n isPollingRef.current = true;\n getVerificationResult(0); // Always start explicitly at 0\n }\n }, [state.session.session_id, isSuccess, isFailed]);\n\n // 2. Strict cleanup on unmount ONLY\n useEffect(() => {\n return () => {\n isMountedRef.current = false;\n if (timeoutIdRef.current) clearTimeout(timeoutIdRef.current);\n isPollingRef.current = false;\n };\n }, []);\n\n // 3. Auto-submit on success\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 // --- RENDER LOGIC ---\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 \n <TouchableOpacity style={[styles.button, styles.primary]} onPress={() => actions.submitVerification()}>\n <Text style={styles.buttonText}>{t('common.continue')}</Text>\n </TouchableOpacity>\n \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: MAX_RETRIES })}`\n : 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});"]}
|
package/package.json
CHANGED
|
@@ -14,25 +14,33 @@ interface VerificationProgressTemplateProps {
|
|
|
14
14
|
language?: string;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
const MAX_RETRIES = 40; // 40 attempts * 3 seconds = exactly 2 minutes of polling
|
|
18
|
+
|
|
17
19
|
export const VerificationProgressTemplate: React.FC<VerificationProgressTemplateProps> = () => {
|
|
18
20
|
const { t } = useI18n();
|
|
19
21
|
const { state, actions } = useTemplateKYCFlowContext();
|
|
22
|
+
|
|
20
23
|
const [retryCount, setRetryCount] = useState(0);
|
|
21
24
|
const [isRetrying, setIsRetrying] = useState(false);
|
|
22
|
-
|
|
25
|
+
|
|
26
|
+
// 🚨 BULLETPROOF REFS: Prevents memory leaks and duplicate polling loops
|
|
27
|
+
const timeoutIdRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
23
28
|
const isPollingRef = useRef(false);
|
|
29
|
+
const isMountedRef = useRef(true);
|
|
24
30
|
|
|
25
31
|
const verification = state.verification;
|
|
26
32
|
const isSuccess = verification.status === 'success';
|
|
27
33
|
const isFailed = verification.status === 'failed';
|
|
28
34
|
|
|
29
|
-
const getVerificationResult = async (currentRetryCount = 0
|
|
35
|
+
const getVerificationResult = async (currentRetryCount = 0) => {
|
|
36
|
+
// If component unmounted while waiting, stop everything
|
|
37
|
+
if (!isMountedRef.current) return;
|
|
38
|
+
|
|
30
39
|
try {
|
|
31
|
-
logger.log(`Starting verification check (attempt ${currentRetryCount + 1}/${
|
|
40
|
+
logger.log(`Starting verification check (attempt ${currentRetryCount + 1}/${MAX_RETRIES})`);
|
|
32
41
|
const result: any = await kycService.getVerificationResult(state.session.session_id);
|
|
33
|
-
|
|
34
42
|
logger.log('getVerificationResult raw result:', JSON.stringify(result, null, 2));
|
|
35
|
-
|
|
43
|
+
|
|
36
44
|
const rootStatus = (result?.status || '').toLowerCase();
|
|
37
45
|
if (rootStatus === 'failed.' || rootStatus === 'failed' || rootStatus === 'rejected' || rootStatus === 'error') {
|
|
38
46
|
actions.setVerificationState({
|
|
@@ -42,22 +50,18 @@ export const VerificationProgressTemplate: React.FC<VerificationProgressTemplate
|
|
|
42
50
|
issues: [result?.message || result?.reason || 'Verification failed. Sent for manual review.']
|
|
43
51
|
} as any
|
|
44
52
|
});
|
|
45
|
-
setIsRetrying(false);
|
|
46
|
-
isPollingRef.current = false;
|
|
53
|
+
if (isMountedRef.current) setIsRetrying(false);
|
|
54
|
+
isPollingRef.current = false;
|
|
47
55
|
return;
|
|
48
56
|
}
|
|
49
|
-
|
|
57
|
+
|
|
50
58
|
// 2. Safely Extract Nested Payload
|
|
51
|
-
let vData = result?.data || result;
|
|
52
|
-
|
|
53
|
-
// Handle stringified JSON
|
|
59
|
+
let vData = result?.data || result;
|
|
60
|
+
|
|
54
61
|
if (typeof vData === 'string') {
|
|
55
|
-
try {
|
|
56
|
-
vData = JSON.parse(vData);
|
|
57
|
-
} catch (e) { }
|
|
62
|
+
try { vData = JSON.parse(vData); } catch (e) { }
|
|
58
63
|
}
|
|
59
|
-
|
|
60
|
-
// Handle backend dictionaries indexed by session_id
|
|
64
|
+
|
|
61
65
|
if (vData && typeof vData === 'object' && vData[state.session.session_id]) {
|
|
62
66
|
let nested = vData[state.session.session_id];
|
|
63
67
|
if (nested && nested.data) {
|
|
@@ -65,132 +69,132 @@ export const VerificationProgressTemplate: React.FC<VerificationProgressTemplate
|
|
|
65
69
|
}
|
|
66
70
|
vData = nested;
|
|
67
71
|
}
|
|
68
|
-
|
|
72
|
+
|
|
69
73
|
if (!vData || typeof vData !== 'object') {
|
|
70
74
|
throw new Error('Verification payload missing or invalid for current session');
|
|
71
75
|
}
|
|
72
|
-
|
|
76
|
+
|
|
73
77
|
const vStatus = (vData.verification_status || vData.status || vData.state || '').toLowerCase();
|
|
74
78
|
const vDecision = (vData.decision || vData.outcome || vData.result || '').toLowerCase();
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
const selfieMatch = vData.selfie_info?.is_match;
|
|
80
|
+
|
|
78
81
|
logger.log(`Parsed Status: [${vStatus}], Decision: [${vDecision}], Selfie Match: [${selfieMatch}]`);
|
|
79
|
-
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
82
|
+
|
|
83
|
+
// SUCCESS CONDITION
|
|
84
|
+
if (
|
|
85
|
+
vStatus === 'approved' || vStatus === 'verified' || vStatus === 'success' ||
|
|
86
|
+
vDecision === 'approved' || vDecision === 'passed' || vDecision === 'clear' ||
|
|
87
|
+
(vStatus === 'completed' && selfieMatch === true)
|
|
88
|
+
) {
|
|
89
|
+
const hasActualData = vData && Object.keys(vData).length > 0;
|
|
90
|
+
if (!hasActualData) {
|
|
91
|
+
actions.setVerificationState({
|
|
92
|
+
status: 'failed',
|
|
93
|
+
result: {
|
|
94
|
+
referenceId: state.session.session_id,
|
|
95
|
+
issues: ['Document text could not be read clearly. Please retake the photo in better lighting.']
|
|
96
|
+
} as any
|
|
97
|
+
});
|
|
98
|
+
if (isMountedRef.current) setIsRetrying(false);
|
|
99
|
+
isPollingRef.current = false;
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
94
103
|
actions.setVerificationState({
|
|
95
|
-
status: '
|
|
96
|
-
result: {
|
|
97
|
-
referenceId: state.session.session_id,
|
|
98
|
-
issues: ['Document text could not be read clearly. Please retake the photo in better lighting.']
|
|
99
|
-
} as any
|
|
104
|
+
status: 'success',
|
|
105
|
+
result: { ...result, referenceId: vData.verification_id || vData.session_id || state.session.session_id } as any
|
|
100
106
|
});
|
|
101
|
-
setIsRetrying(false);
|
|
107
|
+
if (isMountedRef.current) setIsRetrying(false);
|
|
102
108
|
isPollingRef.current = false;
|
|
103
109
|
return;
|
|
104
110
|
}
|
|
105
111
|
|
|
106
|
-
//
|
|
107
|
-
actions.setVerificationState({
|
|
108
|
-
status: 'success',
|
|
109
|
-
result: {
|
|
110
|
-
...result,
|
|
111
|
-
referenceId: vData.verification_id || vData.session_id || state.session.session_id
|
|
112
|
-
} as any
|
|
113
|
-
});
|
|
114
|
-
setIsRetrying(false);
|
|
115
|
-
isPollingRef.current = false;
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
|
|
112
|
+
// PENDING/PROCESSING CONDITION
|
|
119
113
|
if (
|
|
120
114
|
vStatus === 'processing' || vStatus === 'pending' || vStatus === 'in_progress' ||
|
|
121
115
|
vStatus === 'initiated' || (vStatus === 'completed' && selfieMatch === null) || !vStatus
|
|
122
116
|
) {
|
|
123
|
-
if (currentRetryCount <
|
|
117
|
+
if (currentRetryCount < MAX_RETRIES) {
|
|
124
118
|
const nextRetryCount = currentRetryCount + 1;
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
131
|
-
const newTimeoutId = setTimeout(() => {
|
|
132
|
-
getVerificationResult(nextRetryCount, maxRetries);
|
|
133
|
-
}, 3000);
|
|
119
|
+
if (isMountedRef.current) {
|
|
120
|
+
setRetryCount(nextRetryCount);
|
|
121
|
+
setIsRetrying(true);
|
|
122
|
+
}
|
|
123
|
+
logger.log(`Verification still processing, retrying in 3s... (${nextRetryCount}/${MAX_RETRIES})`);
|
|
134
124
|
|
|
135
|
-
|
|
125
|
+
if (timeoutIdRef.current) clearTimeout(timeoutIdRef.current);
|
|
126
|
+
timeoutIdRef.current = setTimeout(() => {
|
|
127
|
+
getVerificationResult(nextRetryCount);
|
|
128
|
+
}, 3000);
|
|
136
129
|
} else {
|
|
137
130
|
logger.error('Max retries reached, verification still processing');
|
|
138
|
-
setIsRetrying(false);
|
|
139
|
-
isPollingRef.current = false;
|
|
140
131
|
actions.setVerificationState({
|
|
141
132
|
status: 'failed',
|
|
142
133
|
result: {
|
|
143
134
|
referenceId: state.session.session_id,
|
|
144
|
-
issues: ['Verification timed out. Please try again.']
|
|
135
|
+
issues: ['Verification timed out after maximum attempts. Please try again.']
|
|
145
136
|
} as any
|
|
146
137
|
});
|
|
138
|
+
if (isMountedRef.current) setIsRetrying(false);
|
|
139
|
+
isPollingRef.current = false;
|
|
147
140
|
}
|
|
148
141
|
return;
|
|
149
142
|
}
|
|
150
|
-
|
|
151
|
-
//
|
|
143
|
+
|
|
144
|
+
// UNKNOWN FALLBACK
|
|
152
145
|
logger.warn(`Unknown verification status received: ${vStatus}`);
|
|
153
|
-
setIsRetrying(false);
|
|
146
|
+
if (isMountedRef.current) setIsRetrying(false);
|
|
154
147
|
isPollingRef.current = false;
|
|
155
|
-
|
|
148
|
+
|
|
156
149
|
} catch (error: any) {
|
|
157
150
|
logger.error('getVerificationResult error', JSON.stringify(errorMessage(error) || { message: error?.message || 'Unknown error' }, null, 2));
|
|
158
151
|
|
|
159
|
-
if (currentRetryCount <
|
|
152
|
+
if (currentRetryCount < MAX_RETRIES) {
|
|
160
153
|
const nextRetryCount = currentRetryCount + 1;
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
154
|
+
if (isMountedRef.current) {
|
|
155
|
+
setRetryCount(nextRetryCount);
|
|
156
|
+
setIsRetrying(true);
|
|
157
|
+
}
|
|
158
|
+
logger.log(`Error occurred, retrying in 3s... (${nextRetryCount}/${MAX_RETRIES})`);
|
|
165
159
|
|
|
166
|
-
if (
|
|
167
|
-
|
|
168
|
-
getVerificationResult(nextRetryCount
|
|
160
|
+
if (timeoutIdRef.current) clearTimeout(timeoutIdRef.current);
|
|
161
|
+
timeoutIdRef.current = setTimeout(() => {
|
|
162
|
+
getVerificationResult(nextRetryCount);
|
|
169
163
|
}, 3000);
|
|
170
|
-
|
|
171
|
-
setTimeoutId(newTimeoutId as any);
|
|
172
164
|
} else {
|
|
173
|
-
setIsRetrying(false);
|
|
174
|
-
isPollingRef.current = false; // Release lock
|
|
175
165
|
logger.error('Max retries reached after errors');
|
|
166
|
+
actions.setVerificationState({
|
|
167
|
+
status: 'failed',
|
|
168
|
+
result: {
|
|
169
|
+
referenceId: state.session.session_id,
|
|
170
|
+
issues: ['Connection failed multiple times. Please check your network and try again.']
|
|
171
|
+
} as any
|
|
172
|
+
});
|
|
173
|
+
if (isMountedRef.current) setIsRetrying(false);
|
|
174
|
+
isPollingRef.current = false;
|
|
176
175
|
}
|
|
177
176
|
}
|
|
178
177
|
};
|
|
179
178
|
|
|
179
|
+
// 1. Kick off polling when component mounts
|
|
180
180
|
useEffect(() => {
|
|
181
|
+
isMountedRef.current = true;
|
|
181
182
|
if (state.session.session_id && !isSuccess && !isFailed && !isPollingRef.current) {
|
|
182
|
-
isPollingRef.current = true;
|
|
183
|
-
getVerificationResult();
|
|
183
|
+
isPollingRef.current = true;
|
|
184
|
+
getVerificationResult(0); // Always start explicitly at 0
|
|
184
185
|
}
|
|
185
186
|
}, [state.session.session_id, isSuccess, isFailed]);
|
|
186
187
|
|
|
188
|
+
// 2. Strict cleanup on unmount ONLY
|
|
187
189
|
useEffect(() => {
|
|
188
190
|
return () => {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
+
isMountedRef.current = false;
|
|
192
|
+
if (timeoutIdRef.current) clearTimeout(timeoutIdRef.current);
|
|
193
|
+
isPollingRef.current = false;
|
|
191
194
|
};
|
|
192
|
-
}, [
|
|
195
|
+
}, []);
|
|
193
196
|
|
|
197
|
+
// 3. Auto-submit on success
|
|
194
198
|
useEffect(() => {
|
|
195
199
|
let autoSubmitTimer: ReturnType<typeof setTimeout>;
|
|
196
200
|
if (isSuccess) {
|
|
@@ -204,14 +208,18 @@ export const VerificationProgressTemplate: React.FC<VerificationProgressTemplate
|
|
|
204
208
|
};
|
|
205
209
|
}, [isSuccess, actions]);
|
|
206
210
|
|
|
211
|
+
// --- RENDER LOGIC ---
|
|
212
|
+
|
|
207
213
|
if (isSuccess) {
|
|
208
214
|
return (
|
|
209
215
|
<View style={styles.container}>
|
|
210
216
|
<Text style={styles.title}>{t('kyc.verificationProgress.steps.complete')}</Text>
|
|
211
217
|
<Text style={styles.subtitle}>{t('kyc.verificationProgress.subtitle')}</Text>
|
|
218
|
+
|
|
212
219
|
<TouchableOpacity style={[styles.button, styles.primary]} onPress={() => actions.submitVerification()}>
|
|
213
220
|
<Text style={styles.buttonText}>{t('common.continue')}</Text>
|
|
214
221
|
</TouchableOpacity>
|
|
222
|
+
|
|
215
223
|
{verification.result?.referenceId ? (
|
|
216
224
|
<Text style={styles.refText}>{`Verification ID: ${verification.result.referenceId}`}</Text>
|
|
217
225
|
) : null}
|
|
@@ -223,22 +231,26 @@ export const VerificationProgressTemplate: React.FC<VerificationProgressTemplate
|
|
|
223
231
|
return (
|
|
224
232
|
<View style={styles.container}>
|
|
225
233
|
<Text style={styles.title}>{t('kyc.verificationProgress.status.failed')}</Text>
|
|
234
|
+
|
|
226
235
|
<View style={styles.issuesBox}>
|
|
227
236
|
<Text style={styles.issuesTitle}>{t('common.error')}</Text>
|
|
228
237
|
{Array.isArray(verification.result?.issues) && verification.result.issues.map((issue: string, idx: number) => (
|
|
229
238
|
<Text key={idx} style={styles.issueItem}>• {issue}</Text>
|
|
230
239
|
))}
|
|
231
240
|
</View>
|
|
241
|
+
|
|
232
242
|
<TouchableOpacity style={[styles.button, styles.primary]} onPress={() => actions.submitVerification()}>
|
|
233
243
|
<Text style={styles.buttonText}>
|
|
234
244
|
{state.currentLanguage === 'en' ? 'OK / Finish' : 'Terminer'}
|
|
235
245
|
</Text>
|
|
236
246
|
</TouchableOpacity>
|
|
247
|
+
|
|
237
248
|
<TouchableOpacity style={[styles.button, styles.secondary]} onPress={() => actions.resetTemplate()}>
|
|
238
249
|
<Text style={styles.secondaryText}>
|
|
239
250
|
{state.currentLanguage === 'en' ? 'Start Over' : 'Recommencer'}
|
|
240
251
|
</Text>
|
|
241
252
|
</TouchableOpacity>
|
|
253
|
+
|
|
242
254
|
{verification.result?.referenceId ? (
|
|
243
255
|
<Text style={styles.refText}>{`Reference ID: ${verification.result.referenceId}`}</Text>
|
|
244
256
|
) : null}
|
|
@@ -250,7 +262,9 @@ export const VerificationProgressTemplate: React.FC<VerificationProgressTemplate
|
|
|
250
262
|
<View style={styles.container}>
|
|
251
263
|
<Text style={styles.title}>{t('kyc.verificationProgress.title')}</Text>
|
|
252
264
|
<Text style={styles.subtitle}>
|
|
253
|
-
{isRetrying
|
|
265
|
+
{isRetrying
|
|
266
|
+
? `${t('kyc.verificationProgress.retrying', { current: retryCount, max: MAX_RETRIES })}`
|
|
267
|
+
: t('kyc.verificationProgress.estimatedTime')}
|
|
254
268
|
</Text>
|
|
255
269
|
|
|
256
270
|
<View style={styles.timeline}>
|
|
@@ -270,10 +284,10 @@ export const VerificationProgressTemplate: React.FC<VerificationProgressTemplate
|
|
|
270
284
|
<View style={styles.card}>
|
|
271
285
|
<Text style={styles.cardTitle}>{t('kyc.idCardCapture.title')}</Text>
|
|
272
286
|
<Text style={styles.cardLine}>{t('kyc.verificationProgress.steps.extracting')}</Text>
|
|
273
|
-
|
|
287
|
+
|
|
274
288
|
<Text style={styles.cardTitle}>{t('kyc.selfieCapture.title')}</Text>
|
|
275
289
|
<Text style={styles.cardLine}>{t('kyc.verificationProgress.steps.analyzing')}</Text>
|
|
276
|
-
|
|
290
|
+
|
|
277
291
|
<Text style={styles.cardTitle}>{t('kyc.verificationProgress.title')}</Text>
|
|
278
292
|
<Text style={styles.cardLine}>
|
|
279
293
|
{isRetrying ? `${t('kyc.verificationProgress.status.processing')}...` : t('kyc.verificationProgress.status.pending')}
|