@ekyc_qoobiss/qbs-ect-cmp 3.6.27 → 3.6.28
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/dist/cjs/agreement-check_19.cjs.entry.js +9498 -0
- package/dist/cjs/base-component-aa9e52bf.js +832 -0
- package/dist/cjs/index-41696e0e.js +1573 -0
- package/dist/cjs/index.cjs.js +2 -0
- package/dist/cjs/loader-dots.cjs.entry.js +19 -0
- package/dist/cjs/loader.cjs.js +22 -0
- package/dist/cjs/qbs-ect-cmp.cjs.js +23 -0
- package/dist/cjs/random-actions.cjs.entry.js +23 -0
- package/dist/collection/assets/canvas-masks/face_green.svg +8 -0
- package/dist/collection/assets/canvas-masks/face_white.svg +8 -0
- package/dist/collection/assets/canvas-masks/id_green.svg +6 -0
- package/dist/collection/assets/canvas-masks/id_white.svg +6 -0
- package/dist/collection/assets/complete.svg +4 -0
- package/dist/collection/assets/landing/device.svg +14 -0
- package/dist/collection/assets/landing/id.svg +3 -0
- package/dist/collection/assets/landing/info.svg +3 -0
- package/dist/collection/assets/landing/validation.svg +16 -0
- package/dist/collection/assets/loader.svg +29 -0
- package/dist/collection/collection-manifest.json +32 -0
- package/dist/collection/components/base-component.js +63 -0
- package/dist/collection/components/common/agreement-check/agreement-check.css +0 -0
- package/dist/collection/components/common/agreement-check/agreement-check.js +104 -0
- package/dist/collection/components/common/camera-error/camera-error.css +0 -0
- package/dist/{qbs-ect-cmp/camera-error.entry.js → collection/components/common/camera-error/camera-error.js} +52 -20
- package/dist/collection/components/common/capture-error/capture-error.css +0 -0
- package/dist/{qbs-ect-cmp/capture-error.entry.js → collection/components/common/capture-error/capture-error.js} +63 -16
- package/dist/collection/components/common/how-to-info/how-to-info.css +0 -0
- package/dist/collection/components/common/how-to-info/how-to-info.js +121 -0
- package/dist/collection/components/common/id-back-capture/id-back-capture.css +35 -0
- package/dist/{qbs-ect-cmp/id-back-capture.entry.js → collection/components/common/id-back-capture/id-back-capture.js} +94 -24
- package/dist/collection/components/common/id-capture/id-capture.css +35 -0
- package/dist/{qbs-ect-cmp/id-capture.entry.js → collection/components/common/id-capture/id-capture.js} +94 -24
- package/dist/collection/components/common/id-tilt/id-tilt.css +35 -0
- package/dist/{qbs-ect-cmp/id-tilt.entry.js → collection/components/common/id-tilt/id-tilt.js} +94 -24
- package/dist/collection/components/common/random-actions/random-actions.css +0 -0
- package/dist/collection/components/common/random-actions/random-actions.js +24 -0
- package/dist/collection/components/common/selfie-capture/selfie-capture.css +7 -0
- package/dist/{qbs-ect-cmp/selfie-capture.entry.js → collection/components/common/selfie-capture/selfie-capture.js} +95 -24
- package/dist/collection/components/common/selfie-tilt/selfie-tilt.css +7 -0
- package/dist/{qbs-ect-cmp/selfie-tilt.entry.js → collection/components/common/selfie-tilt/selfie-tilt.js} +95 -24
- package/dist/collection/components/controls/camera/camera.css +47 -0
- package/dist/collection/components/controls/camera/camera.js +289 -0
- package/dist/collection/components/controls/loader-dots/loader-dots.css +61 -0
- package/dist/collection/components/controls/loader-dots/loader-dots.js +18 -0
- package/dist/collection/components/flow/agreement-info/agreement-info.css +0 -0
- package/dist/{qbs-ect-cmp/agreement-info.entry.js → collection/components/flow/agreement-info/agreement-info.js} +57 -18
- package/dist/collection/components/flow/end-redirect/end-redirect.css +128 -0
- package/dist/collection/components/flow/end-redirect/end-redirect.js +47 -0
- package/dist/collection/components/flow/error-end/error-end.css +0 -0
- package/dist/collection/components/flow/error-end/error-end.js +61 -0
- package/dist/collection/components/flow/landing-validation/landing-validation.css +0 -0
- package/dist/collection/components/flow/landing-validation/landing-validation.js +122 -0
- package/dist/collection/components/flow/mobile-redirect/mobile-redirect.css +10 -0
- package/dist/collection/components/flow/mobile-redirect/mobile-redirect.js +143 -0
- package/dist/collection/components/flow/process-id/process-id.css +0 -0
- package/dist/{qbs-ect-cmp/process-id.entry.js → collection/components/flow/process-id/process-id.js} +100 -32
- package/dist/collection/components/flow/sms-code-validation/sms-code-validation.css +0 -0
- package/dist/{qbs-ect-cmp/sms-code-validation.entry.js → collection/components/flow/sms-code-validation/sms-code-validation.js} +63 -30
- package/dist/collection/components/flow/user-liveness/user-liveness.css +0 -0
- package/dist/{qbs-ect-cmp/user-liveness.entry.js → collection/components/flow/user-liveness/user-liveness.js} +91 -25
- package/dist/collection/components/identification-component/identification-component.css +991 -0
- package/dist/collection/components/identification-component/identification-component.js +408 -0
- package/dist/collection/global.js +0 -0
- package/dist/collection/helpers/ApiCall.js +223 -0
- package/dist/{qbs-ect-cmp/Cameras-dfbebc29.js → collection/helpers/Cameras.js} +6 -9
- package/dist/collection/helpers/DeviceDetection.js +85 -0
- package/dist/collection/helpers/Events.js +58 -0
- package/dist/collection/helpers/ML5.js +38 -0
- package/dist/collection/helpers/Stream.js +229 -0
- package/dist/collection/helpers/TranslationUtils.js +37 -0
- package/dist/collection/helpers/canvas.js +10 -0
- package/dist/collection/helpers/index.js +21 -0
- package/dist/collection/helpers/security.js +25 -0
- package/dist/collection/helpers/store.js +48 -0
- package/dist/collection/helpers/textValues.js +48 -0
- package/dist/collection/index.js +1 -0
- package/dist/collection/libs/FaceML5Detector/FaceML5Detector.js +182 -0
- package/dist/collection/libs/FaceML5Detector/FacePose.js +85 -0
- package/dist/collection/libs/IDML5Detector/IDML5Detector.js +99 -0
- package/dist/{qbs-ect-cmp/IDPose-181bcb25.js → collection/libs/IDML5Detector/IDPose.js} +2 -4
- package/dist/{qbs-ect-cmp/CaptureFlow-db5d90a4.js → collection/models/CaptureFlow.js} +4 -6
- package/dist/collection/models/FlowStatus.js +14 -0
- package/dist/collection/models/FlowSteps.js +30 -0
- package/dist/collection/models/IAbortResult.js +1 -0
- package/dist/collection/models/IAddRequest.js +1 -0
- package/dist/collection/models/IAgreement.js +1 -0
- package/dist/collection/models/ICamera.js +1 -0
- package/dist/{qbs-ect-cmp/IDevice-15ecfdeb.js → collection/models/IDevice.js} +4 -6
- package/dist/collection/models/IEctStore.js +1 -0
- package/dist/collection/models/IGeneration.js +1 -0
- package/dist/collection/models/ILinkSend.js +1 -0
- package/dist/collection/models/ILogResult.js +1 -0
- package/dist/collection/models/IOrderStatus.js +1 -0
- package/dist/collection/models/IOtpCheck.js +1 -0
- package/dist/collection/models/IOtpSend.js +1 -0
- package/dist/collection/models/ITranslationValues.js +1 -0
- package/dist/collection/models/IUploadFile.js +1 -0
- package/dist/collection/models/IVerificationMode.js +5 -0
- package/dist/collection/models/OrderStatuses.js +8 -0
- package/dist/{qbs-ect-cmp/utils-8225f0b7.js → collection/utils/utils.js} +8 -10
- package/dist/esm/agreement-check_19.entry.js +9476 -0
- package/dist/{qbs-ect-cmp/base-component-2e490fd9.js → esm/base-component-b7f50d31.js} +384 -62
- package/dist/esm/index-cf54a432.js +1543 -0
- package/dist/esm/index.js +1 -0
- package/dist/{qbs-ect-cmp → esm}/loader-dots.entry.js +1 -1
- package/dist/esm/loader.js +18 -0
- package/dist/esm/polyfills/core-js.js +11 -0
- package/dist/esm/polyfills/css-shim.js +1 -0
- package/dist/esm/polyfills/dom.js +79 -0
- package/dist/esm/polyfills/es5-html-element.js +1 -0
- package/dist/esm/polyfills/index.js +34 -0
- package/dist/esm/polyfills/system.js +6 -0
- package/dist/esm/qbs-ect-cmp.js +18 -0
- package/dist/{qbs-ect-cmp → esm}/random-actions.entry.js +2 -4
- package/dist/index.cjs.js +1 -0
- package/dist/index.js +1 -0
- package/dist/loader/cdn.js +3 -0
- package/dist/loader/index.cjs.js +3 -0
- package/dist/loader/index.d.ts +21 -0
- package/dist/loader/index.es2017.js +3 -0
- package/dist/loader/index.js +4 -0
- package/dist/loader/package.json +11 -0
- package/dist/qbs-ect-cmp/index.esm.js +0 -1
- package/dist/qbs-ect-cmp/p-054dc5b3.entry.js +1 -0
- package/dist/qbs-ect-cmp/p-215a7e76.entry.js +1 -0
- package/dist/qbs-ect-cmp/p-7bedffaa.js +1 -0
- package/dist/qbs-ect-cmp/p-8942656c.js +2 -0
- package/dist/qbs-ect-cmp/p-c32a782a.entry.js +1373 -0
- package/dist/qbs-ect-cmp/qbs-ect-cmp.css +1 -320
- package/dist/qbs-ect-cmp/qbs-ect-cmp.esm.js +1 -148
- package/package.json +1 -1
- package/dist/qbs-ect-cmp/ML5-657ef934.js +0 -1370
- package/dist/qbs-ect-cmp/Stream-b867a2be.js +0 -3104
- package/dist/qbs-ect-cmp/_commonjsHelpers-321aa363.js +0 -44
- package/dist/qbs-ect-cmp/agreement-check.entry.js +0 -41
- package/dist/qbs-ect-cmp/app-globals-0f993ce5.js +0 -3
- package/dist/qbs-ect-cmp/camera-comp.entry.js +0 -103
- package/dist/qbs-ect-cmp/css-shim-b7d3d95f.js +0 -4
- package/dist/qbs-ect-cmp/dom-64053c71.js +0 -73
- package/dist/qbs-ect-cmp/end-redirect.entry.js +0 -25
- package/dist/qbs-ect-cmp/error-end.entry.js +0 -19
- package/dist/qbs-ect-cmp/how-to-info.entry.js +0 -52
- package/dist/qbs-ect-cmp/identification-component.entry.js +0 -909
- package/dist/qbs-ect-cmp/index-78a05b9e.js +0 -3371
- package/dist/qbs-ect-cmp/landing-validation.entry.js +0 -90
- package/dist/qbs-ect-cmp/mobile-redirect.entry.js +0 -2984
- package/dist/qbs-ect-cmp/shadow-css-98135883.js +0 -387
- package/dist/qbs-ect-cmp/textValues-6bcc85dd.js +0 -302
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Browser, DesktopOS, MobileOS } from '../models/IDevice';
|
|
2
|
+
export class DeviceDetection {
|
|
3
|
+
constructor() {
|
|
4
|
+
var _a, _b, _c, _d;
|
|
5
|
+
this.supportedScreenOrientation = (_b = (_a = ((screen === null || screen === void 0 ? void 0 : screen.orientation) || {}).type) !== null && _a !== void 0 ? _a : screen.mozOrientation) !== null && _b !== void 0 ? _b : screen.msOrientation;
|
|
6
|
+
this.safariScreenOrientation = !(screen === null || screen === void 0 ? void 0 : screen.orientation) && matchMedia('(orientation: portrait)').matches ? 'portrait-primary' : 'landscape-primary';
|
|
7
|
+
this.initialScreenOrientation = (_d = (_c = this.supportedScreenOrientation) !== null && _c !== void 0 ? _c : this.safariScreenOrientation) !== null && _d !== void 0 ? _d : 'portrait-primary';
|
|
8
|
+
this.userAgent = navigator.userAgent || navigator.vendor || window.opera || undefined;
|
|
9
|
+
this.isMobile = this.isMobileDevice();
|
|
10
|
+
this.isTablet = this.isTabletDevice();
|
|
11
|
+
this.isDesktop = !this.isMobile && !this.isTablet;
|
|
12
|
+
}
|
|
13
|
+
// Device typology
|
|
14
|
+
isMobileDevice() {
|
|
15
|
+
const regexs = [/(Android)(.+)(Mobile)/i, /BlackBerry/i, /iPhone|iPod/i, /Opera Mini/i, /IEMobile/i];
|
|
16
|
+
return regexs.some(b => this.userAgent.match(b));
|
|
17
|
+
}
|
|
18
|
+
isTabletDevice() {
|
|
19
|
+
const regex = /(ipad|tablet|(android(?!.*mobile))|(windows(?!.*phone)(.*touch))|kindle|playbook|silk|(puffin(?!.*(IP|AP|WP))))/;
|
|
20
|
+
return regex.test(this.userAgent.toLowerCase());
|
|
21
|
+
}
|
|
22
|
+
// Device Operating System
|
|
23
|
+
getMobileOS() {
|
|
24
|
+
if (this.isMobileDevice()) {
|
|
25
|
+
if (/windows phone/i.test(this.userAgent))
|
|
26
|
+
return MobileOS.WindowsPhone;
|
|
27
|
+
else if (/android/i.test(this.userAgent))
|
|
28
|
+
return MobileOS.Android;
|
|
29
|
+
else if (/iPad|iPhone|iPod/.test(this.userAgent) && !window.MSStream)
|
|
30
|
+
return MobileOS.iOS;
|
|
31
|
+
return MobileOS.Unknown;
|
|
32
|
+
}
|
|
33
|
+
else
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
getDesktopOS() {
|
|
37
|
+
if (this.isDesktop) {
|
|
38
|
+
if (this.userAgent.indexOf('Win') !== -1)
|
|
39
|
+
return DesktopOS.Windows;
|
|
40
|
+
else if (this.userAgent.indexOf('Mac') !== -1)
|
|
41
|
+
return DesktopOS.MacOS;
|
|
42
|
+
else if (this.userAgent.indexOf('X11') !== -1)
|
|
43
|
+
return DesktopOS.Unix;
|
|
44
|
+
else if (this.userAgent.indexOf('Linux') !== -1)
|
|
45
|
+
return DesktopOS.Linux;
|
|
46
|
+
return DesktopOS.Unknown;
|
|
47
|
+
}
|
|
48
|
+
else
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
getDeviceOS() {
|
|
52
|
+
var _a;
|
|
53
|
+
return (_a = this.getMobileOS()) !== null && _a !== void 0 ? _a : this.getDesktopOS();
|
|
54
|
+
}
|
|
55
|
+
getBrowser() {
|
|
56
|
+
if (/XiaoMi/i.test(this.userAgent) || /MiuiBrowser/i.test(this.userAgent))
|
|
57
|
+
return Browser.Mi;
|
|
58
|
+
var isChrome = /chrome/i.test(this.userAgent);
|
|
59
|
+
if (isChrome)
|
|
60
|
+
return Browser.Chrome;
|
|
61
|
+
if (/firefox/i.test(navigator.userAgent))
|
|
62
|
+
return Browser.Firefox;
|
|
63
|
+
else if (!isChrome && /safari/i.test(navigator.userAgent))
|
|
64
|
+
return Browser.Safari;
|
|
65
|
+
else
|
|
66
|
+
return Browser.Unknown;
|
|
67
|
+
}
|
|
68
|
+
getDevice() {
|
|
69
|
+
var device = {
|
|
70
|
+
isDesktop: this.isDesktop,
|
|
71
|
+
desktopOS: this.getDesktopOS(),
|
|
72
|
+
isWindowsDesktop: this.getDeviceOS() === DesktopOS.Windows,
|
|
73
|
+
isLinuxOrUnixDesktop: this.getDeviceOS() === DesktopOS.Linux || this.getDeviceOS() === DesktopOS.Unix,
|
|
74
|
+
isMobile: this.isMobile,
|
|
75
|
+
mobileOS: this.getMobileOS(),
|
|
76
|
+
isAndroidDevice: this.getDeviceOS() === MobileOS.Android,
|
|
77
|
+
isAppleDevice: this.getDeviceOS() === MobileOS.iOS || this.getDeviceOS() === DesktopOS.MacOS,
|
|
78
|
+
isUnknownMobileDevice: this.getDeviceOS() === MobileOS.Unknown,
|
|
79
|
+
browser: this.getBrowser(),
|
|
80
|
+
isTablet: this.isTablet,
|
|
81
|
+
initialScreenOrientation: this.initialScreenOrientation,
|
|
82
|
+
};
|
|
83
|
+
return device;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export default class Events {
|
|
2
|
+
static init(element) {
|
|
3
|
+
this.callingModule = element;
|
|
4
|
+
}
|
|
5
|
+
static flowEvent(step, moment) {
|
|
6
|
+
const eventName = `ect-${step.toString()}-${moment.toString()}-event`;
|
|
7
|
+
this.callingModule.dispatchEvent(new CustomEvent(eventName, {
|
|
8
|
+
detail: {},
|
|
9
|
+
bubbles: true,
|
|
10
|
+
cancelable: true,
|
|
11
|
+
composed: true,
|
|
12
|
+
}));
|
|
13
|
+
}
|
|
14
|
+
static flowStarted() {
|
|
15
|
+
this.callingModule.dispatchEvent(new CustomEvent('ect-started', {
|
|
16
|
+
detail: {},
|
|
17
|
+
bubbles: true,
|
|
18
|
+
cancelable: true,
|
|
19
|
+
composed: true,
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
22
|
+
static flowAborted() {
|
|
23
|
+
sessionStorage.clear();
|
|
24
|
+
this.callingModule.dispatchEvent(new CustomEvent('ect-aborted', {
|
|
25
|
+
detail: {},
|
|
26
|
+
bubbles: true,
|
|
27
|
+
cancelable: true,
|
|
28
|
+
composed: true,
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
31
|
+
static flowCompleted() {
|
|
32
|
+
sessionStorage.clear();
|
|
33
|
+
this.callingModule.dispatchEvent(new CustomEvent('ect-completed', {
|
|
34
|
+
detail: {},
|
|
35
|
+
bubbles: true,
|
|
36
|
+
cancelable: true,
|
|
37
|
+
composed: true,
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
static flowError(error) {
|
|
41
|
+
sessionStorage.clear();
|
|
42
|
+
this.callingModule.dispatchEvent(new CustomEvent('ect-error', {
|
|
43
|
+
detail: { error },
|
|
44
|
+
bubbles: true,
|
|
45
|
+
cancelable: true,
|
|
46
|
+
composed: true,
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
static tokenExpired() {
|
|
50
|
+
sessionStorage.clear();
|
|
51
|
+
this.callingModule.dispatchEvent(new CustomEvent('ect-session-expired', {
|
|
52
|
+
detail: {},
|
|
53
|
+
bubbles: true,
|
|
54
|
+
cancelable: true,
|
|
55
|
+
composed: true,
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import ml5 from 'ml5';
|
|
2
|
+
import store from './store';
|
|
3
|
+
// @ts-ignore
|
|
4
|
+
import preload from '../assets/ml5-preload.png';
|
|
5
|
+
export class ML5 {
|
|
6
|
+
static getInstance() {
|
|
7
|
+
if (!ML5.instance) {
|
|
8
|
+
ML5.instance = new ML5();
|
|
9
|
+
}
|
|
10
|
+
return ML5.instance;
|
|
11
|
+
}
|
|
12
|
+
constructor() {
|
|
13
|
+
this.init();
|
|
14
|
+
}
|
|
15
|
+
async init() {
|
|
16
|
+
return new Promise(async (resolve) => {
|
|
17
|
+
const modelPath = store.hasIdBack ? 'https://ekyc.blob.core.windows.net/$web/md/model.json' : 'https://ekyc.blob.core.windows.net/$web/model.json';
|
|
18
|
+
this.classifier = await ml5.imageClassifier(modelPath, this.loaded);
|
|
19
|
+
this.faceapi = await ml5.faceApi({ withLandmarks: true, withDescriptors: false }, this.loaded);
|
|
20
|
+
//warmup
|
|
21
|
+
const img = new Image();
|
|
22
|
+
img.src = preload;
|
|
23
|
+
this.classifier.classify(img, this.gotResults);
|
|
24
|
+
this.faceapi.detect(img, this.gotResults);
|
|
25
|
+
resolve();
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
loaded() {
|
|
29
|
+
if (store.debug)
|
|
30
|
+
console.log('ML5 LOADED!!!');
|
|
31
|
+
}
|
|
32
|
+
gotResults(error, results) {
|
|
33
|
+
if (store.debug)
|
|
34
|
+
console.log(error);
|
|
35
|
+
if (store.debug)
|
|
36
|
+
console.log(results);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { IDML5Detector } from '../libs/IDML5Detector/IDML5Detector';
|
|
2
|
+
import { FaceML5Detector } from '../libs/FaceML5Detector/FaceML5Detector';
|
|
3
|
+
import { FacePose } from '../libs/FaceML5Detector/FacePose';
|
|
4
|
+
import { FacePosePick } from '../libs/FaceML5Detector/FacePose';
|
|
5
|
+
import { addExifInImg } from './security';
|
|
6
|
+
import store from './store';
|
|
7
|
+
import { Browser, MobileOS } from '../models/IDevice';
|
|
8
|
+
var ImageFormat;
|
|
9
|
+
(function (ImageFormat) {
|
|
10
|
+
ImageFormat["JPEG"] = "image/jpeg";
|
|
11
|
+
ImageFormat["PNG"] = "image/png";
|
|
12
|
+
})(ImageFormat || (ImageFormat = {}));
|
|
13
|
+
export class Stream {
|
|
14
|
+
setFaceDetection(val) {
|
|
15
|
+
this.faceDetection = val;
|
|
16
|
+
this.idDetection = !val;
|
|
17
|
+
}
|
|
18
|
+
setIdDetection(val) {
|
|
19
|
+
this.idDetection = val;
|
|
20
|
+
this.faceDetection = !val;
|
|
21
|
+
}
|
|
22
|
+
// public setProbabilityThreshold(val: number): void {
|
|
23
|
+
// Detector.getInstance().setProbabilityThreshold(val);
|
|
24
|
+
// }
|
|
25
|
+
setCallbackChangeTitle(fun) {
|
|
26
|
+
this.callbackChangeTitle = fun;
|
|
27
|
+
}
|
|
28
|
+
setCallbackVideoStarted(fun) {
|
|
29
|
+
this.callbackVideoStarted = fun;
|
|
30
|
+
}
|
|
31
|
+
setCallbackErrors(fun) {
|
|
32
|
+
this.callbackErrors = fun;
|
|
33
|
+
}
|
|
34
|
+
setCallbackAutoCapturing(fun) {
|
|
35
|
+
this.callbackAutoCapturing = fun;
|
|
36
|
+
}
|
|
37
|
+
// public setCallbackFaceDetectionErrors(fun: (e: PipelineResult) => void): void {
|
|
38
|
+
// this.callbackFaceDetectionErrors = fun;
|
|
39
|
+
// }
|
|
40
|
+
setCallbackRecordingReady(fun) {
|
|
41
|
+
this.callbackRecordingReady = fun;
|
|
42
|
+
}
|
|
43
|
+
setCallbackTimeElapsed(fun) {
|
|
44
|
+
this.callbackTimeElapsed = fun;
|
|
45
|
+
}
|
|
46
|
+
setVerificationFinished(fun) {
|
|
47
|
+
this.verificationFinished = fun;
|
|
48
|
+
}
|
|
49
|
+
constructor(mode) {
|
|
50
|
+
this.streamPaused = false;
|
|
51
|
+
this.recordedChunks = [];
|
|
52
|
+
this.videoSize = { width: 0, height: 0 };
|
|
53
|
+
this.pauseStream = () => {
|
|
54
|
+
this.streamPaused = true;
|
|
55
|
+
this.mediaRecorder.pause();
|
|
56
|
+
this.videoElement.pause();
|
|
57
|
+
// this.dropMask();
|
|
58
|
+
// if (this.faceDetection) Detector.getInstance().stopDetector();
|
|
59
|
+
};
|
|
60
|
+
this.initFacePose();
|
|
61
|
+
this.idML5Detector = IDML5Detector.getInstance(this, store.device.isMobile);
|
|
62
|
+
this.faceML5Detector = FaceML5Detector.getInstance(this, store.device.isMobile);
|
|
63
|
+
this.verificationMode = mode;
|
|
64
|
+
}
|
|
65
|
+
static getInstance(mode) {
|
|
66
|
+
if (!Stream.instance) {
|
|
67
|
+
Stream.instance = new Stream(mode);
|
|
68
|
+
}
|
|
69
|
+
return Stream.instance;
|
|
70
|
+
}
|
|
71
|
+
// public returnErrors(errors: PipelineResult) {
|
|
72
|
+
// this.callbackFaceDetectionErrors(errors);
|
|
73
|
+
// }
|
|
74
|
+
autoCapturing() {
|
|
75
|
+
this.callbackAutoCapturing();
|
|
76
|
+
}
|
|
77
|
+
timeElapsed() {
|
|
78
|
+
this.callbackTimeElapsed();
|
|
79
|
+
}
|
|
80
|
+
verificationReady() {
|
|
81
|
+
this.verificationFinished();
|
|
82
|
+
}
|
|
83
|
+
updateHtmlElements(videoElement, canvasElement, component) {
|
|
84
|
+
this.videoElement = videoElement;
|
|
85
|
+
this.canvasElement = canvasElement;
|
|
86
|
+
this.idML5Detector.updateHtmlElements(this.videoElement, this.canvasElement, component);
|
|
87
|
+
this.faceML5Detector.updateHtmlElements(this.videoElement, this.canvasElement, component);
|
|
88
|
+
}
|
|
89
|
+
static orientationChange() { }
|
|
90
|
+
startStream(stream) {
|
|
91
|
+
if (this.stream)
|
|
92
|
+
this.stream.getTracks().forEach((track) => track.stop());
|
|
93
|
+
this.stream = stream;
|
|
94
|
+
if (!this.videoElement || this.videoElement == null) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if ('srcObject' in this.videoElement) {
|
|
98
|
+
this.videoElement.srcObject = stream;
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
// @ts-ignore
|
|
102
|
+
this.videoElement.src = window.URL.createObjectURL(stream);
|
|
103
|
+
}
|
|
104
|
+
this.videoElement.addEventListener('loadedmetadata', async (_e) => {
|
|
105
|
+
this.videoElement.play().then(() => {
|
|
106
|
+
this.streamPaused = false;
|
|
107
|
+
this.updateCanvasSize(this.canvasElement);
|
|
108
|
+
this.updateVideoSize(this.videoElement);
|
|
109
|
+
this.callbackVideoStarted();
|
|
110
|
+
if (this.idDetection)
|
|
111
|
+
this.startIdDetection();
|
|
112
|
+
if (this.faceDetection)
|
|
113
|
+
this.startFaceDetection();
|
|
114
|
+
});
|
|
115
|
+
}, false);
|
|
116
|
+
}
|
|
117
|
+
async initStream(stream) {
|
|
118
|
+
this.startStream(stream);
|
|
119
|
+
this.recordStream();
|
|
120
|
+
}
|
|
121
|
+
async resumeStream() {
|
|
122
|
+
this.streamPaused = false;
|
|
123
|
+
this.mediaRecorder.resume();
|
|
124
|
+
await this.videoElement.play();
|
|
125
|
+
// this.drawMask();
|
|
126
|
+
// if (this.faceDetection) await Detector.getInstance().startDetector();
|
|
127
|
+
}
|
|
128
|
+
recordStream() {
|
|
129
|
+
if (this.mediaRecorder && this.mediaRecorder.state == 'recording')
|
|
130
|
+
return;
|
|
131
|
+
var options = { mimeType: Stream.webmMimeType.mime, videoBitsPerSecond: 1500000 };
|
|
132
|
+
if (!MediaRecorder.isTypeSupported(options.mimeType)) {
|
|
133
|
+
if (store.device.mobileOS == MobileOS.iOS || store.device.browser == Browser.Safari)
|
|
134
|
+
options.mimeType = Stream.mp4MimeType.mime;
|
|
135
|
+
}
|
|
136
|
+
this.recordedChunks = [];
|
|
137
|
+
this.mediaRecorder = new MediaRecorder(this.stream, options);
|
|
138
|
+
this.mediaRecorder.ondataavailable = event => {
|
|
139
|
+
this.recordedChunks.push(event.data);
|
|
140
|
+
};
|
|
141
|
+
this.mediaRecorder.onstop = _e => {
|
|
142
|
+
var rec = new Blob(this.recordedChunks, {
|
|
143
|
+
type: options.mimeType.split(';')[0],
|
|
144
|
+
});
|
|
145
|
+
this.callbackRecordingReady(rec);
|
|
146
|
+
};
|
|
147
|
+
this.mediaRecorder.start(); // Start recording, and dump data every second
|
|
148
|
+
}
|
|
149
|
+
updateCanvasSize(canvas) {
|
|
150
|
+
this.videoSize = { width: this.videoElement.videoWidth, height: this.videoElement.videoHeight };
|
|
151
|
+
canvas.width = this.videoSize.width;
|
|
152
|
+
canvas.height = this.videoSize.height;
|
|
153
|
+
}
|
|
154
|
+
updateVideoSize(video) {
|
|
155
|
+
this.videoSize = { width: this.videoElement.videoWidth, height: this.videoElement.videoHeight };
|
|
156
|
+
video.width = this.videoSize.width;
|
|
157
|
+
video.height = this.videoSize.height;
|
|
158
|
+
}
|
|
159
|
+
dropStream() {
|
|
160
|
+
if (!this.streamStopped()) {
|
|
161
|
+
this.stream.getTracks().forEach((track) => track.stop());
|
|
162
|
+
this.videoElement.srcObject = null;
|
|
163
|
+
}
|
|
164
|
+
if (this.mediaRecorder && this.mediaRecorder.state != 'inactive') {
|
|
165
|
+
this.mediaRecorder.stop();
|
|
166
|
+
}
|
|
167
|
+
// if (this.faceDetection) Detector.getInstance().stopDetector();
|
|
168
|
+
}
|
|
169
|
+
streamStopped() {
|
|
170
|
+
return !(this.stream && this.stream.getTracks && this.stream.getTracks().length > 0);
|
|
171
|
+
}
|
|
172
|
+
async takePhoto() {
|
|
173
|
+
const canvas = document.createElement('canvas');
|
|
174
|
+
canvas.style.visibility = 'hidden';
|
|
175
|
+
canvas.width = this.videoElement.videoWidth;
|
|
176
|
+
canvas.height = this.videoElement.videoHeight;
|
|
177
|
+
return await this.getFrame(canvas);
|
|
178
|
+
}
|
|
179
|
+
getFrame(canvas) {
|
|
180
|
+
return new Promise(resolve => {
|
|
181
|
+
const context = canvas.getContext('2d');
|
|
182
|
+
context.drawImage(this.videoElement, 0, 0, canvas.width, canvas.height);
|
|
183
|
+
canvas.toBlob((frame) => {
|
|
184
|
+
if (frame.type === ImageFormat.JPEG && !store.device.isAppleDevice) {
|
|
185
|
+
try {
|
|
186
|
+
addExifInImg(frame, this.stream.getTracks()[0], this.videoSize).then(updatedFrame => resolve(updatedFrame));
|
|
187
|
+
}
|
|
188
|
+
catch (e) {
|
|
189
|
+
resolve(frame);
|
|
190
|
+
this.callbackErrors(e, false);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
resolve(frame);
|
|
195
|
+
}
|
|
196
|
+
}, ImageFormat.PNG, 1);
|
|
197
|
+
//let outCanvContext = this.canvasElement.getContext('2d');
|
|
198
|
+
//outCanvContext.drawImage(this.videoElement, 0, 0, this.canvasElement.width, this.canvasElement.height);
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
async startIdDetection() {
|
|
202
|
+
if (this.streamPaused)
|
|
203
|
+
return;
|
|
204
|
+
this.idML5Detector.initDetector(this.verificationMode);
|
|
205
|
+
}
|
|
206
|
+
async startFaceDetection() {
|
|
207
|
+
if (this.streamPaused)
|
|
208
|
+
return;
|
|
209
|
+
this.faceML5Detector.initDetector(this.verificationMode);
|
|
210
|
+
}
|
|
211
|
+
initFacePose() {
|
|
212
|
+
this.facePose = FacePosePick.randomEnum(FacePose);
|
|
213
|
+
}
|
|
214
|
+
requestFacePose() {
|
|
215
|
+
// var pose = FacePose.TiltLeft;
|
|
216
|
+
this.callbackChangeTitle(this.facePose);
|
|
217
|
+
return this.facePose;
|
|
218
|
+
}
|
|
219
|
+
changeFacePose() {
|
|
220
|
+
this.callbackChangeTitle(null);
|
|
221
|
+
}
|
|
222
|
+
changeIDPose(pose) {
|
|
223
|
+
this.callbackChangeTitle(pose);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
Stream.mp4MimeType = { type: 'video/mp4', codec: 'codecs:h264', extension: 'mp4', mime: 'video/mp4;codecs:h264' };
|
|
227
|
+
Stream.webmMimeType = { type: 'video/webm', codec: 'codecs=vp8', extension: 'webm', mime: 'video/webm;codecs=vp8' };
|
|
228
|
+
window.addEventListener('resize', Stream.orientationChange, false);
|
|
229
|
+
window.addEventListener('orientationchange', Stream.orientationChange, false);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import store from './store';
|
|
2
|
+
class TranslationsController {
|
|
3
|
+
async getValues() {
|
|
4
|
+
if (this.values) {
|
|
5
|
+
return this.values;
|
|
6
|
+
}
|
|
7
|
+
else {
|
|
8
|
+
this.values = await this.fetchTranslations();
|
|
9
|
+
return this.values;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
getLocale(element = document.body) {
|
|
13
|
+
const closestElement = element.closest('[lang]');
|
|
14
|
+
return closestElement ? closestElement.lang : store.langIso;
|
|
15
|
+
}
|
|
16
|
+
async fetchTranslations() {
|
|
17
|
+
const locale = this.getLocale();
|
|
18
|
+
const existingTranslations = JSON.parse(sessionStorage.getItem(`i18n.${locale}`));
|
|
19
|
+
if (existingTranslations && Object.keys(existingTranslations).length > 0) {
|
|
20
|
+
return existingTranslations;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
try {
|
|
24
|
+
const result = await fetch(`/i18n/${locale}.json`);
|
|
25
|
+
if (result.ok) {
|
|
26
|
+
const data = await result.json();
|
|
27
|
+
sessionStorage.setItem(`i18n.${locale}`, JSON.stringify(data));
|
|
28
|
+
return data;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch (exception) {
|
|
32
|
+
console.error(`Error loading locale: ${locale}`, exception);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export const Translations = new TranslationsController();
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function videoRatio(videoElement) {
|
|
2
|
+
const hRatio = videoElement.clientWidth / videoElement.videoWidth;
|
|
3
|
+
const vRatio = videoElement.clientHeight / videoElement.videoHeight;
|
|
4
|
+
return Math.min(hRatio, vRatio);
|
|
5
|
+
}
|
|
6
|
+
export function getVideoRatio(videoElement) {
|
|
7
|
+
const hRatio = videoElement.clientWidth / videoElement.videoWidth;
|
|
8
|
+
const vRatio = videoElement.clientHeight / videoElement.videoHeight;
|
|
9
|
+
return Math.min(hRatio, vRatio);
|
|
10
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const convertToDataUrl = async (file) => {
|
|
2
|
+
return new Promise(async (resolve) => {
|
|
3
|
+
let arr = [];
|
|
4
|
+
for (let i = 0; i < file.length; i++) {
|
|
5
|
+
const fr = new FileReader();
|
|
6
|
+
fr.onload = () => {
|
|
7
|
+
arr.push(fr.result);
|
|
8
|
+
if (arr.length === file.length)
|
|
9
|
+
resolve(arr);
|
|
10
|
+
};
|
|
11
|
+
fr.readAsDataURL(file[i]);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
export const blobToBase64 = (blob) => {
|
|
16
|
+
return new Promise((resolve, _) => {
|
|
17
|
+
const reader = new FileReader();
|
|
18
|
+
reader.onloadend = () => resolve(reader.result);
|
|
19
|
+
reader.readAsDataURL(blob);
|
|
20
|
+
});
|
|
21
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { blobToBase64 } from '../utils/utils';
|
|
2
|
+
import * as piexif from 'piexifjs';
|
|
3
|
+
export const addExifInImg = async (blob, track, videoSize) => {
|
|
4
|
+
const base64 = await blobToBase64(blob);
|
|
5
|
+
const exif = piexif.load(base64);
|
|
6
|
+
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
7
|
+
const cameraNames = devices.filter(device => device.kind === 'videoinput').map(device => device.label);
|
|
8
|
+
const json = {
|
|
9
|
+
width: videoSize.width,
|
|
10
|
+
height: videoSize.height,
|
|
11
|
+
usedCamera: track.label,
|
|
12
|
+
camerasOnDevice: cameraNames,
|
|
13
|
+
};
|
|
14
|
+
const newExif = {
|
|
15
|
+
'0th': Object.assign(Object.assign({}, exif['0th']), { [piexif.ImageIFD.Model]: json.usedCamera, [piexif.ImageIFD.ImageWidth]: json.width, [piexif.ImageIFD.ImageLength]: json.height }),
|
|
16
|
+
'Exif': Object.assign(Object.assign({}, exif['Exif']), { [piexif.ExifIFD.UserComment]: JSON.stringify(json) }),
|
|
17
|
+
'GPS': Object.assign({}, exif['GPS']),
|
|
18
|
+
'Interop': Object.assign({}, exif['Interop']),
|
|
19
|
+
'1st': Object.assign({}, exif['1st']),
|
|
20
|
+
'thumbnail': exif['thumbnail'],
|
|
21
|
+
};
|
|
22
|
+
const newExifBinary = piexif.dump(newExif);
|
|
23
|
+
const newPhotoData = piexif.insert(newExifBinary, base64);
|
|
24
|
+
return await fetch(newPhotoData).then(res => res.blob());
|
|
25
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { createStore } from '@stencil/store';
|
|
2
|
+
import { FlowStatus } from '../models/FlowStatus';
|
|
3
|
+
import { SessionKeys } from './textValues';
|
|
4
|
+
const { state, onChange } = createStore({
|
|
5
|
+
flowStatus: FlowStatus.NONE,
|
|
6
|
+
environment: 'PROD',
|
|
7
|
+
debug: false,
|
|
8
|
+
requestId: '',
|
|
9
|
+
redirectId: '',
|
|
10
|
+
initialised: false,
|
|
11
|
+
token: '',
|
|
12
|
+
cameraIds: [],
|
|
13
|
+
cameraId: '',
|
|
14
|
+
hasIdBack: false,
|
|
15
|
+
hasSelfieGesture: false,
|
|
16
|
+
hasIdTilt: false,
|
|
17
|
+
agreementsValidation: true,
|
|
18
|
+
phoneValidation: true,
|
|
19
|
+
phoneNumber: '',
|
|
20
|
+
apiBaseUrl: 'https://apiro.id-kyc.com',
|
|
21
|
+
device: null,
|
|
22
|
+
langIso: 'ro',
|
|
23
|
+
});
|
|
24
|
+
onChange('environment', value => {
|
|
25
|
+
state.debug = value == 'QA';
|
|
26
|
+
});
|
|
27
|
+
onChange('flowStatus', value => {
|
|
28
|
+
sessionStorage.setItem(SessionKeys.FlowStatusKey, FlowStatus[value]);
|
|
29
|
+
});
|
|
30
|
+
onChange('token', value => {
|
|
31
|
+
sessionStorage.setItem(SessionKeys.TokenKey, value);
|
|
32
|
+
});
|
|
33
|
+
onChange('requestId', value => {
|
|
34
|
+
sessionStorage.setItem(SessionKeys.RequestIdKey, value);
|
|
35
|
+
});
|
|
36
|
+
onChange('initialised', value => {
|
|
37
|
+
sessionStorage.setItem(SessionKeys.InitialisedKey, String(value));
|
|
38
|
+
});
|
|
39
|
+
onChange('hasIdBack', value => {
|
|
40
|
+
sessionStorage.setItem(SessionKeys.HasIdBackKey, String(value));
|
|
41
|
+
});
|
|
42
|
+
onChange('agreementsValidation', value => {
|
|
43
|
+
sessionStorage.setItem(SessionKeys.AgreementValidationKey, String(value));
|
|
44
|
+
});
|
|
45
|
+
onChange('phoneValidation', value => {
|
|
46
|
+
sessionStorage.setItem(SessionKeys.PhoneValidationKey, String(value));
|
|
47
|
+
});
|
|
48
|
+
export default state;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import store from './store';
|
|
2
|
+
export class IdCaptureValues {
|
|
3
|
+
}
|
|
4
|
+
IdCaptureValues.IDPoseDemoMapping = {
|
|
5
|
+
0: 'https://ekyc.blob.core.windows.net/$web/animations/id/id_front.mp4',
|
|
6
|
+
1: 'https://ekyc.blob.core.windows.net/$web/animations/id/id_front_tilt.mp4',
|
|
7
|
+
2: 'https://ekyc.blob.core.windows.net/$web/animations/id/id_rotate.mp4',
|
|
8
|
+
3: 'https://ekyc.blob.core.windows.net/$web/animations/id/id_back.mp4',
|
|
9
|
+
4: 'https://ekyc.blob.core.windows.net/$web/animations/id/id_back_tilt.mp4',
|
|
10
|
+
};
|
|
11
|
+
export class SelfieCaptureValues {
|
|
12
|
+
}
|
|
13
|
+
SelfieCaptureValues.FacePoseDemoMapping = {
|
|
14
|
+
0: 'https://ekyc.blob.core.windows.net/$web/animations/selfie/selfie_rotate_left.mp4',
|
|
15
|
+
1: 'https://ekyc.blob.core.windows.net/$web/animations/selfie/selfie_rotate_right.mp4',
|
|
16
|
+
2: 'https://ekyc.blob.core.windows.net/$web/animations/selfie/selfie_tilt_back.mp4',
|
|
17
|
+
3: 'https://ekyc.blob.core.windows.net/$web/animations/selfie/selfie_tilt_front.mp4',
|
|
18
|
+
// 4: 'https://ekyc.blob.core.windows.net/$web/animations/selfie/selfie_tilt_left.mp4',
|
|
19
|
+
// 5: 'https://ekyc.blob.core.windows.net/$web/animations/selfie/selfie_tilt_right.mp4',
|
|
20
|
+
4: 'https://ekyc.blob.core.windows.net/$web/animations/selfie/selfie_main.mp4',
|
|
21
|
+
};
|
|
22
|
+
export class SessionKeys {
|
|
23
|
+
}
|
|
24
|
+
SessionKeys.FlowStatusKey = 'qbs-ect-flowstatus';
|
|
25
|
+
SessionKeys.RequestIdKey = 'qbs-ect-requestid';
|
|
26
|
+
SessionKeys.TokenKey = 'qbs-ect-token';
|
|
27
|
+
SessionKeys.InitialisedKey = 'qbs-ect-initialised';
|
|
28
|
+
SessionKeys.HasIdBackKey = 'qbs-ect-has-id-back';
|
|
29
|
+
SessionKeys.AgreementValidationKey = 'qbs-ect-agreement-validation';
|
|
30
|
+
SessionKeys.PhoneValidationKey = 'qbs-ect-phone-validation';
|
|
31
|
+
SessionKeys.RefreshDoneKey = 'qbs-ect-refresh-done';
|
|
32
|
+
export class ApiUrls {
|
|
33
|
+
constructor() {
|
|
34
|
+
this.uriEnv = '/';
|
|
35
|
+
this.uriEnv = store.environment == 'QA' ? '/dev_' : '/';
|
|
36
|
+
this.OtpSend = this.uriEnv + 'validation/otp/send';
|
|
37
|
+
this.OtpCheck = this.uriEnv + 'validation/otp/check';
|
|
38
|
+
this.IdentityInsert = this.uriEnv + 'validation/identity/insert';
|
|
39
|
+
this.UploadCapture = this.uriEnv + 'validation/upload/capture';
|
|
40
|
+
this.GetAgreement = this.uriEnv + 'validation/agreement/content';
|
|
41
|
+
this.GenerateAgreement = this.uriEnv + 'validation/agreement/generate';
|
|
42
|
+
this.SendLink = this.uriEnv + 'validation/otp/sendlink';
|
|
43
|
+
this.GetStatus = this.uriEnv + 'validation/identity/status';
|
|
44
|
+
this.AddLog = this.uriEnv + 'validation/logs/add';
|
|
45
|
+
this.AddStep = this.uriEnv + 'validation/logs/step';
|
|
46
|
+
this.AbortRequest = this.uriEnv + 'validation/identity/abort';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|