smartcomply-web-sdk 1.0.52 → 1.0.56
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/esm/flow/SmartComplyFlow.d.ts.map +1 -1
- package/dist/esm/flow/SmartComplyFlow.js +41 -10
- package/dist/esm/flow/SmartComplyFlow.js.map +1 -1
- package/dist/esm/modules/liveness/LivenessUI.d.ts +10 -0
- package/dist/esm/modules/liveness/LivenessUI.d.ts.map +1 -1
- package/dist/esm/modules/liveness/LivenessUI.js +129 -7
- package/dist/esm/modules/liveness/LivenessUI.js.map +1 -1
- package/dist/esm/modules/liveness/liveness.d.ts.map +1 -1
- package/dist/esm/modules/liveness/liveness.js +2 -0
- package/dist/esm/modules/liveness/liveness.js.map +1 -1
- package/dist/flow/SmartComplyFlow.d.ts.map +1 -1
- package/dist/flow/SmartComplyFlow.js +41 -10
- package/dist/flow/SmartComplyFlow.js.map +1 -1
- package/dist/modules/liveness/LivenessUI.d.ts +10 -0
- package/dist/modules/liveness/LivenessUI.d.ts.map +1 -1
- package/dist/modules/liveness/LivenessUI.js +129 -7
- package/dist/modules/liveness/LivenessUI.js.map +1 -1
- package/dist/modules/liveness/liveness.d.ts.map +1 -1
- package/dist/modules/liveness/liveness.js +2 -0
- package/dist/modules/liveness/liveness.js.map +1 -1
- package/dist/smartcomply.browser.js +146 -19
- package/dist/smartcomply.browser.js.map +3 -3
- package/package.json +1 -1
|
@@ -4521,6 +4521,20 @@ var SmartComplySDK = (() => {
|
|
|
4521
4521
|
0%,100% { opacity:0.3; transform:scale(0.85); }
|
|
4522
4522
|
50% { opacity:1; transform:scale(1); }
|
|
4523
4523
|
}
|
|
4524
|
+
@keyframes sc-scanline-sweep {
|
|
4525
|
+
0% { transform:translateY(-4%); opacity:0; }
|
|
4526
|
+
8% { opacity:0.9; }
|
|
4527
|
+
92% { opacity:0.9; }
|
|
4528
|
+
100% { transform:translateY(104%); opacity:0; }
|
|
4529
|
+
}
|
|
4530
|
+
@keyframes sc-corner-pulse {
|
|
4531
|
+
0%,100% { opacity:0.55; }
|
|
4532
|
+
50% { opacity:1; }
|
|
4533
|
+
}
|
|
4534
|
+
@keyframes sc-oval-breathe {
|
|
4535
|
+
0%,100% { opacity:0.5; }
|
|
4536
|
+
50% { opacity:0.85; }
|
|
4537
|
+
}
|
|
4524
4538
|
`;
|
|
4525
4539
|
document.head.appendChild(s2);
|
|
4526
4540
|
}
|
|
@@ -4530,11 +4544,15 @@ var SmartComplySDK = (() => {
|
|
|
4530
4544
|
this.videoEl = null;
|
|
4531
4545
|
this.instructionEl = null;
|
|
4532
4546
|
this.confidenceRingEl = null;
|
|
4547
|
+
this.bgOvalEl = null;
|
|
4548
|
+
this.guideWrapEl = null;
|
|
4549
|
+
this.scanlineEl = null;
|
|
4533
4550
|
this.overlayEl = null;
|
|
4534
4551
|
this.dotsEl = null;
|
|
4535
4552
|
this.docCaptureRoot = null;
|
|
4536
4553
|
this.scanStartMs = 0;
|
|
4537
4554
|
this.scanDurationMs = 0;
|
|
4555
|
+
this.faceTracked = false;
|
|
4538
4556
|
}
|
|
4539
4557
|
mount(container, challenge) {
|
|
4540
4558
|
injectLivenessKeyframes();
|
|
@@ -4552,41 +4570,110 @@ var SmartComplySDK = (() => {
|
|
|
4552
4570
|
this.videoEl.muted = true;
|
|
4553
4571
|
this.videoEl.style.cssText = `
|
|
4554
4572
|
width:100%;height:100%;display:block;
|
|
4573
|
+
filter:brightness(1.03) contrast(1.03);
|
|
4555
4574
|
transform:scaleX(-1);object-fit:cover;
|
|
4575
|
+
`;
|
|
4576
|
+
const vignette = document.createElement("div");
|
|
4577
|
+
vignette.style.cssText = `
|
|
4578
|
+
position:absolute;inset:0;pointer-events:none;
|
|
4579
|
+
background:radial-gradient(ellipse 34% 44% at 50% 47%, transparent 55%, rgba(0,0,0,0.55) 100%);
|
|
4556
4580
|
`;
|
|
4557
4581
|
const guideWrap = document.createElement("div");
|
|
4558
4582
|
guideWrap.style.cssText = `
|
|
4559
4583
|
position:absolute;top:50%;left:50%;
|
|
4560
4584
|
transform:translate(-50%,-52%);
|
|
4561
4585
|
width:64%;aspect-ratio:140/180;pointer-events:none;
|
|
4586
|
+
filter:drop-shadow(0 0 18px rgba(59,130,246,0.35));
|
|
4587
|
+
transition:filter 0.3s ease;
|
|
4562
4588
|
`;
|
|
4589
|
+
this.guideWrapEl = guideWrap;
|
|
4563
4590
|
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
4564
4591
|
svg.setAttribute("viewBox", "0 0 140 180");
|
|
4565
|
-
svg.style.cssText = "width:100%;height:100%;";
|
|
4592
|
+
svg.style.cssText = "width:100%;height:100%;overflow:visible;";
|
|
4593
|
+
const defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
|
|
4594
|
+
const clip = document.createElementNS("http://www.w3.org/2000/svg", "clipPath");
|
|
4595
|
+
clip.setAttribute("id", "sc-oval-clip");
|
|
4596
|
+
const clipOval = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
|
|
4597
|
+
clipOval.setAttribute("cx", "70");
|
|
4598
|
+
clipOval.setAttribute("cy", "90");
|
|
4599
|
+
clipOval.setAttribute("rx", "64");
|
|
4600
|
+
clipOval.setAttribute("ry", "86");
|
|
4601
|
+
clip.appendChild(clipOval);
|
|
4602
|
+
defs.appendChild(clip);
|
|
4603
|
+
svg.appendChild(defs);
|
|
4604
|
+
const trackOval = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
|
|
4605
|
+
trackOval.setAttribute("cx", "70");
|
|
4606
|
+
trackOval.setAttribute("cy", "90");
|
|
4607
|
+
trackOval.setAttribute("rx", "58");
|
|
4608
|
+
trackOval.setAttribute("ry", "80");
|
|
4609
|
+
trackOval.setAttribute("fill", "none");
|
|
4610
|
+
trackOval.setAttribute("stroke", "rgba(255,255,255,0.16)");
|
|
4611
|
+
trackOval.setAttribute("stroke-width", "1");
|
|
4612
|
+
trackOval.setAttribute("stroke-dasharray", "2 5");
|
|
4613
|
+
svg.appendChild(trackOval);
|
|
4566
4614
|
const bgOval = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
|
|
4567
4615
|
bgOval.setAttribute("cx", "70");
|
|
4568
4616
|
bgOval.setAttribute("cy", "90");
|
|
4569
4617
|
bgOval.setAttribute("rx", "64");
|
|
4570
4618
|
bgOval.setAttribute("ry", "86");
|
|
4571
4619
|
bgOval.setAttribute("fill", "none");
|
|
4572
|
-
bgOval.setAttribute("stroke", "rgba(255,255,255,0.
|
|
4573
|
-
bgOval.setAttribute("stroke-width", "
|
|
4620
|
+
bgOval.setAttribute("stroke", "rgba(255,255,255,0.4)");
|
|
4621
|
+
bgOval.setAttribute("stroke-width", "1.5");
|
|
4622
|
+
bgOval.style.cssText = "animation:sc-oval-breathe 2.4s ease-in-out infinite;transition:stroke 0.3s ease;";
|
|
4623
|
+
this.bgOvalEl = bgOval;
|
|
4574
4624
|
const confOval = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
|
|
4575
4625
|
confOval.setAttribute("cx", "70");
|
|
4576
4626
|
confOval.setAttribute("cy", "90");
|
|
4577
4627
|
confOval.setAttribute("rx", "64");
|
|
4578
4628
|
confOval.setAttribute("ry", "86");
|
|
4579
4629
|
confOval.setAttribute("fill", "none");
|
|
4580
|
-
confOval.setAttribute("stroke", "#
|
|
4581
|
-
confOval.setAttribute("stroke-width", "
|
|
4630
|
+
confOval.setAttribute("stroke", "#3b82f6");
|
|
4631
|
+
confOval.setAttribute("stroke-width", "2.5");
|
|
4632
|
+
confOval.setAttribute("stroke-linecap", "round");
|
|
4582
4633
|
const circ = 2 * Math.PI * Math.sqrt((64 * 64 + 86 * 86) / 2);
|
|
4583
4634
|
confOval.setAttribute("stroke-dasharray", `${circ}`);
|
|
4584
4635
|
confOval.setAttribute("stroke-dashoffset", `${circ}`);
|
|
4585
|
-
confOval.style.cssText = "transition:stroke-dashoffset 0.2s linear;transform:rotate(-90deg);transform-origin:70px 90px;";
|
|
4636
|
+
confOval.style.cssText = "transition:stroke-dashoffset 0.2s linear,stroke 0.3s ease;transform:rotate(-90deg);transform-origin:70px 90px;";
|
|
4586
4637
|
this.confidenceRingEl = confOval;
|
|
4638
|
+
const bracketGroup = document.createElementNS("http://www.w3.org/2000/svg", "g");
|
|
4639
|
+
bracketGroup.setAttribute("stroke", "#3b82f6");
|
|
4640
|
+
bracketGroup.setAttribute("stroke-width", "3");
|
|
4641
|
+
bracketGroup.setAttribute("stroke-linecap", "round");
|
|
4642
|
+
bracketGroup.setAttribute("fill", "none");
|
|
4643
|
+
bracketGroup.style.cssText = "animation:sc-corner-pulse 2s ease-in-out infinite;";
|
|
4644
|
+
const bracketLen = 14;
|
|
4645
|
+
const bx0 = 70 - 64 * 0.74, bx1 = 70 + 64 * 0.74;
|
|
4646
|
+
const by0 = 90 - 86 * 0.82, by1 = 90 + 86 * 0.82;
|
|
4647
|
+
const brackets = [
|
|
4648
|
+
`M${bx0},${by0 + bracketLen} L${bx0},${by0} L${bx0 + bracketLen},${by0}`,
|
|
4649
|
+
`M${bx1 - bracketLen},${by0} L${bx1},${by0} L${bx1},${by0 + bracketLen}`,
|
|
4650
|
+
`M${bx0},${by1 - bracketLen} L${bx0},${by1} L${bx0 + bracketLen},${by1}`,
|
|
4651
|
+
`M${bx1 - bracketLen},${by1} L${bx1},${by1} L${bx1},${by1 - bracketLen}`
|
|
4652
|
+
];
|
|
4653
|
+
for (const d2 of brackets) {
|
|
4654
|
+
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
4655
|
+
path.setAttribute("d", d2);
|
|
4656
|
+
bracketGroup.appendChild(path);
|
|
4657
|
+
}
|
|
4587
4658
|
svg.appendChild(bgOval);
|
|
4588
4659
|
svg.appendChild(confOval);
|
|
4660
|
+
svg.appendChild(bracketGroup);
|
|
4589
4661
|
guideWrap.appendChild(svg);
|
|
4662
|
+
const scanlineClipWrap = document.createElement("div");
|
|
4663
|
+
scanlineClipWrap.style.cssText = `
|
|
4664
|
+
position:absolute;inset:0;
|
|
4665
|
+
clip-path:ellipse(45.7% 47.8% at 50% 50%);
|
|
4666
|
+
overflow:hidden;
|
|
4667
|
+
`;
|
|
4668
|
+
const scanline = document.createElement("div");
|
|
4669
|
+
scanline.style.cssText = `
|
|
4670
|
+
position:absolute;left:0;right:0;height:26%;top:0;
|
|
4671
|
+
background:linear-gradient(180deg,transparent 0%,rgba(59,130,246,0.32) 45%,rgba(147,197,253,0.55) 50%,rgba(59,130,246,0.32) 55%,transparent 100%);
|
|
4672
|
+
animation:sc-scanline-sweep 2.6s ease-in-out infinite;
|
|
4673
|
+
`;
|
|
4674
|
+
this.scanlineEl = scanline;
|
|
4675
|
+
scanlineClipWrap.appendChild(scanline);
|
|
4676
|
+
guideWrap.appendChild(scanlineClipWrap);
|
|
4590
4677
|
const camTop = document.createElement("div");
|
|
4591
4678
|
camTop.style.cssText = `
|
|
4592
4679
|
position:absolute;top:0;left:0;right:0;
|
|
@@ -4610,13 +4697,14 @@ var SmartComplySDK = (() => {
|
|
|
4610
4697
|
for (let i2 = 0; i2 < 3; i2++) {
|
|
4611
4698
|
const dot = document.createElement("div");
|
|
4612
4699
|
dot.style.cssText = `
|
|
4613
|
-
width:6px;height:6px;border-radius:50%;background:#
|
|
4700
|
+
width:6px;height:6px;border-radius:50%;background:#3b82f6;
|
|
4614
4701
|
animation:sc-scan-dot 1.1s ease-in-out ${i2 * 0.18}s infinite;
|
|
4615
4702
|
`;
|
|
4616
4703
|
this.dotsEl.appendChild(dot);
|
|
4617
4704
|
}
|
|
4618
4705
|
camBottom.appendChild(this.dotsEl);
|
|
4619
4706
|
this.root.appendChild(this.videoEl);
|
|
4707
|
+
this.root.appendChild(vignette);
|
|
4620
4708
|
this.root.appendChild(guideWrap);
|
|
4621
4709
|
this.root.appendChild(camTop);
|
|
4622
4710
|
this.root.appendChild(camBottom);
|
|
@@ -4650,6 +4738,25 @@ var SmartComplySDK = (() => {
|
|
|
4650
4738
|
this.confidenceRingEl.setAttribute("stroke-dashoffset", `${circ * (1 - pct)}`);
|
|
4651
4739
|
this.confidenceRingEl.setAttribute("stroke", livenessConfirmed ? "#22c55e" : "#3b82f6");
|
|
4652
4740
|
}
|
|
4741
|
+
/**
|
|
4742
|
+
* Reflects whether a face is currently detected in-frame — brightens the
|
|
4743
|
+
* oval guide's glow/brackets when locked on, and dims the scan-line sweep
|
|
4744
|
+
* so the UI visibly distinguishes "searching" from "actively scanning".
|
|
4745
|
+
*/
|
|
4746
|
+
setFaceTracking(tracked) {
|
|
4747
|
+
if (this.faceTracked === tracked) return;
|
|
4748
|
+
this.faceTracked = tracked;
|
|
4749
|
+
if (this.guideWrapEl) {
|
|
4750
|
+
this.guideWrapEl.style.filter = tracked ? "drop-shadow(0 0 22px rgba(34,197,94,0.45))" : "drop-shadow(0 0 18px rgba(59,130,246,0.35))";
|
|
4751
|
+
}
|
|
4752
|
+
if (this.bgOvalEl) {
|
|
4753
|
+
this.bgOvalEl.setAttribute("stroke", tracked ? "rgba(74,222,128,0.55)" : "rgba(255,255,255,0.4)");
|
|
4754
|
+
}
|
|
4755
|
+
if (this.scanlineEl) {
|
|
4756
|
+
this.scanlineEl.style.animationPlayState = tracked ? "running" : "paused";
|
|
4757
|
+
this.scanlineEl.style.opacity = tracked ? "1" : "0.4";
|
|
4758
|
+
}
|
|
4759
|
+
}
|
|
4653
4760
|
updateInstruction(text) {
|
|
4654
4761
|
if (this.instructionEl) this.instructionEl.textContent = text;
|
|
4655
4762
|
}
|
|
@@ -4791,6 +4898,10 @@ var SmartComplySDK = (() => {
|
|
|
4791
4898
|
this.confidenceRingEl = null;
|
|
4792
4899
|
this.overlayEl = null;
|
|
4793
4900
|
this.dotsEl = null;
|
|
4901
|
+
this.bgOvalEl = null;
|
|
4902
|
+
this.guideWrapEl = null;
|
|
4903
|
+
this.scanlineEl = null;
|
|
4904
|
+
this.faceTracked = false;
|
|
4794
4905
|
}
|
|
4795
4906
|
};
|
|
4796
4907
|
|
|
@@ -4984,6 +5095,7 @@ var SmartComplySDK = (() => {
|
|
|
4984
5095
|
}
|
|
4985
5096
|
if (videoForDetection.readyState >= 2) {
|
|
4986
5097
|
const detection = faceEngine.detect(videoForDetection, performance.now());
|
|
5098
|
+
ui2.setFaceTracking(detection.faceDetected);
|
|
4987
5099
|
if (detection.faceDetected) {
|
|
4988
5100
|
stableFrames++;
|
|
4989
5101
|
missedFrames = 0;
|
|
@@ -5058,6 +5170,7 @@ var SmartComplySDK = (() => {
|
|
|
5058
5170
|
const detection = faceEngine.detect(videoEl, performance.now());
|
|
5059
5171
|
const scan = actionDetector.check(detection);
|
|
5060
5172
|
ui2.updateScanProgress(scan.livenessConfirmed);
|
|
5173
|
+
ui2.setFaceTracking(detection.faceDetected);
|
|
5061
5174
|
if (!detection.faceDetected) {
|
|
5062
5175
|
ui2.updateInstruction("Move your face into the oval");
|
|
5063
5176
|
} else {
|
|
@@ -6423,7 +6536,6 @@ var SmartComplySDK = (() => {
|
|
|
6423
6536
|
"traceback",
|
|
6424
6537
|
"str(e)",
|
|
6425
6538
|
"error:",
|
|
6426
|
-
"failed:",
|
|
6427
6539
|
"django",
|
|
6428
6540
|
"python",
|
|
6429
6541
|
"http ",
|
|
@@ -6435,11 +6547,19 @@ var SmartComplySDK = (() => {
|
|
|
6435
6547
|
"confidence_percentage",
|
|
6436
6548
|
"threshold_percentage",
|
|
6437
6549
|
"polling_fallback",
|
|
6438
|
-
"resolved_by"
|
|
6550
|
+
"resolved_by",
|
|
6551
|
+
// Billing/wallet messages are an operator problem (fund the account,
|
|
6552
|
+
// configure billing) — never the end user's to act on.
|
|
6553
|
+
"wallet",
|
|
6554
|
+
"fund your wallet",
|
|
6555
|
+
"billing is not configured",
|
|
6556
|
+
"insufficient balance",
|
|
6557
|
+
"insufficient fund"
|
|
6439
6558
|
];
|
|
6440
6559
|
for (const blocked of blocklist) {
|
|
6441
6560
|
if (lower.includes(blocked)) return null;
|
|
6442
6561
|
}
|
|
6562
|
+
if (/failed:\S/i.test(raw)) return null;
|
|
6443
6563
|
if (/[a-z]+_[a-z]+/.test(raw) && !/\s/.test(raw.trim())) return null;
|
|
6444
6564
|
if (raw.trim()[0] === raw.trim()[0].toLowerCase() && /^[a-z]/.test(raw.trim())) return null;
|
|
6445
6565
|
return raw.trim();
|
|
@@ -7048,7 +7168,12 @@ var SmartComplySDK = (() => {
|
|
|
7048
7168
|
{ match: "GHANA", rule: { minLen: 8, maxLen: 20, alphanumeric: true, hint: "Ghana Card number must be 8–20 alphanumeric characters" } },
|
|
7049
7169
|
{ match: "SSNIT", rule: { minLen: 7, maxLen: 15, alphanumeric: true, hint: "SSNIT number must be 7–15 alphanumeric characters" } },
|
|
7050
7170
|
{ match: "TIN", rule: { minLen: 8, maxLen: 20, alphanumeric: true, hint: "TIN must be 8–20 characters" } },
|
|
7051
|
-
{ match: "KRA", rule: { minLen: 10, maxLen: 12, alphanumeric: true, hint: "KRA PIN must be 10–12 characters" } }
|
|
7171
|
+
{ match: "KRA", rule: { minLen: 10, maxLen: 12, alphanumeric: true, hint: "KRA PIN must be 10–12 characters" } },
|
|
7172
|
+
// Backend accepts DD-MM-YYYY, DD/MM/YYYY, YYYY-MM-DD or YYYY/MM/DD
|
|
7173
|
+
// (see _normalize_date_str in ivs_run_check.py) — DD-MM-YYYY shown here
|
|
7174
|
+
// since it matches the date format printed on NIN/BVN records.
|
|
7175
|
+
{ match: "DATE OF BIRTH", rule: { pattern: /^\d{2}[-/]\d{2}[-/]\d{4}$|^\d{4}[-/]\d{2}[-/]\d{2}$/, hint: "Format: DD-MM-YYYY (e.g. 15-06-1996)", placeholder: "DD-MM-YYYY" } },
|
|
7176
|
+
{ match: "DOB", rule: { pattern: /^\d{2}[-/]\d{2}[-/]\d{4}$|^\d{4}[-/]\d{2}[-/]\d{2}$/, hint: "Format: DD-MM-YYYY (e.g. 15-06-1996)", placeholder: "DD-MM-YYYY" } }
|
|
7052
7177
|
];
|
|
7053
7178
|
function getFieldRule(label) {
|
|
7054
7179
|
const upper = label.toUpperCase();
|
|
@@ -7063,6 +7188,7 @@ var SmartComplySDK = (() => {
|
|
|
7063
7188
|
const v2 = value.trim();
|
|
7064
7189
|
if (rule.numeric && !/^\d+$/.test(v2)) return `${label} must contain digits only`;
|
|
7065
7190
|
if (rule.alphanumeric && !/^[A-Za-z0-9]+$/.test(v2)) return `${label} must be alphanumeric (letters and digits only)`;
|
|
7191
|
+
if (rule.pattern && !rule.pattern.test(v2)) return rule.hint;
|
|
7066
7192
|
if (rule.minLen && v2.length < rule.minLen) return rule.hint;
|
|
7067
7193
|
if (rule.maxLen && v2.length > rule.maxLen) return rule.hint;
|
|
7068
7194
|
return null;
|
|
@@ -7156,7 +7282,7 @@ var SmartComplySDK = (() => {
|
|
|
7156
7282
|
input.id = inputId;
|
|
7157
7283
|
input.setAttribute("aria-labelledby", labelId);
|
|
7158
7284
|
input.setAttribute("aria-describedby", hintId);
|
|
7159
|
-
input.placeholder = `Enter ${field.label}`;
|
|
7285
|
+
input.placeholder = rule?.placeholder || `Enter ${field.label}`;
|
|
7160
7286
|
input.maxLength = rule?.maxLen ? rule.maxLen + 2 : 50;
|
|
7161
7287
|
if (rule?.numeric) input.inputMode = "numeric";
|
|
7162
7288
|
input.style.cssText = `
|
|
@@ -7256,7 +7382,7 @@ var SmartComplySDK = (() => {
|
|
|
7256
7382
|
}
|
|
7257
7383
|
this.showStep("confirm_identity");
|
|
7258
7384
|
} else {
|
|
7259
|
-
errorEl.textContent = this.verificationResult.message || "We could not verify your details. Please check and try again.";
|
|
7385
|
+
errorEl.textContent = _sanitizeUserMessage(this.verificationResult.message) || "We could not verify your details. Please check and try again.";
|
|
7260
7386
|
errorEl.style.display = "block";
|
|
7261
7387
|
submitBtn.textContent = "Verify & Continue";
|
|
7262
7388
|
submitBtn.disabled = false;
|
|
@@ -7267,11 +7393,11 @@ var SmartComplySDK = (() => {
|
|
|
7267
7393
|
if (Array.isArray(fieldErrors) && fieldErrors.length > 0) {
|
|
7268
7394
|
const firstMsg = fieldErrors[0]?.message || fieldErrors[0]?.detail || "";
|
|
7269
7395
|
errorEl.textContent = _sanitizeUserMessage(firstMsg) || "Please check your details and try again.";
|
|
7270
|
-
} else if (err.
|
|
7271
|
-
errorEl.textContent = "We could not verify those details. Please check your ID number and try again.";
|
|
7272
|
-
} else if (err.
|
|
7396
|
+
} else if (err.errorCode === "VERIFICATION_FAILED") {
|
|
7397
|
+
errorEl.textContent = _sanitizeUserMessage(err.message) || "We could not verify those details. Please check your ID number and try again.";
|
|
7398
|
+
} else if (err.errorCode === "CHANNEL_NOT_CONFIGURED") {
|
|
7273
7399
|
errorEl.textContent = "This ID type is not currently available. Please choose a different option.";
|
|
7274
|
-
} else if (err.
|
|
7400
|
+
} else if (err.errorCode === "INSUFFICIENT_BALANCE") {
|
|
7275
7401
|
errorEl.textContent = "Verification is temporarily unavailable. Please contact support.";
|
|
7276
7402
|
} else {
|
|
7277
7403
|
errorEl.textContent = _sanitizeUserMessage(err.message) || "Something went wrong. Please try again.";
|
|
@@ -7902,9 +8028,10 @@ var SmartComplySDK = (() => {
|
|
|
7902
8028
|
const isDocQuality = /blurry|blur|quality|glare|dark|bright|lighting/i.test(message);
|
|
7903
8029
|
const isExpiredDoc = /document.*expired|expired.*document/i.test(message);
|
|
7904
8030
|
const isFaceMatch = /face.*match|selfie.*match|does not match/i.test(message);
|
|
7905
|
-
const
|
|
7906
|
-
const
|
|
7907
|
-
const
|
|
8031
|
+
const isBillingErr = /wallet|balance|insufficient.*fund|payment.*required/i.test(message);
|
|
8032
|
+
const errorIcon = isCameraErr ? "📷" : isNetworkErr ? "📡" : isAuthErr ? "⏱" : isDocQuality ? "🔍" : isExpiredDoc ? "📅" : isFaceMatch ? "🤳" : isBillingErr ? "⚠️" : "✕";
|
|
8033
|
+
const errorTitle = isCameraErr ? "Camera Access Required" : isNetworkErr ? "Connection Problem" : isAuthErr ? "Session Expired" : isDocQuality ? "Document Photo Unclear" : isExpiredDoc ? "Document Expired" : isFaceMatch ? "Face Match Failed" : isBillingErr ? "Verification Unavailable" : "Verification Unsuccessful";
|
|
8034
|
+
const userMessage = isCameraErr ? "Please allow camera access in your browser settings and try again." : isNetworkErr ? "Check your internet connection and try again." : isAuthErr ? "Your session has expired. Please start again." : isDocQuality ? _sanitizeUserMessage(message) || "Please retake your document photo in good lighting with no glare." : isExpiredDoc ? "The document you submitted has expired. Please use a valid, current ID." : isFaceMatch ? "Your selfie did not match the photo on your ID. Please ensure you are using your own valid document and face the camera directly." : isBillingErr ? "Verification is temporarily unavailable. Please contact support." : _sanitizeUserMessage(message) || "We were unable to complete your verification. Please try again.";
|
|
7908
8035
|
const iconWrap = document.createElement("div");
|
|
7909
8036
|
iconWrap.style.cssText = `
|
|
7910
8037
|
width:72px;height:72px;border-radius:50%;
|