react-native-unit-components 3.5.1 → 3.5.2
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/lib/commonjs/services/veryfiService.js +68 -12
- package/lib/commonjs/services/veryfiService.js.map +1 -1
- package/lib/commonjs/services/veryfiService.utils.js +87 -0
- package/lib/commonjs/services/veryfiService.utils.js.map +1 -0
- package/lib/commonjs/unitComponentsSdkManager/UnitComponentsSdkManager.js +1 -1
- package/lib/module/services/veryfiService.js +68 -12
- package/lib/module/services/veryfiService.js.map +1 -1
- package/lib/module/services/veryfiService.utils.js +79 -0
- package/lib/module/services/veryfiService.utils.js.map +1 -0
- package/lib/module/unitComponentsSdkManager/UnitComponentsSdkManager.js +1 -1
- package/lib/typescript/src/services/veryfiService.d.ts +2 -4
- package/lib/typescript/src/services/veryfiService.d.ts.map +1 -1
- package/lib/typescript/src/services/veryfiService.utils.d.ts +10 -0
- package/lib/typescript/src/services/veryfiService.utils.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/services/veryfiService.ts +76 -16
- package/src/services/veryfiService.utils.ts +87 -0
- package/src/unitComponentsSdkManager/UnitComponentsSdkManager.ts +1 -1
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.isVeryfiAvailable = exports.configureAndShowVeryfiCamera = void 0;
|
|
7
7
|
var _reactNative = require("react-native");
|
|
8
|
+
var _veryfiService = require("./veryfiService.utils");
|
|
8
9
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9
10
|
let VeryfiLens = null;
|
|
10
11
|
try {
|
|
@@ -20,8 +21,12 @@ exports.isVeryfiAvailable = isVeryfiAvailable;
|
|
|
20
21
|
const CHECK_SETTINGS = {
|
|
21
22
|
documentTypes: ['check'],
|
|
22
23
|
checksBackIsOn: true,
|
|
24
|
+
checksBackIsRequired: true,
|
|
23
25
|
blurDetectionIsOn: true,
|
|
24
26
|
autoDocDetectionAndCropIsOn: true,
|
|
27
|
+
// Without this, a no-document capture is kept in the package and the user
|
|
28
|
+
// lands on the submit screen with an image that can only fail.
|
|
29
|
+
allowSubmitUndetectedDocsIsOn: false,
|
|
25
30
|
dataExtractionEngine: true,
|
|
26
31
|
returnStitchedPDF: true,
|
|
27
32
|
originalImageMaxSizeInMB: 1.4
|
|
@@ -34,6 +39,10 @@ const buildEndorsement = bankName => {
|
|
|
34
39
|
// Bank-agnostic fallback when the bank name is absent, so the copy never reads "...deposit at ".
|
|
35
40
|
return `Please make sure to sign the back and write “For mobile deposit ${bank ? `at ${bank}` : 'only'}”`;
|
|
36
41
|
};
|
|
42
|
+
|
|
43
|
+
// How long to hold delivery waiting for Veryfi's parsed result before falling
|
|
44
|
+
// back to positional labeling.
|
|
45
|
+
const VERDICT_WAIT_MS = 10000;
|
|
37
46
|
const configureAndShowVeryfiCamera = (credentials, bankName, onImages, onError) => {
|
|
38
47
|
if (!VeryfiLens) {
|
|
39
48
|
onError('Veryfi SDK is not available');
|
|
@@ -42,13 +51,45 @@ const configureAndShowVeryfiCamera = (credentials, bankName, onImages, onError)
|
|
|
42
51
|
const emitter = new _reactNative.NativeEventEmitter(VeryfiLens.NativeModule);
|
|
43
52
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
44
53
|
const subscriptions = [];
|
|
45
|
-
let
|
|
54
|
+
let capturing = false;
|
|
55
|
+
let dispatched = false;
|
|
56
|
+
let convertedImages = null;
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
58
|
+
let verdictPages = null;
|
|
59
|
+
let fallbackTimer = null;
|
|
46
60
|
const cleanup = () => {
|
|
47
61
|
subscriptions.forEach(sub => sub.remove());
|
|
62
|
+
if (fallbackTimer != null) {
|
|
63
|
+
clearTimeout(fallbackTimer);
|
|
64
|
+
fallbackTimer = null;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
const dispatchToWeb = images => {
|
|
68
|
+
if (dispatched) return;
|
|
69
|
+
dispatched = true;
|
|
70
|
+
cleanup();
|
|
71
|
+
onImages(images);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// Delivery is held briefly so Veryfi's parsed result — the authoritative
|
|
75
|
+
// source for which image is the front — can label the pair before the web
|
|
76
|
+
// renders it. The positional fallback covers slow or failed uploads;
|
|
77
|
+
// position is unreliable across Veryfi versions (the order reversed in
|
|
78
|
+
// Android lens 2.4.0.0), which is exactly why the verdict is preferred.
|
|
79
|
+
const dispatchWhenReady = () => {
|
|
80
|
+
if (dispatched || !convertedImages) return;
|
|
81
|
+
if (verdictPages) {
|
|
82
|
+
const labeled = (0, _veryfiService.labelSidesFromPages)(convertedImages, verdictPages);
|
|
83
|
+
dispatchToWeb(labeled ?? convertedImages);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (fallbackTimer == null) {
|
|
87
|
+
fallbackTimer = setTimeout(() => dispatchToWeb(convertedImages), VERDICT_WAIT_MS);
|
|
88
|
+
}
|
|
48
89
|
};
|
|
49
|
-
const
|
|
50
|
-
if (
|
|
51
|
-
|
|
90
|
+
const convertImages = imagePaths => {
|
|
91
|
+
if (capturing) return;
|
|
92
|
+
capturing = true;
|
|
52
93
|
let converted = 0;
|
|
53
94
|
const images = [];
|
|
54
95
|
imagePaths.forEach((filePath, index) => {
|
|
@@ -57,10 +98,11 @@ const configureAndShowVeryfiCamera = (credentials, bankName, onImages, onError)
|
|
|
57
98
|
() => {
|
|
58
99
|
converted++;
|
|
59
100
|
if (converted === imagePaths.length) {
|
|
60
|
-
cleanup();
|
|
61
101
|
if (images.length > 0) {
|
|
62
|
-
|
|
102
|
+
convertedImages = images;
|
|
103
|
+
dispatchWhenReady();
|
|
63
104
|
} else {
|
|
105
|
+
cleanup();
|
|
64
106
|
onError('Failed to convert check images');
|
|
65
107
|
}
|
|
66
108
|
}
|
|
@@ -73,8 +115,8 @@ const configureAndShowVeryfiCamera = (credentials, bankName, onImages, onError)
|
|
|
73
115
|
});
|
|
74
116
|
converted++;
|
|
75
117
|
if (converted === imagePaths.length) {
|
|
76
|
-
|
|
77
|
-
|
|
118
|
+
convertedImages = images;
|
|
119
|
+
dispatchWhenReady();
|
|
78
120
|
}
|
|
79
121
|
});
|
|
80
122
|
});
|
|
@@ -87,14 +129,28 @@ const configureAndShowVeryfiCamera = (credentials, bankName, onImages, onError)
|
|
|
87
129
|
if (event.status === 'inprogress' && event.msg === 'img_stitched_pdf_path') {
|
|
88
130
|
const paths = event.img_original_paths || [];
|
|
89
131
|
if (paths.length > 0) {
|
|
90
|
-
|
|
132
|
+
convertImages(paths);
|
|
91
133
|
}
|
|
92
134
|
}
|
|
93
135
|
}));
|
|
136
|
+
subscriptions.push(
|
|
137
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
138
|
+
emitter.addListener(VeryfiLens.Events.onVeryfiLensSuccess, event => {
|
|
139
|
+
verdictPages = event?.data?.meta?.pages ?? null;
|
|
140
|
+
dispatchWhenReady();
|
|
141
|
+
}));
|
|
94
142
|
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
|
|
143
|
+
// User cancelled (X button) without submitting: the web side never resets its
|
|
144
|
+
// loading state on its own, so deliver an empty response to move it off the
|
|
145
|
+
// stuck Continue. Grace period covers a close event racing the stitched event.
|
|
146
|
+
subscriptions.push(emitter.addListener(VeryfiLens.Events.onVeryfiLensClose, () => {
|
|
147
|
+
setTimeout(() => {
|
|
148
|
+
if (capturing || dispatched) return;
|
|
149
|
+
dispatched = true;
|
|
150
|
+
cleanup();
|
|
151
|
+
onImages([]);
|
|
152
|
+
}, 1500);
|
|
153
|
+
}));
|
|
98
154
|
subscriptions.push(
|
|
99
155
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
100
156
|
emitter.addListener(VeryfiLens.Events.onVeryfiLensError, event => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","VeryfiLens","default","isVeryfiAvailable","exports","CHECK_SETTINGS","documentTypes","checksBackIsOn","blurDetectionIsOn","autoDocDetectionAndCropIsOn","dataExtractionEngine","returnStitchedPDF","originalImageMaxSizeInMB","BACK_CAPTURE_MODAL_KEY","buildEndorsement","bankName","bank","trim","configureAndShowVeryfiCamera","credentials","onImages","onError","emitter","NativeEventEmitter","NativeModule","subscriptions","
|
|
1
|
+
{"version":3,"names":["_reactNative","require","_veryfiService","VeryfiLens","default","isVeryfiAvailable","exports","CHECK_SETTINGS","documentTypes","checksBackIsOn","checksBackIsRequired","blurDetectionIsOn","autoDocDetectionAndCropIsOn","allowSubmitUndetectedDocsIsOn","dataExtractionEngine","returnStitchedPDF","originalImageMaxSizeInMB","BACK_CAPTURE_MODAL_KEY","buildEndorsement","bankName","bank","trim","VERDICT_WAIT_MS","configureAndShowVeryfiCamera","credentials","onImages","onError","emitter","NativeEventEmitter","NativeModule","subscriptions","capturing","dispatched","convertedImages","verdictPages","fallbackTimer","cleanup","forEach","sub","remove","clearTimeout","dispatchToWeb","images","dispatchWhenReady","labeled","labelSidesFromPages","setTimeout","convertImages","imagePaths","converted","filePath","index","getFileBase64","length","base64Data","push","base64Img","isFront","addListener","Events","onVeryfiLensUpdate","event","status","msg","paths","img_original_paths","onVeryfiLensSuccess","data","meta","pages","onVeryfiLensClose","onVeryfiLensError","veryfiCredentials","clientId","userName","apiKey","url","endorsement","settings","customLensStrings","en","configureWithCredentials","showCamera"],"sourceRoot":"../../../src","sources":["services/veryfiService.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.readJpegDimensions = exports.labelSidesFromPages = void 0;
|
|
7
|
+
const JPEG_SOF_MARKERS = [0xc0, 0xc1, 0xc2, 0xc3, 0xc5, 0xc6, 0xc7, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf];
|
|
8
|
+
const readJpegDimensions = base64 => {
|
|
9
|
+
try {
|
|
10
|
+
// SOF sits near the file start; a 4-aligned prefix keeps atob happy and cheap.
|
|
11
|
+
const prefix = base64.length > 786432 ? base64.slice(0, 786432) : base64;
|
|
12
|
+
const bytes = atob(prefix);
|
|
13
|
+
if (bytes.charCodeAt(0) !== 0xff || bytes.charCodeAt(1) !== 0xd8) return null;
|
|
14
|
+
let i = 2;
|
|
15
|
+
while (i + 9 < bytes.length) {
|
|
16
|
+
if (bytes.charCodeAt(i) !== 0xff) {
|
|
17
|
+
i++;
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
const marker = bytes.charCodeAt(i + 1);
|
|
21
|
+
if (marker === 0xff) {
|
|
22
|
+
i++;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (marker === 0x01 || marker >= 0xd0 && marker <= 0xd9) {
|
|
26
|
+
i += 2;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (JPEG_SOF_MARKERS.includes(marker)) {
|
|
30
|
+
return {
|
|
31
|
+
height: bytes.charCodeAt(i + 5) * 256 + bytes.charCodeAt(i + 6),
|
|
32
|
+
width: bytes.charCodeAt(i + 7) * 256 + bytes.charCodeAt(i + 8)
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
i += 2 + bytes.charCodeAt(i + 2) * 256 + bytes.charCodeAt(i + 3);
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Veryfi's parsed result is the authority on which image is the front
|
|
44
|
+
// (their meta.pages[].is_front); page order does not correspond to the
|
|
45
|
+
// delivery array's order, so pages are matched to our images by exact
|
|
46
|
+
// pixel dimensions. Returns null whenever the verdict is not unambiguous.
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
48
|
+
exports.readJpegDimensions = readJpegDimensions;
|
|
49
|
+
const labelSidesFromPages = (images, pages) => {
|
|
50
|
+
if (!Array.isArray(pages) || pages.length !== 2 || images.length !== 2) return null;
|
|
51
|
+
const fronts = pages.filter(p => p && p.is_front === true);
|
|
52
|
+
const backs = pages.filter(p => p && p.is_front === false);
|
|
53
|
+
const frontPage = fronts[0];
|
|
54
|
+
const backPage = backs[0];
|
|
55
|
+
if (fronts.length !== 1 || backs.length !== 1 || !frontPage || !backPage) return null;
|
|
56
|
+
if (typeof frontPage.width !== 'number' || typeof frontPage.height !== 'number') return null;
|
|
57
|
+
const dims = [];
|
|
58
|
+
for (const img of images) {
|
|
59
|
+
const d = readJpegDimensions(img.base64Img);
|
|
60
|
+
if (!d) return null;
|
|
61
|
+
dims.push(d);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Veryfi may auto-rotate pages in the parsed result, so dimensions are
|
|
65
|
+
// compared as an unordered pair.
|
|
66
|
+
const sameDims = (d, w, h) => d.width === w && d.height === h || d.width === h && d.height === w;
|
|
67
|
+
const matchesFront = dims.map(d => sameDims(d, frontPage.width, frontPage.height));
|
|
68
|
+
if (matchesFront.filter(Boolean).length !== 1) return null;
|
|
69
|
+
const frontIdx = matchesFront.indexOf(true);
|
|
70
|
+
const backIdx = 1 - frontIdx;
|
|
71
|
+
const frontImage = images[frontIdx];
|
|
72
|
+
const backImage = images[backIdx];
|
|
73
|
+
const backDims = dims[backIdx];
|
|
74
|
+
if (!frontImage || !backImage || !backDims) return null;
|
|
75
|
+
if (typeof backPage.width === 'number' && typeof backPage.height === 'number') {
|
|
76
|
+
if (!sameDims(backDims, backPage.width, backPage.height)) return null;
|
|
77
|
+
}
|
|
78
|
+
return [{
|
|
79
|
+
base64Img: frontImage.base64Img,
|
|
80
|
+
isFront: true
|
|
81
|
+
}, {
|
|
82
|
+
base64Img: backImage.base64Img,
|
|
83
|
+
isFront: false
|
|
84
|
+
}];
|
|
85
|
+
};
|
|
86
|
+
exports.labelSidesFromPages = labelSidesFromPages;
|
|
87
|
+
//# sourceMappingURL=veryfiService.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["JPEG_SOF_MARKERS","readJpegDimensions","base64","prefix","length","slice","bytes","atob","charCodeAt","i","marker","includes","height","width","exports","labelSidesFromPages","images","pages","Array","isArray","fronts","filter","p","is_front","backs","frontPage","backPage","dims","img","d","base64Img","push","sameDims","w","h","matchesFront","map","Boolean","frontIdx","indexOf","backIdx","frontImage","backImage","backDims","isFront"],"sourceRoot":"../../../src","sources":["services/veryfiService.utils.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -21,7 +21,7 @@ var _UNFontFileHelper = require("../nativeModulesHelpers/UNFontFileHelper/UNFont
|
|
|
21
21
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
22
22
|
class UnitComponentsSDK {
|
|
23
23
|
static securitySettings = _UnitComponentsSdk2.UNComponentsSDKConstants.securitySettings;
|
|
24
|
-
static sdkVersion = '3.5.
|
|
24
|
+
static sdkVersion = '3.5.2';
|
|
25
25
|
static iosFontBase64Map = {};
|
|
26
26
|
static init = async (env, theme, language, fonts, webVersioningStrategy = _UnitComponentsSdk2.UNComponentsSDKConstants.webSDKRecommendedStrategy, securitySettings = _UnitComponentsSdk2.UNComponentsSDKConstants.securitySettings) => {
|
|
27
27
|
try {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NativeEventEmitter } from 'react-native';
|
|
2
|
+
import { labelSidesFromPages } from './veryfiService.utils';
|
|
2
3
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3
4
|
let VeryfiLens = null;
|
|
4
5
|
try {
|
|
@@ -13,8 +14,12 @@ export const isVeryfiAvailable = () => {
|
|
|
13
14
|
const CHECK_SETTINGS = {
|
|
14
15
|
documentTypes: ['check'],
|
|
15
16
|
checksBackIsOn: true,
|
|
17
|
+
checksBackIsRequired: true,
|
|
16
18
|
blurDetectionIsOn: true,
|
|
17
19
|
autoDocDetectionAndCropIsOn: true,
|
|
20
|
+
// Without this, a no-document capture is kept in the package and the user
|
|
21
|
+
// lands on the submit screen with an image that can only fail.
|
|
22
|
+
allowSubmitUndetectedDocsIsOn: false,
|
|
18
23
|
dataExtractionEngine: true,
|
|
19
24
|
returnStitchedPDF: true,
|
|
20
25
|
originalImageMaxSizeInMB: 1.4
|
|
@@ -27,6 +32,10 @@ const buildEndorsement = bankName => {
|
|
|
27
32
|
// Bank-agnostic fallback when the bank name is absent, so the copy never reads "...deposit at ".
|
|
28
33
|
return `Please make sure to sign the back and write “For mobile deposit ${bank ? `at ${bank}` : 'only'}”`;
|
|
29
34
|
};
|
|
35
|
+
|
|
36
|
+
// How long to hold delivery waiting for Veryfi's parsed result before falling
|
|
37
|
+
// back to positional labeling.
|
|
38
|
+
const VERDICT_WAIT_MS = 10000;
|
|
30
39
|
export const configureAndShowVeryfiCamera = (credentials, bankName, onImages, onError) => {
|
|
31
40
|
if (!VeryfiLens) {
|
|
32
41
|
onError('Veryfi SDK is not available');
|
|
@@ -35,13 +44,45 @@ export const configureAndShowVeryfiCamera = (credentials, bankName, onImages, on
|
|
|
35
44
|
const emitter = new NativeEventEmitter(VeryfiLens.NativeModule);
|
|
36
45
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
37
46
|
const subscriptions = [];
|
|
38
|
-
let
|
|
47
|
+
let capturing = false;
|
|
48
|
+
let dispatched = false;
|
|
49
|
+
let convertedImages = null;
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
51
|
+
let verdictPages = null;
|
|
52
|
+
let fallbackTimer = null;
|
|
39
53
|
const cleanup = () => {
|
|
40
54
|
subscriptions.forEach(sub => sub.remove());
|
|
55
|
+
if (fallbackTimer != null) {
|
|
56
|
+
clearTimeout(fallbackTimer);
|
|
57
|
+
fallbackTimer = null;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const dispatchToWeb = images => {
|
|
61
|
+
if (dispatched) return;
|
|
62
|
+
dispatched = true;
|
|
63
|
+
cleanup();
|
|
64
|
+
onImages(images);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// Delivery is held briefly so Veryfi's parsed result — the authoritative
|
|
68
|
+
// source for which image is the front — can label the pair before the web
|
|
69
|
+
// renders it. The positional fallback covers slow or failed uploads;
|
|
70
|
+
// position is unreliable across Veryfi versions (the order reversed in
|
|
71
|
+
// Android lens 2.4.0.0), which is exactly why the verdict is preferred.
|
|
72
|
+
const dispatchWhenReady = () => {
|
|
73
|
+
if (dispatched || !convertedImages) return;
|
|
74
|
+
if (verdictPages) {
|
|
75
|
+
const labeled = labelSidesFromPages(convertedImages, verdictPages);
|
|
76
|
+
dispatchToWeb(labeled ?? convertedImages);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (fallbackTimer == null) {
|
|
80
|
+
fallbackTimer = setTimeout(() => dispatchToWeb(convertedImages), VERDICT_WAIT_MS);
|
|
81
|
+
}
|
|
41
82
|
};
|
|
42
|
-
const
|
|
43
|
-
if (
|
|
44
|
-
|
|
83
|
+
const convertImages = imagePaths => {
|
|
84
|
+
if (capturing) return;
|
|
85
|
+
capturing = true;
|
|
45
86
|
let converted = 0;
|
|
46
87
|
const images = [];
|
|
47
88
|
imagePaths.forEach((filePath, index) => {
|
|
@@ -50,10 +91,11 @@ export const configureAndShowVeryfiCamera = (credentials, bankName, onImages, on
|
|
|
50
91
|
() => {
|
|
51
92
|
converted++;
|
|
52
93
|
if (converted === imagePaths.length) {
|
|
53
|
-
cleanup();
|
|
54
94
|
if (images.length > 0) {
|
|
55
|
-
|
|
95
|
+
convertedImages = images;
|
|
96
|
+
dispatchWhenReady();
|
|
56
97
|
} else {
|
|
98
|
+
cleanup();
|
|
57
99
|
onError('Failed to convert check images');
|
|
58
100
|
}
|
|
59
101
|
}
|
|
@@ -66,8 +108,8 @@ export const configureAndShowVeryfiCamera = (credentials, bankName, onImages, on
|
|
|
66
108
|
});
|
|
67
109
|
converted++;
|
|
68
110
|
if (converted === imagePaths.length) {
|
|
69
|
-
|
|
70
|
-
|
|
111
|
+
convertedImages = images;
|
|
112
|
+
dispatchWhenReady();
|
|
71
113
|
}
|
|
72
114
|
});
|
|
73
115
|
});
|
|
@@ -80,14 +122,28 @@ export const configureAndShowVeryfiCamera = (credentials, bankName, onImages, on
|
|
|
80
122
|
if (event.status === 'inprogress' && event.msg === 'img_stitched_pdf_path') {
|
|
81
123
|
const paths = event.img_original_paths || [];
|
|
82
124
|
if (paths.length > 0) {
|
|
83
|
-
|
|
125
|
+
convertImages(paths);
|
|
84
126
|
}
|
|
85
127
|
}
|
|
86
128
|
}));
|
|
129
|
+
subscriptions.push(
|
|
130
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
131
|
+
emitter.addListener(VeryfiLens.Events.onVeryfiLensSuccess, event => {
|
|
132
|
+
verdictPages = event?.data?.meta?.pages ?? null;
|
|
133
|
+
dispatchWhenReady();
|
|
134
|
+
}));
|
|
87
135
|
|
|
88
|
-
//
|
|
89
|
-
//
|
|
90
|
-
|
|
136
|
+
// User cancelled (X button) without submitting: the web side never resets its
|
|
137
|
+
// loading state on its own, so deliver an empty response to move it off the
|
|
138
|
+
// stuck Continue. Grace period covers a close event racing the stitched event.
|
|
139
|
+
subscriptions.push(emitter.addListener(VeryfiLens.Events.onVeryfiLensClose, () => {
|
|
140
|
+
setTimeout(() => {
|
|
141
|
+
if (capturing || dispatched) return;
|
|
142
|
+
dispatched = true;
|
|
143
|
+
cleanup();
|
|
144
|
+
onImages([]);
|
|
145
|
+
}, 1500);
|
|
146
|
+
}));
|
|
91
147
|
subscriptions.push(
|
|
92
148
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
93
149
|
emitter.addListener(VeryfiLens.Events.onVeryfiLensError, event => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeEventEmitter","VeryfiLens","require","default","isVeryfiAvailable","CHECK_SETTINGS","documentTypes","checksBackIsOn","blurDetectionIsOn","autoDocDetectionAndCropIsOn","dataExtractionEngine","returnStitchedPDF","originalImageMaxSizeInMB","BACK_CAPTURE_MODAL_KEY","buildEndorsement","bankName","bank","trim","configureAndShowVeryfiCamera","credentials","onImages","onError","emitter","NativeModule","subscriptions","
|
|
1
|
+
{"version":3,"names":["NativeEventEmitter","labelSidesFromPages","VeryfiLens","require","default","isVeryfiAvailable","CHECK_SETTINGS","documentTypes","checksBackIsOn","checksBackIsRequired","blurDetectionIsOn","autoDocDetectionAndCropIsOn","allowSubmitUndetectedDocsIsOn","dataExtractionEngine","returnStitchedPDF","originalImageMaxSizeInMB","BACK_CAPTURE_MODAL_KEY","buildEndorsement","bankName","bank","trim","VERDICT_WAIT_MS","configureAndShowVeryfiCamera","credentials","onImages","onError","emitter","NativeModule","subscriptions","capturing","dispatched","convertedImages","verdictPages","fallbackTimer","cleanup","forEach","sub","remove","clearTimeout","dispatchToWeb","images","dispatchWhenReady","labeled","setTimeout","convertImages","imagePaths","converted","filePath","index","getFileBase64","length","base64Data","push","base64Img","isFront","addListener","Events","onVeryfiLensUpdate","event","status","msg","paths","img_original_paths","onVeryfiLensSuccess","data","meta","pages","onVeryfiLensClose","onVeryfiLensError","veryfiCredentials","clientId","userName","apiKey","url","endorsement","settings","customLensStrings","en","configureWithCredentials","showCamera"],"sourceRoot":"../../../src","sources":["services/veryfiService.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const JPEG_SOF_MARKERS = [0xc0, 0xc1, 0xc2, 0xc3, 0xc5, 0xc6, 0xc7, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf];
|
|
2
|
+
export const readJpegDimensions = base64 => {
|
|
3
|
+
try {
|
|
4
|
+
// SOF sits near the file start; a 4-aligned prefix keeps atob happy and cheap.
|
|
5
|
+
const prefix = base64.length > 786432 ? base64.slice(0, 786432) : base64;
|
|
6
|
+
const bytes = atob(prefix);
|
|
7
|
+
if (bytes.charCodeAt(0) !== 0xff || bytes.charCodeAt(1) !== 0xd8) return null;
|
|
8
|
+
let i = 2;
|
|
9
|
+
while (i + 9 < bytes.length) {
|
|
10
|
+
if (bytes.charCodeAt(i) !== 0xff) {
|
|
11
|
+
i++;
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
const marker = bytes.charCodeAt(i + 1);
|
|
15
|
+
if (marker === 0xff) {
|
|
16
|
+
i++;
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
if (marker === 0x01 || marker >= 0xd0 && marker <= 0xd9) {
|
|
20
|
+
i += 2;
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (JPEG_SOF_MARKERS.includes(marker)) {
|
|
24
|
+
return {
|
|
25
|
+
height: bytes.charCodeAt(i + 5) * 256 + bytes.charCodeAt(i + 6),
|
|
26
|
+
width: bytes.charCodeAt(i + 7) * 256 + bytes.charCodeAt(i + 8)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
i += 2 + bytes.charCodeAt(i + 2) * 256 + bytes.charCodeAt(i + 3);
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
} catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Veryfi's parsed result is the authority on which image is the front
|
|
38
|
+
// (their meta.pages[].is_front); page order does not correspond to the
|
|
39
|
+
// delivery array's order, so pages are matched to our images by exact
|
|
40
|
+
// pixel dimensions. Returns null whenever the verdict is not unambiguous.
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
42
|
+
export const labelSidesFromPages = (images, pages) => {
|
|
43
|
+
if (!Array.isArray(pages) || pages.length !== 2 || images.length !== 2) return null;
|
|
44
|
+
const fronts = pages.filter(p => p && p.is_front === true);
|
|
45
|
+
const backs = pages.filter(p => p && p.is_front === false);
|
|
46
|
+
const frontPage = fronts[0];
|
|
47
|
+
const backPage = backs[0];
|
|
48
|
+
if (fronts.length !== 1 || backs.length !== 1 || !frontPage || !backPage) return null;
|
|
49
|
+
if (typeof frontPage.width !== 'number' || typeof frontPage.height !== 'number') return null;
|
|
50
|
+
const dims = [];
|
|
51
|
+
for (const img of images) {
|
|
52
|
+
const d = readJpegDimensions(img.base64Img);
|
|
53
|
+
if (!d) return null;
|
|
54
|
+
dims.push(d);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Veryfi may auto-rotate pages in the parsed result, so dimensions are
|
|
58
|
+
// compared as an unordered pair.
|
|
59
|
+
const sameDims = (d, w, h) => d.width === w && d.height === h || d.width === h && d.height === w;
|
|
60
|
+
const matchesFront = dims.map(d => sameDims(d, frontPage.width, frontPage.height));
|
|
61
|
+
if (matchesFront.filter(Boolean).length !== 1) return null;
|
|
62
|
+
const frontIdx = matchesFront.indexOf(true);
|
|
63
|
+
const backIdx = 1 - frontIdx;
|
|
64
|
+
const frontImage = images[frontIdx];
|
|
65
|
+
const backImage = images[backIdx];
|
|
66
|
+
const backDims = dims[backIdx];
|
|
67
|
+
if (!frontImage || !backImage || !backDims) return null;
|
|
68
|
+
if (typeof backPage.width === 'number' && typeof backPage.height === 'number') {
|
|
69
|
+
if (!sameDims(backDims, backPage.width, backPage.height)) return null;
|
|
70
|
+
}
|
|
71
|
+
return [{
|
|
72
|
+
base64Img: frontImage.base64Img,
|
|
73
|
+
isFront: true
|
|
74
|
+
}, {
|
|
75
|
+
base64Img: backImage.base64Img,
|
|
76
|
+
isFront: false
|
|
77
|
+
}];
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=veryfiService.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["JPEG_SOF_MARKERS","readJpegDimensions","base64","prefix","length","slice","bytes","atob","charCodeAt","i","marker","includes","height","width","labelSidesFromPages","images","pages","Array","isArray","fronts","filter","p","is_front","backs","frontPage","backPage","dims","img","d","base64Img","push","sameDims","w","h","matchesFront","map","Boolean","frontIdx","indexOf","backIdx","frontImage","backImage","backDims","isFront"],"sourceRoot":"../../../src","sources":["services/veryfiService.utils.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -14,7 +14,7 @@ import UNSnapshotProtectionHelper from '../nativeModulesHelpers/UNSanpshotProtec
|
|
|
14
14
|
import { loadIosFontBase64 } from '../nativeModulesHelpers/UNFontFileHelper/UNFontFileHelper';
|
|
15
15
|
export class UnitComponentsSDK {
|
|
16
16
|
static securitySettings = UNComponentsSDKConstants.securitySettings;
|
|
17
|
-
static sdkVersion = '3.5.
|
|
17
|
+
static sdkVersion = '3.5.2';
|
|
18
18
|
static iosFontBase64Map = {};
|
|
19
19
|
static init = async (env, theme, language, fonts, webVersioningStrategy = UNComponentsSDKConstants.webSDKRecommendedStrategy, securitySettings = UNComponentsSDKConstants.securitySettings) => {
|
|
20
20
|
try {
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import type { UNVeryfiCredentials } from '../types/shared/veryfi.types';
|
|
2
|
+
import type { UNVeryfiImage } from './veryfiService.utils';
|
|
3
|
+
export type { UNVeryfiImage } from './veryfiService.utils';
|
|
2
4
|
export declare const isVeryfiAvailable: () => boolean;
|
|
3
|
-
export interface UNVeryfiImage {
|
|
4
|
-
base64Img: string;
|
|
5
|
-
isFront: boolean;
|
|
6
|
-
}
|
|
7
5
|
export declare const configureAndShowVeryfiCamera: (credentials: UNVeryfiCredentials, bankName: string | undefined, onImages: (images: UNVeryfiImage[]) => void, onError: (error: string) => void) => void;
|
|
8
6
|
//# sourceMappingURL=veryfiService.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"veryfiService.d.ts","sourceRoot":"","sources":["../../../../src/services/veryfiService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"veryfiService.d.ts","sourceRoot":"","sources":["../../../../src/services/veryfiService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAExE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAW3D,eAAO,MAAM,iBAAiB,QAAO,OAEpC,CAAC;AA6BF,eAAO,MAAM,4BAA4B,gBAC1B,mBAAmB,YACtB,MAAM,GAAG,SAAS,qBACT,aAAa,EAAE,KAAK,IAAI,mBAC1B,MAAM,KAAK,IAAI,KAC/B,IAsJF,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface UNVeryfiImage {
|
|
2
|
+
base64Img: string;
|
|
3
|
+
isFront: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare const readJpegDimensions: (base64: string) => {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
} | null;
|
|
9
|
+
export declare const labelSidesFromPages: (images: UNVeryfiImage[], pages: any) => UNVeryfiImage[] | null;
|
|
10
|
+
//# sourceMappingURL=veryfiService.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"veryfiService.utils.d.ts","sourceRoot":"","sources":["../../../../src/services/veryfiService.utils.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB;AAID,eAAO,MAAM,kBAAkB,WAAY,MAAM,KAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAiCvF,CAAC;AAOF,eAAO,MAAM,mBAAmB,WAAY,aAAa,EAAE,SAAS,GAAG,KAAG,aAAa,EAAE,GAAG,IAuC3F,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { NativeEventEmitter } from 'react-native';
|
|
2
2
|
import type { UNVeryfiCredentials } from '../types/shared/veryfi.types';
|
|
3
|
+
import { labelSidesFromPages } from './veryfiService.utils';
|
|
4
|
+
import type { UNVeryfiImage } from './veryfiService.utils';
|
|
5
|
+
|
|
6
|
+
export type { UNVeryfiImage } from './veryfiService.utils';
|
|
3
7
|
|
|
4
8
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5
9
|
let VeryfiLens: any = null;
|
|
@@ -14,16 +18,15 @@ export const isVeryfiAvailable = (): boolean => {
|
|
|
14
18
|
return VeryfiLens != null;
|
|
15
19
|
};
|
|
16
20
|
|
|
17
|
-
export interface UNVeryfiImage {
|
|
18
|
-
base64Img: string;
|
|
19
|
-
isFront: boolean;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
21
|
const CHECK_SETTINGS = {
|
|
23
22
|
documentTypes: ['check'],
|
|
24
23
|
checksBackIsOn: true,
|
|
24
|
+
checksBackIsRequired: true,
|
|
25
25
|
blurDetectionIsOn: true,
|
|
26
26
|
autoDocDetectionAndCropIsOn: true,
|
|
27
|
+
// Without this, a no-document capture is kept in the package and the user
|
|
28
|
+
// lands on the submit screen with an image that can only fail.
|
|
29
|
+
allowSubmitUndetectedDocsIsOn: false,
|
|
27
30
|
dataExtractionEngine: true,
|
|
28
31
|
returnStitchedPDF: true,
|
|
29
32
|
originalImageMaxSizeInMB: 1.4,
|
|
@@ -38,6 +41,10 @@ const buildEndorsement = (bankName?: string): string => {
|
|
|
38
41
|
return `Please make sure to sign the back and write “For mobile deposit ${bank ? `at ${bank}` : 'only'}”`;
|
|
39
42
|
};
|
|
40
43
|
|
|
44
|
+
// How long to hold delivery waiting for Veryfi's parsed result before falling
|
|
45
|
+
// back to positional labeling.
|
|
46
|
+
const VERDICT_WAIT_MS = 10000;
|
|
47
|
+
|
|
41
48
|
export const configureAndShowVeryfiCamera = (
|
|
42
49
|
credentials: UNVeryfiCredentials,
|
|
43
50
|
bankName: string | undefined,
|
|
@@ -52,15 +59,48 @@ export const configureAndShowVeryfiCamera = (
|
|
|
52
59
|
const emitter = new NativeEventEmitter(VeryfiLens.NativeModule);
|
|
53
60
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
54
61
|
const subscriptions: any[] = [];
|
|
55
|
-
let
|
|
62
|
+
let capturing = false;
|
|
63
|
+
let dispatched = false;
|
|
64
|
+
let convertedImages: UNVeryfiImage[] | null = null;
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
66
|
+
let verdictPages: any = null;
|
|
67
|
+
let fallbackTimer: ReturnType<typeof setTimeout> | null = null;
|
|
56
68
|
|
|
57
69
|
const cleanup = () => {
|
|
58
70
|
subscriptions.forEach((sub) => sub.remove());
|
|
71
|
+
if (fallbackTimer != null) {
|
|
72
|
+
clearTimeout(fallbackTimer);
|
|
73
|
+
fallbackTimer = null;
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const dispatchToWeb = (images: UNVeryfiImage[]) => {
|
|
78
|
+
if (dispatched) return;
|
|
79
|
+
dispatched = true;
|
|
80
|
+
cleanup();
|
|
81
|
+
onImages(images);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// Delivery is held briefly so Veryfi's parsed result — the authoritative
|
|
85
|
+
// source for which image is the front — can label the pair before the web
|
|
86
|
+
// renders it. The positional fallback covers slow or failed uploads;
|
|
87
|
+
// position is unreliable across Veryfi versions (the order reversed in
|
|
88
|
+
// Android lens 2.4.0.0), which is exactly why the verdict is preferred.
|
|
89
|
+
const dispatchWhenReady = () => {
|
|
90
|
+
if (dispatched || !convertedImages) return;
|
|
91
|
+
if (verdictPages) {
|
|
92
|
+
const labeled = labelSidesFromPages(convertedImages, verdictPages);
|
|
93
|
+
dispatchToWeb(labeled ?? convertedImages);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (fallbackTimer == null) {
|
|
97
|
+
fallbackTimer = setTimeout(() => dispatchToWeb(convertedImages as UNVeryfiImage[]), VERDICT_WAIT_MS);
|
|
98
|
+
}
|
|
59
99
|
};
|
|
60
100
|
|
|
61
|
-
const
|
|
62
|
-
if (
|
|
63
|
-
|
|
101
|
+
const convertImages = (imagePaths: string[]) => {
|
|
102
|
+
if (capturing) return;
|
|
103
|
+
capturing = true;
|
|
64
104
|
|
|
65
105
|
let converted = 0;
|
|
66
106
|
const images: UNVeryfiImage[] = [];
|
|
@@ -72,10 +112,11 @@ export const configureAndShowVeryfiCamera = (
|
|
|
72
112
|
() => {
|
|
73
113
|
converted++;
|
|
74
114
|
if (converted === imagePaths.length) {
|
|
75
|
-
cleanup();
|
|
76
115
|
if (images.length > 0) {
|
|
77
|
-
|
|
116
|
+
convertedImages = images;
|
|
117
|
+
dispatchWhenReady();
|
|
78
118
|
} else {
|
|
119
|
+
cleanup();
|
|
79
120
|
onError('Failed to convert check images');
|
|
80
121
|
}
|
|
81
122
|
}
|
|
@@ -88,8 +129,8 @@ export const configureAndShowVeryfiCamera = (
|
|
|
88
129
|
});
|
|
89
130
|
converted++;
|
|
90
131
|
if (converted === imagePaths.length) {
|
|
91
|
-
|
|
92
|
-
|
|
132
|
+
convertedImages = images;
|
|
133
|
+
dispatchWhenReady();
|
|
93
134
|
}
|
|
94
135
|
}
|
|
95
136
|
);
|
|
@@ -103,14 +144,33 @@ export const configureAndShowVeryfiCamera = (
|
|
|
103
144
|
if (event.status === 'inprogress' && event.msg === 'img_stitched_pdf_path') {
|
|
104
145
|
const paths = event.img_original_paths || [];
|
|
105
146
|
if (paths.length > 0) {
|
|
106
|
-
|
|
147
|
+
convertImages(paths);
|
|
107
148
|
}
|
|
108
149
|
}
|
|
109
150
|
})
|
|
110
151
|
);
|
|
111
152
|
|
|
112
|
-
|
|
113
|
-
|
|
153
|
+
subscriptions.push(
|
|
154
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
155
|
+
emitter.addListener(VeryfiLens.Events.onVeryfiLensSuccess, (event: any) => {
|
|
156
|
+
verdictPages = event?.data?.meta?.pages ?? null;
|
|
157
|
+
dispatchWhenReady();
|
|
158
|
+
})
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
// User cancelled (X button) without submitting: the web side never resets its
|
|
162
|
+
// loading state on its own, so deliver an empty response to move it off the
|
|
163
|
+
// stuck Continue. Grace period covers a close event racing the stitched event.
|
|
164
|
+
subscriptions.push(
|
|
165
|
+
emitter.addListener(VeryfiLens.Events.onVeryfiLensClose, () => {
|
|
166
|
+
setTimeout(() => {
|
|
167
|
+
if (capturing || dispatched) return;
|
|
168
|
+
dispatched = true;
|
|
169
|
+
cleanup();
|
|
170
|
+
onImages([]);
|
|
171
|
+
}, 1500);
|
|
172
|
+
})
|
|
173
|
+
);
|
|
114
174
|
|
|
115
175
|
subscriptions.push(
|
|
116
176
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
export interface UNVeryfiImage {
|
|
2
|
+
base64Img: string;
|
|
3
|
+
isFront: boolean;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const JPEG_SOF_MARKERS = [0xc0, 0xc1, 0xc2, 0xc3, 0xc5, 0xc6, 0xc7, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf];
|
|
7
|
+
|
|
8
|
+
export const readJpegDimensions = (base64: string): { width: number; height: number } | null => {
|
|
9
|
+
try {
|
|
10
|
+
// SOF sits near the file start; a 4-aligned prefix keeps atob happy and cheap.
|
|
11
|
+
const prefix = base64.length > 786432 ? base64.slice(0, 786432) : base64;
|
|
12
|
+
const bytes = atob(prefix);
|
|
13
|
+
if (bytes.charCodeAt(0) !== 0xff || bytes.charCodeAt(1) !== 0xd8) return null;
|
|
14
|
+
let i = 2;
|
|
15
|
+
while (i + 9 < bytes.length) {
|
|
16
|
+
if (bytes.charCodeAt(i) !== 0xff) {
|
|
17
|
+
i++;
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
const marker = bytes.charCodeAt(i + 1);
|
|
21
|
+
if (marker === 0xff) {
|
|
22
|
+
i++;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (marker === 0x01 || (marker >= 0xd0 && marker <= 0xd9)) {
|
|
26
|
+
i += 2;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (JPEG_SOF_MARKERS.includes(marker)) {
|
|
30
|
+
return {
|
|
31
|
+
height: bytes.charCodeAt(i + 5) * 256 + bytes.charCodeAt(i + 6),
|
|
32
|
+
width: bytes.charCodeAt(i + 7) * 256 + bytes.charCodeAt(i + 8),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
i += 2 + bytes.charCodeAt(i + 2) * 256 + bytes.charCodeAt(i + 3);
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Veryfi's parsed result is the authority on which image is the front
|
|
44
|
+
// (their meta.pages[].is_front); page order does not correspond to the
|
|
45
|
+
// delivery array's order, so pages are matched to our images by exact
|
|
46
|
+
// pixel dimensions. Returns null whenever the verdict is not unambiguous.
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
48
|
+
export const labelSidesFromPages = (images: UNVeryfiImage[], pages: any): UNVeryfiImage[] | null => {
|
|
49
|
+
if (!Array.isArray(pages) || pages.length !== 2 || images.length !== 2) return null;
|
|
50
|
+
|
|
51
|
+
const fronts = pages.filter((p) => p && p.is_front === true);
|
|
52
|
+
const backs = pages.filter((p) => p && p.is_front === false);
|
|
53
|
+
const frontPage = fronts[0];
|
|
54
|
+
const backPage = backs[0];
|
|
55
|
+
if (fronts.length !== 1 || backs.length !== 1 || !frontPage || !backPage) return null;
|
|
56
|
+
if (typeof frontPage.width !== 'number' || typeof frontPage.height !== 'number') return null;
|
|
57
|
+
|
|
58
|
+
const dims: { width: number; height: number }[] = [];
|
|
59
|
+
for (const img of images) {
|
|
60
|
+
const d = readJpegDimensions(img.base64Img);
|
|
61
|
+
if (!d) return null;
|
|
62
|
+
dims.push(d);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Veryfi may auto-rotate pages in the parsed result, so dimensions are
|
|
66
|
+
// compared as an unordered pair.
|
|
67
|
+
const sameDims = (d: { width: number; height: number }, w: number, h: number) =>
|
|
68
|
+
(d.width === w && d.height === h) || (d.width === h && d.height === w);
|
|
69
|
+
|
|
70
|
+
const matchesFront = dims.map((d) => sameDims(d, frontPage.width, frontPage.height));
|
|
71
|
+
if (matchesFront.filter(Boolean).length !== 1) return null;
|
|
72
|
+
|
|
73
|
+
const frontIdx = matchesFront.indexOf(true);
|
|
74
|
+
const backIdx = 1 - frontIdx;
|
|
75
|
+
const frontImage = images[frontIdx];
|
|
76
|
+
const backImage = images[backIdx];
|
|
77
|
+
const backDims = dims[backIdx];
|
|
78
|
+
if (!frontImage || !backImage || !backDims) return null;
|
|
79
|
+
if (typeof backPage.width === 'number' && typeof backPage.height === 'number') {
|
|
80
|
+
if (!sameDims(backDims, backPage.width, backPage.height)) return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return [
|
|
84
|
+
{ base64Img: frontImage.base64Img, isFront: true },
|
|
85
|
+
{ base64Img: backImage.base64Img, isFront: false },
|
|
86
|
+
];
|
|
87
|
+
};
|
|
@@ -27,7 +27,7 @@ export class UnitComponentsSDK {
|
|
|
27
27
|
protected static fonts?: UNFonts;
|
|
28
28
|
protected static signedNonce?: string;
|
|
29
29
|
protected static pushProvisionModule?: typeof NativeModules;
|
|
30
|
-
protected static sdkVersion = '3.5.
|
|
30
|
+
protected static sdkVersion = '3.5.2';
|
|
31
31
|
static iosFontBase64Map: Record<string, string> = {};
|
|
32
32
|
|
|
33
33
|
public static init = async (
|