smartcomply-web-sdk 1.0.53 → 1.0.57
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 +57 -13
- package/dist/esm/flow/SmartComplyFlow.js.map +1 -1
- package/dist/flow/SmartComplyFlow.d.ts.map +1 -1
- package/dist/flow/SmartComplyFlow.js +57 -13
- package/dist/flow/SmartComplyFlow.js.map +1 -1
- package/dist/smartcomply.browser.js +31 -13
- package/dist/smartcomply.browser.js.map +2 -2
- package/package.json +1 -1
|
@@ -6536,7 +6536,6 @@ var SmartComplySDK = (() => {
|
|
|
6536
6536
|
"traceback",
|
|
6537
6537
|
"str(e)",
|
|
6538
6538
|
"error:",
|
|
6539
|
-
"failed:",
|
|
6540
6539
|
"django",
|
|
6541
6540
|
"python",
|
|
6542
6541
|
"http ",
|
|
@@ -6548,11 +6547,19 @@ var SmartComplySDK = (() => {
|
|
|
6548
6547
|
"confidence_percentage",
|
|
6549
6548
|
"threshold_percentage",
|
|
6550
6549
|
"polling_fallback",
|
|
6551
|
-
"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"
|
|
6552
6558
|
];
|
|
6553
6559
|
for (const blocked of blocklist) {
|
|
6554
6560
|
if (lower.includes(blocked)) return null;
|
|
6555
6561
|
}
|
|
6562
|
+
if (/failed:\S/i.test(raw)) return null;
|
|
6556
6563
|
if (/[a-z]+_[a-z]+/.test(raw) && !/\s/.test(raw.trim())) return null;
|
|
6557
6564
|
if (raw.trim()[0] === raw.trim()[0].toLowerCase() && /^[a-z]/.test(raw.trim())) return null;
|
|
6558
6565
|
return raw.trim();
|
|
@@ -7161,7 +7168,12 @@ var SmartComplySDK = (() => {
|
|
|
7161
7168
|
{ match: "GHANA", rule: { minLen: 8, maxLen: 20, alphanumeric: true, hint: "Ghana Card number must be 8–20 alphanumeric characters" } },
|
|
7162
7169
|
{ match: "SSNIT", rule: { minLen: 7, maxLen: 15, alphanumeric: true, hint: "SSNIT number must be 7–15 alphanumeric characters" } },
|
|
7163
7170
|
{ match: "TIN", rule: { minLen: 8, maxLen: 20, alphanumeric: true, hint: "TIN must be 8–20 characters" } },
|
|
7164
|
-
{ 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" } }
|
|
7165
7177
|
];
|
|
7166
7178
|
function getFieldRule(label) {
|
|
7167
7179
|
const upper = label.toUpperCase();
|
|
@@ -7176,6 +7188,7 @@ var SmartComplySDK = (() => {
|
|
|
7176
7188
|
const v2 = value.trim();
|
|
7177
7189
|
if (rule.numeric && !/^\d+$/.test(v2)) return `${label} must contain digits only`;
|
|
7178
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;
|
|
7179
7192
|
if (rule.minLen && v2.length < rule.minLen) return rule.hint;
|
|
7180
7193
|
if (rule.maxLen && v2.length > rule.maxLen) return rule.hint;
|
|
7181
7194
|
return null;
|
|
@@ -7269,7 +7282,7 @@ var SmartComplySDK = (() => {
|
|
|
7269
7282
|
input.id = inputId;
|
|
7270
7283
|
input.setAttribute("aria-labelledby", labelId);
|
|
7271
7284
|
input.setAttribute("aria-describedby", hintId);
|
|
7272
|
-
input.placeholder = `Enter ${field.label}`;
|
|
7285
|
+
input.placeholder = rule?.placeholder || `Enter ${field.label}`;
|
|
7273
7286
|
input.maxLength = rule?.maxLen ? rule.maxLen + 2 : 50;
|
|
7274
7287
|
if (rule?.numeric) input.inputMode = "numeric";
|
|
7275
7288
|
input.style.cssText = `
|
|
@@ -7369,7 +7382,7 @@ var SmartComplySDK = (() => {
|
|
|
7369
7382
|
}
|
|
7370
7383
|
this.showStep("confirm_identity");
|
|
7371
7384
|
} else {
|
|
7372
|
-
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.";
|
|
7373
7386
|
errorEl.style.display = "block";
|
|
7374
7387
|
submitBtn.textContent = "Verify & Continue";
|
|
7375
7388
|
submitBtn.disabled = false;
|
|
@@ -7380,11 +7393,11 @@ var SmartComplySDK = (() => {
|
|
|
7380
7393
|
if (Array.isArray(fieldErrors) && fieldErrors.length > 0) {
|
|
7381
7394
|
const firstMsg = fieldErrors[0]?.message || fieldErrors[0]?.detail || "";
|
|
7382
7395
|
errorEl.textContent = _sanitizeUserMessage(firstMsg) || "Please check your details and try again.";
|
|
7383
|
-
} else if (err.
|
|
7384
|
-
errorEl.textContent = "We could not verify those details. Please check your ID number and try again.";
|
|
7385
|
-
} 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") {
|
|
7386
7399
|
errorEl.textContent = "This ID type is not currently available. Please choose a different option.";
|
|
7387
|
-
} else if (err.
|
|
7400
|
+
} else if (err.errorCode === "INSUFFICIENT_BALANCE") {
|
|
7388
7401
|
errorEl.textContent = "Verification is temporarily unavailable. Please contact support.";
|
|
7389
7402
|
} else {
|
|
7390
7403
|
errorEl.textContent = _sanitizeUserMessage(err.message) || "Something went wrong. Please try again.";
|
|
@@ -7615,7 +7628,7 @@ var SmartComplySDK = (() => {
|
|
|
7615
7628
|
return;
|
|
7616
7629
|
}
|
|
7617
7630
|
const entryId = this.livenessEntryId;
|
|
7618
|
-
const MAX_POLLS =
|
|
7631
|
+
const MAX_POLLS = 45;
|
|
7619
7632
|
let polls = 0;
|
|
7620
7633
|
const poll = async () => {
|
|
7621
7634
|
if (this.isDestroyed) return;
|
|
@@ -7650,6 +7663,10 @@ var SmartComplySDK = (() => {
|
|
|
7650
7663
|
this.showStep("document_confirm");
|
|
7651
7664
|
return;
|
|
7652
7665
|
}
|
|
7666
|
+
if (polls === 10 && !this.isDestroyed) {
|
|
7667
|
+
statusEl.textContent = "Still reading your document…";
|
|
7668
|
+
subEl.textContent = "Documents with a back side can take a little longer. Please keep waiting.";
|
|
7669
|
+
}
|
|
7653
7670
|
if (polls < MAX_POLLS && !this.isDestroyed) {
|
|
7654
7671
|
this._ocrPollTimer = setTimeout(poll, 2e3);
|
|
7655
7672
|
} else if (!this.isDestroyed) {
|
|
@@ -8015,9 +8032,10 @@ var SmartComplySDK = (() => {
|
|
|
8015
8032
|
const isDocQuality = /blurry|blur|quality|glare|dark|bright|lighting/i.test(message);
|
|
8016
8033
|
const isExpiredDoc = /document.*expired|expired.*document/i.test(message);
|
|
8017
8034
|
const isFaceMatch = /face.*match|selfie.*match|does not match/i.test(message);
|
|
8018
|
-
const
|
|
8019
|
-
const
|
|
8020
|
-
const
|
|
8035
|
+
const isBillingErr = /wallet|balance|insufficient.*fund|payment.*required/i.test(message);
|
|
8036
|
+
const errorIcon = isCameraErr ? "📷" : isNetworkErr ? "📡" : isAuthErr ? "⏱" : isDocQuality ? "🔍" : isExpiredDoc ? "📅" : isFaceMatch ? "🤳" : isBillingErr ? "⚠️" : "✕";
|
|
8037
|
+
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";
|
|
8038
|
+
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.";
|
|
8021
8039
|
const iconWrap = document.createElement("div");
|
|
8022
8040
|
iconWrap.style.cssText = `
|
|
8023
8041
|
width:72px;height:72px;border-radius:50%;
|