@dynamicore/jumio-sdk 1.0.0 → 1.0.2
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/README.md +238 -160
- package/dist/client-BwEiGMPy.d.mts +515 -0
- package/dist/client-BwEiGMPy.d.ts +515 -0
- package/dist/core/index.d.mts +94 -4
- package/dist/core/index.d.ts +94 -4
- package/dist/core/index.js +545 -125
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +506 -83
- package/dist/core/index.mjs.map +1 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +747 -126
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +706 -83
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.d.mts +146 -2
- package/dist/react/index.d.ts +146 -2
- package/dist/react/index.js +766 -142
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +766 -143
- package/dist/react/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/client-BR1xIZ0X.d.mts +0 -252
- package/dist/client-BR1xIZ0X.d.ts +0 -252
package/dist/index.js
CHANGED
|
@@ -7,86 +7,81 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
|
7
7
|
|
|
8
8
|
var axios__default = /*#__PURE__*/_interopDefault(axios);
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
var
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
rawData;
|
|
15
|
-
code;
|
|
16
|
-
constructor(message, options) {
|
|
17
|
-
super(message);
|
|
18
|
-
this.name = "JumioError";
|
|
19
|
-
this.statusCode = options?.statusCode;
|
|
20
|
-
this.rawData = options?.rawData;
|
|
21
|
-
this.code = options?.code;
|
|
22
|
-
if (options?.cause) {
|
|
23
|
-
this.cause = options.cause;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
var JumioTimeoutError = class extends JumioError {
|
|
28
|
-
constructor(message = "El servicio de verificaci\xF3n de Jumio excedi\xF3 el tiempo l\xEDmite de espera.", rawData) {
|
|
29
|
-
super(message, { code: "TIMEOUT", rawData });
|
|
30
|
-
this.name = "JumioTimeoutError";
|
|
31
|
-
}
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
12
|
+
var __esm = (fn, res) => function __init() {
|
|
13
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
32
14
|
};
|
|
33
|
-
var
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
this.name = "JumioNetworkError";
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
var JumioValidationError = class extends JumioError {
|
|
40
|
-
constructor(message = "El documento no pudo ser validado o fue rechazado por Jumio.", rawData) {
|
|
41
|
-
super(message, { code: "VALIDATION_FAILED", rawData });
|
|
42
|
-
this.name = "JumioValidationError";
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
var JumioImageProcessingError = class extends JumioError {
|
|
46
|
-
constructor(message, cause) {
|
|
47
|
-
super(message, { code: "IMAGE_PROCESSING_ERROR", cause });
|
|
48
|
-
this.name = "JumioImageProcessingError";
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
var JumioPollingTimeoutError = class extends JumioError {
|
|
52
|
-
attempts;
|
|
53
|
-
constructor(attempts, message = "La validaci\xF3n sigue en proceso. Por favor verifica nuevamente m\xE1s tarde.", rawData) {
|
|
54
|
-
super(message, { code: "POLLING_TIMEOUT", rawData });
|
|
55
|
-
this.name = "JumioPollingTimeoutError";
|
|
56
|
-
this.attempts = attempts;
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
var JumioAbortError = class extends JumioError {
|
|
60
|
-
constructor(message = "La operaci\xF3n de validaci\xF3n de Jumio fue cancelada.") {
|
|
61
|
-
super(message, { code: "ABORTED" });
|
|
62
|
-
this.name = "JumioAbortError";
|
|
63
|
-
}
|
|
15
|
+
var __export = (target, all) => {
|
|
16
|
+
for (var name in all)
|
|
17
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
64
18
|
};
|
|
19
|
+
|
|
20
|
+
// src/core/errors.ts
|
|
65
21
|
function isJumioError(error) {
|
|
66
|
-
return error instanceof JumioError || typeof error === "object" && error !== null && "isJumioError" in error && error.isJumioError === true;
|
|
22
|
+
return error instanceof exports.JumioError || typeof error === "object" && error !== null && "isJumioError" in error && error.isJumioError === true;
|
|
67
23
|
}
|
|
24
|
+
exports.JumioError = void 0; exports.JumioTimeoutError = void 0; exports.JumioNetworkError = void 0; exports.JumioValidationError = void 0; exports.JumioImageProcessingError = void 0; exports.JumioPollingTimeoutError = void 0; exports.JumioAbortError = void 0;
|
|
25
|
+
var init_errors = __esm({
|
|
26
|
+
"src/core/errors.ts"() {
|
|
27
|
+
exports.JumioError = class extends Error {
|
|
28
|
+
isJumioError = true;
|
|
29
|
+
statusCode;
|
|
30
|
+
rawData;
|
|
31
|
+
code;
|
|
32
|
+
constructor(message, options) {
|
|
33
|
+
super(message);
|
|
34
|
+
this.name = "JumioError";
|
|
35
|
+
this.statusCode = options?.statusCode;
|
|
36
|
+
this.rawData = options?.rawData;
|
|
37
|
+
this.code = options?.code;
|
|
38
|
+
if (options?.cause) {
|
|
39
|
+
this.cause = options.cause;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
exports.JumioTimeoutError = class extends exports.JumioError {
|
|
44
|
+
constructor(message = "El servicio de verificaci\xF3n de Jumio excedi\xF3 el tiempo l\xEDmite de espera.", rawData) {
|
|
45
|
+
super(message, { code: "TIMEOUT", rawData });
|
|
46
|
+
this.name = "JumioTimeoutError";
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
exports.JumioNetworkError = class extends exports.JumioError {
|
|
50
|
+
constructor(message = "No fue posible comunicarse con los servidores de validaci\xF3n de identidad.", cause) {
|
|
51
|
+
super(message, { code: "NETWORK_ERROR", cause });
|
|
52
|
+
this.name = "JumioNetworkError";
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
exports.JumioValidationError = class extends exports.JumioError {
|
|
56
|
+
constructor(message = "El documento no pudo ser validado o fue rechazado por Jumio.", rawData) {
|
|
57
|
+
super(message, { code: "VALIDATION_FAILED", rawData });
|
|
58
|
+
this.name = "JumioValidationError";
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
exports.JumioImageProcessingError = class extends exports.JumioError {
|
|
62
|
+
constructor(message, cause) {
|
|
63
|
+
super(message, { code: "IMAGE_PROCESSING_ERROR", cause });
|
|
64
|
+
this.name = "JumioImageProcessingError";
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
exports.JumioPollingTimeoutError = class extends exports.JumioError {
|
|
68
|
+
attempts;
|
|
69
|
+
constructor(attempts, message = "La validaci\xF3n sigue en proceso. Por favor verifica nuevamente m\xE1s tarde.", rawData) {
|
|
70
|
+
super(message, { code: "POLLING_TIMEOUT", rawData });
|
|
71
|
+
this.name = "JumioPollingTimeoutError";
|
|
72
|
+
this.attempts = attempts;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
exports.JumioAbortError = class extends exports.JumioError {
|
|
76
|
+
constructor(message = "La operaci\xF3n de validaci\xF3n de Jumio fue cancelada.") {
|
|
77
|
+
super(message, { code: "ABORTED" });
|
|
78
|
+
this.name = "JumioAbortError";
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
});
|
|
68
83
|
|
|
69
84
|
// src/core/envelope.ts
|
|
70
|
-
var FINAL_JUMIO_STATUSES = [
|
|
71
|
-
"PROCESSED",
|
|
72
|
-
"APPROVED_VERIFIED",
|
|
73
|
-
"REJECTED",
|
|
74
|
-
"FAILED",
|
|
75
|
-
"ERROR",
|
|
76
|
-
"DENIED",
|
|
77
|
-
"EXPIRED",
|
|
78
|
-
"ABANDONED",
|
|
79
|
-
"DONE",
|
|
80
|
-
"COMPLETED",
|
|
81
|
-
"NOT_READABLE",
|
|
82
|
-
"FRAUD",
|
|
83
|
-
"UNSUPPORTED_ID_TYPE"
|
|
84
|
-
];
|
|
85
|
-
var APPROVED_JUMIO_STATUSES = [
|
|
86
|
-
"APPROVED_VERIFIED",
|
|
87
|
-
"DONE",
|
|
88
|
-
"COMPLETED"
|
|
89
|
-
];
|
|
90
85
|
function toLowerText(value) {
|
|
91
86
|
return String(value ?? "").trim().toLowerCase();
|
|
92
87
|
}
|
|
@@ -94,10 +89,13 @@ function toUpperText(value) {
|
|
|
94
89
|
return String(value ?? "").trim().toUpperCase();
|
|
95
90
|
}
|
|
96
91
|
function extractEnvelopeData(responseData) {
|
|
97
|
-
if (responseData && typeof responseData === "object"
|
|
98
|
-
const
|
|
99
|
-
if (
|
|
100
|
-
return
|
|
92
|
+
if (responseData && typeof responseData === "object") {
|
|
93
|
+
const obj = responseData;
|
|
94
|
+
if ("data" in obj && obj.data !== void 0) {
|
|
95
|
+
return obj.data;
|
|
96
|
+
}
|
|
97
|
+
if ("values" in obj && obj.values !== void 0) {
|
|
98
|
+
return obj.values;
|
|
101
99
|
}
|
|
102
100
|
}
|
|
103
101
|
return responseData;
|
|
@@ -149,7 +147,7 @@ function extractJumioMessage(source) {
|
|
|
149
147
|
function isFinalJumioStatus(status) {
|
|
150
148
|
const upperStatus = toUpperText(status);
|
|
151
149
|
if (!upperStatus) return false;
|
|
152
|
-
return FINAL_JUMIO_STATUSES.some((s) => s === upperStatus);
|
|
150
|
+
return exports.FINAL_JUMIO_STATUSES.some((s) => s === upperStatus);
|
|
153
151
|
}
|
|
154
152
|
function isApprovedJumioStatus(status) {
|
|
155
153
|
const upperStatus = toUpperText(status);
|
|
@@ -168,12 +166,54 @@ function resolveVerificationValidity(data, fallbackStatus) {
|
|
|
168
166
|
}
|
|
169
167
|
return isApprovedJumioStatus(fallbackStatus);
|
|
170
168
|
}
|
|
169
|
+
function encodeUrlToBase64UrlSafe(url) {
|
|
170
|
+
try {
|
|
171
|
+
let base64;
|
|
172
|
+
if (typeof Buffer !== "undefined") {
|
|
173
|
+
base64 = Buffer.from(url, "utf-8").toString("base64");
|
|
174
|
+
} else if (typeof TextEncoder !== "undefined") {
|
|
175
|
+
const encoder = new TextEncoder();
|
|
176
|
+
const data = encoder.encode(url);
|
|
177
|
+
base64 = btoa(String.fromCharCode(...new Uint8Array(data)));
|
|
178
|
+
} else {
|
|
179
|
+
base64 = btoa(url);
|
|
180
|
+
}
|
|
181
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
182
|
+
} catch {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
exports.FINAL_JUMIO_STATUSES = void 0; exports.APPROVED_JUMIO_STATUSES = void 0;
|
|
187
|
+
var init_envelope = __esm({
|
|
188
|
+
"src/core/envelope.ts"() {
|
|
189
|
+
exports.FINAL_JUMIO_STATUSES = [
|
|
190
|
+
"PROCESSED",
|
|
191
|
+
"APPROVED_VERIFIED",
|
|
192
|
+
"REJECTED",
|
|
193
|
+
"FAILED",
|
|
194
|
+
"ERROR",
|
|
195
|
+
"DENIED",
|
|
196
|
+
"EXPIRED",
|
|
197
|
+
"ABANDONED",
|
|
198
|
+
"DONE",
|
|
199
|
+
"COMPLETED",
|
|
200
|
+
"NOT_READABLE",
|
|
201
|
+
"FRAUD",
|
|
202
|
+
"UNSUPPORTED_ID_TYPE"
|
|
203
|
+
];
|
|
204
|
+
exports.APPROVED_JUMIO_STATUSES = [
|
|
205
|
+
"APPROVED_VERIFIED",
|
|
206
|
+
"DONE",
|
|
207
|
+
"COMPLETED"
|
|
208
|
+
];
|
|
209
|
+
}
|
|
210
|
+
});
|
|
171
211
|
|
|
172
212
|
// src/core/retry.ts
|
|
173
213
|
function delay(ms, signal) {
|
|
174
214
|
return new Promise((resolve, reject) => {
|
|
175
215
|
if (signal?.aborted) {
|
|
176
|
-
return reject(new JumioAbortError());
|
|
216
|
+
return reject(new exports.JumioAbortError());
|
|
177
217
|
}
|
|
178
218
|
const timer = setTimeout(() => {
|
|
179
219
|
signal?.removeEventListener("abort", abortHandler);
|
|
@@ -181,7 +221,7 @@ function delay(ms, signal) {
|
|
|
181
221
|
}, ms);
|
|
182
222
|
const abortHandler = () => {
|
|
183
223
|
clearTimeout(timer);
|
|
184
|
-
reject(new JumioAbortError());
|
|
224
|
+
reject(new exports.JumioAbortError());
|
|
185
225
|
};
|
|
186
226
|
signal?.addEventListener("abort", abortHandler, { once: true });
|
|
187
227
|
});
|
|
@@ -215,14 +255,14 @@ async function withRetry(operation, options = {}) {
|
|
|
215
255
|
let lastError;
|
|
216
256
|
for (let attempt = 1; attempt <= maxRetries; attempt += 1) {
|
|
217
257
|
if (signal?.aborted) {
|
|
218
|
-
throw new JumioAbortError();
|
|
258
|
+
throw new exports.JumioAbortError();
|
|
219
259
|
}
|
|
220
260
|
try {
|
|
221
261
|
return await operation(attempt);
|
|
222
262
|
} catch (error) {
|
|
223
263
|
lastError = error;
|
|
224
264
|
if (signal?.aborted) {
|
|
225
|
-
throw new JumioAbortError();
|
|
265
|
+
throw new exports.JumioAbortError();
|
|
226
266
|
}
|
|
227
267
|
const isLastAttempt = attempt >= maxRetries;
|
|
228
268
|
const isRetryable = shouldRetry(error);
|
|
@@ -239,8 +279,268 @@ async function withRetry(operation, options = {}) {
|
|
|
239
279
|
}
|
|
240
280
|
throw lastError;
|
|
241
281
|
}
|
|
282
|
+
var init_retry = __esm({
|
|
283
|
+
"src/core/retry.ts"() {
|
|
284
|
+
init_envelope();
|
|
285
|
+
init_errors();
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// src/core/webflow.ts
|
|
290
|
+
var webflow_exports = {};
|
|
291
|
+
__export(webflow_exports, {
|
|
292
|
+
buildRedirectUrl: () => buildRedirectUrl,
|
|
293
|
+
parseWebflowReturnParams: () => parseWebflowReturnParams,
|
|
294
|
+
pollWebflowStatus: () => pollWebflowStatus,
|
|
295
|
+
resolveWebflowResult: () => resolveWebflowResult,
|
|
296
|
+
startWebflowSession: () => startWebflowSession
|
|
297
|
+
});
|
|
298
|
+
function buildRedirectUrl(returnUrl, proxyUrl) {
|
|
299
|
+
if (!proxyUrl) {
|
|
300
|
+
return returnUrl;
|
|
301
|
+
}
|
|
302
|
+
const encoded = encodeUrlToBase64UrlSafe(returnUrl);
|
|
303
|
+
if (!encoded) {
|
|
304
|
+
throw new exports.JumioValidationError(
|
|
305
|
+
`No fue posible codificar la URL de retorno: "${returnUrl}"`
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
const normalizedProxy = proxyUrl.endsWith("/") ? proxyUrl : `${proxyUrl}/`;
|
|
309
|
+
return `${normalizedProxy}${encoded}`;
|
|
310
|
+
}
|
|
311
|
+
function parseWebflowReturnParams(source) {
|
|
312
|
+
let searchString;
|
|
313
|
+
if (!source) {
|
|
314
|
+
if (typeof window !== "undefined" && window.location) {
|
|
315
|
+
searchString = window.location.search;
|
|
316
|
+
} else {
|
|
317
|
+
return { allParams: {} };
|
|
318
|
+
}
|
|
319
|
+
} else if (typeof source === "string") {
|
|
320
|
+
const questionIdx = source.indexOf("?");
|
|
321
|
+
searchString = questionIdx >= 0 ? source.slice(questionIdx) : "";
|
|
322
|
+
} else if (source instanceof URLSearchParams) {
|
|
323
|
+
searchString = `?${source.toString()}`;
|
|
324
|
+
} else {
|
|
325
|
+
const hrefSearch = source.href ? (() => {
|
|
326
|
+
try {
|
|
327
|
+
return new URL(source.href).search;
|
|
328
|
+
} catch {
|
|
329
|
+
return "";
|
|
330
|
+
}
|
|
331
|
+
})() : "";
|
|
332
|
+
searchString = source.search ?? hrefSearch;
|
|
333
|
+
}
|
|
334
|
+
const params = new URLSearchParams(searchString);
|
|
335
|
+
const allParams = {};
|
|
336
|
+
params.forEach((value, key) => {
|
|
337
|
+
allParams[key] = value;
|
|
338
|
+
});
|
|
339
|
+
const accountId = params.get("accountId") ?? void 0;
|
|
340
|
+
let workflowId = params.get("workflowExecutionId") ?? params.get("workflowId") ?? void 0;
|
|
341
|
+
const rawStatus = params.get("status") ?? void 0;
|
|
342
|
+
if (rawStatus && (!accountId || !workflowId)) {
|
|
343
|
+
const statusParts = rawStatus.split("?");
|
|
344
|
+
const nestedSearch = statusParts.length > 1 ? `?${statusParts.slice(1).join("?")}` : "";
|
|
345
|
+
if (nestedSearch && nestedSearch !== "?") {
|
|
346
|
+
const nestedParams = new URLSearchParams(nestedSearch);
|
|
347
|
+
nestedParams.forEach((value, key) => {
|
|
348
|
+
if (!allParams[key]) allParams[key] = value;
|
|
349
|
+
});
|
|
350
|
+
if (!workflowId) {
|
|
351
|
+
workflowId = nestedParams.get("workflowExecutionId") ?? nestedParams.get("workflowId") ?? workflowId;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return {
|
|
356
|
+
accountId: accountId || void 0,
|
|
357
|
+
workflowId: workflowId || void 0,
|
|
358
|
+
rawStatus,
|
|
359
|
+
allParams
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
function resolveWebflowResult(rawData, accountId, workflowId) {
|
|
363
|
+
if (!rawData || typeof rawData !== "object") return null;
|
|
364
|
+
const data = rawData;
|
|
365
|
+
if (data.valid === true) {
|
|
366
|
+
return {
|
|
367
|
+
valid: true,
|
|
368
|
+
status: String(data.workflowStatus ?? data.status ?? "APPROVED_VERIFIED"),
|
|
369
|
+
decision: data.decision,
|
|
370
|
+
extraction: data.extraction,
|
|
371
|
+
accountId,
|
|
372
|
+
workflowId,
|
|
373
|
+
data: rawData
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
if (data.valid === false) {
|
|
377
|
+
return {
|
|
378
|
+
valid: false,
|
|
379
|
+
status: String(data.workflowStatus ?? data.status ?? "REJECTED"),
|
|
380
|
+
decision: data.decision,
|
|
381
|
+
accountId,
|
|
382
|
+
workflowId,
|
|
383
|
+
data: rawData,
|
|
384
|
+
errorMessage: extractJumioMessage(rawData) || "El documento fue rechazado durante la verificacion."
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
const capData = data;
|
|
388
|
+
const decisionType = capData?.decision?.type;
|
|
389
|
+
const extractionArr = capData?.capabilities?.extraction ?? [];
|
|
390
|
+
const extraction = extractionArr[0];
|
|
391
|
+
const isExtractionEmpty = extraction !== void 0 && Object.keys(extraction).length === 0;
|
|
392
|
+
if (decisionType === "REJECTED") {
|
|
393
|
+
return {
|
|
394
|
+
valid: false,
|
|
395
|
+
status: "REJECTED",
|
|
396
|
+
decision: decisionType,
|
|
397
|
+
accountId,
|
|
398
|
+
workflowId,
|
|
399
|
+
data: rawData,
|
|
400
|
+
errorMessage: extractJumioMessage(rawData) || "El documento fue rechazado por Jumio."
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
if (extraction && !isExtractionEmpty) {
|
|
404
|
+
const isApproved = decisionType === "PASSED" || decisionType === "WARNING";
|
|
405
|
+
return {
|
|
406
|
+
valid: isApproved,
|
|
407
|
+
status: isApproved ? decisionType ?? "PASSED" : decisionType ?? "REJECTED",
|
|
408
|
+
decision: decisionType,
|
|
409
|
+
extraction,
|
|
410
|
+
accountId,
|
|
411
|
+
workflowId,
|
|
412
|
+
data: rawData,
|
|
413
|
+
...!isApproved ? {
|
|
414
|
+
errorMessage: extractJumioMessage(rawData) || "La verificacion no fue aprobada."
|
|
415
|
+
} : {}
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
return null;
|
|
419
|
+
}
|
|
420
|
+
async function pollWebflowStatus(http, params, options = {}) {
|
|
421
|
+
const config = http.getConfig();
|
|
422
|
+
const maxAttempts = options.maxAttempts ?? config.maxPollingAttempts ?? 20;
|
|
423
|
+
const intervalMs = options.pollingIntervalMs ?? config.pollingIntervalMs ?? 1e4;
|
|
424
|
+
const signal = options.signal;
|
|
425
|
+
let lastRawData = {};
|
|
426
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
427
|
+
if (signal?.aborted) {
|
|
428
|
+
throw new exports.JumioAbortError();
|
|
429
|
+
}
|
|
430
|
+
const responseData = await withRetry(
|
|
431
|
+
() => http.getVerificationStatus(params.accountId, params.workflowId, {
|
|
432
|
+
signal,
|
|
433
|
+
timeout: config.statusTimeout,
|
|
434
|
+
clientId: params.clientId
|
|
435
|
+
}),
|
|
436
|
+
{
|
|
437
|
+
maxRetries: config.maxRetries ?? 3,
|
|
438
|
+
initialDelayMs: config.retryDelayMs ?? 800,
|
|
439
|
+
signal
|
|
440
|
+
}
|
|
441
|
+
);
|
|
442
|
+
const firstLevel = extractEnvelopeData(responseData);
|
|
443
|
+
const statusData = extractNestedData(firstLevel) ?? {};
|
|
444
|
+
lastRawData = statusData;
|
|
445
|
+
options.onAttempt?.(attempt, maxAttempts, statusData);
|
|
446
|
+
const result = resolveWebflowResult(
|
|
447
|
+
statusData,
|
|
448
|
+
params.accountId,
|
|
449
|
+
params.workflowId
|
|
450
|
+
);
|
|
451
|
+
if (result !== null) {
|
|
452
|
+
return result;
|
|
453
|
+
}
|
|
454
|
+
if (attempt < maxAttempts) {
|
|
455
|
+
await delay(intervalMs, signal);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
const lastMessage = extractJumioMessage(lastRawData) || "La verificacion Jumio sigue en proceso. Intenta nuevamente en unos momentos.";
|
|
459
|
+
throw new exports.JumioPollingTimeoutError(maxAttempts, lastMessage, lastRawData);
|
|
460
|
+
}
|
|
461
|
+
async function startWebflowSession(http, config, input) {
|
|
462
|
+
const {
|
|
463
|
+
clientId,
|
|
464
|
+
successUrl,
|
|
465
|
+
errorUrl,
|
|
466
|
+
useRedirectProxy = false,
|
|
467
|
+
autoRedirect = false,
|
|
468
|
+
openInNewTab = false,
|
|
469
|
+
signal
|
|
470
|
+
} = input;
|
|
471
|
+
if (!clientId?.trim()) {
|
|
472
|
+
throw new exports.JumioValidationError(
|
|
473
|
+
"Se requiere un identificador de cliente valido (clientId)."
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
if (!successUrl?.trim()) {
|
|
477
|
+
throw new exports.JumioValidationError("Se requiere la URL de exito (successUrl).");
|
|
478
|
+
}
|
|
479
|
+
if (!errorUrl?.trim()) {
|
|
480
|
+
throw new exports.JumioValidationError("Se requiere la URL de error (errorUrl).");
|
|
481
|
+
}
|
|
482
|
+
if (signal?.aborted) {
|
|
483
|
+
throw new exports.JumioAbortError();
|
|
484
|
+
}
|
|
485
|
+
const proxyUrl = useRedirectProxy ? config.redirectProxyUrl ?? void 0 : void 0;
|
|
486
|
+
const finalSuccessUrl = buildRedirectUrl(successUrl, proxyUrl);
|
|
487
|
+
const finalErrorUrl = buildRedirectUrl(errorUrl, proxyUrl);
|
|
488
|
+
try {
|
|
489
|
+
const responseData = await withRetry(
|
|
490
|
+
() => http.postVerification(
|
|
491
|
+
{
|
|
492
|
+
client: clientId.trim(),
|
|
493
|
+
successUrl: finalSuccessUrl,
|
|
494
|
+
errorUrl: finalErrorUrl
|
|
495
|
+
},
|
|
496
|
+
{ signal, timeout: config.requestTimeout }
|
|
497
|
+
),
|
|
498
|
+
{
|
|
499
|
+
maxRetries: config.maxRetries ?? 3,
|
|
500
|
+
initialDelayMs: config.retryDelayMs ?? 800,
|
|
501
|
+
signal
|
|
502
|
+
}
|
|
503
|
+
);
|
|
504
|
+
const firstLevel = extractEnvelopeData(responseData);
|
|
505
|
+
const payload = extractNestedData(firstLevel) ?? {};
|
|
506
|
+
const href = payload?.href;
|
|
507
|
+
if (!href) {
|
|
508
|
+
throw new exports.JumioError(
|
|
509
|
+
extractJumioMessage(payload) || "El backend no devolvio la URL de verificacion de Jumio (href).",
|
|
510
|
+
{ rawData: payload }
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
const result = {
|
|
514
|
+
href,
|
|
515
|
+
accountId: payload?.accountId,
|
|
516
|
+
workflowId: payload?.workflowId,
|
|
517
|
+
data: payload
|
|
518
|
+
};
|
|
519
|
+
if (typeof window !== "undefined") {
|
|
520
|
+
if (openInNewTab) {
|
|
521
|
+
const win = window.open(href, "_blank");
|
|
522
|
+
if (!win || win.closed || typeof win.closed === "undefined") {
|
|
523
|
+
window.location.href = href;
|
|
524
|
+
}
|
|
525
|
+
} else if (autoRedirect) {
|
|
526
|
+
window.location.href = href;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
return result;
|
|
530
|
+
} catch (err) {
|
|
531
|
+
throw err;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
var init_webflow = __esm({
|
|
535
|
+
"src/core/webflow.ts"() {
|
|
536
|
+
init_envelope();
|
|
537
|
+
init_errors();
|
|
538
|
+
init_retry();
|
|
539
|
+
}
|
|
540
|
+
});
|
|
242
541
|
|
|
243
542
|
// src/core/image.ts
|
|
543
|
+
init_errors();
|
|
244
544
|
function stripDataUrlPrefix(dataUrl) {
|
|
245
545
|
if (!dataUrl) return "";
|
|
246
546
|
const commaIndex = dataUrl.indexOf(",");
|
|
@@ -278,7 +578,7 @@ function blobToBase64(blob) {
|
|
|
278
578
|
blob.arrayBuffer().then((buffer) => {
|
|
279
579
|
resolve(arrayBufferToBase64(buffer));
|
|
280
580
|
}).catch(
|
|
281
|
-
(err) => reject(new JumioImageProcessingError("No se pudo leer el archivo binario.", err))
|
|
581
|
+
(err) => reject(new exports.JumioImageProcessingError("No se pudo leer el archivo binario.", err))
|
|
282
582
|
);
|
|
283
583
|
return;
|
|
284
584
|
}
|
|
@@ -287,7 +587,7 @@ function blobToBase64(blob) {
|
|
|
287
587
|
const dataUrl = String(reader.result ?? "");
|
|
288
588
|
resolve(stripDataUrlPrefix(dataUrl));
|
|
289
589
|
};
|
|
290
|
-
reader.onerror = () => reject(new JumioImageProcessingError("No se pudo convertir la imagen a base64.", reader.error));
|
|
590
|
+
reader.onerror = () => reject(new exports.JumioImageProcessingError("No se pudo convertir la imagen a base64.", reader.error));
|
|
291
591
|
reader.readAsDataURL(blob);
|
|
292
592
|
});
|
|
293
593
|
}
|
|
@@ -306,7 +606,7 @@ function arrayBufferToBase64(buffer) {
|
|
|
306
606
|
}
|
|
307
607
|
async function fetchUrlAsBase64(url, signal) {
|
|
308
608
|
if (signal?.aborted) {
|
|
309
|
-
throw new JumioAbortError();
|
|
609
|
+
throw new exports.JumioAbortError();
|
|
310
610
|
}
|
|
311
611
|
const trimmed = url.trim();
|
|
312
612
|
if (trimmed.startsWith("data:")) {
|
|
@@ -315,7 +615,7 @@ async function fetchUrlAsBase64(url, signal) {
|
|
|
315
615
|
try {
|
|
316
616
|
const response = await fetch(trimmed, { signal });
|
|
317
617
|
if (!response.ok) {
|
|
318
|
-
throw new JumioImageProcessingError(
|
|
618
|
+
throw new exports.JumioImageProcessingError(
|
|
319
619
|
`No se pudo descargar la imagen desde la URL remota (HTTP ${response.status}).`
|
|
320
620
|
);
|
|
321
621
|
}
|
|
@@ -323,12 +623,12 @@ async function fetchUrlAsBase64(url, signal) {
|
|
|
323
623
|
return await blobToBase64(blob);
|
|
324
624
|
} catch (error) {
|
|
325
625
|
if (signal?.aborted || error instanceof Error && error.name === "AbortError") {
|
|
326
|
-
throw new JumioAbortError();
|
|
626
|
+
throw new exports.JumioAbortError();
|
|
327
627
|
}
|
|
328
|
-
if (error instanceof JumioImageProcessingError) {
|
|
628
|
+
if (error instanceof exports.JumioImageProcessingError) {
|
|
329
629
|
throw error;
|
|
330
630
|
}
|
|
331
|
-
throw new JumioImageProcessingError(
|
|
631
|
+
throw new exports.JumioImageProcessingError(
|
|
332
632
|
`Error al descargar o procesar la imagen desde la URL: ${url}`,
|
|
333
633
|
error
|
|
334
634
|
);
|
|
@@ -336,10 +636,10 @@ async function fetchUrlAsBase64(url, signal) {
|
|
|
336
636
|
}
|
|
337
637
|
async function resolveImageSourceToBase64(source, s3Signer, signal) {
|
|
338
638
|
if (signal?.aborted) {
|
|
339
|
-
throw new JumioAbortError();
|
|
639
|
+
throw new exports.JumioAbortError();
|
|
340
640
|
}
|
|
341
641
|
if (!source) {
|
|
342
|
-
throw new JumioImageProcessingError("No se proporcion\xF3 una imagen v\xE1lida para la verificaci\xF3n.");
|
|
642
|
+
throw new exports.JumioImageProcessingError("No se proporcion\xF3 una imagen v\xE1lida para la verificaci\xF3n.");
|
|
343
643
|
}
|
|
344
644
|
if (typeof Blob !== "undefined" && source instanceof Blob) {
|
|
345
645
|
return blobToBase64(source);
|
|
@@ -356,7 +656,7 @@ async function resolveImageSourceToBase64(source, s3Signer, signal) {
|
|
|
356
656
|
if (typeof source === "string") {
|
|
357
657
|
const text = source.trim();
|
|
358
658
|
if (!text) {
|
|
359
|
-
throw new JumioImageProcessingError("La ruta o contenido de la imagen est\xE1 vac\xEDo.");
|
|
659
|
+
throw new exports.JumioImageProcessingError("La ruta o contenido de la imagen est\xE1 vac\xEDo.");
|
|
360
660
|
}
|
|
361
661
|
if (text.startsWith("data:")) {
|
|
362
662
|
return stripDataUrlPrefix(text);
|
|
@@ -381,7 +681,7 @@ async function resolveImageSourceToBase64(source, s3Signer, signal) {
|
|
|
381
681
|
return await fetchUrlAsBase64(signedUrl, signal);
|
|
382
682
|
}
|
|
383
683
|
} catch (err) {
|
|
384
|
-
throw new JumioImageProcessingError(
|
|
684
|
+
throw new exports.JumioImageProcessingError(
|
|
385
685
|
`No se pudo firmar la ruta de almacenamiento S3: ${text}`,
|
|
386
686
|
err
|
|
387
687
|
);
|
|
@@ -390,12 +690,16 @@ async function resolveImageSourceToBase64(source, s3Signer, signal) {
|
|
|
390
690
|
if (isBase64String(text)) {
|
|
391
691
|
return stripDataUrlPrefix(text);
|
|
392
692
|
}
|
|
393
|
-
throw new JumioImageProcessingError(
|
|
693
|
+
throw new exports.JumioImageProcessingError(
|
|
394
694
|
`Formato de imagen no reconocido o ruta inv\xE1lida: ${text.slice(0, 50)}...`
|
|
395
695
|
);
|
|
396
696
|
}
|
|
397
|
-
throw new JumioImageProcessingError("Tipo de dato de imagen no soportado.");
|
|
697
|
+
throw new exports.JumioImageProcessingError("Tipo de dato de imagen no soportado.");
|
|
398
698
|
}
|
|
699
|
+
|
|
700
|
+
// src/core/http.ts
|
|
701
|
+
init_errors();
|
|
702
|
+
init_envelope();
|
|
399
703
|
var JumioHttpClient = class {
|
|
400
704
|
client;
|
|
401
705
|
config;
|
|
@@ -453,7 +757,7 @@ var JumioHttpClient = class {
|
|
|
453
757
|
* Normaliza cualquier error de Axios a una excepción tipada JumioError.
|
|
454
758
|
*/
|
|
455
759
|
normalizeError(error) {
|
|
456
|
-
if (error instanceof JumioError) {
|
|
760
|
+
if (error instanceof exports.JumioError) {
|
|
457
761
|
return error;
|
|
458
762
|
}
|
|
459
763
|
if (axios__default.default.isAxiosError(error)) {
|
|
@@ -462,18 +766,18 @@ var JumioHttpClient = class {
|
|
|
462
766
|
const responseData = axiosErr.response?.data;
|
|
463
767
|
const serverMessage = extractJumioMessage(responseData) || extractJumioMessage(axiosErr);
|
|
464
768
|
if (axiosErr.code === "ECONNABORTED" || axiosErr.code === "ETIMEDOUT") {
|
|
465
|
-
return new JumioTimeoutError(
|
|
769
|
+
return new exports.JumioTimeoutError(
|
|
466
770
|
serverMessage || "La solicitud al servicio de Jumio excedi\xF3 el tiempo l\xEDmite.",
|
|
467
771
|
responseData
|
|
468
772
|
);
|
|
469
773
|
}
|
|
470
774
|
if (!axiosErr.response) {
|
|
471
|
-
return new JumioNetworkError(
|
|
775
|
+
return new exports.JumioNetworkError(
|
|
472
776
|
serverMessage || "No fue posible comunicarse con el servicio de Jumio.",
|
|
473
777
|
axiosErr
|
|
474
778
|
);
|
|
475
779
|
}
|
|
476
|
-
return new JumioError(serverMessage || `Error en la solicitud HTTP (${status}).`, {
|
|
780
|
+
return new exports.JumioError(serverMessage || `Error en la solicitud HTTP (${status}).`, {
|
|
477
781
|
statusCode: status,
|
|
478
782
|
rawData: responseData,
|
|
479
783
|
code: axiosErr.code,
|
|
@@ -482,18 +786,18 @@ var JumioHttpClient = class {
|
|
|
482
786
|
}
|
|
483
787
|
if (error instanceof Error) {
|
|
484
788
|
if (error.name === "AbortError") {
|
|
485
|
-
return new JumioAbortError();
|
|
789
|
+
return new exports.JumioAbortError();
|
|
486
790
|
}
|
|
487
|
-
return new JumioError(error.message, { cause: error });
|
|
791
|
+
return new exports.JumioError(error.message, { cause: error });
|
|
488
792
|
}
|
|
489
|
-
return new JumioError("Ocurri\xF3 un error inesperado al contactar a Jumio.");
|
|
793
|
+
return new exports.JumioError("Ocurri\xF3 un error inesperado al contactar a Jumio.");
|
|
490
794
|
}
|
|
491
795
|
/**
|
|
492
796
|
* Ejecuta una petición POST al endpoint de Jumio para iniciar o procesar la verificación.
|
|
493
797
|
*/
|
|
494
798
|
async postVerification(payload, options) {
|
|
495
799
|
if (options?.signal?.aborted) {
|
|
496
|
-
throw new JumioAbortError();
|
|
800
|
+
throw new exports.JumioAbortError();
|
|
497
801
|
}
|
|
498
802
|
try {
|
|
499
803
|
const dynamicHeaders = await this.resolveHeaders();
|
|
@@ -511,21 +815,26 @@ var JumioHttpClient = class {
|
|
|
511
815
|
}
|
|
512
816
|
/**
|
|
513
817
|
* Ejecuta una petición GET para consultar el estado actual de una verificación de INE.
|
|
818
|
+
* Soporta un `clientId` opcional requerido por algunos endpoints de DynamiCore (p. ej. Hosted Webflow).
|
|
514
819
|
*/
|
|
515
820
|
async getVerificationStatus(accountId, workflowId, options) {
|
|
516
821
|
if (options?.signal?.aborted) {
|
|
517
|
-
throw new JumioAbortError();
|
|
822
|
+
throw new exports.JumioAbortError();
|
|
518
823
|
}
|
|
519
824
|
try {
|
|
520
825
|
const dynamicHeaders = await this.resolveHeaders();
|
|
521
826
|
const endpoint = this.config.endpoint || "/marketplace/apps/jumio";
|
|
522
827
|
const timeout = options?.timeout ?? this.config.statusTimeout ?? 12e4;
|
|
828
|
+
const queryParams = {
|
|
829
|
+
type: "ine",
|
|
830
|
+
accountId,
|
|
831
|
+
workflowId
|
|
832
|
+
};
|
|
833
|
+
if (options?.clientId) {
|
|
834
|
+
queryParams.clientId = options.clientId;
|
|
835
|
+
}
|
|
523
836
|
const response = await this.client.get(endpoint, {
|
|
524
|
-
params:
|
|
525
|
-
type: "ine",
|
|
526
|
-
accountId,
|
|
527
|
-
workflowId
|
|
528
|
-
},
|
|
837
|
+
params: queryParams,
|
|
529
838
|
headers: dynamicHeaders,
|
|
530
839
|
timeout,
|
|
531
840
|
signal: options?.signal
|
|
@@ -541,6 +850,9 @@ var JumioHttpClient = class {
|
|
|
541
850
|
};
|
|
542
851
|
|
|
543
852
|
// src/core/polling.ts
|
|
853
|
+
init_envelope();
|
|
854
|
+
init_errors();
|
|
855
|
+
init_retry();
|
|
544
856
|
async function pollJumioStatus(http, accountId, workflowId, options = {}) {
|
|
545
857
|
const config = http.getConfig();
|
|
546
858
|
const maxAttempts = options.maxAttempts ?? config.maxPollingAttempts ?? 20;
|
|
@@ -549,7 +861,7 @@ async function pollJumioStatus(http, accountId, workflowId, options = {}) {
|
|
|
549
861
|
let lastData = {};
|
|
550
862
|
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
551
863
|
if (signal?.aborted) {
|
|
552
|
-
throw new JumioAbortError();
|
|
864
|
+
throw new exports.JumioAbortError();
|
|
553
865
|
}
|
|
554
866
|
const responseData = await withRetry(
|
|
555
867
|
() => http.getVerificationStatus(accountId, workflowId, {
|
|
@@ -593,10 +905,14 @@ async function pollJumioStatus(http, accountId, workflowId, options = {}) {
|
|
|
593
905
|
}
|
|
594
906
|
}
|
|
595
907
|
const lastMessage = extractJumioMessage(lastData) || "La validaci\xF3n de INE sigue en proceso. Intenta nuevamente en unos momentos.";
|
|
596
|
-
throw new JumioPollingTimeoutError(maxAttempts, lastMessage, lastData);
|
|
908
|
+
throw new exports.JumioPollingTimeoutError(maxAttempts, lastMessage, lastData);
|
|
597
909
|
}
|
|
598
910
|
|
|
599
911
|
// src/core/client.ts
|
|
912
|
+
init_envelope();
|
|
913
|
+
init_errors();
|
|
914
|
+
init_retry();
|
|
915
|
+
init_webflow();
|
|
600
916
|
var JumioClient = class {
|
|
601
917
|
http;
|
|
602
918
|
config;
|
|
@@ -610,10 +926,10 @@ var JumioClient = class {
|
|
|
610
926
|
async startIneVerification(params) {
|
|
611
927
|
const { clientId, frontImage, backImage, signal, onProgress } = params;
|
|
612
928
|
if (!clientId || !clientId.trim()) {
|
|
613
|
-
throw new JumioValidationError("Se requiere un identificador de cliente v\xE1lido (clientId).");
|
|
929
|
+
throw new exports.JumioValidationError("Se requiere un identificador de cliente v\xE1lido (clientId).");
|
|
614
930
|
}
|
|
615
931
|
if (signal?.aborted) {
|
|
616
|
-
throw new JumioAbortError();
|
|
932
|
+
throw new exports.JumioAbortError();
|
|
617
933
|
}
|
|
618
934
|
onProgress?.("RESOLVING_IMAGES", 10);
|
|
619
935
|
const [frontBase64, backBase64] = await Promise.all([
|
|
@@ -621,7 +937,7 @@ var JumioClient = class {
|
|
|
621
937
|
resolveImageSourceToBase64(backImage, this.config.s3Signer, signal)
|
|
622
938
|
]);
|
|
623
939
|
if (signal?.aborted) {
|
|
624
|
-
throw new JumioAbortError();
|
|
940
|
+
throw new exports.JumioAbortError();
|
|
625
941
|
}
|
|
626
942
|
onProgress?.("SENDING_PAYLOAD", 40);
|
|
627
943
|
const payload = {
|
|
@@ -709,7 +1025,7 @@ var JumioClient = class {
|
|
|
709
1025
|
const workflowId = String(startData?.workflowId ?? "").trim();
|
|
710
1026
|
if (!accountId || !workflowId) {
|
|
711
1027
|
const errorMessage = extractJumioMessage(startData) || "No fue posible obtener los identificadores de seguimiento de la validaci\xF3n.";
|
|
712
|
-
const error = new JumioError(errorMessage, { rawData: startData });
|
|
1028
|
+
const error = new exports.JumioError(errorMessage, { rawData: startData });
|
|
713
1029
|
onStatusError?.(error);
|
|
714
1030
|
throw error;
|
|
715
1031
|
}
|
|
@@ -736,10 +1052,110 @@ var JumioClient = class {
|
|
|
736
1052
|
onStatusResolved?.(finalResult);
|
|
737
1053
|
return finalResult;
|
|
738
1054
|
}
|
|
1055
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1056
|
+
// Hosted Webflow (Redirección)
|
|
1057
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
1058
|
+
/**
|
|
1059
|
+
* Construye la URL de redirección de retorno para el flujo Hosted Webflow.
|
|
1060
|
+
*
|
|
1061
|
+
* Si el cliente está configurado con un `redirectProxyUrl` y `useProxy` es `true`,
|
|
1062
|
+
* la URL de retorno se codifica en Base64 URL-safe y se adjunta al proxy.
|
|
1063
|
+
*
|
|
1064
|
+
* @param returnUrl URL de la aplicación a la que Jumio redirigirá tras la verificación.
|
|
1065
|
+
* @param useProxy Si es `true` y hay `redirectProxyUrl` configurado, usa el proxy.
|
|
1066
|
+
* @returns URL de redirección construida.
|
|
1067
|
+
*/
|
|
1068
|
+
buildRedirectUrl(returnUrl, useProxy = false) {
|
|
1069
|
+
const proxyUrl = useProxy ? this.config.redirectProxyUrl ?? void 0 : void 0;
|
|
1070
|
+
return buildRedirectUrl(returnUrl, proxyUrl);
|
|
1071
|
+
}
|
|
1072
|
+
/**
|
|
1073
|
+
* Inicia el flujo Hosted Webflow solicitando al backend de DynamiCore la URL
|
|
1074
|
+
* de verificación de Jumio (`href`).
|
|
1075
|
+
*
|
|
1076
|
+
* El usuario debe ser redirigido a esa URL para completar la verificación en la
|
|
1077
|
+
* página oficial de Jumio. Al terminar, Jumio redirige de vuelta a la aplicación
|
|
1078
|
+
* con `accountId` y `workflowExecutionId` como query params.
|
|
1079
|
+
*
|
|
1080
|
+
* @param input Parámetros del flujo: `clientId`, `successUrl`, `errorUrl`, opciones de proxy y redirección.
|
|
1081
|
+
* @returns `StartWebflowResult` con la URL de Jumio (`href`) y datos adicionales.
|
|
1082
|
+
*
|
|
1083
|
+
* @example
|
|
1084
|
+
* ```ts
|
|
1085
|
+
* const { href } = await client.startWebflow({
|
|
1086
|
+
* clientId: "usr_123",
|
|
1087
|
+
* successUrl: "https://app.example.com/verify/success",
|
|
1088
|
+
* errorUrl: "https://app.example.com/verify/error",
|
|
1089
|
+
* });
|
|
1090
|
+
* window.location.href = href;
|
|
1091
|
+
* ```
|
|
1092
|
+
*/
|
|
1093
|
+
async startWebflow(input) {
|
|
1094
|
+
return startWebflowSession(this.http, this.config, input);
|
|
1095
|
+
}
|
|
1096
|
+
/**
|
|
1097
|
+
* Extrae los parámetros de seguimiento de Jumio de la URL de retorno.
|
|
1098
|
+
*
|
|
1099
|
+
* Jumio añade `accountId` y `workflowExecutionId` (o `workflowId`) como query
|
|
1100
|
+
* params al redirigir de vuelta a la aplicación tras la verificación.
|
|
1101
|
+
*
|
|
1102
|
+
* @param source URL completa, `URLSearchParams`, objeto con `search`/`href`, o nada para leer `window.location`.
|
|
1103
|
+
* @returns `WebflowReturnParams` con `accountId`, `workflowId`, `rawStatus` y todos los params.
|
|
1104
|
+
*
|
|
1105
|
+
* @example En React, en el componente de retorno:
|
|
1106
|
+
* ```ts
|
|
1107
|
+
* const { accountId, workflowId } = client.parseWebflowReturnParams(window.location.href);
|
|
1108
|
+
* ```
|
|
1109
|
+
*/
|
|
1110
|
+
parseWebflowReturnParams(source) {
|
|
1111
|
+
return parseWebflowReturnParams(source);
|
|
1112
|
+
}
|
|
1113
|
+
/**
|
|
1114
|
+
* Consulta una única vez el estado actual de la verificación del flujo Hosted Webflow.
|
|
1115
|
+
*
|
|
1116
|
+
* @param input Parámetros de consulta: `accountId`, `workflowId`, y `clientId` opcional.
|
|
1117
|
+
* @returns `WebflowResult | null` — `null` si la verificación aún está pendiente.
|
|
1118
|
+
*/
|
|
1119
|
+
async getWebflowStatus(input) {
|
|
1120
|
+
const { accountId, workflowId, clientId, signal } = input;
|
|
1121
|
+
const responseData = await this.http.getVerificationStatus(accountId, workflowId, {
|
|
1122
|
+
signal,
|
|
1123
|
+
timeout: this.config.statusTimeout,
|
|
1124
|
+
clientId
|
|
1125
|
+
});
|
|
1126
|
+
const firstLevel = extractEnvelopeData(responseData);
|
|
1127
|
+
const statusData = extractNestedData(firstLevel) ?? {};
|
|
1128
|
+
const { resolveWebflowResult: resolveWebflowResult2 } = await Promise.resolve().then(() => (init_webflow(), webflow_exports));
|
|
1129
|
+
return resolveWebflowResult2(statusData, accountId, workflowId);
|
|
1130
|
+
}
|
|
1131
|
+
/**
|
|
1132
|
+
* Sondea periódicamente el estado de verificación de un flujo Hosted Webflow de Jumio.
|
|
1133
|
+
*
|
|
1134
|
+
* Continúa consultando hasta obtener un resultado definitivo o agotar los intentos.
|
|
1135
|
+
*
|
|
1136
|
+
* @param params `accountId`, `workflowId` y `clientId` opcional.
|
|
1137
|
+
* @param options Opciones de sondeo (`maxAttempts`, `pollingIntervalMs`, `signal`, `onAttempt`).
|
|
1138
|
+
* @returns `WebflowResult` con el resultado definitivo.
|
|
1139
|
+
*
|
|
1140
|
+
* @example
|
|
1141
|
+
* ```ts
|
|
1142
|
+
* // En el componente de retorno, tras leer los params de la URL:
|
|
1143
|
+
* const result = await client.pollWebflowStatus({ accountId, workflowId, clientId });
|
|
1144
|
+
* if (result.valid) {
|
|
1145
|
+
* console.log("Verificación aprobada:", result.extraction);
|
|
1146
|
+
* } else {
|
|
1147
|
+
* console.warn("Rechazado:", result.errorMessage);
|
|
1148
|
+
* }
|
|
1149
|
+
* ```
|
|
1150
|
+
*/
|
|
1151
|
+
async pollWebflowStatus(params, options) {
|
|
1152
|
+
return pollWebflowStatus(this.http, params, options);
|
|
1153
|
+
}
|
|
739
1154
|
};
|
|
740
1155
|
function createJumioClient(config) {
|
|
741
1156
|
return new JumioClient(config);
|
|
742
1157
|
}
|
|
1158
|
+
init_errors();
|
|
743
1159
|
var INITIAL_STATE = {
|
|
744
1160
|
isSubmitting: false,
|
|
745
1161
|
isPolling: false,
|
|
@@ -890,7 +1306,14 @@ function useJumioVerification(options = {}) {
|
|
|
890
1306
|
callbacksRef.current.onStatusResolved?.(res);
|
|
891
1307
|
};
|
|
892
1308
|
const handleError = (err) => {
|
|
893
|
-
if (err instanceof JumioAbortError) {
|
|
1309
|
+
if (err instanceof exports.JumioAbortError) {
|
|
1310
|
+
setState((prev) => ({
|
|
1311
|
+
...prev,
|
|
1312
|
+
isSubmitting: false,
|
|
1313
|
+
isPolling: false,
|
|
1314
|
+
isLoading: false,
|
|
1315
|
+
stage: "CANCELLED"
|
|
1316
|
+
}));
|
|
894
1317
|
return;
|
|
895
1318
|
}
|
|
896
1319
|
setState((prev) => ({
|
|
@@ -954,22 +1377,215 @@ function useJumioVerification(options = {}) {
|
|
|
954
1377
|
client
|
|
955
1378
|
};
|
|
956
1379
|
}
|
|
1380
|
+
init_errors();
|
|
1381
|
+
var INITIAL_STATE2 = {
|
|
1382
|
+
isStarting: false,
|
|
1383
|
+
isChecking: false,
|
|
1384
|
+
isLoading: false,
|
|
1385
|
+
result: null,
|
|
1386
|
+
error: null,
|
|
1387
|
+
isValid: false,
|
|
1388
|
+
isRejected: false
|
|
1389
|
+
};
|
|
1390
|
+
function useJumioWebflow(options = {}) {
|
|
1391
|
+
const {
|
|
1392
|
+
client: customClient,
|
|
1393
|
+
baseUrl,
|
|
1394
|
+
endpoint,
|
|
1395
|
+
context,
|
|
1396
|
+
authToken,
|
|
1397
|
+
authTokenPrefix,
|
|
1398
|
+
requestTimeout,
|
|
1399
|
+
statusTimeout,
|
|
1400
|
+
maxRetries,
|
|
1401
|
+
retryDelayMs,
|
|
1402
|
+
pollingIntervalMs,
|
|
1403
|
+
maxPollingAttempts,
|
|
1404
|
+
redirectProxyUrl,
|
|
1405
|
+
s3Signer,
|
|
1406
|
+
customHeaders,
|
|
1407
|
+
axiosInstance,
|
|
1408
|
+
onResult: globalOnResult,
|
|
1409
|
+
onError: globalOnError
|
|
1410
|
+
} = options;
|
|
1411
|
+
const client = react.useMemo(() => {
|
|
1412
|
+
if (customClient) return customClient;
|
|
1413
|
+
return new JumioClient({
|
|
1414
|
+
baseUrl,
|
|
1415
|
+
endpoint,
|
|
1416
|
+
context,
|
|
1417
|
+
authToken,
|
|
1418
|
+
authTokenPrefix,
|
|
1419
|
+
requestTimeout,
|
|
1420
|
+
statusTimeout,
|
|
1421
|
+
maxRetries,
|
|
1422
|
+
retryDelayMs,
|
|
1423
|
+
pollingIntervalMs,
|
|
1424
|
+
maxPollingAttempts,
|
|
1425
|
+
redirectProxyUrl,
|
|
1426
|
+
s3Signer,
|
|
1427
|
+
customHeaders,
|
|
1428
|
+
axiosInstance
|
|
1429
|
+
});
|
|
1430
|
+
}, [
|
|
1431
|
+
customClient,
|
|
1432
|
+
baseUrl,
|
|
1433
|
+
endpoint,
|
|
1434
|
+
context,
|
|
1435
|
+
authToken,
|
|
1436
|
+
authTokenPrefix,
|
|
1437
|
+
requestTimeout,
|
|
1438
|
+
statusTimeout,
|
|
1439
|
+
maxRetries,
|
|
1440
|
+
retryDelayMs,
|
|
1441
|
+
pollingIntervalMs,
|
|
1442
|
+
maxPollingAttempts,
|
|
1443
|
+
redirectProxyUrl,
|
|
1444
|
+
s3Signer,
|
|
1445
|
+
customHeaders,
|
|
1446
|
+
axiosInstance
|
|
1447
|
+
]);
|
|
1448
|
+
const [state, setState] = react.useState(INITIAL_STATE2);
|
|
1449
|
+
const abortControllerRef = react.useRef(null);
|
|
1450
|
+
const callbacksRef = react.useRef({ onResult: globalOnResult, onError: globalOnError });
|
|
1451
|
+
react.useEffect(() => {
|
|
1452
|
+
callbacksRef.current = { onResult: globalOnResult, onError: globalOnError };
|
|
1453
|
+
}, [globalOnResult, globalOnError]);
|
|
1454
|
+
react.useEffect(() => {
|
|
1455
|
+
return () => {
|
|
1456
|
+
abortControllerRef.current?.abort();
|
|
1457
|
+
};
|
|
1458
|
+
}, []);
|
|
1459
|
+
const cancel = react.useCallback(() => {
|
|
1460
|
+
abortControllerRef.current?.abort();
|
|
1461
|
+
abortControllerRef.current = null;
|
|
1462
|
+
setState((prev) => ({
|
|
1463
|
+
...prev,
|
|
1464
|
+
isStarting: false,
|
|
1465
|
+
isChecking: false,
|
|
1466
|
+
isLoading: false
|
|
1467
|
+
}));
|
|
1468
|
+
}, []);
|
|
1469
|
+
const reset = react.useCallback(() => {
|
|
1470
|
+
cancel();
|
|
1471
|
+
setState(INITIAL_STATE2);
|
|
1472
|
+
}, [cancel]);
|
|
1473
|
+
const handleError = react.useCallback((err) => {
|
|
1474
|
+
if (err instanceof exports.JumioAbortError) {
|
|
1475
|
+
setState((prev) => ({
|
|
1476
|
+
...prev,
|
|
1477
|
+
isStarting: false,
|
|
1478
|
+
isChecking: false,
|
|
1479
|
+
isLoading: false
|
|
1480
|
+
}));
|
|
1481
|
+
return;
|
|
1482
|
+
}
|
|
1483
|
+
setState((prev) => ({
|
|
1484
|
+
...prev,
|
|
1485
|
+
isStarting: false,
|
|
1486
|
+
isChecking: false,
|
|
1487
|
+
isLoading: false,
|
|
1488
|
+
error: err,
|
|
1489
|
+
isRejected: true
|
|
1490
|
+
}));
|
|
1491
|
+
callbacksRef.current.onError?.(err);
|
|
1492
|
+
}, []);
|
|
1493
|
+
const handleResult = react.useCallback((result) => {
|
|
1494
|
+
setState((prev) => ({
|
|
1495
|
+
...prev,
|
|
1496
|
+
isChecking: false,
|
|
1497
|
+
isLoading: false,
|
|
1498
|
+
result,
|
|
1499
|
+
isValid: result.valid,
|
|
1500
|
+
isRejected: !result.valid,
|
|
1501
|
+
error: result.valid ? null : new Error(result.errorMessage ?? "Verificacion de identidad rechazada")
|
|
1502
|
+
}));
|
|
1503
|
+
callbacksRef.current.onResult?.(result);
|
|
1504
|
+
}, []);
|
|
1505
|
+
const startWebflow = react.useCallback(
|
|
1506
|
+
async (input) => {
|
|
1507
|
+
if (abortControllerRef.current) {
|
|
1508
|
+
abortControllerRef.current.abort();
|
|
1509
|
+
}
|
|
1510
|
+
const controller = new AbortController();
|
|
1511
|
+
abortControllerRef.current = controller;
|
|
1512
|
+
setState({
|
|
1513
|
+
...INITIAL_STATE2,
|
|
1514
|
+
isStarting: true,
|
|
1515
|
+
isLoading: true
|
|
1516
|
+
});
|
|
1517
|
+
try {
|
|
1518
|
+
const result = await client.startWebflow({
|
|
1519
|
+
...input,
|
|
1520
|
+
signal: input.signal ?? controller.signal
|
|
1521
|
+
});
|
|
1522
|
+
setState((prev) => ({
|
|
1523
|
+
...prev,
|
|
1524
|
+
isStarting: false,
|
|
1525
|
+
isLoading: false
|
|
1526
|
+
}));
|
|
1527
|
+
return result;
|
|
1528
|
+
} catch (err) {
|
|
1529
|
+
const normalizedError = err instanceof Error ? err : new Error(String(err));
|
|
1530
|
+
handleError(normalizedError);
|
|
1531
|
+
throw normalizedError;
|
|
1532
|
+
}
|
|
1533
|
+
},
|
|
1534
|
+
[client, handleError]
|
|
1535
|
+
);
|
|
1536
|
+
const checkResult = react.useCallback(
|
|
1537
|
+
async (params, pollOptions) => {
|
|
1538
|
+
if (abortControllerRef.current) {
|
|
1539
|
+
abortControllerRef.current.abort();
|
|
1540
|
+
}
|
|
1541
|
+
const controller = new AbortController();
|
|
1542
|
+
abortControllerRef.current = controller;
|
|
1543
|
+
setState((prev) => ({
|
|
1544
|
+
...prev,
|
|
1545
|
+
isChecking: true,
|
|
1546
|
+
isLoading: true,
|
|
1547
|
+
error: null
|
|
1548
|
+
}));
|
|
1549
|
+
try {
|
|
1550
|
+
const result = await client.pollWebflowStatus(params, {
|
|
1551
|
+
...pollOptions,
|
|
1552
|
+
signal: pollOptions?.signal ?? controller.signal
|
|
1553
|
+
});
|
|
1554
|
+
handleResult(result);
|
|
1555
|
+
return result;
|
|
1556
|
+
} catch (err) {
|
|
1557
|
+
const normalizedError = err instanceof Error ? err : new Error(String(err));
|
|
1558
|
+
handleError(normalizedError);
|
|
1559
|
+
throw normalizedError;
|
|
1560
|
+
}
|
|
1561
|
+
},
|
|
1562
|
+
[client, handleResult, handleError]
|
|
1563
|
+
);
|
|
1564
|
+
const parseReturnParams = react.useCallback(
|
|
1565
|
+
(source) => {
|
|
1566
|
+
return client.parseWebflowReturnParams(source);
|
|
1567
|
+
},
|
|
1568
|
+
[client]
|
|
1569
|
+
);
|
|
1570
|
+
return {
|
|
1571
|
+
...state,
|
|
1572
|
+
startWebflow,
|
|
1573
|
+
checkResult,
|
|
1574
|
+
parseReturnParams,
|
|
1575
|
+
cancel,
|
|
1576
|
+
reset,
|
|
1577
|
+
client
|
|
1578
|
+
};
|
|
1579
|
+
}
|
|
957
1580
|
|
|
958
|
-
exports.APPROVED_JUMIO_STATUSES = APPROVED_JUMIO_STATUSES;
|
|
959
|
-
exports.FINAL_JUMIO_STATUSES = FINAL_JUMIO_STATUSES;
|
|
960
|
-
exports.JumioAbortError = JumioAbortError;
|
|
961
1581
|
exports.JumioClient = JumioClient;
|
|
962
|
-
exports.JumioError = JumioError;
|
|
963
1582
|
exports.JumioHttpClient = JumioHttpClient;
|
|
964
|
-
exports.JumioImageProcessingError = JumioImageProcessingError;
|
|
965
|
-
exports.JumioNetworkError = JumioNetworkError;
|
|
966
|
-
exports.JumioPollingTimeoutError = JumioPollingTimeoutError;
|
|
967
|
-
exports.JumioTimeoutError = JumioTimeoutError;
|
|
968
|
-
exports.JumioValidationError = JumioValidationError;
|
|
969
1583
|
exports.arrayBufferToBase64 = arrayBufferToBase64;
|
|
970
1584
|
exports.blobToBase64 = blobToBase64;
|
|
1585
|
+
exports.buildRedirectUrl = buildRedirectUrl;
|
|
971
1586
|
exports.createJumioClient = createJumioClient;
|
|
972
1587
|
exports.delay = delay;
|
|
1588
|
+
exports.encodeUrlToBase64UrlSafe = encodeUrlToBase64UrlSafe;
|
|
973
1589
|
exports.extractEnvelopeData = extractEnvelopeData;
|
|
974
1590
|
exports.extractJumioMessage = extractJumioMessage;
|
|
975
1591
|
exports.extractNestedData = extractNestedData;
|
|
@@ -980,14 +1596,19 @@ exports.isFinalJumioStatus = isFinalJumioStatus;
|
|
|
980
1596
|
exports.isJumioError = isJumioError;
|
|
981
1597
|
exports.isPassedJumioDecision = isPassedJumioDecision;
|
|
982
1598
|
exports.normalizeSignedUrl = normalizeSignedUrl;
|
|
1599
|
+
exports.parseWebflowReturnParams = parseWebflowReturnParams;
|
|
983
1600
|
exports.pollJumioStatus = pollJumioStatus;
|
|
1601
|
+
exports.pollWebflowStatus = pollWebflowStatus;
|
|
984
1602
|
exports.resolveImageSourceToBase64 = resolveImageSourceToBase64;
|
|
985
1603
|
exports.resolveVerificationValidity = resolveVerificationValidity;
|
|
1604
|
+
exports.resolveWebflowResult = resolveWebflowResult;
|
|
986
1605
|
exports.shouldRetryJumio = shouldRetryJumio;
|
|
1606
|
+
exports.startWebflowSession = startWebflowSession;
|
|
987
1607
|
exports.stripDataUrlPrefix = stripDataUrlPrefix;
|
|
988
1608
|
exports.toLowerText = toLowerText;
|
|
989
1609
|
exports.toUpperText = toUpperText;
|
|
990
1610
|
exports.useJumioVerification = useJumioVerification;
|
|
1611
|
+
exports.useJumioWebflow = useJumioWebflow;
|
|
991
1612
|
exports.withRetry = withRetry;
|
|
992
1613
|
//# sourceMappingURL=index.js.map
|
|
993
1614
|
//# sourceMappingURL=index.js.map
|