@sanctum-key/react-native-sdk 1.0.18 → 1.0.20
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/README.md +1 -1
- package/build/package.json +3 -2
- package/build/src/components/EnhancedCameraView.d.ts.map +1 -1
- package/build/src/components/EnhancedCameraView.js +19 -182
- package/build/src/components/EnhancedCameraView.js.map +1 -1
- package/build/src/components/KYCElements/CountrySelectionTemplate.d.ts.map +1 -1
- package/build/src/components/KYCElements/CountrySelectionTemplate.js +40 -128
- package/build/src/components/KYCElements/CountrySelectionTemplate.js.map +1 -1
- package/build/src/components/KYCElements/IDCardCapture.d.ts.map +1 -1
- package/build/src/components/KYCElements/IDCardCapture.js +224 -189
- package/build/src/components/KYCElements/IDCardCapture.js.map +1 -1
- package/build/src/components/KYCElements/PhoneVerificationTemplate.d.ts.map +1 -1
- package/build/src/components/KYCElements/PhoneVerificationTemplate.js +0 -2
- package/build/src/components/KYCElements/PhoneVerificationTemplate.js.map +1 -1
- package/build/src/components/KYCElements/VerificationProgressTemplate.d.ts.map +1 -1
- package/build/src/components/KYCElements/VerificationProgressTemplate.js +38 -33
- package/build/src/components/KYCElements/VerificationProgressTemplate.js.map +1 -1
- package/build/src/components/OverLay/IdCard.d.ts +6 -1
- package/build/src/components/OverLay/IdCard.d.ts.map +1 -1
- package/build/src/components/OverLay/IdCard.js +36 -34
- package/build/src/components/OverLay/IdCard.js.map +1 -1
- package/build/src/config/countriesData.d.ts.map +1 -1
- package/build/src/config/countriesData.js.map +1 -1
- package/build/src/hooks/useTemplateKYCFlow.js +1 -1
- package/build/src/hooks/useTemplateKYCFlow.js.map +1 -1
- package/build/src/modules/api/CardAuthentification.d.ts +5 -0
- package/build/src/modules/api/CardAuthentification.d.ts.map +1 -1
- package/build/src/modules/api/CardAuthentification.js +67 -14
- package/build/src/modules/api/CardAuthentification.js.map +1 -1
- package/build/src/modules/api/KYCService.d.ts +10 -0
- package/build/src/modules/api/KYCService.d.ts.map +1 -1
- package/build/src/modules/api/KYCService.js +135 -49
- package/build/src/modules/api/KYCService.js.map +1 -1
- package/build/src/web/WebKYCEntry.d.ts.map +1 -1
- package/build/src/web/WebKYCEntry.js +34 -6
- package/build/src/web/WebKYCEntry.js.map +1 -1
- package/package.json +3 -2
- package/src/components/EnhancedCameraView.tsx +28 -219
- package/src/components/KYCElements/CountrySelectionTemplate.tsx +53 -133
- package/src/components/KYCElements/IDCardCapture.tsx +606 -570
- package/src/components/KYCElements/PhoneVerificationTemplate.tsx +0 -2
- package/src/components/KYCElements/VerificationProgressTemplate.tsx +54 -66
- package/src/components/OverLay/IdCard.tsx +48 -36
- package/src/config/countriesData.ts +0 -4
- package/src/hooks/useTemplateKYCFlow.tsx +14 -14
- package/src/modules/api/CardAuthentification.ts +133 -67
- package/src/modules/api/KYCService.ts +189 -66
- package/src/web/WebKYCEntry.tsx +42 -7
|
@@ -30,19 +30,20 @@ export async function frontVerification(
|
|
|
30
30
|
code: string,
|
|
31
31
|
currentSide: string,
|
|
32
32
|
templatePath?: string,
|
|
33
|
-
mrzType?: string
|
|
33
|
+
mrzType?: string,
|
|
34
|
+
issuingSubdivision?: string
|
|
34
35
|
},
|
|
35
36
|
env: KycEnvironment = 'PRODUCTION'
|
|
36
37
|
) {
|
|
37
38
|
try {
|
|
38
39
|
console.log("Front verification START", JSON.stringify({ result }, null, 2));
|
|
39
40
|
logger.log("Front verification", JSON.stringify({ result }, null, 2));
|
|
40
|
-
|
|
41
|
+
|
|
41
42
|
const authMethods = Array.isArray(result.regionMapping?.authMethod)
|
|
42
43
|
? result.regionMapping.authMethod.map(m => String(m).toUpperCase())
|
|
43
44
|
: [];
|
|
44
45
|
const hasMrz = authMethods.some(m => m.includes('MRZ'));
|
|
45
|
-
|
|
46
|
+
|
|
46
47
|
if (env === 'SANDBOX') {
|
|
47
48
|
console.log("SANDBOX mode: Skipping AI verification for front document");
|
|
48
49
|
const mockBbox: IBbox = { minX: 400, minY: 800, width: 2200, height: 1400 };
|
|
@@ -69,25 +70,25 @@ export async function frontVerification(
|
|
|
69
70
|
};
|
|
70
71
|
return mockResponse;
|
|
71
72
|
}
|
|
72
|
-
|
|
73
|
+
|
|
73
74
|
const token = await authentification();
|
|
74
75
|
const detected = await kycService.detectFaceOnId(
|
|
75
76
|
result?.path || '', token, result?.selectedDocumentType || '', env
|
|
76
77
|
) as ApiVerificationResponse;
|
|
77
|
-
|
|
78
|
+
|
|
78
79
|
if (!detected.result) {
|
|
79
80
|
throw new Error('Aucun visage détecté sur la carte. Veuillez reprendre.');
|
|
80
81
|
}
|
|
81
|
-
|
|
82
|
+
|
|
82
83
|
const cardData = detected.card_obb && Array.isArray(detected.card_obb) && detected.card_obb.length > 0
|
|
83
84
|
? detected.card_obb[0]
|
|
84
85
|
: null;
|
|
85
|
-
|
|
86
|
+
|
|
86
87
|
let points: number[][] | null = null;
|
|
88
|
+
console.log(points)
|
|
87
89
|
let isCardInFrame = true;
|
|
88
90
|
let hasCroppedSides = false;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
+
|
|
91
92
|
if (cardData) {
|
|
92
93
|
points = cardData.obb;
|
|
93
94
|
if (typeof cardData.card_in_frame !== 'undefined') {
|
|
@@ -95,27 +96,45 @@ export async function frontVerification(
|
|
|
95
96
|
hasCroppedSides = Array.isArray(cardData.cropped_sides) && cardData.cropped_sides.length > 0;
|
|
96
97
|
}
|
|
97
98
|
}
|
|
98
|
-
|
|
99
|
+
|
|
99
100
|
if (!isCardInFrame || hasCroppedSides) {
|
|
100
101
|
logger.log(`Front Framing failed. Cropped sides detected by backend.`);
|
|
101
102
|
throw new Error('CARD_NOT_FULLY_IN_FRAME');
|
|
102
103
|
}
|
|
103
|
-
|
|
104
|
+
|
|
104
105
|
const obbConfidence = getObbConfidence(detected.card_obb);
|
|
105
106
|
if (obbConfidence !== null && obbConfidence < OBB_CONFIDENCE_THRESHOLD) {
|
|
106
107
|
throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');
|
|
107
108
|
}
|
|
108
|
-
|
|
109
|
+
|
|
109
110
|
let croppedBase64: string | undefined;
|
|
110
111
|
let bbox: IBbox | undefined;
|
|
111
112
|
let mrz: any | undefined;
|
|
112
|
-
|
|
113
|
+
let documentData: any | undefined;
|
|
114
|
+
|
|
113
115
|
try {
|
|
114
116
|
const crop = await cropByObb(result?.path || '', detected.card_obb);
|
|
115
117
|
croppedBase64 = crop.base64;
|
|
116
118
|
bbox = crop.bbox;
|
|
117
119
|
} catch { }
|
|
118
120
|
|
|
121
|
+
if (result.code === 'CA') {
|
|
122
|
+
try {
|
|
123
|
+
logger.log("Tentative d'extraction OCR (Front) - Canada Only");
|
|
124
|
+
documentData = await kycService.extractDocumentInformation({
|
|
125
|
+
fileUri: result.path || '',
|
|
126
|
+
docType: result.selectedDocumentType,
|
|
127
|
+
docRegion: result.code,
|
|
128
|
+
templatePath: result.templatePath || '',
|
|
129
|
+
issuingSubdivision: result.issuingSubdivision,
|
|
130
|
+
token: token,
|
|
131
|
+
postfix: result.currentSide || 'front'
|
|
132
|
+
});
|
|
133
|
+
} catch (err: any) {
|
|
134
|
+
logger.log("Front OCR Extraction Error:", err?.message || err);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
119
138
|
if (hasMrz) {
|
|
120
139
|
try {
|
|
121
140
|
logger.log("Tentative d'extraction MRZ (Front)");
|
|
@@ -131,11 +150,11 @@ export async function frontVerification(
|
|
|
131
150
|
},
|
|
132
151
|
env
|
|
133
152
|
);
|
|
134
|
-
|
|
153
|
+
|
|
135
154
|
mrz = typeof mrzResponse === 'string' ? JSON.parse(mrzResponse) : mrzResponse;
|
|
136
|
-
|
|
155
|
+
|
|
137
156
|
if (mrz?.parsed_data?.status === 'FAILURE' || mrz?.success === false) {
|
|
138
|
-
logger.log("
|
|
157
|
+
logger.log("Front MRZ Extraction Failed:", mrz?.parsed_data?.status_message);
|
|
139
158
|
throw new Error(`MRZ illisible: ${mrz?.parsed_data?.status_message || 'Veuillez nettoyer l\'objectif et réessayer'}`);
|
|
140
159
|
}
|
|
141
160
|
} catch (err: any) {
|
|
@@ -143,9 +162,10 @@ export async function frontVerification(
|
|
|
143
162
|
throw new Error(err?.message || "Erreur lors de l'extraction MRZ. Veuillez reprendre la photo.");
|
|
144
163
|
}
|
|
145
164
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
165
|
+
|
|
166
|
+
// Return detected frame, crop, MRZ, AND the new extracted OCR documentData
|
|
167
|
+
return { ...detected, croppedBase64, bbox, ...(mrz ? { mrz } : {}), ...(documentData ? { documentData } : {}) };
|
|
168
|
+
|
|
149
169
|
} catch (e: any) {
|
|
150
170
|
logger.log('Error front verification:', e?.message);
|
|
151
171
|
throw new Error(e?.message || 'Erreur de détection du visage');
|
|
@@ -161,22 +181,23 @@ export async function backVerification(
|
|
|
161
181
|
currentSide: string,
|
|
162
182
|
templatePath?: string,
|
|
163
183
|
mrzType?: string,
|
|
164
|
-
templateResponse?: ApiVerificationResponse
|
|
184
|
+
templateResponse?: ApiVerificationResponse,
|
|
185
|
+
issuingSubdivision?: string, // Capture province/state
|
|
186
|
+
frontTemplatePath?: string // Capture the front template to compare against
|
|
165
187
|
},
|
|
166
188
|
env: KycEnvironment = 'PRODUCTION'
|
|
167
189
|
) {
|
|
168
190
|
try {
|
|
169
191
|
if (!result.path) throw new Error('No path provided');
|
|
170
192
|
logger.log("result.regionMapping", result.regionMapping, result.currentSide, result.code);
|
|
171
|
-
|
|
172
|
-
|
|
193
|
+
|
|
173
194
|
const authMethods = Array.isArray(result.regionMapping?.authMethod)
|
|
174
195
|
? result.regionMapping.authMethod.map(m => String(m).toUpperCase())
|
|
175
196
|
: [];
|
|
176
|
-
|
|
177
|
-
const hasMrz = authMethods.some(m => m.includes('MRZ'))
|
|
197
|
+
|
|
198
|
+
const hasMrz = authMethods.some(m => m.includes('MRZ'));
|
|
178
199
|
const hasBarcode = authMethods.some(m => m.includes('BARCODE') || m.includes('2D'));
|
|
179
|
-
|
|
200
|
+
|
|
180
201
|
if (env === 'SANDBOX') {
|
|
181
202
|
console.log("SANDBOX mode: Skipping AI verification for back document");
|
|
182
203
|
const mockBbox: IBbox = { minX: 400, minY: 800, width: 2200, height: 1400 };
|
|
@@ -211,34 +232,34 @@ export async function backVerification(
|
|
|
211
232
|
}
|
|
212
233
|
return { success: true, bbox: mockBbox, card_obb: mockCardObb };
|
|
213
234
|
}
|
|
214
|
-
|
|
235
|
+
|
|
215
236
|
const token = await authentification();
|
|
216
237
|
logger.log("1. Checking template and framing for back document...");
|
|
217
|
-
|
|
238
|
+
|
|
218
239
|
const templateResponse: ApiVerificationResponse = result.templateResponse ||
|
|
219
240
|
await kycService.checkTemplateType({
|
|
220
241
|
fileUri: result.path,
|
|
221
242
|
docType: result.selectedDocumentType as any,
|
|
222
243
|
docRegion: result.code,
|
|
223
244
|
postfix: 'back',
|
|
224
|
-
token: token
|
|
245
|
+
token: token,
|
|
225
246
|
}, env);
|
|
226
|
-
|
|
247
|
+
|
|
227
248
|
if (templateResponse.success === false || templateResponse.Error) {
|
|
228
249
|
throw new Error('Impossible de lire le document. Veuillez vous rapprocher et stabiliser la caméra.');
|
|
229
250
|
}
|
|
230
|
-
|
|
251
|
+
|
|
231
252
|
const cardData = templateResponse?.card_obb && Array.isArray(templateResponse.card_obb) && templateResponse.card_obb.length > 0
|
|
232
253
|
? templateResponse.card_obb[0]
|
|
233
254
|
: null;
|
|
234
|
-
|
|
255
|
+
|
|
235
256
|
if (!cardData) throw new Error('CARD_NOT_FULLY_IN_FRAME');
|
|
236
|
-
|
|
257
|
+
|
|
237
258
|
let points: number[][] | null = null;
|
|
259
|
+
console.log(points)
|
|
238
260
|
let isCardInFrame = false;
|
|
239
261
|
let hasCroppedSides = true;
|
|
240
|
-
|
|
241
|
-
|
|
262
|
+
|
|
242
263
|
if (cardData.obb) {
|
|
243
264
|
points = cardData.obb;
|
|
244
265
|
if (typeof cardData.card_in_frame !== 'undefined') {
|
|
@@ -249,35 +270,78 @@ export async function backVerification(
|
|
|
249
270
|
points = cardData[0];
|
|
250
271
|
isCardInFrame = true;
|
|
251
272
|
hasCroppedSides = false;
|
|
252
|
-
// 🚨 ARTIFICIAL CHECK REMOVED HERE
|
|
253
273
|
}
|
|
254
|
-
|
|
274
|
+
|
|
255
275
|
if (!isCardInFrame || hasCroppedSides) {
|
|
256
276
|
logger.log(`Back Framing failed. Backend reported document out of bounds.`);
|
|
257
277
|
throw new Error('CARD_NOT_FULLY_IN_FRAME');
|
|
258
278
|
}
|
|
259
|
-
|
|
279
|
+
|
|
260
280
|
const obbConf = getObbConfidence(templateResponse?.card_obb);
|
|
261
281
|
if (obbConf !== null && obbConf < OBB_CONFIDENCE_THRESHOLD) {
|
|
262
282
|
throw new Error('Carte non entièrement visible. Positionnez toute la carte dans le cadre.');
|
|
263
283
|
}
|
|
264
|
-
|
|
284
|
+
|
|
265
285
|
const activeTemplatePath = templateResponse.template_path || result.templatePath || '';
|
|
286
|
+
|
|
266
287
|
if (activeTemplatePath) {
|
|
267
288
|
const expectedCountryName = countryData[result.code]?.name_en || '';
|
|
268
289
|
const hasCodeMatch = activeTemplatePath.includes(`_${result.code}_`);
|
|
269
290
|
const hasNameMatch = expectedCountryName && activeTemplatePath.toLowerCase().includes(expectedCountryName.toLowerCase());
|
|
270
|
-
|
|
291
|
+
|
|
271
292
|
if (!hasCodeMatch && !hasNameMatch) {
|
|
272
293
|
logger.log(`Template mismatch! Expected: ${result.code} (${expectedCountryName}), Detected: ${activeTemplatePath}`);
|
|
273
294
|
throw new Error(`Le document ne correspond pas au pays sélectionné (${result.code}).`);
|
|
274
295
|
}
|
|
275
296
|
}
|
|
276
297
|
|
|
277
|
-
|
|
278
|
-
|
|
298
|
+
// 🚨 STRICT FRONT VS BACK TEMPLATE VALIDATION 🚨
|
|
299
|
+
if (result.frontTemplatePath && activeTemplatePath) {
|
|
300
|
+
const frontPy = result.frontTemplatePath.split("/").pop()?.replace(/\.(jpg|png)$/i, ".py");
|
|
301
|
+
const backPy = activeTemplatePath.split("/").pop()?.replace(/\.(jpg|png)$/i, ".py");
|
|
302
|
+
|
|
303
|
+
if (frontPy && backPy) {
|
|
304
|
+
logger.log(`Validating Front (${frontPy}) vs Back (${backPy}) for region ${result.code}`);
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
const matchValidation = await kycService.validateBackTemplate({
|
|
308
|
+
region: result.code,
|
|
309
|
+
docType: result.selectedDocumentType,
|
|
310
|
+
frontTemplateName: frontPy,
|
|
311
|
+
backTemplateName: backPy,
|
|
312
|
+
subRegion: result.issuingSubdivision || "",
|
|
313
|
+
token: token
|
|
314
|
+
}, env);
|
|
315
|
+
|
|
316
|
+
// If the API succeeds but explicitly returns false, stop immediately.
|
|
317
|
+
if (!matchValidation || matchValidation.is_match === false) {
|
|
318
|
+
logger.log(`Front/Back Mismatch: ${matchValidation?.status_message}`);
|
|
319
|
+
throw new Error(`Le verso ne correspond pas au recto fourni. Vous avez scanné un document différent.`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
logger.log("Framing, Country, and Match verified successfully. Proceeding to Data Extraction.");
|
|
279
325
|
let extractionResult: any = {};
|
|
280
326
|
|
|
327
|
+
if (result.code === 'CA') {
|
|
328
|
+
try {
|
|
329
|
+
logger.log("Tentative d'extraction OCR (Back) - Canada Only");
|
|
330
|
+
const documentData = await kycService.extractDocumentInformation({
|
|
331
|
+
fileUri: result.path!,
|
|
332
|
+
docType: result.selectedDocumentType,
|
|
333
|
+
docRegion: result.code,
|
|
334
|
+
templatePath: activeTemplatePath,
|
|
335
|
+
issuingSubdivision: result.issuingSubdivision,
|
|
336
|
+
token: token,
|
|
337
|
+
postfix: result.currentSide || 'back'
|
|
338
|
+
});
|
|
339
|
+
extractionResult.documentData = documentData;
|
|
340
|
+
} catch (err: any) {
|
|
341
|
+
logger.log("Back OCR Extraction Error:", err?.message || err);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
281
345
|
if (hasMrz) {
|
|
282
346
|
try {
|
|
283
347
|
logger.log("Tentative d'extraction MRZ (Back)");
|
|
@@ -290,35 +354,31 @@ export async function backVerification(
|
|
|
290
354
|
template_path: activeTemplatePath,
|
|
291
355
|
mrz_type: result?.mrzType || 'TD1'
|
|
292
356
|
}, env);
|
|
293
|
-
|
|
357
|
+
|
|
294
358
|
const mrz = typeof mrzResponse === 'string' ? JSON.parse(mrzResponse) : mrzResponse;
|
|
295
|
-
|
|
359
|
+
|
|
296
360
|
if (mrz?.parsed_data?.status === 'FAILURE' || mrz?.success === false) {
|
|
297
361
|
throw new Error(mrz?.parsed_data?.status_message || 'Lecture MRZ échouée');
|
|
298
362
|
}
|
|
299
|
-
|
|
300
|
-
extractionResult.mrz = mrz; // Attaching securely to result object
|
|
301
|
-
|
|
363
|
+
extractionResult.mrz = mrz;
|
|
302
364
|
} catch (mrzError: any) {
|
|
303
365
|
logger.log(`MRZ échoué: ${mrzError?.message}`);
|
|
304
|
-
// If MRZ fails, we MUST throw an error so the user is forced to retake it!
|
|
305
366
|
throw new Error(`Lecture MRZ invalide: ${mrzError?.message || 'Veuillez nettoyer l\'objectif et réessayer'}`);
|
|
306
367
|
}
|
|
307
368
|
}
|
|
308
|
-
|
|
369
|
+
|
|
309
370
|
if (hasBarcode) {
|
|
310
371
|
try {
|
|
311
372
|
logger.log("Tentative d'extraction barcode");
|
|
312
373
|
const barcode = await kycService.extractBarcode({ fileUri: result.path!, token: token }, env);
|
|
313
374
|
extractionResult.barcode = barcode;
|
|
314
375
|
} catch (e: any) {
|
|
315
|
-
// Only throw barcode error if MRZ wasn't already successfully extracted
|
|
316
376
|
if (!extractionResult.mrz) {
|
|
317
377
|
throw new Error(`Lecture Barcode échouée: ${e?.message}`);
|
|
318
378
|
}
|
|
319
379
|
}
|
|
320
380
|
}
|
|
321
|
-
|
|
381
|
+
|
|
322
382
|
let bbox: IBbox | undefined;
|
|
323
383
|
let croppedBase64: string | undefined;
|
|
324
384
|
try {
|
|
@@ -326,7 +386,7 @@ export async function backVerification(
|
|
|
326
386
|
bbox = crop.bbox;
|
|
327
387
|
croppedBase64 = crop.base64;
|
|
328
388
|
} catch { }
|
|
329
|
-
|
|
389
|
+
|
|
330
390
|
return {
|
|
331
391
|
success: true,
|
|
332
392
|
...extractionResult,
|
|
@@ -334,15 +394,21 @@ export async function backVerification(
|
|
|
334
394
|
croppedBase64,
|
|
335
395
|
card_obb: templateResponse.card_obb
|
|
336
396
|
};
|
|
337
|
-
|
|
397
|
+
|
|
338
398
|
} catch (e: any) {
|
|
339
|
-
if (e?.message === 'CARD_NOT_FULLY_IN_FRAME') throw e;
|
|
399
|
+
if (e?.message === 'CARD_NOT_FULLY_IN_FRAME') throw e;
|
|
340
400
|
throw new Error(e?.message || 'Erreur de détection des données');
|
|
341
401
|
}
|
|
342
402
|
}
|
|
343
403
|
|
|
344
404
|
export async function checkTemplateType(
|
|
345
|
-
result: {
|
|
405
|
+
result: {
|
|
406
|
+
path?: string,
|
|
407
|
+
docType: string,
|
|
408
|
+
docRegion: string,
|
|
409
|
+
postfix: string,
|
|
410
|
+
issuingSubdivision?: string
|
|
411
|
+
},
|
|
346
412
|
env: KycEnvironment = 'PRODUCTION'
|
|
347
413
|
) {
|
|
348
414
|
try {
|
|
@@ -357,7 +423,7 @@ export async function checkTemplateType(
|
|
|
357
423
|
}]
|
|
358
424
|
};
|
|
359
425
|
}
|
|
360
|
-
|
|
426
|
+
|
|
361
427
|
const token = await authentification();
|
|
362
428
|
const templateType = await kycService.checkTemplateType({
|
|
363
429
|
fileUri: result.path || '',
|
|
@@ -366,23 +432,23 @@ export async function checkTemplateType(
|
|
|
366
432
|
postfix: result?.postfix,
|
|
367
433
|
token: token
|
|
368
434
|
}, env);
|
|
369
|
-
|
|
435
|
+
|
|
370
436
|
if (templateType.success === false || templateType.Error) {
|
|
371
437
|
logger.log("Backend returned an error:", templateType.Error);
|
|
372
438
|
throw new Error('Impossible de lire le document. Veuillez vous rapprocher et stabiliser la caméra.');
|
|
373
439
|
}
|
|
374
|
-
|
|
440
|
+
|
|
375
441
|
const cardData = templateType.card_obb && Array.isArray(templateType.card_obb) && templateType.card_obb.length > 0
|
|
376
442
|
? templateType.card_obb[0]
|
|
377
443
|
: null;
|
|
378
|
-
|
|
444
|
+
|
|
379
445
|
if (!cardData) throw new Error('CARD_NOT_FULLY_IN_FRAME');
|
|
380
|
-
|
|
446
|
+
|
|
381
447
|
let points: number[][] | null = null;
|
|
448
|
+
console.log(points)
|
|
382
449
|
let isCardInFrame = false;
|
|
383
450
|
let hasCroppedSides = true;
|
|
384
|
-
|
|
385
|
-
|
|
451
|
+
|
|
386
452
|
if (cardData.obb) {
|
|
387
453
|
points = cardData.obb;
|
|
388
454
|
if (typeof cardData.card_in_frame !== 'undefined') {
|
|
@@ -393,25 +459,25 @@ export async function checkTemplateType(
|
|
|
393
459
|
points = cardData[0];
|
|
394
460
|
isCardInFrame = true;
|
|
395
461
|
hasCroppedSides = false;
|
|
396
|
-
// 🚨 ARTIFICIAL CHECK REMOVED HERE
|
|
397
462
|
}
|
|
398
|
-
|
|
463
|
+
|
|
399
464
|
if (!isCardInFrame || hasCroppedSides) {
|
|
400
465
|
logger.log(`Template Framing failed by backend check.`);
|
|
401
466
|
throw new Error('CARD_NOT_FULLY_IN_FRAME');
|
|
402
467
|
}
|
|
403
|
-
|
|
468
|
+
|
|
404
469
|
const LPIPS_THRESHOLD = 0.75;
|
|
405
470
|
if (templateType.lpips_score !== undefined && templateType.lpips_score > LPIPS_THRESHOLD) {
|
|
406
471
|
logger.log(`🛑 Country Mismatch! LPIPS: ${templateType.lpips_score}`);
|
|
407
472
|
throw new Error(`Le document présenté ne correspond pas au pays sélectionné (${result.docRegion}).`);
|
|
408
473
|
}
|
|
409
|
-
|
|
474
|
+
|
|
410
475
|
logger.log("templateType result", JSON.stringify(truncateFields(templateType), null, 2));
|
|
411
476
|
return templateType;
|
|
477
|
+
|
|
412
478
|
} catch (e: any) {
|
|
413
|
-
logger.log('
|
|
414
|
-
if (e?.message === 'CARD_NOT_FULLY_IN_FRAME' || e?.message?.includes('ne correspond pas')) throw e;
|
|
479
|
+
logger.log('Error checking template type:', JSON.stringify(errorMessage(e), null, 2));
|
|
480
|
+
if (e?.message === 'CARD_NOT_FULLY_IN_FRAME' || e?.message?.includes('ne correspond pas')) throw e;
|
|
415
481
|
throw new Error(e?.message || 'Erreur de vérification du template');
|
|
416
482
|
}
|
|
417
483
|
}
|