react-native-unit-components 3.5.3 → 3.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/com/unitreactnativecomponents/UnitReactNativeComponentsPackage.kt +2 -0
- package/android/src/main/java/com/unitreactnativecomponents/nativeModules/backHandler/UNBackHandlerModule.kt +93 -0
- package/android/src/main/res/values/strings.xml +1 -1
- package/lib/commonjs/components/UNWhiteLabelAppComponent/UNWhiteLabelAppComponent.js +11 -0
- package/lib/commonjs/components/UNWhiteLabelAppComponent/UNWhiteLabelAppComponent.js.map +1 -1
- package/lib/commonjs/components/UNWhiteLabelAppComponent/UNWhiteLabelAppComponent.utils.js +2 -0
- package/lib/commonjs/components/UNWhiteLabelAppComponent/UNWhiteLabelAppComponent.utils.js.map +1 -1
- package/lib/commonjs/helpers/BottomSheet/BottomSheet.js +29 -2
- package/lib/commonjs/helpers/BottomSheet/BottomSheet.js.map +1 -1
- package/lib/commonjs/messages/webMessages/applicationFormMessage.js +12 -0
- package/lib/commonjs/messages/webMessages/applicationFormMessage.js.map +1 -0
- package/lib/commonjs/nativeModulesHelpers/UNBackHandlerHelper.js +33 -0
- package/lib/commonjs/nativeModulesHelpers/UNBackHandlerHelper.js.map +1 -0
- package/lib/commonjs/scripts/html/bodyScript.js +16 -0
- package/lib/commonjs/scripts/html/bodyScript.js.map +1 -1
- package/lib/commonjs/services/veryfiService.js +20 -43
- package/lib/commonjs/services/veryfiService.js.map +1 -1
- package/lib/commonjs/types/shared/applicationForm.types.js +2 -0
- package/lib/commonjs/types/shared/applicationForm.types.js.map +1 -0
- package/lib/commonjs/types/shared/index.js +11 -0
- package/lib/commonjs/types/shared/index.js.map +1 -1
- package/lib/commonjs/unitComponentsSdkManager/UnitComponentsSdkManager.js +1 -1
- package/lib/module/components/UNWhiteLabelAppComponent/UNWhiteLabelAppComponent.js +11 -0
- package/lib/module/components/UNWhiteLabelAppComponent/UNWhiteLabelAppComponent.js.map +1 -1
- package/lib/module/components/UNWhiteLabelAppComponent/UNWhiteLabelAppComponent.utils.js +2 -0
- package/lib/module/components/UNWhiteLabelAppComponent/UNWhiteLabelAppComponent.utils.js.map +1 -1
- package/lib/module/helpers/BottomSheet/BottomSheet.js +29 -2
- package/lib/module/helpers/BottomSheet/BottomSheet.js.map +1 -1
- package/lib/module/messages/webMessages/applicationFormMessage.js +6 -0
- package/lib/module/messages/webMessages/applicationFormMessage.js.map +1 -0
- package/lib/module/nativeModulesHelpers/UNBackHandlerHelper.js +25 -0
- package/lib/module/nativeModulesHelpers/UNBackHandlerHelper.js.map +1 -0
- package/lib/module/scripts/html/bodyScript.js +16 -0
- package/lib/module/scripts/html/bodyScript.js.map +1 -1
- package/lib/module/services/veryfiService.js +20 -43
- package/lib/module/services/veryfiService.js.map +1 -1
- package/lib/module/types/shared/applicationForm.types.js +2 -0
- package/lib/module/types/shared/applicationForm.types.js.map +1 -0
- package/lib/module/types/shared/index.js +1 -0
- package/lib/module/types/shared/index.js.map +1 -1
- package/lib/module/unitComponentsSdkManager/UnitComponentsSdkManager.js +1 -1
- package/lib/typescript/src/components/UNWhiteLabelAppComponent/UNWhiteLabelAppComponent.d.ts +4 -0
- package/lib/typescript/src/components/UNWhiteLabelAppComponent/UNWhiteLabelAppComponent.d.ts.map +1 -1
- package/lib/typescript/src/components/UNWhiteLabelAppComponent/UNWhiteLabelAppComponent.utils.d.ts.map +1 -1
- package/lib/typescript/src/helpers/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/lib/typescript/src/messages/webMessages/applicationFormMessage.d.ts +10 -0
- package/lib/typescript/src/messages/webMessages/applicationFormMessage.d.ts.map +1 -0
- package/lib/typescript/src/messages/webMessages/index.d.ts +3 -2
- package/lib/typescript/src/messages/webMessages/index.d.ts.map +1 -1
- package/lib/typescript/src/nativeModulesHelpers/UNBackHandlerHelper.d.ts +4 -0
- package/lib/typescript/src/nativeModulesHelpers/UNBackHandlerHelper.d.ts.map +1 -0
- package/lib/typescript/src/scripts/html/bodyScript.d.ts +2 -0
- package/lib/typescript/src/scripts/html/bodyScript.d.ts.map +1 -1
- package/lib/typescript/src/services/veryfiService.d.ts +4 -2
- package/lib/typescript/src/services/veryfiService.d.ts.map +1 -1
- package/lib/typescript/src/types/shared/applicationForm.types.d.ts +10 -0
- package/lib/typescript/src/types/shared/applicationForm.types.d.ts.map +1 -0
- package/lib/typescript/src/types/shared/index.d.ts +1 -0
- package/lib/typescript/src/types/shared/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/components/UNWhiteLabelAppComponent/UNWhiteLabelAppComponent.tsx +16 -0
- package/src/components/UNWhiteLabelAppComponent/UNWhiteLabelAppComponent.utils.ts +2 -0
- package/src/helpers/BottomSheet/BottomSheet.tsx +29 -2
- package/src/messages/webMessages/applicationFormMessage.ts +12 -0
- package/src/messages/webMessages/index.ts +3 -0
- package/src/nativeModulesHelpers/UNBackHandlerHelper.ts +34 -0
- package/src/scripts/html/bodyScript.ts +16 -0
- package/src/services/veryfiService.ts +25 -47
- package/src/types/shared/applicationForm.types.ts +18 -0
- package/src/types/shared/index.ts +1 -0
- package/src/unitComponentsSdkManager/UnitComponentsSdkManager.ts +1 -1
- package/lib/commonjs/services/veryfiService.utils.js +0 -87
- package/lib/commonjs/services/veryfiService.utils.js.map +0 -1
- package/lib/module/services/veryfiService.utils.js +0 -79
- package/lib/module/services/veryfiService.utils.js.map +0 -1
- package/lib/typescript/src/services/veryfiService.utils.d.ts +0 -10
- package/lib/typescript/src/services/veryfiService.utils.d.ts.map +0 -1
- package/src/services/veryfiService.utils.ts +0 -87
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
|
|
2
|
+
|
|
3
|
+
const UNBackHandlerModule = Platform.OS === 'android'
|
|
4
|
+
? NativeModules.UNBackHandlerModule
|
|
5
|
+
: undefined;
|
|
6
|
+
|
|
7
|
+
const backEventEmitter = UNBackHandlerModule
|
|
8
|
+
? new NativeEventEmitter(UNBackHandlerModule)
|
|
9
|
+
: undefined;
|
|
10
|
+
|
|
11
|
+
const BACK_INVOKED_EVENT = 'UNBackInvoked';
|
|
12
|
+
|
|
13
|
+
export async function registerBackCallback(): Promise<boolean> {
|
|
14
|
+
if (!UNBackHandlerModule) return false;
|
|
15
|
+
try {
|
|
16
|
+
return await UNBackHandlerModule.registerBackCallback();
|
|
17
|
+
} catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function unregisterBackCallback(): Promise<boolean> {
|
|
23
|
+
if (!UNBackHandlerModule) return false;
|
|
24
|
+
try {
|
|
25
|
+
return await UNBackHandlerModule.unregisterBackCallback();
|
|
26
|
+
} catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function addBackInvokedListener(handler: () => void): () => void {
|
|
32
|
+
const subscription = backEventEmitter?.addListener(BACK_INVOKED_EVENT, handler);
|
|
33
|
+
return () => subscription?.remove();
|
|
34
|
+
}
|
|
@@ -3,6 +3,7 @@ import { CardMessage } from '../../messages/webMessages/cardMessage';
|
|
|
3
3
|
import { PageMessage } from '../../messages/webMessages/pageMessage';
|
|
4
4
|
import { UnitComponentsMessage } from '../../messages/webMessages/unitComponentsMessages';
|
|
5
5
|
import { AccountMessage } from '../../messages/webMessages/accountMessage';
|
|
6
|
+
import { ApplicationFormMessage } from '../../messages/webMessages/applicationFormMessage';
|
|
6
7
|
import { ActivityMessage } from '../../messages/webMessages/activityMessage';
|
|
7
8
|
import { PlaidMessage } from '../../messages/webMessages/plaidMessages';
|
|
8
9
|
import { PayeeManagementMessage } from '../../messages/webMessages/payeeManagementMessage';
|
|
@@ -249,6 +250,21 @@ export const LISTENERS = {
|
|
|
249
250
|
})
|
|
250
251
|
});
|
|
251
252
|
`,
|
|
253
|
+
unitApplicationFormCompleted: `
|
|
254
|
+
window.addEventListener("${ApplicationFormMessage.UNIT_APPLICATION_FORM_COMPLETED}", (e) => {
|
|
255
|
+
const response = e.detail;
|
|
256
|
+
response.then((data) => {
|
|
257
|
+
postMessageToSDK({ type: "${ApplicationFormMessage.UNIT_APPLICATION_FORM_COMPLETED}", details: { applicationForm: data.data } })
|
|
258
|
+
}).catch((e) => {
|
|
259
|
+
console.log(e)
|
|
260
|
+
})
|
|
261
|
+
});
|
|
262
|
+
`,
|
|
263
|
+
unitApplicationFormApproved: `
|
|
264
|
+
window.addEventListener("${ApplicationFormMessage.UNIT_APPLICATION_FORM_APPROVED}", (e) => {
|
|
265
|
+
postMessageToSDK({ type: "${ApplicationFormMessage.UNIT_APPLICATION_FORM_APPROVED}" })
|
|
266
|
+
});
|
|
267
|
+
`,
|
|
252
268
|
unitUnauthorizedToken: `
|
|
253
269
|
window.addEventListener("${UnitComponentsMessage.UNIT_UNAUTHORIZED_TOKEN}", (e) => {
|
|
254
270
|
postMessageToSDK({ type: "${UnitComponentsMessage.UNIT_UNAUTHORIZED_TOKEN}", details: "Clean the current user tokens" })
|
|
@@ -1,9 +1,10 @@
|
|
|
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
3
|
|
|
6
|
-
export
|
|
4
|
+
export interface UNVeryfiImage {
|
|
5
|
+
base64Img: string;
|
|
6
|
+
isFront: boolean;
|
|
7
|
+
}
|
|
7
8
|
|
|
8
9
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9
10
|
let VeryfiLens: any = null;
|
|
@@ -38,12 +39,24 @@ const BACK_CAPTURE_MODAL_KEY = 'Capture the back side of the check?';
|
|
|
38
39
|
const buildEndorsement = (bankName?: string): string => {
|
|
39
40
|
const bank = bankName?.trim();
|
|
40
41
|
// Bank-agnostic fallback when the bank name is absent, so the copy never reads "...deposit at ".
|
|
41
|
-
return `Please
|
|
42
|
+
return `Please complete both steps on the back of the check: sign it and write “For Mobile Deposit ${bank ? `at ${bank}` : 'only'}.”`;
|
|
42
43
|
};
|
|
43
44
|
|
|
44
|
-
//
|
|
45
|
-
//
|
|
46
|
-
|
|
45
|
+
// Veryfi reports each capture's side in the update event's `images`, whose
|
|
46
|
+
// order does not track `img_original_paths` — sides are matched by file path.
|
|
47
|
+
// Returns null unless every path resolves, so a partial match falls back to
|
|
48
|
+
// positional labeling rather than producing two fronts.
|
|
49
|
+
const labelsFromEventImages = (imagePaths: string[], eventImages: unknown): boolean[] | null => {
|
|
50
|
+
if (!Array.isArray(eventImages)) return null;
|
|
51
|
+
|
|
52
|
+
const labels: boolean[] = [];
|
|
53
|
+
for (const filePath of imagePaths) {
|
|
54
|
+
const match = eventImages.find((image) => image?.path === filePath);
|
|
55
|
+
if (typeof match?.is_front !== 'boolean') return null;
|
|
56
|
+
labels.push(match.is_front);
|
|
57
|
+
}
|
|
58
|
+
return labels;
|
|
59
|
+
};
|
|
47
60
|
|
|
48
61
|
export const configureAndShowVeryfiCamera = (
|
|
49
62
|
credentials: UNVeryfiCredentials,
|
|
@@ -61,17 +74,9 @@ export const configureAndShowVeryfiCamera = (
|
|
|
61
74
|
const subscriptions: any[] = [];
|
|
62
75
|
let capturing = false;
|
|
63
76
|
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;
|
|
68
77
|
|
|
69
78
|
const cleanup = () => {
|
|
70
79
|
subscriptions.forEach((sub) => sub.remove());
|
|
71
|
-
if (fallbackTimer != null) {
|
|
72
|
-
clearTimeout(fallbackTimer);
|
|
73
|
-
fallbackTimer = null;
|
|
74
|
-
}
|
|
75
80
|
};
|
|
76
81
|
|
|
77
82
|
const dispatchToWeb = (images: UNVeryfiImage[]) => {
|
|
@@ -81,24 +86,7 @@ export const configureAndShowVeryfiCamera = (
|
|
|
81
86
|
onImages(images);
|
|
82
87
|
};
|
|
83
88
|
|
|
84
|
-
|
|
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
|
-
}
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
const convertImages = (imagePaths: string[]) => {
|
|
89
|
+
const convertImages = (imagePaths: string[], labels: boolean[] | null) => {
|
|
102
90
|
if (capturing) return;
|
|
103
91
|
capturing = true;
|
|
104
92
|
|
|
@@ -113,8 +101,7 @@ export const configureAndShowVeryfiCamera = (
|
|
|
113
101
|
converted++;
|
|
114
102
|
if (converted === imagePaths.length) {
|
|
115
103
|
if (images.length > 0) {
|
|
116
|
-
|
|
117
|
-
dispatchWhenReady();
|
|
104
|
+
dispatchToWeb(images);
|
|
118
105
|
} else {
|
|
119
106
|
cleanup();
|
|
120
107
|
onError('Failed to convert check images');
|
|
@@ -125,12 +112,11 @@ export const configureAndShowVeryfiCamera = (
|
|
|
125
112
|
(base64Data: string) => {
|
|
126
113
|
images.push({
|
|
127
114
|
base64Img: base64Data,
|
|
128
|
-
isFront: index === 1,
|
|
115
|
+
isFront: labels ? labels[index] === true : index === 1,
|
|
129
116
|
});
|
|
130
117
|
converted++;
|
|
131
118
|
if (converted === imagePaths.length) {
|
|
132
|
-
|
|
133
|
-
dispatchWhenReady();
|
|
119
|
+
dispatchToWeb(images);
|
|
134
120
|
}
|
|
135
121
|
}
|
|
136
122
|
);
|
|
@@ -144,20 +130,12 @@ export const configureAndShowVeryfiCamera = (
|
|
|
144
130
|
if (event.status === 'inprogress' && event.msg === 'img_stitched_pdf_path') {
|
|
145
131
|
const paths = event.img_original_paths || [];
|
|
146
132
|
if (paths.length > 0) {
|
|
147
|
-
convertImages(paths);
|
|
133
|
+
convertImages(paths, labelsFromEventImages(paths, event.images));
|
|
148
134
|
}
|
|
149
135
|
}
|
|
150
136
|
})
|
|
151
137
|
);
|
|
152
138
|
|
|
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
139
|
// User cancelled (X button) without submitting: the web side never resets its
|
|
162
140
|
// loading state on its own, so deliver an empty response to move it off the
|
|
163
141
|
// stuck Continue. Grace period covers a close event racing the stitched event.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type UNApplicationFormStatus =
|
|
2
|
+
| 'AwaitingDocuments'
|
|
3
|
+
| 'AwaitingIdentityVerification'
|
|
4
|
+
| 'PendingReview'
|
|
5
|
+
| 'Approved'
|
|
6
|
+
| 'Denied'
|
|
7
|
+
| 'Pending'
|
|
8
|
+
| 'New'
|
|
9
|
+
| 'Canceled';
|
|
10
|
+
|
|
11
|
+
export interface UNApplicationForm {
|
|
12
|
+
type: string;
|
|
13
|
+
id: string;
|
|
14
|
+
attributes: {
|
|
15
|
+
applicationStatus?: UNApplicationFormStatus;
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -5,6 +5,7 @@ export * from './card.types';
|
|
|
5
5
|
export * from './onLoadResponse.types';
|
|
6
6
|
export * from './ach.types';
|
|
7
7
|
export * from './account.types';
|
|
8
|
+
export * from './applicationForm.types';
|
|
8
9
|
export * from './checkDeposit.types';
|
|
9
10
|
export * from './counterparty.types';
|
|
10
11
|
export * from './activity.types';
|
|
@@ -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.5';
|
|
31
31
|
static iosFontBase64Map: Record<string, string> = {};
|
|
32
32
|
|
|
33
33
|
public static init = async (
|
|
@@ -1,87 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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":[]}
|
|
@@ -1,79 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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":[]}
|
|
@@ -1,10 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1,87 +0,0 @@
|
|
|
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
|
-
};
|