@transfergratis/react-native-sdk 0.1.24 → 0.1.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/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +12 -5
- package/android/build/intermediates/aar_main_jar/debug/syncDebugLibJars/classes.jar +0 -0
- package/android/build/intermediates/annotations_typedef_file/debug/extractDebugAnnotations/typedefs.txt +0 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
- package/android/build/intermediates/incremental/debug-mergeJavaRes/merge-state +0 -0
- package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +61 -59
- package/android/build/intermediates/merged_java_res/debug/mergeDebugJavaResource/feature-transfergratis-react-native-sdk.jar +0 -0
- package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +12 -5
- package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
- package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
- package/android/build/outputs/aar/transfergratis-react-native-sdk-debug.aar +0 -0
- package/android/build/outputs/logs/manifest-merger-debug-report.txt +26 -34
- package/android/src/main/AndroidManifest.xml +10 -7
- package/build/components/KYCElements/AdditionalDocumentsTemplate.d.ts +12 -0
- package/build/components/KYCElements/AdditionalDocumentsTemplate.d.ts.map +1 -0
- package/build/components/KYCElements/AdditionalDocumentsTemplate.js +283 -0
- package/build/components/KYCElements/AdditionalDocumentsTemplate.js.map +1 -0
- package/build/components/KYCElements/EmailVerificationTemplate.d.ts +12 -0
- package/build/components/KYCElements/EmailVerificationTemplate.d.ts.map +1 -0
- package/build/components/KYCElements/EmailVerificationTemplate.js +193 -0
- package/build/components/KYCElements/EmailVerificationTemplate.js.map +1 -0
- package/build/components/KYCElements/IDCardCapture.d.ts.map +1 -1
- package/build/components/KYCElements/IDCardCapture.js +180 -7
- package/build/components/KYCElements/IDCardCapture.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCapture.d.ts +2 -0
- package/build/components/KYCElements/OrientationVideoCapture.d.ts.map +1 -1
- package/build/components/KYCElements/OrientationVideoCapture.js +2 -2
- package/build/components/KYCElements/OrientationVideoCapture.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.d.ts +2 -0
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.d.ts.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js +2 -2
- package/build/components/KYCElements/OrientationVideoCaptureEnhanced.js.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureFinal.d.ts +2 -0
- package/build/components/KYCElements/OrientationVideoCaptureFinal.d.ts.map +1 -1
- package/build/components/KYCElements/OrientationVideoCaptureFinal.js +2 -2
- package/build/components/KYCElements/OrientationVideoCaptureFinal.js.map +1 -1
- package/build/components/KYCElements/PersonalInformationTemplate.d.ts +12 -0
- package/build/components/KYCElements/PersonalInformationTemplate.d.ts.map +1 -0
- package/build/components/KYCElements/PersonalInformationTemplate.js +120 -0
- package/build/components/KYCElements/PersonalInformationTemplate.js.map +1 -0
- package/build/components/KYCElements/PhoneVerificationTemplate.d.ts +12 -0
- package/build/components/KYCElements/PhoneVerificationTemplate.d.ts.map +1 -0
- package/build/components/KYCElements/PhoneVerificationTemplate.js +185 -0
- package/build/components/KYCElements/PhoneVerificationTemplate.js.map +1 -0
- package/build/components/KYCElements/SelfieCaptureTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/SelfieCaptureTemplate.js +7 -3
- package/build/components/KYCElements/SelfieCaptureTemplate.js.map +1 -1
- package/build/components/TemplateKYCExample.d.ts +4 -0
- package/build/components/TemplateKYCExample.d.ts.map +1 -1
- package/build/components/TemplateKYCExample.js +7 -30
- package/build/components/TemplateKYCExample.js.map +1 -1
- package/build/components/TemplateKYCFlowRefactored.d.ts +4 -0
- package/build/components/TemplateKYCFlowRefactored.d.ts.map +1 -1
- package/build/components/TemplateKYCFlowRefactored.js +14 -2
- package/build/components/TemplateKYCFlowRefactored.js.map +1 -1
- package/build/config/KYCConfig.d.ts +14 -0
- package/build/config/KYCConfig.d.ts.map +1 -0
- package/build/config/KYCConfig.js +26 -0
- package/build/config/KYCConfig.js.map +1 -0
- package/build/config/allowedDomains.d.ts.map +1 -1
- package/build/config/allowedDomains.js +4 -19
- package/build/config/allowedDomains.js.map +1 -1
- package/build/hooks/useOrientationVideo.d.ts +2 -1
- package/build/hooks/useOrientationVideo.d.ts.map +1 -1
- package/build/hooks/useOrientationVideo.js +3 -3
- package/build/hooks/useOrientationVideo.js.map +1 -1
- package/build/hooks/useTemplateKYCFlow.d.ts +6 -1
- package/build/hooks/useTemplateKYCFlow.d.ts.map +1 -1
- package/build/hooks/useTemplateKYCFlow.js +286 -23
- package/build/hooks/useTemplateKYCFlow.js.map +1 -1
- package/build/i18n/en/index.d.ts +40 -0
- package/build/i18n/en/index.d.ts.map +1 -1
- package/build/i18n/en/index.js +41 -1
- package/build/i18n/en/index.js.map +1 -1
- package/build/i18n/fr/index.d.ts +26 -0
- package/build/i18n/fr/index.d.ts.map +1 -1
- package/build/i18n/fr/index.js +27 -1
- package/build/i18n/fr/index.js.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -0
- package/build/index.js.map +1 -1
- package/build/modules/api/CardAuthentification.d.ts +24 -3
- package/build/modules/api/CardAuthentification.d.ts.map +1 -1
- package/build/modules/api/CardAuthentification.js +68 -10
- package/build/modules/api/CardAuthentification.js.map +1 -1
- package/build/modules/api/KYCService.d.ts +7 -7
- package/build/modules/api/KYCService.d.ts.map +1 -1
- package/build/modules/api/KYCService.js +101 -37
- package/build/modules/api/KYCService.js.map +1 -1
- package/build/modules/api/SelfieVerification.d.ts +3 -1
- package/build/modules/api/SelfieVerification.d.ts.map +1 -1
- package/build/modules/api/SelfieVerification.js +17 -1
- package/build/modules/api/SelfieVerification.js.map +1 -1
- package/build/modules/api/TemplateService.d.ts +0 -1
- package/build/modules/api/TemplateService.d.ts.map +1 -1
- package/build/modules/api/TemplateService.js +3 -3
- package/build/modules/api/TemplateService.js.map +1 -1
- package/build/types/KYC.types.d.ts +124 -3
- package/build/types/KYC.types.d.ts.map +1 -1
- package/build/types/KYC.types.js.map +1 -1
- package/build/types/env.types.d.ts +13 -0
- package/build/types/env.types.d.ts.map +1 -0
- package/build/types/env.types.js +2 -0
- package/build/types/env.types.js.map +1 -0
- package/build/utils/deviceDetection.d.ts +6 -0
- package/build/utils/deviceDetection.d.ts.map +1 -0
- package/build/utils/deviceDetection.js +12 -0
- package/build/utils/deviceDetection.js.map +1 -0
- package/build/utils/platformAlert.d.ts.map +1 -1
- package/build/utils/platformAlert.js.map +1 -1
- package/build/utils/template-transformer.d.ts.map +1 -1
- package/build/utils/template-transformer.js +12 -0
- package/build/utils/template-transformer.js.map +1 -1
- package/build/web/WebKYCEntry.d.ts.map +1 -1
- package/build/web/WebKYCEntry.js +82 -38
- package/build/web/WebKYCEntry.js.map +1 -1
- package/package.json +1 -1
- package/plugin/build/withVisionCamera.js +3 -4
- package/plugin/src/withVisionCamera.js +3 -4
- package/plugin/src/withVisionCamera.ts +3 -4
- package/src/components/KYCElements/AdditionalDocumentsTemplate.tsx +346 -0
- package/src/components/KYCElements/EmailVerificationTemplate.tsx +264 -0
- package/src/components/KYCElements/IDCardCapture.tsx +216 -15
- package/src/components/KYCElements/OrientationVideoCapture.tsx +4 -1
- package/src/components/KYCElements/OrientationVideoCaptureEnhanced.tsx +4 -1
- package/src/components/KYCElements/OrientationVideoCaptureFinal.tsx +4 -1
- package/src/components/KYCElements/PersonalInformationTemplate.tsx +158 -0
- package/src/components/KYCElements/PhoneVerificationTemplate.tsx +253 -0
- package/src/components/KYCElements/SelfieCaptureTemplate.tsx +6 -3
- package/src/components/TemplateKYCExample.tsx +31 -46
- package/src/components/TemplateKYCFlowRefactored.tsx +27 -1
- package/src/config/KYCConfig.ts +34 -0
- package/src/config/allowedDomains.ts +7 -26
- package/src/hooks/useOrientationVideo.ts +5 -4
- package/src/hooks/useTemplateKYCFlow.tsx +314 -21
- package/src/i18n/en/index.ts +43 -2
- package/src/i18n/fr/index.ts +28 -1
- package/src/index.ts +3 -0
- package/src/modules/api/CardAuthentification.ts +75 -10
- package/src/modules/api/KYCService.ts +117 -37
- package/src/modules/api/SelfieVerification.ts +25 -3
- package/src/modules/api/TemplateService.ts +4 -4
- package/src/types/KYC.types.ts +146 -3
- package/src/types/env.types.ts +13 -0
- package/src/utils/deviceDetection.ts +11 -0
- package/src/utils/platformAlert.ts +1 -0
- package/src/utils/template-transformer.ts +20 -8
- package/src/web/WebKYCEntry.tsx +112 -61
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { View, Text, StyleSheet, TextInput, TouchableOpacity, Alert } from 'react-native';
|
|
3
|
+
import { TemplateComponent, LocalizedText } from '../../types/KYC.types';
|
|
4
|
+
import { useTemplateKYCFlowContext } from '../../hooks/useTemplateKYCFlow';
|
|
5
|
+
import { useI18n } from '../../hooks/useI18n';
|
|
6
|
+
import { Button } from '../ui/Button';
|
|
7
|
+
|
|
8
|
+
interface PhoneVerificationTemplateProps {
|
|
9
|
+
component: TemplateComponent;
|
|
10
|
+
value?: any;
|
|
11
|
+
onValueChange: (data: any) => void;
|
|
12
|
+
error?: string;
|
|
13
|
+
language?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type VerificationStep = 'phone' | 'otp';
|
|
17
|
+
|
|
18
|
+
export const PhoneVerificationTemplate: React.FC<PhoneVerificationTemplateProps> = ({
|
|
19
|
+
component,
|
|
20
|
+
value,
|
|
21
|
+
onValueChange,
|
|
22
|
+
error: propError,
|
|
23
|
+
}) => {
|
|
24
|
+
const { actions, getLocalizedText } = useTemplateKYCFlowContext();
|
|
25
|
+
const { t } = useI18n();
|
|
26
|
+
// const config = component.config as PhoneVerificationConfig;
|
|
27
|
+
|
|
28
|
+
// State
|
|
29
|
+
const [step, setStep] = useState<VerificationStep>('phone');
|
|
30
|
+
const [phone, setPhone] = useState('');
|
|
31
|
+
const [otp, setOtp] = useState('');
|
|
32
|
+
const [localError, setLocalError] = useState<string | null>(null);
|
|
33
|
+
const [isSimulating, setIsSimulating] = useState(false);
|
|
34
|
+
|
|
35
|
+
const title = getLocalizedText(component.labels as LocalizedText);
|
|
36
|
+
const instructions = getLocalizedText(component.instructions as LocalizedText);
|
|
37
|
+
|
|
38
|
+
// Determine button text based on step
|
|
39
|
+
const verifyButtonText = getLocalizedText((component.ui as any).buttonText) || t('common.verify') || 'Verify';
|
|
40
|
+
const sendButtonText = t('common.sendCode') || 'Send Verification Code';
|
|
41
|
+
const buttonText = step === 'phone' ? sendButtonText : verifyButtonText;
|
|
42
|
+
|
|
43
|
+
const handleSendCode = () => {
|
|
44
|
+
if (!phone || phone.length < 5) {
|
|
45
|
+
setLocalError(t('errors.invalidPhone') || 'Please enter a valid phone number');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
setLocalError(null);
|
|
50
|
+
setIsSimulating(true);
|
|
51
|
+
|
|
52
|
+
// Simulate API call to send code
|
|
53
|
+
setTimeout(() => {
|
|
54
|
+
setIsSimulating(false);
|
|
55
|
+
setStep('otp');
|
|
56
|
+
}, 1500);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const handleVerifyCode = () => {
|
|
60
|
+
if (!otp || otp.length < 4) {
|
|
61
|
+
setLocalError(t('errors.invalidCode') || 'Please enter the 6-digit code');
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
setLocalError(null);
|
|
66
|
+
setIsSimulating(true);
|
|
67
|
+
|
|
68
|
+
// Simulate verification API
|
|
69
|
+
setTimeout(() => {
|
|
70
|
+
setIsSimulating(false);
|
|
71
|
+
|
|
72
|
+
// Mock validation logic
|
|
73
|
+
if (otp === '123456') {
|
|
74
|
+
onValueChange({ phone, otp, verified: true });
|
|
75
|
+
actions.nextComponent();
|
|
76
|
+
} else {
|
|
77
|
+
setLocalError(t('errors.wrongCode') || 'Invalid verification code. Try 123456');
|
|
78
|
+
}
|
|
79
|
+
}, 1500);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const onChangePhone = (text: string) => {
|
|
83
|
+
setPhone(text);
|
|
84
|
+
if (localError) setLocalError(null);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const onChangeOtp = (text: string) => {
|
|
88
|
+
setOtp(text);
|
|
89
|
+
if (localError) setLocalError(null);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const handleBackToPhone = () => {
|
|
93
|
+
setStep('phone');
|
|
94
|
+
setOtp('');
|
|
95
|
+
setLocalError(null);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<View style={styles.container}>
|
|
100
|
+
<Text style={styles.title}>{title}</Text>
|
|
101
|
+
<Text style={styles.instructions}>
|
|
102
|
+
{step === 'phone' ? instructions : (t('kyc.enterCodeSent') || `Please enter the code sent to ${phone}`)}
|
|
103
|
+
</Text>
|
|
104
|
+
|
|
105
|
+
<View style={styles.contentContainer}>
|
|
106
|
+
{step === 'phone' ? (
|
|
107
|
+
<View style={styles.inputContainer}>
|
|
108
|
+
<Text style={styles.label}>{t('common.phone') || 'Phone Number'}</Text>
|
|
109
|
+
<TextInput
|
|
110
|
+
style={styles.input}
|
|
111
|
+
placeholder="+1234567890"
|
|
112
|
+
value={phone}
|
|
113
|
+
onChangeText={onChangePhone}
|
|
114
|
+
keyboardType="phone-pad"
|
|
115
|
+
autoComplete="tel"
|
|
116
|
+
editable={!isSimulating}
|
|
117
|
+
/>
|
|
118
|
+
</View>
|
|
119
|
+
) : (
|
|
120
|
+
<View style={styles.inputContainer}>
|
|
121
|
+
<Text style={styles.label}>{t('common.verificationCode') || 'Verification Code'}</Text>
|
|
122
|
+
<TextInput
|
|
123
|
+
style={styles.input}
|
|
124
|
+
placeholder="123456"
|
|
125
|
+
value={otp}
|
|
126
|
+
onChangeText={onChangeOtp}
|
|
127
|
+
keyboardType="number-pad"
|
|
128
|
+
maxLength={6}
|
|
129
|
+
editable={!isSimulating}
|
|
130
|
+
/>
|
|
131
|
+
<TouchableOpacity onPress={handleBackToPhone} style={styles.changeLink}>
|
|
132
|
+
<Text style={styles.changeText}>{t('common.back') || 'Change number'}</Text>
|
|
133
|
+
</TouchableOpacity>
|
|
134
|
+
</View>
|
|
135
|
+
)}
|
|
136
|
+
|
|
137
|
+
{(localError || propError) && (
|
|
138
|
+
<Text style={styles.errorText}>{localError || propError}</Text>
|
|
139
|
+
)}
|
|
140
|
+
|
|
141
|
+
<Button
|
|
142
|
+
title={isSimulating ? (t('common.processing') || 'Processing...') : buttonText}
|
|
143
|
+
onPress={step === 'phone' ? handleSendCode : handleVerifyCode}
|
|
144
|
+
style={styles.button}
|
|
145
|
+
disabled={
|
|
146
|
+
isSimulating ||
|
|
147
|
+
(step === 'phone' ? !phone : !otp)
|
|
148
|
+
}
|
|
149
|
+
/>
|
|
150
|
+
|
|
151
|
+
{step === 'otp' && (
|
|
152
|
+
<TouchableOpacity
|
|
153
|
+
onPress={() => {
|
|
154
|
+
// Resend logic
|
|
155
|
+
Alert.alert(
|
|
156
|
+
t('common.codeResent') || 'Code Resent',
|
|
157
|
+
t('common.codeResentMessage', { email: phone }) || 'Code resent to ' + phone
|
|
158
|
+
);
|
|
159
|
+
}}
|
|
160
|
+
style={styles.resendButton}
|
|
161
|
+
disabled={isSimulating}
|
|
162
|
+
>
|
|
163
|
+
<Text style={styles.resendText}>{t('common.resendCode') || 'Resend Code'}</Text>
|
|
164
|
+
</TouchableOpacity>
|
|
165
|
+
)}
|
|
166
|
+
</View>
|
|
167
|
+
</View>
|
|
168
|
+
);
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const styles = StyleSheet.create({
|
|
172
|
+
container: {
|
|
173
|
+
padding: 24,
|
|
174
|
+
backgroundColor: 'white',
|
|
175
|
+
borderRadius: 16,
|
|
176
|
+
margin: 16,
|
|
177
|
+
shadowColor: '#000',
|
|
178
|
+
shadowOffset: { width: 0, height: 4 },
|
|
179
|
+
shadowOpacity: 0.1,
|
|
180
|
+
shadowRadius: 12,
|
|
181
|
+
elevation: 5,
|
|
182
|
+
width: '95%',
|
|
183
|
+
},
|
|
184
|
+
title: {
|
|
185
|
+
fontSize: 24,
|
|
186
|
+
fontWeight: '700',
|
|
187
|
+
marginBottom: 8,
|
|
188
|
+
color: '#1a1a1a',
|
|
189
|
+
textAlign: 'center',
|
|
190
|
+
},
|
|
191
|
+
instructions: {
|
|
192
|
+
fontSize: 16,
|
|
193
|
+
color: '#666',
|
|
194
|
+
marginBottom: 32,
|
|
195
|
+
lineHeight: 24,
|
|
196
|
+
textAlign: 'center',
|
|
197
|
+
},
|
|
198
|
+
contentContainer: {
|
|
199
|
+
// width: '100%',
|
|
200
|
+
},
|
|
201
|
+
inputContainer: {
|
|
202
|
+
marginBottom: 24,
|
|
203
|
+
},
|
|
204
|
+
label: {
|
|
205
|
+
fontSize: 14,
|
|
206
|
+
fontWeight: '600',
|
|
207
|
+
color: '#333',
|
|
208
|
+
marginBottom: 8,
|
|
209
|
+
marginLeft: 4,
|
|
210
|
+
},
|
|
211
|
+
input: {
|
|
212
|
+
borderWidth: 1,
|
|
213
|
+
borderColor: '#e0e0e0',
|
|
214
|
+
padding: 16,
|
|
215
|
+
borderRadius: 12,
|
|
216
|
+
fontSize: 16,
|
|
217
|
+
backgroundColor: '#f8f9fa',
|
|
218
|
+
color: '#333',
|
|
219
|
+
},
|
|
220
|
+
errorText: {
|
|
221
|
+
color: '#dc2626',
|
|
222
|
+
marginBottom: 16,
|
|
223
|
+
fontSize: 14,
|
|
224
|
+
textAlign: 'center',
|
|
225
|
+
backgroundColor: '#fee2e2',
|
|
226
|
+
padding: 8,
|
|
227
|
+
borderRadius: 8,
|
|
228
|
+
overflow: 'hidden',
|
|
229
|
+
},
|
|
230
|
+
button: {
|
|
231
|
+
height: 50,
|
|
232
|
+
borderRadius: 12,
|
|
233
|
+
width: "100%"
|
|
234
|
+
},
|
|
235
|
+
changeLink: {
|
|
236
|
+
alignSelf: 'flex-end',
|
|
237
|
+
marginTop: 8,
|
|
238
|
+
},
|
|
239
|
+
changeText: {
|
|
240
|
+
color: '#2DBD60',
|
|
241
|
+
fontSize: 14,
|
|
242
|
+
fontWeight: '500',
|
|
243
|
+
},
|
|
244
|
+
resendButton: {
|
|
245
|
+
marginTop: 16,
|
|
246
|
+
alignItems: 'center',
|
|
247
|
+
},
|
|
248
|
+
resendText: {
|
|
249
|
+
color: '#666',
|
|
250
|
+
fontSize: 14,
|
|
251
|
+
textDecorationLine: 'underline',
|
|
252
|
+
},
|
|
253
|
+
});
|
|
@@ -33,7 +33,7 @@ export const SelfieCaptureTemplate: React.FC<SelfieCaptureTemplateProps> = ({
|
|
|
33
33
|
const { t } = useI18n();
|
|
34
34
|
// const config = component.config as SelfieConfig;
|
|
35
35
|
const orientations: OrientationType[] = (['center','left','right']) as OrientationType[];
|
|
36
|
-
const { actions, state, } = useTemplateKYCFlowContext();
|
|
36
|
+
const { actions, state, env } = useTemplateKYCFlowContext();
|
|
37
37
|
|
|
38
38
|
const [silentCaptureResult, setSilentCaptureResult] = useState<ISilentCaptureResult>({ success: false, isAnalyzing: false });
|
|
39
39
|
|
|
@@ -152,10 +152,13 @@ export const SelfieCaptureTemplate: React.FC<SelfieCaptureTemplateProps> = ({
|
|
|
152
152
|
}
|
|
153
153
|
if (result.success && result.path) {
|
|
154
154
|
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: true, success: false, error: '' }));
|
|
155
|
-
selfieVerification(result.path).then((response) => {
|
|
155
|
+
selfieVerification(result.path, env).then((response) => {
|
|
156
156
|
if (response.length > 0) {
|
|
157
157
|
const res = response[0];
|
|
158
|
-
|
|
158
|
+
// In SANDBOX mode, always accept the result regardless of orientation
|
|
159
|
+
if (env === 'SANDBOX' && res?.capture) {
|
|
160
|
+
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: true, error: '', path: result.path }));
|
|
161
|
+
} else if (res?.orientation_direction === getOrientationOpposite(currentOrientation) && res?.capture) {
|
|
159
162
|
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: true, error: '', path: result.path }));
|
|
160
163
|
} else {
|
|
161
164
|
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: 'Le selfie n\'est pas correct' }));
|
|
@@ -2,8 +2,11 @@ import React from 'react';
|
|
|
2
2
|
import { View, SafeAreaView } from 'react-native';
|
|
3
3
|
import { TemplateKYCFlow } from './TemplateKYCFlowRefactored';
|
|
4
4
|
import { KYCTemplate, VerificationState } from '../types/KYC.types';
|
|
5
|
+
import { KycEnvironment } from '../types/env.types';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
5
9
|
|
|
6
|
-
// Template JSON basé sur votre exemple
|
|
7
10
|
const advancedVerificationTemplate: KYCTemplate = {
|
|
8
11
|
id: 1,
|
|
9
12
|
name: {
|
|
@@ -103,7 +106,7 @@ const advancedVerificationTemplate: KYCTemplate = {
|
|
|
103
106
|
allowed_formats: ["jpg", "png"],
|
|
104
107
|
max_size_mb: 5,
|
|
105
108
|
document_types: ["drivers_licence", "passport", "drivers_licence", "national_id"],
|
|
106
|
-
|
|
109
|
+
|
|
107
110
|
} as const
|
|
108
111
|
},
|
|
109
112
|
{
|
|
@@ -130,42 +133,21 @@ const advancedVerificationTemplate: KYCTemplate = {
|
|
|
130
133
|
orientations: ["center", "left", "right"]
|
|
131
134
|
} as const
|
|
132
135
|
},
|
|
133
|
-
// {
|
|
134
|
-
// id: 4,
|
|
135
|
-
// type: "file_upload" as const,
|
|
136
|
-
// order: 6,
|
|
137
|
-
// labels: {
|
|
138
|
-
// en: "Upload proof of address",
|
|
139
|
-
// fr: "Téléversez un justificatif de domicile"
|
|
140
|
-
// },
|
|
141
|
-
// instructions: {
|
|
142
|
-
// en: "Upload a recent utility bill or bank statement (PDF, JPG, PNG).",
|
|
143
|
-
// fr: "Téléversez une facture récente ou un relevé bancaire (PDF, JPG, PNG)."
|
|
144
|
-
// },
|
|
145
|
-
// ui: {
|
|
146
|
-
// icon: "file-upload-icon.png",
|
|
147
|
-
// themeColor: "#2DBD60",
|
|
148
|
-
// buttonText: { en: "Upload", fr: "Téléverser" }
|
|
149
|
-
// },
|
|
150
|
-
// config: {
|
|
151
|
-
// allowed_formats: ["pdf", "jpg", "png"],
|
|
152
|
-
// max_size_mb: 10,
|
|
153
|
-
// required: true
|
|
154
|
-
// } as const
|
|
155
|
-
// },
|
|
156
|
-
|
|
157
136
|
]
|
|
158
137
|
};
|
|
159
138
|
|
|
160
|
-
export const TemplateKYCExample: React.FC<{
|
|
161
|
-
onComplete: (data: VerificationState) => void;
|
|
162
|
-
onCancel: () => void;
|
|
163
|
-
onError: (error: string) => void;
|
|
164
|
-
language: string;
|
|
139
|
+
export const TemplateKYCExample: React.FC<{
|
|
140
|
+
onComplete: (data: VerificationState) => void;
|
|
141
|
+
onCancel: () => void;
|
|
142
|
+
onError: (error: string) => void;
|
|
143
|
+
language: string;
|
|
165
144
|
API_KEY?: string;
|
|
166
145
|
templateId?: string;
|
|
167
146
|
template?: KYCTemplate;
|
|
168
|
-
|
|
147
|
+
env?: KycEnvironment;
|
|
148
|
+
existingSessionId?: string;
|
|
149
|
+
initialStep?: number;
|
|
150
|
+
}> = ({ onComplete, onCancel, onError, language, API_KEY, templateId, template, env = 'PRODUCTION', existingSessionId, initialStep }) => {
|
|
169
151
|
const handleComplete = (data: VerificationState) => {
|
|
170
152
|
console.log('KYC Template completed with data:', data);
|
|
171
153
|
onComplete(data);
|
|
@@ -182,24 +164,27 @@ export const TemplateKYCExample: React.FC<{
|
|
|
182
164
|
onError(error);
|
|
183
165
|
};
|
|
184
166
|
|
|
167
|
+
// Transform backend template to SDK format
|
|
185
168
|
// Determine which template to use: prefer templateId for dynamic loading, then template prop, then fallback to hardcoded
|
|
186
169
|
const templateToUse = templateId ? undefined : (template || advancedVerificationTemplate);
|
|
187
170
|
|
|
188
171
|
return (
|
|
189
|
-
<SafeAreaView style={{ flex: 1
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
172
|
+
<SafeAreaView style={{ flex: 1, paddingVertical: 25 }}>
|
|
173
|
+
<View style={{ flex: 1 }}>
|
|
174
|
+
<TemplateKYCFlow
|
|
175
|
+
template={templateToUse}
|
|
176
|
+
templateId={templateId}
|
|
177
|
+
onComplete={handleComplete}
|
|
178
|
+
onError={handleError}
|
|
179
|
+
onCancel={handleCancel}
|
|
180
|
+
language={language} // ou "en" pour l'anglais
|
|
181
|
+
API_KEY={API_KEY}
|
|
182
|
+
env={env}
|
|
183
|
+
existingSessionId={existingSessionId}
|
|
184
|
+
initialStep={initialStep}
|
|
185
|
+
/>
|
|
186
|
+
</View>
|
|
187
|
+
</SafeAreaView>
|
|
202
188
|
);
|
|
203
189
|
};
|
|
204
190
|
|
|
205
|
-
|
|
@@ -14,6 +14,11 @@ import { ReviewSubmitTemplate } from './KYCElements/ReviewSubmitTemplate';
|
|
|
14
14
|
import { VerificationProgressTemplate } from './KYCElements/VerificationProgressTemplate';
|
|
15
15
|
import { useTemplateLoader } from '../hooks/useTemplateLoader';
|
|
16
16
|
import { WelcomeTemplate } from './KYCElements/WelcomeTemplate';
|
|
17
|
+
import { EmailVerificationTemplate } from './KYCElements/EmailVerificationTemplate';
|
|
18
|
+
import { PhoneVerificationTemplate } from './KYCElements/PhoneVerificationTemplate';
|
|
19
|
+
import { PersonalInformationTemplate } from './KYCElements/PersonalInformationTemplate';
|
|
20
|
+
import { AdditionalDocumentsTemplate } from './KYCElements/AdditionalDocumentsTemplate';
|
|
21
|
+
import { KycEnvironment } from '../types/env.types';
|
|
17
22
|
|
|
18
23
|
interface TemplateKYCFlowProps {
|
|
19
24
|
template?: KYCTemplate; // Format SDK direct (existing, now optional)
|
|
@@ -23,6 +28,9 @@ interface TemplateKYCFlowProps {
|
|
|
23
28
|
language?: string;
|
|
24
29
|
onCancel?: () => void;
|
|
25
30
|
API_KEY?: string; // Required if templateId is used
|
|
31
|
+
env?: KycEnvironment; // Environment mode: PRODUCTION or SANDBOX
|
|
32
|
+
existingSessionId?: string;
|
|
33
|
+
initialStep?: number; // Initial step index to resume verification
|
|
26
34
|
}
|
|
27
35
|
|
|
28
36
|
export const TemplateKYCFlow: React.FC<TemplateKYCFlowProps> = ({
|
|
@@ -33,6 +41,9 @@ export const TemplateKYCFlow: React.FC<TemplateKYCFlowProps> = ({
|
|
|
33
41
|
language = 'fr',
|
|
34
42
|
onCancel,
|
|
35
43
|
API_KEY,
|
|
44
|
+
env = 'PRODUCTION',
|
|
45
|
+
existingSessionId,
|
|
46
|
+
initialStep,
|
|
36
47
|
}) => {
|
|
37
48
|
const { t } = useI18n();
|
|
38
49
|
const { template: loadedTemplate, isLoading, error, loadTemplate } = useTemplateLoader();
|
|
@@ -123,6 +134,9 @@ export const TemplateKYCFlow: React.FC<TemplateKYCFlowProps> = ({
|
|
|
123
134
|
onCancel={OnCancel}
|
|
124
135
|
initialLanguage={language}
|
|
125
136
|
apiKey={API_KEY}
|
|
137
|
+
env={env}
|
|
138
|
+
existingSessionId={existingSessionId}
|
|
139
|
+
initialStep={initialStep}
|
|
126
140
|
>
|
|
127
141
|
<TemplateKYCFlowContent onCancel={OnCancel} />
|
|
128
142
|
</TemplateKYCFlowProvider>
|
|
@@ -187,6 +201,18 @@ const TemplateKYCFlowContent: React.FC<{ onCancel?: () => void }> = ({ onCancel
|
|
|
187
201
|
case 'review_submit':
|
|
188
202
|
return <ReviewSubmitTemplate {...commonProps} />;
|
|
189
203
|
|
|
204
|
+
case 'email_verification':
|
|
205
|
+
return <EmailVerificationTemplate {...commonProps} />;
|
|
206
|
+
|
|
207
|
+
case 'phone_verification':
|
|
208
|
+
return <PhoneVerificationTemplate {...commonProps} />;
|
|
209
|
+
|
|
210
|
+
case 'personal_information':
|
|
211
|
+
return <PersonalInformationTemplate {...commonProps} />;
|
|
212
|
+
|
|
213
|
+
case 'additional_documents':
|
|
214
|
+
return <AdditionalDocumentsTemplate {...commonProps} />;
|
|
215
|
+
|
|
190
216
|
case 'verification_progress':
|
|
191
217
|
return <VerificationProgressTemplate {...commonProps} />;
|
|
192
218
|
|
|
@@ -238,7 +264,7 @@ const TemplateKYCFlowContent: React.FC<{ onCancel?: () => void }> = ({ onCancel
|
|
|
238
264
|
) : null}
|
|
239
265
|
|
|
240
266
|
{/* Contenu principal */}
|
|
241
|
-
<ScrollView
|
|
267
|
+
<ScrollView
|
|
242
268
|
style={styles.scrollView}
|
|
243
269
|
contentContainerStyle={styles.content}
|
|
244
270
|
showsVerticalScrollIndicator={Platform.OS === 'web'}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { BackendEnvironment } from '../types/env.types';
|
|
2
|
+
|
|
3
|
+
class KYCConfig {
|
|
4
|
+
private static instance: KYCConfig;
|
|
5
|
+
private backendEnvironment: BackendEnvironment = 'PRODUCTION';
|
|
6
|
+
|
|
7
|
+
private backendUrls: Record<BackendEnvironment, string> = {
|
|
8
|
+
PRODUCTION: 'https://service.sanctumkey.com/api/v1',
|
|
9
|
+
TEST: 'https://test-service.sanctumkey.com/api/v1', // Placeholder URL
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
private constructor() { }
|
|
13
|
+
|
|
14
|
+
public static getInstance(): KYCConfig {
|
|
15
|
+
if (!KYCConfig.instance) {
|
|
16
|
+
KYCConfig.instance = new KYCConfig();
|
|
17
|
+
}
|
|
18
|
+
return KYCConfig.instance;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public setBackendEnvironment(env: BackendEnvironment) {
|
|
22
|
+
this.backendEnvironment = env;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public getBackendUrl(): string {
|
|
26
|
+
return this.backendUrls[this.backendEnvironment];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public getBackendEnvironment(): BackendEnvironment {
|
|
30
|
+
return this.backendEnvironment;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default KYCConfig.getInstance();
|
|
@@ -16,6 +16,7 @@ const DEFAULT_CONFIG: AllowedDomainConfig = {
|
|
|
16
16
|
'www.transfergratis.com',
|
|
17
17
|
'admin.transfergratis.com',
|
|
18
18
|
'dashboard.transfergratis.com',
|
|
19
|
+
'preweb.transfergratis.net',
|
|
19
20
|
// Add other trusted domains here
|
|
20
21
|
],
|
|
21
22
|
enforceHttps: true,
|
|
@@ -45,7 +46,7 @@ export const getAllowedDomainsConfig = (): AllowedDomainConfig => {
|
|
|
45
46
|
*/
|
|
46
47
|
export const isDomainAllowed = (domain: string): boolean => {
|
|
47
48
|
const config = getAllowedDomainsConfig();
|
|
48
|
-
|
|
49
|
+
|
|
49
50
|
// Allow localhost in development
|
|
50
51
|
if (config.allowLocalhost && (domain === 'localhost' || domain.startsWith('127.0.0.1'))) {
|
|
51
52
|
return true;
|
|
@@ -57,12 +58,12 @@ export const isDomainAllowed = (domain: string): boolean => {
|
|
|
57
58
|
if (domain === allowedDomain) {
|
|
58
59
|
return true;
|
|
59
60
|
}
|
|
60
|
-
|
|
61
|
+
|
|
61
62
|
// Subdomain match (e.g., app.transfergratis.com matches transfergratis.com)
|
|
62
63
|
if (domain.endsWith('.' + allowedDomain)) {
|
|
63
64
|
return true;
|
|
64
65
|
}
|
|
65
|
-
|
|
66
|
+
|
|
66
67
|
return false;
|
|
67
68
|
});
|
|
68
69
|
};
|
|
@@ -71,30 +72,10 @@ export const isDomainAllowed = (domain: string): boolean => {
|
|
|
71
72
|
* Validate if a URL is allowed for callback
|
|
72
73
|
*/
|
|
73
74
|
export const isCallbackUrlAllowed = (url: string): { allowed: boolean; reason?: string } => {
|
|
74
|
-
const config = getAllowedDomainsConfig();
|
|
75
|
-
|
|
76
75
|
try {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
//
|
|
80
|
-
if (config.enforceHttps && urlObj.protocol !== 'https:') {
|
|
81
|
-
// Allow http for localhost in development
|
|
82
|
-
if (!(config.allowLocalhost && (urlObj.hostname === 'localhost' || urlObj.hostname.startsWith('127.0.0.1')))) {
|
|
83
|
-
return {
|
|
84
|
-
allowed: false,
|
|
85
|
-
reason: 'HTTPS required for callback URLs',
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Check domain
|
|
91
|
-
if (!isDomainAllowed(urlObj.hostname)) {
|
|
92
|
-
return {
|
|
93
|
-
allowed: false,
|
|
94
|
-
reason: `Domain '${urlObj.hostname}' is not in the allowed list`,
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
76
|
+
// Check if valid URL
|
|
77
|
+
new URL(url);
|
|
78
|
+
// Allow all URLs for redirection as requested
|
|
98
79
|
return { allowed: true };
|
|
99
80
|
} catch (error) {
|
|
100
81
|
return {
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
OrientationVideoResult,
|
|
7
7
|
OrientationType
|
|
8
8
|
} from '../types/KYC.types';
|
|
9
|
+
import { KycEnvironment } from '../types/env.types';
|
|
9
10
|
import kycService from '../modules/api/KYCService';
|
|
10
11
|
|
|
11
12
|
export interface UseOrientationVideoReturn {
|
|
@@ -15,8 +16,8 @@ export interface UseOrientationVideoReturn {
|
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export const useOrientationVideo = (
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
config?: Partial<OrientationVideoConfig>,
|
|
20
|
+
env: KycEnvironment = 'PRODUCTION'
|
|
20
21
|
): UseOrientationVideoReturn => {
|
|
21
22
|
const defaultConfig: OrientationVideoConfig = {
|
|
22
23
|
duration: 10,
|
|
@@ -66,7 +67,7 @@ export const useOrientationVideo = (
|
|
|
66
67
|
setState(prev => ({ ...prev, isProcessing: true, error: null }));
|
|
67
68
|
|
|
68
69
|
try {
|
|
69
|
-
const result = await kycService.processOrientationVideo(state.recordedVideo);
|
|
70
|
+
const result = await kycService.processOrientationVideo(state.recordedVideo, env);
|
|
70
71
|
|
|
71
72
|
if (result.success && result.data) {
|
|
72
73
|
setState(prev => ({
|
|
@@ -93,7 +94,7 @@ export const useOrientationVideo = (
|
|
|
93
94
|
}));
|
|
94
95
|
throw error;
|
|
95
96
|
}
|
|
96
|
-
}, [state.recordedVideo, state.isProcessing,
|
|
97
|
+
}, [state.recordedVideo, state.isProcessing, env]);
|
|
97
98
|
|
|
98
99
|
const retake = useCallback(() => {
|
|
99
100
|
if (state.retakeCount >= finalConfig.maxRetakes) {
|