smartcomply-web-sdk 1.0.90 → 1.0.92
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/camera/ActionDetector.d.ts +2 -1
- package/dist/camera/ActionDetector.d.ts.map +1 -1
- package/dist/camera/ActionDetector.js +21 -5
- package/dist/camera/ActionDetector.js.map +1 -1
- package/dist/client/Smartcomply.d.ts +2 -2
- package/dist/client/Smartcomply.js +2 -2
- package/dist/esm/camera/ActionDetector.d.ts +2 -1
- package/dist/esm/camera/ActionDetector.d.ts.map +1 -1
- package/dist/esm/camera/ActionDetector.js +21 -5
- package/dist/esm/camera/ActionDetector.js.map +1 -1
- package/dist/esm/client/Smartcomply.d.ts +2 -2
- package/dist/esm/client/Smartcomply.js +2 -2
- package/dist/esm/flow/SmartComplyFlow.d.ts +10 -0
- package/dist/esm/flow/SmartComplyFlow.d.ts.map +1 -1
- package/dist/esm/flow/SmartComplyFlow.js +106 -33
- package/dist/esm/flow/SmartComplyFlow.js.map +1 -1
- package/dist/esm/flow/spinner.js +14 -14
- package/dist/esm/modules/liveness/LivenessUI.js +83 -83
- package/dist/flow/SmartComplyFlow.d.ts +10 -0
- package/dist/flow/SmartComplyFlow.d.ts.map +1 -1
- package/dist/flow/SmartComplyFlow.js +107 -33
- package/dist/flow/SmartComplyFlow.js.map +1 -1
- package/dist/flow/spinner.js +14 -14
- package/dist/modules/liveness/LivenessUI.js +83 -83
- package/dist/smartcomply.browser.js +60 -16
- package/dist/smartcomply.browser.js.map +2 -2
- package/package.json +1 -1
- package/dist/esm/components/CameraView.d.ts +0 -59
- package/dist/esm/components/CameraView.d.ts.map +0 -1
- package/dist/esm/components/CameraView.js +0 -238
- package/dist/esm/components/CameraView.js.map +0 -1
- package/dist/esm/components/DocumentUpload.d.ts +0 -21
- package/dist/esm/components/DocumentUpload.d.ts.map +0 -1
- package/dist/esm/components/DocumentUpload.js +0 -216
- package/dist/esm/components/DocumentUpload.js.map +0 -1
|
@@ -9,7 +9,8 @@ export declare class ActionDetector {
|
|
|
9
9
|
private blinkHoldCount;
|
|
10
10
|
private blinkDetected;
|
|
11
11
|
private motionDetected;
|
|
12
|
-
private
|
|
12
|
+
private minYaw;
|
|
13
|
+
private maxYaw;
|
|
13
14
|
check(result: FaceDetectionResult): ScanProgress;
|
|
14
15
|
/** Snapshot of what's been detected so far — for reading the result after
|
|
15
16
|
* the scan loop has already ended (e.g. to report alongside the submit
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionDetector.d.ts","sourceRoot":"","sources":["../../src/camera/ActionDetector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAwBrD,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAAS;
|
|
1
|
+
{"version":3,"file":"ActionDetector.d.ts","sourceRoot":"","sources":["../../src/camera/ActionDetector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAwBrD,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAAS;IAG/B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,MAAM,CAAuB;IAErC,KAAK,CAAC,MAAM,EAAE,mBAAmB,GAAG,YAAY;IA2ChD;;4DAEwD;IACxD,WAAW,IAAI,YAAY;IAI3B,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,UAAU;CAInB"}
|
|
@@ -26,7 +26,10 @@ class ActionDetector {
|
|
|
26
26
|
this.blinkHoldCount = 0;
|
|
27
27
|
this.blinkDetected = false;
|
|
28
28
|
this.motionDetected = false;
|
|
29
|
-
|
|
29
|
+
// Running min/max yaw seen so far in the scan, not a single fixed
|
|
30
|
+
// first-frame baseline (see check() below for why).
|
|
31
|
+
this.minYaw = null;
|
|
32
|
+
this.maxYaw = null;
|
|
30
33
|
}
|
|
31
34
|
check(result) {
|
|
32
35
|
if (!result.faceDetected) {
|
|
@@ -47,10 +50,23 @@ class ActionDetector {
|
|
|
47
50
|
}
|
|
48
51
|
if (!this.motionDetected) {
|
|
49
52
|
const yaw = this.getHeadYaw(result.transformMatrix);
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
// A single first-frame baseline used to anchor this check — but the
|
|
54
|
+
// scan's first frame is essentially never a settled, neutral pose
|
|
55
|
+
// (camera/UI is still initializing, the user hasn't found center
|
|
56
|
+
// yet), and that baseline was never re-anchored for the rest of the
|
|
57
|
+
// window. A genuine head turn that happened to move TOWARD that
|
|
58
|
+
// arbitrary first reading, rather than away from it, read as a small
|
|
59
|
+
// delta and was missed — reported live as "blink saved, motion not,"
|
|
60
|
+
// on an ordinary fast look-around. Tracking the running min/max yaw
|
|
61
|
+
// and firing on their SPREAD instead fixes this: it's baseline-free,
|
|
62
|
+
// so it doesn't matter which frame happened to come first or which
|
|
63
|
+
// direction the real turn went — only that a genuine range of motion
|
|
64
|
+
// occurred somewhere across the window.
|
|
65
|
+
if (this.minYaw === null || yaw < this.minYaw)
|
|
66
|
+
this.minYaw = yaw;
|
|
67
|
+
if (this.maxYaw === null || yaw > this.maxYaw)
|
|
68
|
+
this.maxYaw = yaw;
|
|
69
|
+
if (this.maxYaw - this.minYaw >= YAW_MOTION_THRESHOLD_DEG) {
|
|
54
70
|
this.motionDetected = true;
|
|
55
71
|
}
|
|
56
72
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionDetector.js","sourceRoot":"","sources":["../../src/camera/ActionDetector.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,eAAe,GAAG,IAAI,CAAC;AAC7B,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAC5B,MAAM,wBAAwB,GAAG,CAAC,CAAC,CAAC,oDAAoD;AASxF,MAAa,cAAc;IAA3B;QACU,mBAAc,GAAG,CAAC,CAAC;QACnB,kBAAa,GAAG,KAAK,CAAC;QACtB,mBAAc,GAAG,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"ActionDetector.js","sourceRoot":"","sources":["../../src/camera/ActionDetector.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,7 +22,7 @@ export declare class SmartComply {
|
|
|
22
22
|
* CDN tag they installed with (e.g. @1, which floats to the latest
|
|
23
23
|
* matching release) actually resolved to the version they expect.
|
|
24
24
|
*/
|
|
25
|
-
static readonly VERSION = "1.0.
|
|
25
|
+
static readonly VERSION = "1.0.92";
|
|
26
26
|
private http;
|
|
27
27
|
private clientId;
|
|
28
28
|
private _sessionToken;
|
|
@@ -62,7 +62,7 @@ export declare class SmartComply {
|
|
|
62
62
|
* the request, so the resume_token has to be the one in use throughout.
|
|
63
63
|
*
|
|
64
64
|
* No expires_at is set here — the resume_token's own issuance response
|
|
65
|
-
* only carries resume_expires_at (a
|
|
65
|
+
* only carries resume_expires_at (a 24h invite-link window), not the
|
|
66
66
|
* session's own runtime expiry the way createSession() returns one. The
|
|
67
67
|
* backend still enforces the real expiry server-side regardless; this
|
|
68
68
|
* only means the client-side "session about to expire" warning timer
|
|
@@ -75,7 +75,7 @@ class SmartComply {
|
|
|
75
75
|
* the request, so the resume_token has to be the one in use throughout.
|
|
76
76
|
*
|
|
77
77
|
* No expires_at is set here — the resume_token's own issuance response
|
|
78
|
-
* only carries resume_expires_at (a
|
|
78
|
+
* only carries resume_expires_at (a 24h invite-link window), not the
|
|
79
79
|
* session's own runtime expiry the way createSession() returns one. The
|
|
80
80
|
* backend still enforces the real expiry server-side regardless; this
|
|
81
81
|
* only means the client-side "session about to expire" warning timer
|
|
@@ -125,5 +125,5 @@ exports.SmartComply = SmartComply;
|
|
|
125
125
|
* CDN tag they installed with (e.g. @1, which floats to the latest
|
|
126
126
|
* matching release) actually resolved to the version they expect.
|
|
127
127
|
*/
|
|
128
|
-
SmartComply.VERSION = "1.0.
|
|
128
|
+
SmartComply.VERSION = "1.0.92";
|
|
129
129
|
//# sourceMappingURL=Smartcomply.js.map
|
|
@@ -9,7 +9,8 @@ export declare class ActionDetector {
|
|
|
9
9
|
private blinkHoldCount;
|
|
10
10
|
private blinkDetected;
|
|
11
11
|
private motionDetected;
|
|
12
|
-
private
|
|
12
|
+
private minYaw;
|
|
13
|
+
private maxYaw;
|
|
13
14
|
check(result: FaceDetectionResult): ScanProgress;
|
|
14
15
|
/** Snapshot of what's been detected so far — for reading the result after
|
|
15
16
|
* the scan loop has already ended (e.g. to report alongside the submit
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionDetector.d.ts","sourceRoot":"","sources":["../../../src/camera/ActionDetector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAwBrD,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAAS;
|
|
1
|
+
{"version":3,"file":"ActionDetector.d.ts","sourceRoot":"","sources":["../../../src/camera/ActionDetector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAwBrD,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAAS;IAG/B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,MAAM,CAAuB;IAErC,KAAK,CAAC,MAAM,EAAE,mBAAmB,GAAG,YAAY;IA2ChD;;4DAEwD;IACxD,WAAW,IAAI,YAAY;IAI3B,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,UAAU;CAInB"}
|
|
@@ -23,7 +23,10 @@ export class ActionDetector {
|
|
|
23
23
|
this.blinkHoldCount = 0;
|
|
24
24
|
this.blinkDetected = false;
|
|
25
25
|
this.motionDetected = false;
|
|
26
|
-
|
|
26
|
+
// Running min/max yaw seen so far in the scan, not a single fixed
|
|
27
|
+
// first-frame baseline (see check() below for why).
|
|
28
|
+
this.minYaw = null;
|
|
29
|
+
this.maxYaw = null;
|
|
27
30
|
}
|
|
28
31
|
check(result) {
|
|
29
32
|
if (!result.faceDetected) {
|
|
@@ -44,10 +47,23 @@ export class ActionDetector {
|
|
|
44
47
|
}
|
|
45
48
|
if (!this.motionDetected) {
|
|
46
49
|
const yaw = this.getHeadYaw(result.transformMatrix);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
// A single first-frame baseline used to anchor this check — but the
|
|
51
|
+
// scan's first frame is essentially never a settled, neutral pose
|
|
52
|
+
// (camera/UI is still initializing, the user hasn't found center
|
|
53
|
+
// yet), and that baseline was never re-anchored for the rest of the
|
|
54
|
+
// window. A genuine head turn that happened to move TOWARD that
|
|
55
|
+
// arbitrary first reading, rather than away from it, read as a small
|
|
56
|
+
// delta and was missed — reported live as "blink saved, motion not,"
|
|
57
|
+
// on an ordinary fast look-around. Tracking the running min/max yaw
|
|
58
|
+
// and firing on their SPREAD instead fixes this: it's baseline-free,
|
|
59
|
+
// so it doesn't matter which frame happened to come first or which
|
|
60
|
+
// direction the real turn went — only that a genuine range of motion
|
|
61
|
+
// occurred somewhere across the window.
|
|
62
|
+
if (this.minYaw === null || yaw < this.minYaw)
|
|
63
|
+
this.minYaw = yaw;
|
|
64
|
+
if (this.maxYaw === null || yaw > this.maxYaw)
|
|
65
|
+
this.maxYaw = yaw;
|
|
66
|
+
if (this.maxYaw - this.minYaw >= YAW_MOTION_THRESHOLD_DEG) {
|
|
51
67
|
this.motionDetected = true;
|
|
52
68
|
}
|
|
53
69
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionDetector.js","sourceRoot":"","sources":["../../../src/camera/ActionDetector.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,eAAe,GAAG,IAAI,CAAC;AAC7B,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAC5B,MAAM,wBAAwB,GAAG,CAAC,CAAC,CAAC,oDAAoD;AASxF,MAAM,OAAO,cAAc;IAA3B;QACU,mBAAc,GAAG,CAAC,CAAC;QACnB,kBAAa,GAAG,KAAK,CAAC;QACtB,mBAAc,GAAG,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"ActionDetector.js","sourceRoot":"","sources":["../../../src/camera/ActionDetector.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,7 +22,7 @@ export declare class SmartComply {
|
|
|
22
22
|
* CDN tag they installed with (e.g. @1, which floats to the latest
|
|
23
23
|
* matching release) actually resolved to the version they expect.
|
|
24
24
|
*/
|
|
25
|
-
static readonly VERSION = "1.0.
|
|
25
|
+
static readonly VERSION = "1.0.92";
|
|
26
26
|
private http;
|
|
27
27
|
private clientId;
|
|
28
28
|
private _sessionToken;
|
|
@@ -62,7 +62,7 @@ export declare class SmartComply {
|
|
|
62
62
|
* the request, so the resume_token has to be the one in use throughout.
|
|
63
63
|
*
|
|
64
64
|
* No expires_at is set here — the resume_token's own issuance response
|
|
65
|
-
* only carries resume_expires_at (a
|
|
65
|
+
* only carries resume_expires_at (a 24h invite-link window), not the
|
|
66
66
|
* session's own runtime expiry the way createSession() returns one. The
|
|
67
67
|
* backend still enforces the real expiry server-side regardless; this
|
|
68
68
|
* only means the client-side "session about to expire" warning timer
|
|
@@ -72,7 +72,7 @@ export class SmartComply {
|
|
|
72
72
|
* the request, so the resume_token has to be the one in use throughout.
|
|
73
73
|
*
|
|
74
74
|
* No expires_at is set here — the resume_token's own issuance response
|
|
75
|
-
* only carries resume_expires_at (a
|
|
75
|
+
* only carries resume_expires_at (a 24h invite-link window), not the
|
|
76
76
|
* session's own runtime expiry the way createSession() returns one. The
|
|
77
77
|
* backend still enforces the real expiry server-side regardless; this
|
|
78
78
|
* only means the client-side "session about to expire" warning timer
|
|
@@ -121,5 +121,5 @@ export class SmartComply {
|
|
|
121
121
|
* CDN tag they installed with (e.g. @1, which floats to the latest
|
|
122
122
|
* matching release) actually resolved to the version they expect.
|
|
123
123
|
*/
|
|
124
|
-
SmartComply.VERSION = "1.0.
|
|
124
|
+
SmartComply.VERSION = "1.0.92";
|
|
125
125
|
//# sourceMappingURL=Smartcomply.js.map
|
|
@@ -40,6 +40,16 @@ export interface FlowResult {
|
|
|
40
40
|
submittedAt: string | null;
|
|
41
41
|
verificationResult?: VerifyIdentityResponse;
|
|
42
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Whether a showErrorStep() message is about an expired/invalid resume or
|
|
45
|
+
* resubmit link (RESUME_TARGET_UNAVAILABLE / NOT_A_RESUME_TOKEN — see
|
|
46
|
+
* SmartComplyFlow._resolveResumeStep), rather than a plain session timeout.
|
|
47
|
+
* Extracted to a standalone function so this specific classification is
|
|
48
|
+
* independently testable, same as resolveIdTypeInfo below — showErrorStep's
|
|
49
|
+
* own regex-based classification block is otherwise tightly coupled to DOM
|
|
50
|
+
* rendering it doesn't make sense to extract wholesale for this fix.
|
|
51
|
+
*/
|
|
52
|
+
export declare function isResumeLinkErrorMessage(message: string): boolean;
|
|
43
53
|
export declare function resolveIdTypeInfo(typeName: string, isDocumentFlow: boolean): {
|
|
44
54
|
icon: string;
|
|
45
55
|
desc: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SmartComplyFlow.d.ts","sourceRoot":"","sources":["../../../src/flow/SmartComplyFlow.ts"],"names":[],"mappings":"AACA,OAAO,EAA6B,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAIxF,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAoB,YAAY,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"SmartComplyFlow.d.ts","sourceRoot":"","sources":["../../../src/flow/SmartComplyFlow.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ import { requiresBackSide } from "../utils/documentRules";
|
|
|
6
6
|
import { DEFAULT_CHALLENGE_ACTIONS } from "../utils/constants";
|
|
7
7
|
import { icon } from "./icons";
|
|
8
8
|
import { renderSpinner, renderInlineSpinner } from "./spinner";
|
|
9
|
+
import { SDKError } from "../errors/SDKError";
|
|
9
10
|
// A dropped camera/network/upload error is not the user's fault and must not
|
|
10
11
|
// cost them a retry attempt — only a genuine verification outcome should.
|
|
11
12
|
// Classified by message rather than a typed error class since the errors
|
|
@@ -66,6 +67,18 @@ const COUNTRY_LABELS = {
|
|
|
66
67
|
function isUploadFieldType(type) {
|
|
67
68
|
return type === "upload" || type === "image" || type === "file";
|
|
68
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Whether a showErrorStep() message is about an expired/invalid resume or
|
|
72
|
+
* resubmit link (RESUME_TARGET_UNAVAILABLE / NOT_A_RESUME_TOKEN — see
|
|
73
|
+
* SmartComplyFlow._resolveResumeStep), rather than a plain session timeout.
|
|
74
|
+
* Extracted to a standalone function so this specific classification is
|
|
75
|
+
* independently testable, same as resolveIdTypeInfo below — showErrorStep's
|
|
76
|
+
* own regex-based classification block is otherwise tightly coupled to DOM
|
|
77
|
+
* rendering it doesn't make sense to extract wholesale for this fix.
|
|
78
|
+
*/
|
|
79
|
+
export function isResumeLinkErrorMessage(message) {
|
|
80
|
+
return /resume link|resubmit link/i.test(message);
|
|
81
|
+
}
|
|
69
82
|
export function resolveIdTypeInfo(typeName, isDocumentFlow) {
|
|
70
83
|
const u = typeName.toUpperCase();
|
|
71
84
|
const advanced = u.includes("ADVANCED");
|
|
@@ -654,7 +667,18 @@ export class SmartComplyFlow {
|
|
|
654
667
|
}
|
|
655
668
|
if (this.isDestroyed)
|
|
656
669
|
return;
|
|
657
|
-
|
|
670
|
+
if (this.options.resumeToken) {
|
|
671
|
+
// null means _resolveResumeStep already rendered an error itself
|
|
672
|
+
// (a provably expired/invalid resume link — see that method) and
|
|
673
|
+
// there is no step left to show; calling showStep() in that case
|
|
674
|
+
// would wipe the error message straight back out.
|
|
675
|
+
const resumeStep = await this._resolveResumeStep();
|
|
676
|
+
if (resumeStep !== null)
|
|
677
|
+
this.showStep(resumeStep);
|
|
678
|
+
}
|
|
679
|
+
else {
|
|
680
|
+
this.showStep("welcome");
|
|
681
|
+
}
|
|
658
682
|
}
|
|
659
683
|
catch (err) {
|
|
660
684
|
this.showErrorStep(err.message || "Failed to initialize. Please try again.");
|
|
@@ -665,9 +689,23 @@ export class SmartComplyFlow {
|
|
|
665
689
|
// same state renderCountrySelect/renderIdTypeSelect's own click handlers
|
|
666
690
|
// set) so document_capture/liveness render correctly instead of assuming
|
|
667
691
|
// state that was never set. Falls back to "welcome" on anything that
|
|
668
|
-
// doesn't resolve cleanly
|
|
669
|
-
//
|
|
670
|
-
//
|
|
692
|
+
// doesn't resolve cleanly for an UNCERTAIN reason (network error, timeout)
|
|
693
|
+
// — this is a UX improvement, not a requirement: the backend's own
|
|
694
|
+
// resume-match at create/ time still works correctly even if the widget
|
|
695
|
+
// can't figure out which screen to pre-select.
|
|
696
|
+
//
|
|
697
|
+
// Returns null instead when the lookup fails for a CERTAIN, known reason
|
|
698
|
+
// — the resume link itself is provably expired or already used
|
|
699
|
+
// (RESUME_TARGET_UNAVAILABLE) or was never a resume link at all
|
|
700
|
+
// (NOT_A_RESUME_TOKEN). Unlike a transient failure, there is no "try the
|
|
701
|
+
// real request and it'll still work" fallback for these: create/'s own
|
|
702
|
+
// resume-match reads the exact same resume_target_entry binding this
|
|
703
|
+
// lookup just found missing/invalid, so falling through to a generic
|
|
704
|
+
// welcome screen would silently walk the customer into a brand-new,
|
|
705
|
+
// unrelated verification attempt with no explanation — worse than telling
|
|
706
|
+
// them plainly that their link no longer works. The caller shows this
|
|
707
|
+
// error itself (via showErrorStep, called here directly) rather than
|
|
708
|
+
// rendering a step.
|
|
671
709
|
async _resolveResumeStep() {
|
|
672
710
|
try {
|
|
673
711
|
const info = await this.sdk.getResumeInfo();
|
|
@@ -719,10 +757,21 @@ export class SmartComplyFlow {
|
|
|
719
757
|
// server-side regardless of which screen the widget shows first.
|
|
720
758
|
return "welcome";
|
|
721
759
|
}
|
|
722
|
-
catch {
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
760
|
+
catch (err) {
|
|
761
|
+
const code = err instanceof SDKError ? err.errorCode : undefined;
|
|
762
|
+
if (code === "RESUME_TARGET_UNAVAILABLE" || code === "NOT_A_RESUME_TOKEN") {
|
|
763
|
+
// A certain, known failure — this specific link is provably no
|
|
764
|
+
// longer usable (already used, expired, or was never a resume link
|
|
765
|
+
// at all). Tell the customer plainly rather than silently starting
|
|
766
|
+
// a new, unrelated verification on a welcome screen with no
|
|
767
|
+
// explanation — see this method's own docstring above.
|
|
768
|
+
this.showErrorStep("This resume link has expired or is no longer valid.");
|
|
769
|
+
return null;
|
|
770
|
+
}
|
|
771
|
+
// Anything else (network error, timeout, an SDKError with a
|
|
772
|
+
// different/absent code) — never block the flow on this lookup.
|
|
773
|
+
// create/'s own resume-match still runs correctly once the customer
|
|
774
|
+
// gets there, so falling through to a generic welcome screen is safe.
|
|
726
775
|
return "welcome";
|
|
727
776
|
}
|
|
728
777
|
}
|
|
@@ -2086,7 +2135,20 @@ export class SmartComplyFlow {
|
|
|
2086
2135
|
identifier,
|
|
2087
2136
|
identifier_type: this.selectedIdType,
|
|
2088
2137
|
country,
|
|
2089
|
-
|
|
2138
|
+
// Was hardcoded to ["BLINK"] only. This entry is reused for the
|
|
2139
|
+
// liveness step later via existingEntryId (see liveness.ts's
|
|
2140
|
+
// startCheck) — that reuse path builds a LOCAL stub object and
|
|
2141
|
+
// never calls create() again, so whatever challenge_actions is
|
|
2142
|
+
// sent HERE is what the backend permanently stores for this
|
|
2143
|
+
// entry, regardless of what the widget actually challenges the
|
|
2144
|
+
// user for afterward. A document-flow entry's liveness_challenges
|
|
2145
|
+
// was stuck showing only BLINK even when the customer genuinely
|
|
2146
|
+
// completed a full blink-and-motion scan, because the stored
|
|
2147
|
+
// set never included TURN_HEAD to begin with. Match
|
|
2148
|
+
// DEFAULT_CHALLENGE_ACTIONS so this is consistent with what the
|
|
2149
|
+
// liveness step (SmartComplyFlow's other startCheck call) and
|
|
2150
|
+
// the widget's own ActionDetector actually check for.
|
|
2151
|
+
challenge_actions: [...DEFAULT_CHALLENGE_ACTIONS],
|
|
2090
2152
|
document: blob,
|
|
2091
2153
|
document_back: this.documentBackBlob || undefined,
|
|
2092
2154
|
device_type: deviceMeta.device_type,
|
|
@@ -2330,7 +2392,14 @@ export class SmartComplyFlow {
|
|
|
2330
2392
|
// Classify the error into a user-friendly category
|
|
2331
2393
|
const isCameraErr = /camera|permission|notallowed|notfound/i.test(message);
|
|
2332
2394
|
const isNetworkErr = /network|timeout|connection|fetch/i.test(message);
|
|
2333
|
-
|
|
2395
|
+
// Checked before the generic isAuthErr below — a resume/resubmit link
|
|
2396
|
+
// (RESUME_TARGET_UNAVAILABLE / NOT_A_RESUME_TOKEN from the backend, see
|
|
2397
|
+
// _resolveResumeStep) also matches "token...expired"/"link" wording, but
|
|
2398
|
+
// the corrective action is different from a plain session timeout: the
|
|
2399
|
+
// customer can't just "start again" themselves, they need a fresh link
|
|
2400
|
+
// from whoever sent them this one.
|
|
2401
|
+
const isResumeLinkErr = isResumeLinkErrorMessage(message);
|
|
2402
|
+
const isAuthErr = !isResumeLinkErr && /session.*expired|token.*expired|authentication/i.test(message);
|
|
2334
2403
|
const isDocQuality = /blurry|blur|quality|glare|dark|bright|lighting/i.test(message);
|
|
2335
2404
|
const isExpiredDoc = /document.*expired|expired.*document/i.test(message);
|
|
2336
2405
|
const isFaceMatch = /face.*match|selfie.*match|does not match/i.test(message);
|
|
@@ -2340,36 +2409,40 @@ export class SmartComplyFlow {
|
|
|
2340
2409
|
const isBillingErr = /wallet|balance|insufficient.*fund|payment.*required/i.test(message);
|
|
2341
2410
|
const errorIconName = isCameraErr ? "camera"
|
|
2342
2411
|
: isNetworkErr ? "network"
|
|
2343
|
-
:
|
|
2344
|
-
:
|
|
2345
|
-
:
|
|
2346
|
-
:
|
|
2347
|
-
:
|
|
2348
|
-
: "
|
|
2412
|
+
: isResumeLinkErr ? "clock"
|
|
2413
|
+
: isAuthErr ? "clock"
|
|
2414
|
+
: isDocQuality ? "search"
|
|
2415
|
+
: isExpiredDoc ? "calendar"
|
|
2416
|
+
: isFaceMatch ? "face"
|
|
2417
|
+
: isBillingErr ? "warning"
|
|
2418
|
+
: "close";
|
|
2349
2419
|
const errorTitle = isCameraErr ? "Camera Access Required"
|
|
2350
2420
|
: isNetworkErr ? "Connection Problem"
|
|
2351
|
-
:
|
|
2352
|
-
:
|
|
2353
|
-
:
|
|
2354
|
-
:
|
|
2355
|
-
:
|
|
2356
|
-
: "Verification
|
|
2421
|
+
: isResumeLinkErr ? "Link No Longer Valid"
|
|
2422
|
+
: isAuthErr ? "Session Expired"
|
|
2423
|
+
: isDocQuality ? "Document Photo Unclear"
|
|
2424
|
+
: isExpiredDoc ? "Document Expired"
|
|
2425
|
+
: isFaceMatch ? "Face Match Failed"
|
|
2426
|
+
: isBillingErr ? "Verification Unavailable"
|
|
2427
|
+
: "Verification Unsuccessful";
|
|
2357
2428
|
// Map to user-facing guidance — never show raw internal message
|
|
2358
2429
|
const userMessage = isCameraErr
|
|
2359
2430
|
? "Please allow camera access in your browser settings and try again."
|
|
2360
2431
|
: isNetworkErr
|
|
2361
2432
|
? "Check your internet connection and try again."
|
|
2362
|
-
:
|
|
2363
|
-
? "
|
|
2364
|
-
:
|
|
2365
|
-
?
|
|
2366
|
-
:
|
|
2367
|
-
? "
|
|
2368
|
-
:
|
|
2369
|
-
? "
|
|
2370
|
-
:
|
|
2371
|
-
? "
|
|
2372
|
-
:
|
|
2433
|
+
: isResumeLinkErr
|
|
2434
|
+
? "This link has expired or has already been used. Please contact us to request a new one."
|
|
2435
|
+
: isAuthErr
|
|
2436
|
+
? "Your session has expired. Please start again."
|
|
2437
|
+
: isDocQuality
|
|
2438
|
+
? _sanitizeUserMessage(message) || "Please retake your document photo in good lighting with no glare."
|
|
2439
|
+
: isExpiredDoc
|
|
2440
|
+
? "The document you submitted has expired. Please use a valid, current ID."
|
|
2441
|
+
: isFaceMatch
|
|
2442
|
+
? "Your selfie did not match the photo on your ID. Please ensure you are using your own valid document and face the camera directly."
|
|
2443
|
+
: isBillingErr
|
|
2444
|
+
? "Verification is temporarily unavailable. Please contact support."
|
|
2445
|
+
: _sanitizeUserMessage(message) || "We were unable to complete your verification. Please try again.";
|
|
2373
2446
|
const iconWrap = document.createElement("div");
|
|
2374
2447
|
iconWrap.style.cssText = `
|
|
2375
2448
|
width:72px;height:72px;border-radius:50%;
|