@transfergratis/react-native-sdk 0.1.28 → 0.1.29
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/components/EnhancedCameraView.js +1 -1
- package/build/components/EnhancedCameraView.js.map +1 -1
- package/build/components/KYCElements/CountrySelectionTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/CountrySelectionTemplate.js +13 -42
- package/build/components/KYCElements/CountrySelectionTemplate.js.map +1 -1
- package/build/components/KYCElements/IDCardCapture.d.ts.map +1 -1
- package/build/components/KYCElements/IDCardCapture.js +64 -31
- package/build/components/KYCElements/IDCardCapture.js.map +1 -1
- package/build/components/KYCElements/SelfieCaptureTemplate.js +2 -2
- package/build/components/KYCElements/SelfieCaptureTemplate.js.map +1 -1
- package/build/hooks/useTemplateKYCFlow.js +1 -1
- package/build/hooks/useTemplateKYCFlow.js.map +1 -1
- package/build/modules/api/CardAuthentification.d.ts +15 -7
- package/build/modules/api/CardAuthentification.d.ts.map +1 -1
- package/build/modules/api/CardAuthentification.js +215 -50
- package/build/modules/api/CardAuthentification.js.map +1 -1
- package/build/modules/api/KYCService.d.ts +2 -0
- package/build/modules/api/KYCService.d.ts.map +1 -1
- package/build/modules/api/KYCService.js +16 -19
- package/build/modules/api/KYCService.js.map +1 -1
- package/build/modules/camera/VisionCameraModule.js +2 -2
- package/build/modules/camera/VisionCameraModule.js.map +1 -1
- package/build/utils/cropByObb.d.ts +8 -0
- package/build/utils/cropByObb.d.ts.map +1 -1
- package/build/utils/cropByObb.js +20 -3
- package/build/utils/cropByObb.js.map +1 -1
- package/build/utils/pathToBase64.js +1 -1
- package/build/utils/pathToBase64.js.map +1 -1
- package/package.json +1 -1
- package/src/components/EnhancedCameraView.tsx +1 -1
- package/src/components/KYCElements/CountrySelectionTemplate.tsx +24 -52
- package/src/components/KYCElements/IDCardCapture.tsx +115 -86
- package/src/components/KYCElements/SelfieCaptureTemplate.tsx +2 -2
- package/src/hooks/useTemplateKYCFlow.tsx +1 -1
- package/src/modules/api/CardAuthentification.ts +289 -64
- package/src/modules/api/KYCService.ts +25 -33
- package/src/modules/camera/VisionCameraModule.ts +2 -2
- package/src/utils/cropByObb.ts +22 -3
- package/src/utils/pathToBase64.ts +1 -1
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
import kycService, { authentification, errorMessage, truncateFields } from "./KYCService";
|
|
2
|
-
import { cropByObb,
|
|
2
|
+
import { cropByObb, getObbConfidence, OBB_CONFIDENCE_THRESHOLD } from "../../utils/cropByObb";
|
|
3
3
|
import { logger } from "../../utils/logger";
|
|
4
|
+
import { countryData } from "../../config/countriesData";
|
|
4
5
|
export async function frontVerification(result, env = 'PRODUCTION') {
|
|
5
6
|
try {
|
|
6
7
|
console.log("Front verification START", JSON.stringify({ result }, null, 2));
|
|
7
8
|
logger.log("Front verification", JSON.stringify({ result }, null, 2));
|
|
8
|
-
// SANDBOX mode
|
|
9
|
+
// SANDBOX mode
|
|
9
10
|
if (env === 'SANDBOX') {
|
|
10
11
|
console.log("SANDBOX mode: Skipping AI verification for front document");
|
|
11
12
|
logger.log("SANDBOX mode: Returning mock front verification response");
|
|
12
|
-
const mockBbox = { minX:
|
|
13
|
+
const mockBbox = { minX: 400, minY: 800, width: 2200, height: 1400 };
|
|
13
14
|
const mockResponse = {
|
|
14
15
|
result: true,
|
|
15
16
|
detail: [{ confidence: 0.95 }],
|
|
16
|
-
card_obb: {
|
|
17
|
+
card_obb: [{
|
|
18
|
+
obb: [[400, 800], [2600, 800], [2600, 2200], [400, 2200]],
|
|
19
|
+
confidence: 0.95,
|
|
20
|
+
card_in_frame: true,
|
|
21
|
+
cropped_sides: []
|
|
22
|
+
}],
|
|
17
23
|
bbox: mockBbox,
|
|
18
|
-
...(result.regionMapping
|
|
24
|
+
...(result.regionMapping?.authMethod?.includes('MRZ') ? {
|
|
19
25
|
mrz: {
|
|
20
26
|
success: true,
|
|
21
27
|
parsed_data: {
|
|
@@ -29,21 +35,30 @@ export async function frontVerification(result, env = 'PRODUCTION') {
|
|
|
29
35
|
return mockResponse;
|
|
30
36
|
}
|
|
31
37
|
const token = await authentification();
|
|
38
|
+
// Cast the response so TypeScript knows about card_obb
|
|
32
39
|
const detected = await kycService.detectFaceOnId(result?.path || '', token, result?.selectedDocumentType || '', env);
|
|
33
40
|
if (!detected.result) {
|
|
34
41
|
throw new Error('Aucun visage détecté sur la carte. Veuillez reprendre.');
|
|
35
42
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
43
|
+
const cardData = detected.card_obb && Array.isArray(detected.card_obb) && detected.card_obb.length > 0
|
|
44
|
+
? detected.card_obb[0]
|
|
45
|
+
: null;
|
|
46
|
+
// --- STRICT FRAMING CHECK ---
|
|
47
|
+
if (cardData && typeof cardData.card_in_frame !== 'undefined') {
|
|
48
|
+
const isCardInFrame = cardData.card_in_frame === true;
|
|
49
|
+
const hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;
|
|
50
|
+
// If it is NOT in the frame, OR if any side is cropped, block progression
|
|
51
|
+
if (!isCardInFrame || hasCroppedSides) {
|
|
52
|
+
logger.log(`Framing failed. Cropped sides: ${hasCroppedSides ? cardData.cropped_sides?.join(', ') : 'none'}`);
|
|
53
|
+
throw new Error('CARD_NOT_FULLY_IN_FRAME');
|
|
54
|
+
}
|
|
41
55
|
}
|
|
56
|
+
// Check Confidence Threshold
|
|
42
57
|
const obbConfidence = getObbConfidence(detected.card_obb);
|
|
43
58
|
if (obbConfidence !== null && obbConfidence < OBB_CONFIDENCE_THRESHOLD) {
|
|
44
59
|
throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');
|
|
45
60
|
}
|
|
46
|
-
// Optional: crop image using card_obb for better MRZ/barcode extraction
|
|
61
|
+
// Optional: crop image using card_obb for better MRZ/barcode extraction
|
|
47
62
|
let croppedBase64;
|
|
48
63
|
let bbox;
|
|
49
64
|
let mrz;
|
|
@@ -53,7 +68,8 @@ export async function frontVerification(result, env = 'PRODUCTION') {
|
|
|
53
68
|
bbox = crop.bbox;
|
|
54
69
|
}
|
|
55
70
|
catch { }
|
|
56
|
-
|
|
71
|
+
// MRZ Extraction
|
|
72
|
+
if (result.regionMapping?.authMethod?.length > 0 && result.regionMapping.authMethod.includes('MRZ')) {
|
|
57
73
|
mrz = await kycService.extractMrzText({
|
|
58
74
|
fileUri: result.path || '',
|
|
59
75
|
docType: result?.selectedDocumentType || '',
|
|
@@ -71,17 +87,125 @@ export async function frontVerification(result, env = 'PRODUCTION') {
|
|
|
71
87
|
throw new Error(e?.message || 'Erreur de détection du visage');
|
|
72
88
|
}
|
|
73
89
|
}
|
|
90
|
+
// export async function frontVerification(
|
|
91
|
+
// result: { path?: string, regionMapping: { authMethod: string[], mrzTypes: string[] }, selectedDocumentType: string, code: string, currentSide: string, templatePath?: string, mrzType?: string },
|
|
92
|
+
// env: KycEnvironment = 'PRODUCTION'
|
|
93
|
+
// ) {
|
|
94
|
+
// try {
|
|
95
|
+
// console.log("Front verification START", JSON.stringify({ result }, null, 2));
|
|
96
|
+
// logger.log("Front verification", JSON.stringify({ result }, null, 2));
|
|
97
|
+
// // SANDBOX mode
|
|
98
|
+
// if (env === 'SANDBOX') {
|
|
99
|
+
// console.log("SANDBOX mode: Skipping AI verification for front document");
|
|
100
|
+
// logger.log("SANDBOX mode: Returning mock front verification response");
|
|
101
|
+
// const mockBbox: IBbox = { minX: 400, minY: 800, width: 2200, height: 1400 };
|
|
102
|
+
// // ==========================================
|
|
103
|
+
// // 🧪 TEST OVERRIDE (SANDBOX) 🧪
|
|
104
|
+
// // Immediately throw the error to test the UI
|
|
105
|
+
// // ==========================================
|
|
106
|
+
// throw new Error('CARD_NOT_FULLY_IN_FRAME');
|
|
107
|
+
// const mockResponse = {
|
|
108
|
+
// result: true,
|
|
109
|
+
// detail: [{ confidence: 0.95 }],
|
|
110
|
+
// card_obb: [{
|
|
111
|
+
// obb: [[400,800], [2600,800], [2600,2200], [400,2200]],
|
|
112
|
+
// confidence: 0.95,
|
|
113
|
+
// card_in_frame: false, // Hardcoded to false
|
|
114
|
+
// cropped_sides: ['left', 'top'] // Hardcoded cropped sides
|
|
115
|
+
// }],
|
|
116
|
+
// bbox: mockBbox,
|
|
117
|
+
// ...(result.regionMapping?.authMethod?.includes('MRZ') ? {
|
|
118
|
+
// mrz: {
|
|
119
|
+
// success: true,
|
|
120
|
+
// parsed_data: {
|
|
121
|
+
// status: 'success',
|
|
122
|
+
// document_type: result.selectedDocumentType,
|
|
123
|
+
// mrz_type: result.mrzType || 'TD1'
|
|
124
|
+
// }
|
|
125
|
+
// }
|
|
126
|
+
// } : {})
|
|
127
|
+
// };
|
|
128
|
+
// return mockResponse;
|
|
129
|
+
// }
|
|
130
|
+
// const token = await authentification();
|
|
131
|
+
// // Cast the response so TypeScript knows about card_obb
|
|
132
|
+
// const detected = await kycService.detectFaceOnId(result?.path || '', token, result?.selectedDocumentType || '', env) as ApiVerificationResponse;
|
|
133
|
+
// // ==========================================
|
|
134
|
+
// // 🧪 TEST OVERRIDE (PRODUCTION) 🧪
|
|
135
|
+
// // Hijack the real API response and force it to look cropped
|
|
136
|
+
// // ==========================================
|
|
137
|
+
// if (detected.card_obb && Array.isArray(detected.card_obb) && detected.card_obb.length > 0) {
|
|
138
|
+
// detected.card_obb[0].card_in_frame = false;
|
|
139
|
+
// detected.card_obb[0].cropped_sides = ['left', 'top'];
|
|
140
|
+
// console.warn("⚠️ FORCING CROPPED ERROR FOR UI TESTING ⚠️");
|
|
141
|
+
// }
|
|
142
|
+
// // ==========================================
|
|
143
|
+
// if (!detected.result) {
|
|
144
|
+
// throw new Error('Aucun visage détecté sur la carte. Veuillez reprendre.');
|
|
145
|
+
// }
|
|
146
|
+
// const cardData = detected.card_obb && Array.isArray(detected.card_obb) && detected.card_obb.length > 0
|
|
147
|
+
// ? detected.card_obb[0]
|
|
148
|
+
// : null;
|
|
149
|
+
// // --- STRICT FRAMING CHECK ---
|
|
150
|
+
// if (cardData && typeof cardData.card_in_frame !== 'undefined') {
|
|
151
|
+
// const isCardInFrame = cardData.card_in_frame === true;
|
|
152
|
+
// const hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;
|
|
153
|
+
// // If it is NOT in the frame, OR if any side is cropped, block progression
|
|
154
|
+
// if (!isCardInFrame || hasCroppedSides) {
|
|
155
|
+
// logger.log(`Framing failed. Cropped sides: ${hasCroppedSides ? cardData.cropped_sides?.join(', ') : 'none'}`);
|
|
156
|
+
// throw new Error('CARD_NOT_FULLY_IN_FRAME');
|
|
157
|
+
// }
|
|
158
|
+
// }
|
|
159
|
+
// // Check Confidence Threshold
|
|
160
|
+
// const obbConfidence = getObbConfidence(detected.card_obb);
|
|
161
|
+
// if (obbConfidence !== null && obbConfidence < OBB_CONFIDENCE_THRESHOLD) {
|
|
162
|
+
// throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');
|
|
163
|
+
// }
|
|
164
|
+
// // Optional: crop image using card_obb for better MRZ/barcode extraction
|
|
165
|
+
// let croppedBase64: string | undefined;
|
|
166
|
+
// let bbox: IBbox | undefined;
|
|
167
|
+
// let mrz: any | undefined;
|
|
168
|
+
// try {
|
|
169
|
+
// const crop = await cropByObb(result?.path || '', detected.card_obb);
|
|
170
|
+
// croppedBase64 = crop.base64;
|
|
171
|
+
// bbox = crop.bbox;
|
|
172
|
+
// } catch { }
|
|
173
|
+
// // MRZ Extraction
|
|
174
|
+
// if (result.regionMapping?.authMethod?.length > 0 && result.regionMapping.authMethod.includes('MRZ')) {
|
|
175
|
+
// mrz = await kycService.extractMrzText(
|
|
176
|
+
// {
|
|
177
|
+
// fileUri: result.path || '',
|
|
178
|
+
// docType: result?.selectedDocumentType || '',
|
|
179
|
+
// docRegion: result?.code || "",
|
|
180
|
+
// postfix: result?.currentSide,
|
|
181
|
+
// token: token,
|
|
182
|
+
// template_path: result?.templatePath || '',
|
|
183
|
+
// mrz_type: result?.mrzType || ''
|
|
184
|
+
// },
|
|
185
|
+
// env
|
|
186
|
+
// );
|
|
187
|
+
// }
|
|
188
|
+
// return { ...detected, croppedBase64, bbox, ...(mrz ? { mrz } : {}) };
|
|
189
|
+
// } catch (e: any) {
|
|
190
|
+
// logger.error('Error front verification:', JSON.stringify(errorMessage(e), null, 2));
|
|
191
|
+
// throw new Error(e?.message || 'Erreur de détection du visage');
|
|
192
|
+
// }
|
|
193
|
+
// }
|
|
74
194
|
export async function backVerification(result, env = 'PRODUCTION') {
|
|
75
195
|
try {
|
|
76
196
|
if (!result.path)
|
|
77
197
|
throw new Error('No path provided');
|
|
78
198
|
logger.log("result.regionMapping", result.regionMapping, result.currentSide, result.code);
|
|
79
|
-
// SANDBOX mode: skip AI verification and return mock response
|
|
80
199
|
if (env === 'SANDBOX') {
|
|
81
200
|
console.log("SANDBOX mode: Skipping AI verification for back document");
|
|
82
|
-
|
|
83
|
-
const
|
|
84
|
-
|
|
201
|
+
const mockBbox = { minX: 400, minY: 800, width: 2200, height: 1400 };
|
|
202
|
+
const mockCardObb = [{
|
|
203
|
+
obb: [[400, 800], [2600, 800], [2600, 2200], [400, 2200]],
|
|
204
|
+
confidence: 0.95,
|
|
205
|
+
card_in_frame: true,
|
|
206
|
+
cropped_sides: []
|
|
207
|
+
}];
|
|
208
|
+
if (result.regionMapping?.authMethod?.includes('MRZ')) {
|
|
85
209
|
return {
|
|
86
210
|
success: true,
|
|
87
211
|
parsed_data: {
|
|
@@ -90,20 +214,54 @@ export async function backVerification(result, env = 'PRODUCTION') {
|
|
|
90
214
|
mrz_type: result.mrzType || 'TD1'
|
|
91
215
|
},
|
|
92
216
|
bbox: mockBbox,
|
|
93
|
-
card_obb:
|
|
217
|
+
card_obb: mockCardObb
|
|
94
218
|
};
|
|
95
219
|
}
|
|
96
|
-
else if (result.regionMapping
|
|
220
|
+
else if (result.regionMapping?.authMethod?.includes('2D_barcode')) {
|
|
97
221
|
return {
|
|
98
222
|
barcode_data: 'SANDBOX_MOCK_BARCODE',
|
|
99
223
|
bbox: mockBbox,
|
|
100
|
-
card_obb:
|
|
224
|
+
card_obb: mockCardObb
|
|
101
225
|
};
|
|
102
226
|
}
|
|
103
227
|
return { bbox: mockBbox };
|
|
104
228
|
}
|
|
105
229
|
const token = await authentification();
|
|
106
|
-
|
|
230
|
+
logger.log("1. Checking template and framing for back document...");
|
|
231
|
+
const templateResponse = await kycService.checkTemplateType({
|
|
232
|
+
fileUri: result.path,
|
|
233
|
+
docType: result.selectedDocumentType,
|
|
234
|
+
docRegion: result.code,
|
|
235
|
+
postfix: 'back',
|
|
236
|
+
token: token
|
|
237
|
+
}, env);
|
|
238
|
+
// STRICT FRAMING CHECK
|
|
239
|
+
const cardData = templateResponse?.card_obb && Array.isArray(templateResponse.card_obb) && templateResponse.card_obb.length > 0
|
|
240
|
+
? templateResponse.card_obb[0]
|
|
241
|
+
: null;
|
|
242
|
+
if (cardData && typeof cardData.card_in_frame !== 'undefined') {
|
|
243
|
+
const isCardInFrame = cardData.card_in_frame === true;
|
|
244
|
+
const hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;
|
|
245
|
+
if (!isCardInFrame || hasCroppedSides) {
|
|
246
|
+
logger.log(`Back Framing failed. Cropped sides: ${hasCroppedSides ? cardData.cropped_sides?.join(', ') : 'none'}`);
|
|
247
|
+
throw new Error('CARD_NOT_FULLY_IN_FRAME');
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
const obbConf = getObbConfidence(templateResponse?.card_obb);
|
|
251
|
+
if (obbConf !== null && obbConf < OBB_CONFIDENCE_THRESHOLD) {
|
|
252
|
+
throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');
|
|
253
|
+
}
|
|
254
|
+
const activeTemplatePath = templateResponse.template_path || result.templatePath || '';
|
|
255
|
+
if (activeTemplatePath) {
|
|
256
|
+
const expectedCountryName = countryData[result.code]?.name_en || '';
|
|
257
|
+
const hasCodeMatch = activeTemplatePath.includes(`_${result.code}_`);
|
|
258
|
+
const hasNameMatch = expectedCountryName && activeTemplatePath.toLowerCase().includes(expectedCountryName.toLowerCase());
|
|
259
|
+
if (!hasCodeMatch && !hasNameMatch) {
|
|
260
|
+
logger.log(`Template mismatch! Expected country: ${result.code} (${expectedCountryName}), Detected: ${activeTemplatePath}`);
|
|
261
|
+
throw new Error(`Le document ne correspond pas au pays sélectionné (${result.code}).`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
logger.log("Framing and Country Template verified successfully. Proceeding to Data Extraction.");
|
|
107
265
|
const tryMrzWithBarcodeFallback = async () => {
|
|
108
266
|
try {
|
|
109
267
|
logger.log("Tentative d'extraction MRZ");
|
|
@@ -113,17 +271,14 @@ export async function backVerification(result, env = 'PRODUCTION') {
|
|
|
113
271
|
docRegion: result?.code || '',
|
|
114
272
|
postfix: 'back',
|
|
115
273
|
token: token,
|
|
116
|
-
template_path:
|
|
274
|
+
template_path: activeTemplatePath, // Use the verified template
|
|
117
275
|
mrz_type: result?.mrzType || ''
|
|
118
276
|
}, env);
|
|
119
|
-
const mrzObbConf = getObbConfidence(mrz.card_obb);
|
|
120
|
-
if (mrzObbConf !== null && mrzObbConf < OBB_CONFIDENCE_THRESHOLD) {
|
|
121
|
-
throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');
|
|
122
|
-
}
|
|
123
277
|
let bbox;
|
|
124
278
|
let croppedBase64;
|
|
125
279
|
try {
|
|
126
|
-
|
|
280
|
+
// We use the OBB from our template check to ensure clean cropping
|
|
281
|
+
const crop = await cropByObb(result?.path || '', templateResponse.card_obb);
|
|
127
282
|
bbox = crop.bbox;
|
|
128
283
|
croppedBase64 = crop.base64;
|
|
129
284
|
}
|
|
@@ -134,10 +289,6 @@ export async function backVerification(result, env = 'PRODUCTION') {
|
|
|
134
289
|
logger.log("MRZ échoué, tentative d'extraction barcode");
|
|
135
290
|
try {
|
|
136
291
|
const barcode = await kycService.extractBarcode({ fileUri: result.path, token: token }, env);
|
|
137
|
-
const barcodeObbConf = getObbConfidence(barcode.card_obb);
|
|
138
|
-
if (barcodeObbConf !== null && barcodeObbConf < OBB_CONFIDENCE_THRESHOLD) {
|
|
139
|
-
throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');
|
|
140
|
-
}
|
|
141
292
|
return barcode;
|
|
142
293
|
}
|
|
143
294
|
catch (barcodeError) {
|
|
@@ -145,28 +296,23 @@ export async function backVerification(result, env = 'PRODUCTION') {
|
|
|
145
296
|
}
|
|
146
297
|
}
|
|
147
298
|
};
|
|
148
|
-
if (result.regionMapping
|
|
299
|
+
if (result.regionMapping?.authMethod?.length > 2 && (!result?.mrzType || result?.mrzType.length === 0)) {
|
|
149
300
|
return await tryMrzWithBarcodeFallback();
|
|
150
301
|
}
|
|
151
|
-
if (result.regionMapping
|
|
302
|
+
if (result.regionMapping?.authMethod?.length > 0 && result.regionMapping.authMethod.includes('MRZ') && result?.mrzType && result?.mrzType.length > 0) {
|
|
152
303
|
try {
|
|
153
|
-
|
|
154
|
-
mrz = await kycService.extractMrzText({
|
|
304
|
+
const mrz = await kycService.extractMrzText({
|
|
155
305
|
fileUri: result.path,
|
|
156
306
|
docType: result?.selectedDocumentType || '',
|
|
157
307
|
docRegion: result?.code || '',
|
|
158
308
|
postfix: 'back',
|
|
159
309
|
token: token,
|
|
160
|
-
template_path:
|
|
310
|
+
template_path: activeTemplatePath,
|
|
161
311
|
mrz_type: result?.mrzType || ''
|
|
162
312
|
}, env);
|
|
163
|
-
const mrzObbConf = getObbConfidence(mrz.card_obb);
|
|
164
|
-
if (mrzObbConf !== null && mrzObbConf < OBB_CONFIDENCE_THRESHOLD) {
|
|
165
|
-
throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');
|
|
166
|
-
}
|
|
167
313
|
let bbox;
|
|
168
314
|
try {
|
|
169
|
-
const crop = await cropByObb(result?.path || '',
|
|
315
|
+
const crop = await cropByObb(result?.path || '', templateResponse.card_obb);
|
|
170
316
|
bbox = crop.bbox;
|
|
171
317
|
}
|
|
172
318
|
catch { }
|
|
@@ -176,17 +322,13 @@ export async function backVerification(result, env = 'PRODUCTION') {
|
|
|
176
322
|
throw new Error(`MRZ et barcode ont échoué. MRZ: ${mrzError?.message}, Barcode: ${mrzError?.message}`);
|
|
177
323
|
}
|
|
178
324
|
}
|
|
179
|
-
if (result.regionMapping
|
|
325
|
+
if (result.regionMapping?.authMethod?.length > 0 && result.regionMapping.authMethod.includes('2D_barcode')) {
|
|
180
326
|
try {
|
|
181
327
|
logger.log("Tentative d'extraction barcode");
|
|
182
328
|
const barcode = await kycService.extractBarcode({ fileUri: result.path, token: token }, env);
|
|
183
|
-
const barcodeObbConf = getObbConfidence(barcode.card_obb);
|
|
184
|
-
if (barcodeObbConf !== null && barcodeObbConf < OBB_CONFIDENCE_THRESHOLD) {
|
|
185
|
-
throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');
|
|
186
|
-
}
|
|
187
329
|
let bbox;
|
|
188
330
|
try {
|
|
189
|
-
const crop = await cropByObb(result?.path || '',
|
|
331
|
+
const crop = await cropByObb(result?.path || '', templateResponse.card_obb);
|
|
190
332
|
bbox = crop.bbox;
|
|
191
333
|
}
|
|
192
334
|
catch { }
|
|
@@ -199,6 +341,8 @@ export async function backVerification(result, env = 'PRODUCTION') {
|
|
|
199
341
|
return null;
|
|
200
342
|
}
|
|
201
343
|
catch (e) {
|
|
344
|
+
if (e?.message === 'CARD_NOT_FULLY_IN_FRAME')
|
|
345
|
+
throw e; // Bubble the strict framing error specifically
|
|
202
346
|
throw new Error(e?.message || 'Erreur de détection du MRZ ou barcode');
|
|
203
347
|
}
|
|
204
348
|
}
|
|
@@ -209,22 +353,43 @@ export async function backVerification(result, env = 'PRODUCTION') {
|
|
|
209
353
|
*/
|
|
210
354
|
export async function checkTemplateType(result, env = 'PRODUCTION') {
|
|
211
355
|
try {
|
|
212
|
-
// SANDBOX mode: skip AI verification and return mock response
|
|
213
356
|
if (env === 'SANDBOX') {
|
|
214
|
-
console.log("SANDBOX mode: Skipping AI template type check");
|
|
215
|
-
logger.log("SANDBOX mode: Returning mock template type response");
|
|
216
357
|
return {
|
|
217
358
|
template_path: `templates/${result.docType}_${result.docRegion}_${result.postfix}.jpg`,
|
|
218
|
-
card_obb: {
|
|
359
|
+
card_obb: [{
|
|
360
|
+
obb: [[400, 800], [2600, 800], [2600, 2200], [400, 2200]],
|
|
361
|
+
confidence: 0.95,
|
|
362
|
+
card_in_frame: true,
|
|
363
|
+
cropped_sides: []
|
|
364
|
+
}]
|
|
219
365
|
};
|
|
220
366
|
}
|
|
221
367
|
const token = await authentification();
|
|
222
368
|
const templateType = await kycService.checkTemplateType({ fileUri: result.path || '', docType: result?.docType, docRegion: result?.docRegion || "", postfix: result?.postfix, token: token }, env);
|
|
369
|
+
const cardData = templateType.card_obb && Array.isArray(templateType.card_obb) && templateType.card_obb.length > 0
|
|
370
|
+
? templateType.card_obb[0]
|
|
371
|
+
: null;
|
|
372
|
+
if (cardData && typeof cardData.card_in_frame !== 'undefined') {
|
|
373
|
+
const isCardInFrame = cardData.card_in_frame === true;
|
|
374
|
+
const hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;
|
|
375
|
+
if (!isCardInFrame || hasCroppedSides) {
|
|
376
|
+
logger.log(`Template Framing failed. Cropped sides: ${hasCroppedSides ? cardData.cropped_sides?.join(', ') : 'none'}`);
|
|
377
|
+
throw new Error('CARD_NOT_FULLY_IN_FRAME');
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
const LPIPS_THRESHOLD = 0.75;
|
|
381
|
+
if (templateType.lpips_score !== undefined && templateType.lpips_score > LPIPS_THRESHOLD) {
|
|
382
|
+
logger.log(`🛑 Country Mismatch! LPIPS Score too high: ${templateType.lpips_score}`);
|
|
383
|
+
throw new Error(`Le document présenté ne correspond pas au pays sélectionné (${result.docRegion}).`);
|
|
384
|
+
}
|
|
223
385
|
logger.log("templateType result", JSON.stringify(truncateFields(templateType), null, 2));
|
|
224
386
|
return templateType;
|
|
225
387
|
}
|
|
226
388
|
catch (e) {
|
|
227
389
|
logger.error('Error checking template type:', JSON.stringify(errorMessage(e), null, 2));
|
|
390
|
+
if (e?.message === 'CARD_NOT_FULLY_IN_FRAME' || e?.message?.includes('ne correspond pas')) {
|
|
391
|
+
throw e;
|
|
392
|
+
}
|
|
228
393
|
throw new Error(e?.message || 'Erreur de vérification du template');
|
|
229
394
|
}
|
|
230
395
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CardAuthentification.js","sourceRoot":"","sources":["../../../src/modules/api/CardAuthentification.ts"],"names":[],"mappings":"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","sourcesContent":["import kycService, { authentification, errorMessage, truncateFields } from \"./KYCService\";\nimport { cropByObb, getCardInFrame, getObbConfidence, OBB_CONFIDENCE_THRESHOLD } from \"../../utils/cropByObb\";\nimport { GovernmentDocumentType, IBbox } from \"../../types/KYC.types\";\nimport { KycEnvironment } from \"../../types/env.types\";\nimport { logger } from \"../../utils/logger\";\n\nexport async function frontVerification(result: { path?: string, regionMapping: { authMethod: string[], mrzTypes: string[] }, selectedDocumentType: string, code: string, currentSide: string, templatePath?: string, mrzType?: string }, env: KycEnvironment = 'PRODUCTION') {\n try {\n console.log(\"Front verification START\", JSON.stringify({ result }, null, 2));\n logger.log(\"Front verification\", JSON.stringify({ result }, null, 2));\n \n // SANDBOX mode: skip AI verification and return mock response\n if (env === 'SANDBOX') {\n console.log(\"SANDBOX mode: Skipping AI verification for front document\");\n logger.log(\"SANDBOX mode: Returning mock front verification response\");\n const mockBbox: IBbox = { minX: 50, minY: 50, width: 200, height: 200 };\n const mockResponse = {\n result: true,\n detail: [{ confidence: 0.95 }],\n card_obb: { x: 50, y: 50, width: 200, height: 200 },\n bbox: mockBbox,\n ...(result.regionMapping.authMethod.includes('MRZ') ? {\n mrz: {\n success: true,\n parsed_data: {\n status: 'success',\n document_type: result.selectedDocumentType,\n mrz_type: result.mrzType || 'TD1'\n }\n }\n } : {})\n };\n return mockResponse;\n }\n \n const token = await authentification();\n const detected = await kycService.detectFaceOnId(result?.path || '', token, result?.selectedDocumentType || '', env)\n\n if (!detected.result) {\n throw new Error('Aucun visage détecté sur la carte. Veuillez reprendre.');\n }\n\n // If the backend indicates that the card is not fully in frame, stop early\n const cardInFrame = getCardInFrame((detected as any).card_obb);\n if (cardInFrame === false) {\n // Use a stable error code; the UI maps this to a localized i18n message (cardNotFullyInFrame)\n throw new Error('CARD_NOT_FULLY_IN_FRAME');\n }\n\n const obbConfidence = getObbConfidence((detected as any).card_obb);\n if (obbConfidence !== null && obbConfidence < OBB_CONFIDENCE_THRESHOLD) {\n throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');\n }\n\n // Optional: crop image using card_obb for better MRZ/barcode extraction (only when confidence >= threshold)\n let croppedBase64: string | undefined;\n let bbox: IBbox | undefined;\n let mrz: any | undefined;\n try {\n const crop = await cropByObb(result?.path || '', (detected as any).card_obb);\n croppedBase64 = crop.base64;\n bbox = crop.bbox;\n } catch { }\n\n if (result.regionMapping.authMethod.length > 0 && result.regionMapping.authMethod.includes('MRZ')) {\n\n\n mrz = await kycService.extractMrzText(\n {\n fileUri: result.path || '',\n docType: result?.selectedDocumentType || '',\n docRegion: result?.code || \"\",\n postfix: result?.currentSide,\n token: token,\n template_path: result?.templatePath || '',\n mrz_type: result?.mrzType || ''\n },\n env)\n\n }\n\n return { ...detected, croppedBase64, bbox, ...(mrz ? { mrz } : {}) };\n } catch (e: any) {\n logger.error('Error front verification:', JSON.stringify(errorMessage(e), null, 2));\n throw new Error(e?.message || 'Erreur de détection du visage');\n }\n}\n\nexport async function backVerification(result: { path?: string, regionMapping: { authMethod: string[], mrzTypes: string[] }, selectedDocumentType: string, code: string, currentSide: string, templatePath?: string, mrzType?: string }, env: KycEnvironment = 'PRODUCTION') {\n try {\n if (!result.path) throw new Error('No path provided');\n logger.log(\"result.regionMapping\", result.regionMapping, result.currentSide, result.code);\n \n // SANDBOX mode: skip AI verification and return mock response\n if (env === 'SANDBOX') {\n console.log(\"SANDBOX mode: Skipping AI verification for back document\");\n logger.log(\"SANDBOX mode: Returning mock back verification response\");\n const mockBbox: IBbox = { minX: 50, minY: 50, width: 200, height: 200 };\n \n if (result.regionMapping.authMethod.includes('MRZ')) {\n return {\n success: true,\n parsed_data: {\n status: 'success',\n document_type: result.selectedDocumentType,\n mrz_type: result.mrzType || 'TD1'\n },\n bbox: mockBbox,\n card_obb: { x: 50, y: 50, width: 200, height: 200 }\n };\n } else if (result.regionMapping.authMethod.includes('2D_barcode')) {\n return {\n barcode_data: 'SANDBOX_MOCK_BARCODE',\n bbox: mockBbox,\n card_obb: { x: 50, y: 50, width: 200, height: 200 }\n };\n }\n return { bbox: mockBbox };\n }\n \n const token = await authentification();\n\n\n\n // Fonction helper pour essayer MRZ puis barcode en fallback\n const tryMrzWithBarcodeFallback = async () => {\n try {\n\n logger.log(\"Tentative d'extraction MRZ\");\n const mrz = await kycService.extractMrzText({\n fileUri: result.path!,\n docType: result?.selectedDocumentType || '',\n docRegion: result?.code || '',\n postfix: 'back',\n token: token,\n template_path: result?.templatePath || '',\n mrz_type: result?.mrzType || ''\n }, env);\n const mrzObbConf = getObbConfidence((mrz as any).card_obb);\n if (mrzObbConf !== null && mrzObbConf < OBB_CONFIDENCE_THRESHOLD) {\n throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');\n }\n let bbox: IBbox | undefined;\n let croppedBase64: string | undefined;\n\n try {\n const crop = await cropByObb(result?.path || '', (mrz as any).card_obb);\n bbox = crop.bbox;\n croppedBase64 = crop.base64;\n\n } catch { }\n return { ...mrz, bbox, croppedBase64 }\n } catch (mrzError: any) {\n logger.log(\"MRZ échoué, tentative d'extraction barcode\");\n try {\n const barcode = await kycService.extractBarcode({ fileUri: result.path!, token: token }, env);\n const barcodeObbConf = getObbConfidence((barcode as any).card_obb);\n if (barcodeObbConf !== null && barcodeObbConf < OBB_CONFIDENCE_THRESHOLD) {\n throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');\n }\n return barcode;\n } catch (barcodeError: any) {\n throw new Error(`MRZ et barcode ont échoué. MRZ: ${mrzError?.message}, Barcode: ${barcodeError?.message}`);\n }\n }\n };\n\n\n\n if (result.regionMapping.authMethod.length > 2 && (!result?.mrzType || result?.mrzType.length === 0)) {\n return await tryMrzWithBarcodeFallback();\n }\n\n if (result.regionMapping.authMethod.length > 0 && result.regionMapping.authMethod.includes('MRZ') && result?.mrzType && result?.mrzType.length > 0) {\n try {\n\n let mrz: any | undefined;\n mrz = await kycService.extractMrzText({\n fileUri: result.path!,\n docType: result?.selectedDocumentType || '',\n docRegion: result?.code || '',\n postfix: 'back',\n token: token,\n template_path: result?.templatePath || '',\n mrz_type: result?.mrzType || ''\n }, env);\n const mrzObbConf = getObbConfidence((mrz as any).card_obb);\n if (mrzObbConf !== null && mrzObbConf < OBB_CONFIDENCE_THRESHOLD) {\n throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');\n }\n let bbox: IBbox | undefined;\n try {\n const crop = await cropByObb(result?.path || '', (mrz as any).card_obb);\n bbox = crop.bbox;\n } catch { }\n return { ...mrz, bbox };\n } catch (mrzError: any) {\n throw new Error(`MRZ et barcode ont échoué. MRZ: ${mrzError?.message}, Barcode: ${mrzError?.message}`);\n }\n }\n\n if (result.regionMapping.authMethod.length > 0 && result.regionMapping.authMethod.includes('2D_barcode')) {\n try {\n logger.log(\"Tentative d'extraction barcode\");\n const barcode = await kycService.extractBarcode({ fileUri: result.path!, token: token }, env);\n const barcodeObbConf = getObbConfidence((barcode as any).card_obb);\n if (barcodeObbConf !== null && barcodeObbConf < OBB_CONFIDENCE_THRESHOLD) {\n throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');\n }\n let bbox: IBbox | undefined;\n try {\n const crop = await cropByObb(result?.path || '', (barcode as any).card_obb);\n bbox = crop.bbox;\n } catch { }\n return { ...barcode, bbox };\n } catch (barcodeError: any) {\n throw new Error(`Barcode et MRZ ont échoué. Barcode: ${barcodeError?.message}, MRZ: ${barcodeError?.message}`);\n }\n }\n return null;\n } catch (e: any) {\n throw new Error(e?.message || 'Erreur de détection du MRZ ou barcode');\n }\n}\n\n/**\n * Check template type\n * @param result \n * @returns \n */\nexport async function checkTemplateType(result: { path?: string, docType: string, docRegion: string, postfix: string }, env: KycEnvironment = 'PRODUCTION') {\n try {\n // SANDBOX mode: skip AI verification and return mock response\n if (env === 'SANDBOX') {\n console.log(\"SANDBOX mode: Skipping AI template type check\");\n logger.log(\"SANDBOX mode: Returning mock template type response\");\n return {\n template_path: `templates/${result.docType}_${result.docRegion}_${result.postfix}.jpg`,\n card_obb: { x: 50, y: 50, width: 200, height: 200 }\n };\n }\n \n const token = await authentification();\n const templateType = await kycService.checkTemplateType({ fileUri: result.path || '', docType: result?.docType as GovernmentDocumentType, docRegion: result?.docRegion || \"\", postfix: result?.postfix, token: token }, env);\n\n logger.log(\"templateType result\", JSON.stringify(truncateFields(templateType), null, 2));\n return templateType;\n } catch (e: any) {\n logger.error('Error checking template type:', JSON.stringify(errorMessage(e), null, 2));\n throw new Error(e?.message || 'Erreur de vérification du template');\n }\n}"]}
|
|
1
|
+
{"version":3,"file":"CardAuthentification.js","sourceRoot":"","sources":["../../../src/modules/api/CardAuthentification.ts"],"names":[],"mappings":"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","sourcesContent":["import kycService, { authentification, errorMessage, truncateFields } from \"./KYCService\";\nimport { cropByObb, getObbConfidence, OBB_CONFIDENCE_THRESHOLD } from \"../../utils/cropByObb\";\nimport { GovernmentDocumentType, IBbox } from \"../../types/KYC.types\";\nimport { KycEnvironment } from \"../../types/env.types\";\nimport { logger } from \"../../utils/logger\";\nimport { countryData } from \"../../config/countriesData\";\n\n// 1. Add this interface to tell TypeScript what the AI response actually looks like\ninterface CardObbData {\n obb: number[][];\n confidence: number;\n card_in_frame?: boolean;\n cropped_sides?: string[];\n}\n\ninterface ApiVerificationResponse {\n result?: boolean;\n detail?: any[];\n card_obb?: CardObbData[] | any; \n [key: string]: any; \n}\n\nexport async function frontVerification(\n result: { path?: string, regionMapping: { authMethod: string[], mrzTypes: string[] }, selectedDocumentType: string, code: string, currentSide: string, templatePath?: string, mrzType?: string }, \n env: KycEnvironment = 'PRODUCTION'\n) {\n try {\n console.log(\"Front verification START\", JSON.stringify({ result }, null, 2));\n logger.log(\"Front verification\", JSON.stringify({ result }, null, 2));\n \n // SANDBOX mode\n if (env === 'SANDBOX') {\n console.log(\"SANDBOX mode: Skipping AI verification for front document\");\n logger.log(\"SANDBOX mode: Returning mock front verification response\");\n const mockBbox: IBbox = { minX: 400, minY: 800, width: 2200, height: 1400 };\n \n const mockResponse = {\n result: true,\n detail: [{ confidence: 0.95 }],\n card_obb: [{\n obb: [[400,800], [2600,800], [2600,2200], [400,2200]],\n confidence: 0.95,\n card_in_frame: true,\n cropped_sides: []\n }],\n bbox: mockBbox,\n ...(result.regionMapping?.authMethod?.includes('MRZ') ? {\n mrz: {\n success: true,\n parsed_data: {\n status: 'success',\n document_type: result.selectedDocumentType,\n mrz_type: result.mrzType || 'TD1'\n }\n }\n } : {})\n };\n return mockResponse;\n }\n \n const token = await authentification();\n \n // Cast the response so TypeScript knows about card_obb\n const detected = await kycService.detectFaceOnId(result?.path || '', token, result?.selectedDocumentType || '', env) as ApiVerificationResponse;\n\n if (!detected.result) {\n throw new Error('Aucun visage détecté sur la carte. Veuillez reprendre.');\n }\n\n const cardData = detected.card_obb && Array.isArray(detected.card_obb) && detected.card_obb.length > 0 \n ? detected.card_obb[0] \n : null;\n\n // --- STRICT FRAMING CHECK ---\n if (cardData && typeof cardData.card_in_frame !== 'undefined') {\n const isCardInFrame = cardData.card_in_frame === true;\n const hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;\n\n // If it is NOT in the frame, OR if any side is cropped, block progression\n if (!isCardInFrame || hasCroppedSides) {\n logger.log(`Framing failed. Cropped sides: ${hasCroppedSides ? cardData.cropped_sides?.join(', ') : 'none'}`);\n throw new Error('CARD_NOT_FULLY_IN_FRAME');\n }\n }\n\n // Check Confidence Threshold\n const obbConfidence = getObbConfidence(detected.card_obb);\n if (obbConfidence !== null && obbConfidence < OBB_CONFIDENCE_THRESHOLD) {\n throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');\n }\n\n // Optional: crop image using card_obb for better MRZ/barcode extraction\n let croppedBase64: string | undefined;\n let bbox: IBbox | undefined;\n let mrz: any | undefined;\n try {\n const crop = await cropByObb(result?.path || '', detected.card_obb);\n croppedBase64 = crop.base64;\n bbox = crop.bbox;\n } catch { }\n\n // MRZ Extraction\n if (result.regionMapping?.authMethod?.length > 0 && result.regionMapping.authMethod.includes('MRZ')) {\n mrz = await kycService.extractMrzText(\n {\n fileUri: result.path || '',\n docType: result?.selectedDocumentType || '',\n docRegion: result?.code || \"\",\n postfix: result?.currentSide,\n token: token,\n template_path: result?.templatePath || '',\n mrz_type: result?.mrzType || ''\n },\n env\n );\n }\n\n return { ...detected, croppedBase64, bbox, ...(mrz ? { mrz } : {}) };\n } catch (e: any) {\n logger.error('Error front verification:', JSON.stringify(errorMessage(e), null, 2));\n throw new Error(e?.message || 'Erreur de détection du visage');\n }\n}\n\n// export async function frontVerification(\n// result: { path?: string, regionMapping: { authMethod: string[], mrzTypes: string[] }, selectedDocumentType: string, code: string, currentSide: string, templatePath?: string, mrzType?: string }, \n// env: KycEnvironment = 'PRODUCTION'\n// ) {\n// try {\n// console.log(\"Front verification START\", JSON.stringify({ result }, null, 2));\n// logger.log(\"Front verification\", JSON.stringify({ result }, null, 2));\n \n// // SANDBOX mode\n// if (env === 'SANDBOX') {\n// console.log(\"SANDBOX mode: Skipping AI verification for front document\");\n// logger.log(\"SANDBOX mode: Returning mock front verification response\");\n// const mockBbox: IBbox = { minX: 400, minY: 800, width: 2200, height: 1400 };\n \n// // ==========================================\n// // 🧪 TEST OVERRIDE (SANDBOX) 🧪\n// // Immediately throw the error to test the UI\n// // ==========================================\n// throw new Error('CARD_NOT_FULLY_IN_FRAME'); \n\n// const mockResponse = {\n// result: true,\n// detail: [{ confidence: 0.95 }],\n// card_obb: [{\n// obb: [[400,800], [2600,800], [2600,2200], [400,2200]],\n// confidence: 0.95,\n// card_in_frame: false, // Hardcoded to false\n// cropped_sides: ['left', 'top'] // Hardcoded cropped sides\n// }],\n// bbox: mockBbox,\n// ...(result.regionMapping?.authMethod?.includes('MRZ') ? {\n// mrz: {\n// success: true,\n// parsed_data: {\n// status: 'success',\n// document_type: result.selectedDocumentType,\n// mrz_type: result.mrzType || 'TD1'\n// }\n// }\n// } : {})\n// };\n// return mockResponse;\n// }\n \n// const token = await authentification();\n \n// // Cast the response so TypeScript knows about card_obb\n// const detected = await kycService.detectFaceOnId(result?.path || '', token, result?.selectedDocumentType || '', env) as ApiVerificationResponse;\n\n// // ==========================================\n// // 🧪 TEST OVERRIDE (PRODUCTION) 🧪\n// // Hijack the real API response and force it to look cropped\n// // ==========================================\n// if (detected.card_obb && Array.isArray(detected.card_obb) && detected.card_obb.length > 0) {\n// detected.card_obb[0].card_in_frame = false;\n// detected.card_obb[0].cropped_sides = ['left', 'top'];\n// console.warn(\"⚠️ FORCING CROPPED ERROR FOR UI TESTING ⚠️\");\n// }\n// // ==========================================\n\n// if (!detected.result) {\n// throw new Error('Aucun visage détecté sur la carte. Veuillez reprendre.');\n// }\n\n// const cardData = detected.card_obb && Array.isArray(detected.card_obb) && detected.card_obb.length > 0 \n// ? detected.card_obb[0] \n// : null;\n\n// // --- STRICT FRAMING CHECK ---\n// if (cardData && typeof cardData.card_in_frame !== 'undefined') {\n// const isCardInFrame = cardData.card_in_frame === true;\n// const hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;\n\n// // If it is NOT in the frame, OR if any side is cropped, block progression\n// if (!isCardInFrame || hasCroppedSides) {\n// logger.log(`Framing failed. Cropped sides: ${hasCroppedSides ? cardData.cropped_sides?.join(', ') : 'none'}`);\n// throw new Error('CARD_NOT_FULLY_IN_FRAME');\n// }\n// }\n\n// // Check Confidence Threshold\n// const obbConfidence = getObbConfidence(detected.card_obb);\n// if (obbConfidence !== null && obbConfidence < OBB_CONFIDENCE_THRESHOLD) {\n// throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');\n// }\n\n// // Optional: crop image using card_obb for better MRZ/barcode extraction\n// let croppedBase64: string | undefined;\n// let bbox: IBbox | undefined;\n// let mrz: any | undefined;\n// try {\n// const crop = await cropByObb(result?.path || '', detected.card_obb);\n// croppedBase64 = crop.base64;\n// bbox = crop.bbox;\n// } catch { }\n\n// // MRZ Extraction\n// if (result.regionMapping?.authMethod?.length > 0 && result.regionMapping.authMethod.includes('MRZ')) {\n// mrz = await kycService.extractMrzText(\n// {\n// fileUri: result.path || '',\n// docType: result?.selectedDocumentType || '',\n// docRegion: result?.code || \"\",\n// postfix: result?.currentSide,\n// token: token,\n// template_path: result?.templatePath || '',\n// mrz_type: result?.mrzType || ''\n// },\n// env\n// );\n// }\n\n// return { ...detected, croppedBase64, bbox, ...(mrz ? { mrz } : {}) };\n// } catch (e: any) {\n// logger.error('Error front verification:', JSON.stringify(errorMessage(e), null, 2));\n// throw new Error(e?.message || 'Erreur de détection du visage');\n// }\n// }\n\n\nexport async function backVerification(\n result: { path?: string, regionMapping: { authMethod: string[], mrzTypes: string[] }, selectedDocumentType: string, code: string, currentSide: string, templatePath?: string, mrzType?: string }, \n env: KycEnvironment = 'PRODUCTION'\n) {\n try {\n if (!result.path) throw new Error('No path provided');\n logger.log(\"result.regionMapping\", result.regionMapping, result.currentSide, result.code);\n \n \n if (env === 'SANDBOX') {\n console.log(\"SANDBOX mode: Skipping AI verification for back document\");\n \n const mockBbox: IBbox = { minX: 400, minY: 800, width: 2200, height: 1400 };\n const mockCardObb = [{\n obb: [[400,800], [2600,800], [2600,2200], [400,2200]],\n confidence: 0.95,\n card_in_frame: true,\n cropped_sides: []\n }];\n \n if (result.regionMapping?.authMethod?.includes('MRZ')) {\n return {\n success: true,\n parsed_data: {\n status: 'success',\n document_type: result.selectedDocumentType,\n mrz_type: result.mrzType || 'TD1'\n },\n bbox: mockBbox,\n card_obb: mockCardObb\n };\n } else if (result.regionMapping?.authMethod?.includes('2D_barcode')) {\n return {\n barcode_data: 'SANDBOX_MOCK_BARCODE',\n bbox: mockBbox,\n card_obb: mockCardObb\n };\n }\n return { bbox: mockBbox };\n }\n \n const token = await authentification();\n\n \n logger.log(\"1. Checking template and framing for back document...\");\n \n const templateResponse = await kycService.checkTemplateType({\n fileUri: result.path,\n docType: result.selectedDocumentType as any,\n docRegion: result.code,\n postfix: 'back',\n token: token\n }, env) as ApiVerificationResponse;\n\n // STRICT FRAMING CHECK\n const cardData = templateResponse?.card_obb && Array.isArray(templateResponse.card_obb) && templateResponse.card_obb.length > 0 \n ? templateResponse.card_obb[0] \n : null;\n\n if (cardData && typeof cardData.card_in_frame !== 'undefined') {\n const isCardInFrame = cardData.card_in_frame === true;\n const hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;\n\n if (!isCardInFrame || hasCroppedSides) {\n logger.log(`Back Framing failed. Cropped sides: ${hasCroppedSides ? cardData.cropped_sides?.join(', ') : 'none'}`);\n throw new Error('CARD_NOT_FULLY_IN_FRAME');\n }\n }\n \n const obbConf = getObbConfidence(templateResponse?.card_obb);\n if (obbConf !== null && obbConf < OBB_CONFIDENCE_THRESHOLD) {\n throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');\n }\n\n\n const activeTemplatePath = templateResponse.template_path || result.templatePath || '';\n \n if (activeTemplatePath) {\n const expectedCountryName = countryData[result.code]?.name_en || '';\n \n const hasCodeMatch = activeTemplatePath.includes(`_${result.code}_`);\n const hasNameMatch = expectedCountryName && activeTemplatePath.toLowerCase().includes(expectedCountryName.toLowerCase());\n\n if (!hasCodeMatch && !hasNameMatch) {\n logger.log(`Template mismatch! Expected country: ${result.code} (${expectedCountryName}), Detected: ${activeTemplatePath}`);\n throw new Error(`Le document ne correspond pas au pays sélectionné (${result.code}).`);\n }\n }\n\n logger.log(\"Framing and Country Template verified successfully. Proceeding to Data Extraction.\");\n\n \n const tryMrzWithBarcodeFallback = async () => {\n try {\n logger.log(\"Tentative d'extraction MRZ\");\n const mrz = await kycService.extractMrzText({\n fileUri: result.path!,\n docType: result?.selectedDocumentType || '',\n docRegion: result?.code || '',\n postfix: 'back',\n token: token,\n template_path: activeTemplatePath, // Use the verified template\n mrz_type: result?.mrzType || ''\n }, env);\n \n let bbox: IBbox | undefined;\n let croppedBase64: string | undefined;\n\n try {\n // We use the OBB from our template check to ensure clean cropping\n const crop = await cropByObb(result?.path || '', templateResponse.card_obb);\n bbox = crop.bbox;\n croppedBase64 = crop.base64;\n } catch { }\n return { ...mrz, bbox, croppedBase64 }\n \n } catch (mrzError: any) {\n logger.log(\"MRZ échoué, tentative d'extraction barcode\");\n try {\n const barcode = await kycService.extractBarcode({ fileUri: result.path!, token: token }, env);\n return barcode;\n } catch (barcodeError: any) {\n throw new Error(`MRZ et barcode ont échoué. MRZ: ${mrzError?.message}, Barcode: ${barcodeError?.message}`);\n }\n }\n };\n\n if (result.regionMapping?.authMethod?.length > 2 && (!result?.mrzType || result?.mrzType.length === 0)) {\n return await tryMrzWithBarcodeFallback();\n }\n\n if (result.regionMapping?.authMethod?.length > 0 && result.regionMapping.authMethod.includes('MRZ') && result?.mrzType && result?.mrzType.length > 0) {\n try {\n const mrz = await kycService.extractMrzText({\n fileUri: result.path!,\n docType: result?.selectedDocumentType || '',\n docRegion: result?.code || '',\n postfix: 'back',\n token: token,\n template_path: activeTemplatePath,\n mrz_type: result?.mrzType || ''\n }, env);\n \n let bbox: IBbox | undefined;\n try {\n const crop = await cropByObb(result?.path || '', templateResponse.card_obb);\n bbox = crop.bbox;\n } catch { }\n return { ...mrz, bbox };\n } catch (mrzError: any) {\n throw new Error(`MRZ et barcode ont échoué. MRZ: ${mrzError?.message}, Barcode: ${mrzError?.message}`);\n }\n }\n\n if (result.regionMapping?.authMethod?.length > 0 && result.regionMapping.authMethod.includes('2D_barcode')) {\n try {\n logger.log(\"Tentative d'extraction barcode\");\n const barcode = await kycService.extractBarcode({ fileUri: result.path!, token: token }, env);\n \n let bbox: IBbox | undefined;\n try {\n const crop = await cropByObb(result?.path || '', templateResponse.card_obb);\n bbox = crop.bbox;\n } catch { }\n return { ...barcode, bbox };\n } catch (barcodeError: any) {\n throw new Error(`Barcode et MRZ ont échoué. Barcode: ${barcodeError?.message}, MRZ: ${barcodeError?.message}`);\n }\n }\n return null;\n } catch (e: any) {\n if (e?.message === 'CARD_NOT_FULLY_IN_FRAME') throw e; // Bubble the strict framing error specifically\n throw new Error(e?.message || 'Erreur de détection du MRZ ou barcode');\n }\n}\n\n\n/**\n * Check template type\n * @param result \n * @returns \n */\nexport async function checkTemplateType(result: { path?: string, docType: string, docRegion: string, postfix: string }, env: KycEnvironment = 'PRODUCTION') {\n try {\n if (env === 'SANDBOX') {\n return {\n template_path: `templates/${result.docType}_${result.docRegion}_${result.postfix}.jpg`,\n card_obb: [{\n obb: [[400,800], [2600,800], [2600,2200], [400,2200]],\n confidence: 0.95,\n card_in_frame: true,\n cropped_sides: []\n }]\n };\n }\n \n const token = await authentification();\n const templateType = await kycService.checkTemplateType({ fileUri: result.path || '', docType: result?.docType as GovernmentDocumentType, docRegion: result?.docRegion || \"\", postfix: result?.postfix, token: token }, env);\n\n const cardData = templateType.card_obb && Array.isArray(templateType.card_obb) && templateType.card_obb.length > 0 \n ? templateType.card_obb[0] \n : null;\n\n if (cardData && typeof cardData.card_in_frame !== 'undefined') {\n const isCardInFrame = cardData.card_in_frame === true;\n const hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;\n\n if (!isCardInFrame || hasCroppedSides) {\n logger.log(`Template Framing failed. Cropped sides: ${hasCroppedSides ? cardData.cropped_sides?.join(', ') : 'none'}`);\n throw new Error('CARD_NOT_FULLY_IN_FRAME');\n }\n }\n\n \n const LPIPS_THRESHOLD = 0.75; \n \n if (templateType.lpips_score !== undefined && templateType.lpips_score > LPIPS_THRESHOLD) {\n logger.log(`🛑 Country Mismatch! LPIPS Score too high: ${templateType.lpips_score}`);\n throw new Error(`Le document présenté ne correspond pas au pays sélectionné (${result.docRegion}).`);\n }\n\n logger.log(\"templateType result\", JSON.stringify(truncateFields(templateType), null, 2));\n return templateType;\n } catch (e: any) {\n logger.error('Error checking template type:', JSON.stringify(errorMessage(e), null, 2));\n \n if (e?.message === 'CARD_NOT_FULLY_IN_FRAME' || e?.message?.includes('ne correspond pas')) {\n throw e; \n }\n \n throw new Error(e?.message || 'Erreur de vérification du template');\n }\n}"]}
|
|
@@ -62,10 +62,12 @@ export declare class KYCService {
|
|
|
62
62
|
docType: string;
|
|
63
63
|
docRegion: string;
|
|
64
64
|
token: string;
|
|
65
|
+
postfix?: string;
|
|
65
66
|
}): Promise<any>;
|
|
66
67
|
extractBarcode(params: {
|
|
67
68
|
fileUri: string;
|
|
68
69
|
token: string;
|
|
70
|
+
postfix?: string;
|
|
69
71
|
}, env?: KycEnvironment): Promise<any>;
|
|
70
72
|
extractMrzText(params: {
|
|
71
73
|
fileUri: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KYCService.d.ts","sourceRoot":"","sources":["../../../src/modules/api/KYCService.ts"],"names":[],"mappings":"AACA,OAAO,EAAyD,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAExH,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAC;AAC1F,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAgBvD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,UAAU,GAAG,SAAS,GAAG,iBAAiB,CAAC;CAC1D;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,qBAAqB,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAGD,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO,CAAC,cAAc,CAAgD;IACtE,OAAO,CAAC,wBAAwB,CAAgD;IAChF,OAAO,CAAC,aAAa,CAAgD;IACrE,OAAO,CAAC,iBAAiB,CAAgD;IACzE,OAAO,CAAC,qBAAqB,CAAgC;gBAEjD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAK3C,OAAO,CAAC,UAAU;IAOZ,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC;IAcjD,UAAU,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IActE,gBAAgB,CAAC,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAc3E,YAAY,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAa1D,+BAA+B,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAoBjG,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,GAAE,cAA6B,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAiEjH,cAAc,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,GAAE,cAA6B,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,GAAG,EAAE,CAAA;KAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"KYCService.d.ts","sourceRoot":"","sources":["../../../src/modules/api/KYCService.ts"],"names":[],"mappings":"AACA,OAAO,EAAyD,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAExH,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAC;AAC1F,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAgBvD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,UAAU,GAAG,SAAS,GAAG,iBAAiB,CAAC;CAC1D;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,qBAAqB,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAGD,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO,CAAC,cAAc,CAAgD;IACtE,OAAO,CAAC,wBAAwB,CAAgD;IAChF,OAAO,CAAC,aAAa,CAAgD;IACrE,OAAO,CAAC,iBAAiB,CAAgD;IACzE,OAAO,CAAC,qBAAqB,CAAgC;gBAEjD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAK3C,OAAO,CAAC,UAAU;IAOZ,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC;IAcjD,UAAU,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IActE,gBAAgB,CAAC,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAc3E,YAAY,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAa1D,+BAA+B,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAoBjG,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,GAAE,cAA6B,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAiEjH,cAAc,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,GAAE,cAA6B,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,GAAG,EAAE,CAAA;KAAE,CAAC;IAqCvJ,iBAAiB,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,GAAG,GAAE,cAA6B,GAAG,OAAO,CAAC,GAAG,CAAC;IAoCpK,0BAA0B,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IA2B1I,cAAc,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,GAAG,GAAE,cAA6B,GAAG,OAAO,CAAC,GAAG,CAAC;IAwC9H,cAAc,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,GAAG,GAAE,cAA6B,GAAG,OAAO,CAAC,GAAG,CAAC;IAsD3M,aAAa,CAAC,MAAM,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,EAAE,GAAG,GAAE,cAA6B,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAwBzM,mBAAmB,IAAI,OAAO,CAAC,GAAG,CAAC;IAKnC,oBAAoB,IAAI,OAAO,CAAC,GAAG,CAAC;IAKpC,gBAAgB,IAAI,OAAO,CAAC,GAAG,CAAC;IAKhC,wBAAwB,IAAI,OAAO,CAAC,GAAG,CAAC;IAKxC,UAAU,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,eAAe,CAAC;IA6B5F,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,GAAG,CAAC;IAwC5E,sEAAsE;IAChE,yBAAyB,CAC7B,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GACzC,OAAO,CAAC,OAAO,CAAC;IAgBnB,iEAAiE;IAC3D,eAAe,CACnB,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GACzC,OAAO,CAAC,OAAO,CAAC;IAgBb,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAa7E;AAED,QAAA,MAAM,UAAU,YAAyB,CAAC;AAC1C,eAAe,UAAU,CAAC;AAG1B,wBAAgB,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,SAAM,GAAG,GAAG,CAgB7D;AAED,eAAO,MAAM,gBAAgB,oBAoC5B,CAAA;AAED,eAAO,MAAM,YAAY,GAAI,OAAO,GAAG,QAKtC,CAAA"}
|