@hexar/biometric-identity-sdk-core 1.0.15 → 1.0.16
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.
|
@@ -89,6 +89,14 @@ export declare class BiometricIdentitySDK {
|
|
|
89
89
|
* Compress image in browser environment using Canvas API
|
|
90
90
|
*/
|
|
91
91
|
private compressImageBrowser;
|
|
92
|
+
/**
|
|
93
|
+
* Fix base64 padding issues
|
|
94
|
+
*/
|
|
95
|
+
private fixBase64Padding;
|
|
96
|
+
/**
|
|
97
|
+
* Validate if string is valid base64
|
|
98
|
+
*/
|
|
99
|
+
private isValidBase64;
|
|
92
100
|
/**
|
|
93
101
|
* Get current SDK state
|
|
94
102
|
*/
|
|
@@ -308,13 +308,34 @@ class BiometricIdentitySDK {
|
|
|
308
308
|
sampledCount: videoFrames.length
|
|
309
309
|
});
|
|
310
310
|
}
|
|
311
|
-
const compressedFrontImage = await this.compressImage(this.state.frontID.data);
|
|
311
|
+
const compressedFrontImage = this.fixBase64Padding(await this.compressImage(this.state.frontID.data));
|
|
312
312
|
const compressedBackImage = this.state.backID?.data
|
|
313
|
-
? await this.compressImage(this.state.backID.data)
|
|
313
|
+
? this.fixBase64Padding(await this.compressImage(this.state.backID.data))
|
|
314
314
|
: undefined;
|
|
315
|
-
const
|
|
315
|
+
const validFrames = [];
|
|
316
|
+
for (let i = 0; i < videoFrames.length; i++) {
|
|
317
|
+
const frame = videoFrames[i];
|
|
318
|
+
if (!frame || typeof frame !== 'string') {
|
|
319
|
+
logger_1.logger.warn(`Skipping invalid frame ${i}: not a string`);
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
if (frame.length < 100) {
|
|
323
|
+
logger_1.logger.warn(`Skipping invalid frame ${i}: too short (${frame.length} chars), likely a file path`);
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
if (!this.isValidBase64(frame)) {
|
|
327
|
+
logger_1.logger.warn(`Skipping invalid frame ${i}: not valid base64`);
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
const compressedFrame = this.fixBase64Padding(await this.compressImage(frame));
|
|
331
|
+
validFrames.push(compressedFrame);
|
|
332
|
+
}
|
|
333
|
+
if (validFrames.length < 10) {
|
|
334
|
+
logger_1.logger.error(`Insufficient valid frames: ${validFrames.length} < 10`);
|
|
335
|
+
throw new Error(`Insufficient valid video frames: ${validFrames.length} frames available, minimum 10 required`);
|
|
336
|
+
}
|
|
316
337
|
logger_1.logger.info('Sending validation request to backend', {
|
|
317
|
-
framesCount:
|
|
338
|
+
framesCount: validFrames.length,
|
|
318
339
|
duration: this.state.videoData.duration,
|
|
319
340
|
challengesCount: this.state.videoData.challengesCompleted?.length || 0,
|
|
320
341
|
frontImageSize: compressedFrontImage.length,
|
|
@@ -326,7 +347,7 @@ class BiometricIdentitySDK {
|
|
|
326
347
|
const response = await this.backendClient.fullValidation({
|
|
327
348
|
frontIdImage: compressedFrontImage,
|
|
328
349
|
backIdImage: compressedBackImage,
|
|
329
|
-
videoFrames:
|
|
350
|
+
videoFrames: validFrames,
|
|
330
351
|
videoDurationMs: this.state.videoData.duration,
|
|
331
352
|
challengesCompleted: this.state.videoData.challengesCompleted || [],
|
|
332
353
|
});
|
|
@@ -452,6 +473,35 @@ class BiometricIdentitySDK {
|
|
|
452
473
|
img.src = `data:image/jpeg;base64,${base64Image}`;
|
|
453
474
|
});
|
|
454
475
|
}
|
|
476
|
+
/**
|
|
477
|
+
* Fix base64 padding issues
|
|
478
|
+
*/
|
|
479
|
+
fixBase64Padding(base64) {
|
|
480
|
+
if (!base64)
|
|
481
|
+
return base64;
|
|
482
|
+
let cleaned = base64.replace(/\s/g, '');
|
|
483
|
+
if (cleaned.includes(',')) {
|
|
484
|
+
cleaned = cleaned.split(',')[1] || cleaned;
|
|
485
|
+
}
|
|
486
|
+
const padding = cleaned.length % 4;
|
|
487
|
+
if (padding > 0) {
|
|
488
|
+
cleaned += '='.repeat(4 - padding);
|
|
489
|
+
}
|
|
490
|
+
return cleaned;
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Validate if string is valid base64
|
|
494
|
+
*/
|
|
495
|
+
isValidBase64(str) {
|
|
496
|
+
if (!str || typeof str !== 'string')
|
|
497
|
+
return false;
|
|
498
|
+
const cleaned = str.replace(/\s/g, '');
|
|
499
|
+
if (cleaned.includes(',')) {
|
|
500
|
+
return true;
|
|
501
|
+
}
|
|
502
|
+
const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
503
|
+
return base64Regex.test(cleaned) && cleaned.length > 100;
|
|
504
|
+
}
|
|
455
505
|
/**
|
|
456
506
|
* Get current SDK state
|
|
457
507
|
*/
|
package/package.json
CHANGED
|
@@ -391,16 +391,40 @@ export class BiometricIdentitySDK {
|
|
|
391
391
|
});
|
|
392
392
|
}
|
|
393
393
|
|
|
394
|
-
const compressedFrontImage = await this.compressImage(this.state.frontID.data);
|
|
394
|
+
const compressedFrontImage = this.fixBase64Padding(await this.compressImage(this.state.frontID.data));
|
|
395
395
|
const compressedBackImage = this.state.backID?.data
|
|
396
|
-
? await this.compressImage(this.state.backID.data)
|
|
396
|
+
? this.fixBase64Padding(await this.compressImage(this.state.backID.data))
|
|
397
397
|
: undefined;
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
)
|
|
398
|
+
|
|
399
|
+
const validFrames: string[] = [];
|
|
400
|
+
for (let i = 0; i < videoFrames.length; i++) {
|
|
401
|
+
const frame = videoFrames[i];
|
|
402
|
+
if (!frame || typeof frame !== 'string') {
|
|
403
|
+
logger.warn(`Skipping invalid frame ${i}: not a string`);
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
if (frame.length < 100) {
|
|
408
|
+
logger.warn(`Skipping invalid frame ${i}: too short (${frame.length} chars), likely a file path`);
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
if (!this.isValidBase64(frame)) {
|
|
413
|
+
logger.warn(`Skipping invalid frame ${i}: not valid base64`);
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
const compressedFrame = this.fixBase64Padding(await this.compressImage(frame));
|
|
418
|
+
validFrames.push(compressedFrame);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
if (validFrames.length < 10) {
|
|
422
|
+
logger.error(`Insufficient valid frames: ${validFrames.length} < 10`);
|
|
423
|
+
throw new Error(`Insufficient valid video frames: ${validFrames.length} frames available, minimum 10 required`);
|
|
424
|
+
}
|
|
401
425
|
|
|
402
426
|
logger.info('Sending validation request to backend', {
|
|
403
|
-
framesCount:
|
|
427
|
+
framesCount: validFrames.length,
|
|
404
428
|
duration: this.state.videoData.duration,
|
|
405
429
|
challengesCount: this.state.videoData.challengesCompleted?.length || 0,
|
|
406
430
|
frontImageSize: compressedFrontImage.length,
|
|
@@ -413,7 +437,7 @@ export class BiometricIdentitySDK {
|
|
|
413
437
|
const response = await this.backendClient.fullValidation({
|
|
414
438
|
frontIdImage: compressedFrontImage,
|
|
415
439
|
backIdImage: compressedBackImage,
|
|
416
|
-
videoFrames:
|
|
440
|
+
videoFrames: validFrames,
|
|
417
441
|
videoDurationMs: this.state.videoData.duration,
|
|
418
442
|
challengesCompleted: this.state.videoData.challengesCompleted || [],
|
|
419
443
|
});
|
|
@@ -563,6 +587,41 @@ export class BiometricIdentitySDK {
|
|
|
563
587
|
});
|
|
564
588
|
}
|
|
565
589
|
|
|
590
|
+
/**
|
|
591
|
+
* Fix base64 padding issues
|
|
592
|
+
*/
|
|
593
|
+
private fixBase64Padding(base64: string): string {
|
|
594
|
+
if (!base64) return base64;
|
|
595
|
+
|
|
596
|
+
let cleaned = base64.replace(/\s/g, '');
|
|
597
|
+
|
|
598
|
+
if (cleaned.includes(',')) {
|
|
599
|
+
cleaned = cleaned.split(',')[1] || cleaned;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
const padding = cleaned.length % 4;
|
|
603
|
+
if (padding > 0) {
|
|
604
|
+
cleaned += '='.repeat(4 - padding);
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
return cleaned;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* Validate if string is valid base64
|
|
612
|
+
*/
|
|
613
|
+
private isValidBase64(str: string): boolean {
|
|
614
|
+
if (!str || typeof str !== 'string') return false;
|
|
615
|
+
|
|
616
|
+
const cleaned = str.replace(/\s/g, '');
|
|
617
|
+
if (cleaned.includes(',')) {
|
|
618
|
+
return true;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
622
|
+
return base64Regex.test(cleaned) && cleaned.length > 100;
|
|
623
|
+
}
|
|
624
|
+
|
|
566
625
|
/**
|
|
567
626
|
* Get current SDK state
|
|
568
627
|
*/
|