@neofaceid/web-sdk 1.13.0 → 1.14.0
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.
|
@@ -1841,11 +1841,13 @@ const registerPersonWithoutFace = async (personData, applicationToken, options)
|
|
|
1841
1841
|
password_confirm: personData.password
|
|
1842
1842
|
};
|
|
1843
1843
|
if (documentFrontBase64) {
|
|
1844
|
-
body.document_images = [
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1844
|
+
body.document_images = [
|
|
1845
|
+
{
|
|
1846
|
+
front: documentFrontBase64,
|
|
1847
|
+
back: documentBackBase64 || void 0,
|
|
1848
|
+
type: (options == null ? void 0 : options.documentType) || "RG"
|
|
1849
|
+
}
|
|
1850
|
+
];
|
|
1849
1851
|
}
|
|
1850
1852
|
const response = await fetch(`${getApiBaseUrl()}/api/v1/signup/donor/`, {
|
|
1851
1853
|
method: "POST",
|
|
@@ -1935,11 +1937,13 @@ const registerPersonWithBiometric = async (personData, facePhotos, applicationTo
|
|
|
1935
1937
|
face_photos: facePhotosBase64
|
|
1936
1938
|
};
|
|
1937
1939
|
if (documentFrontBase64) {
|
|
1938
|
-
body.document_images = [
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1940
|
+
body.document_images = [
|
|
1941
|
+
{
|
|
1942
|
+
front: documentFrontBase64,
|
|
1943
|
+
back: documentBackBase64 || void 0,
|
|
1944
|
+
type: (options == null ? void 0 : options.documentType) || "RG"
|
|
1945
|
+
}
|
|
1946
|
+
];
|
|
1943
1947
|
}
|
|
1944
1948
|
const response = await fetch(`${getApiBaseUrl()}/api/v1/signup/donor/`, {
|
|
1945
1949
|
method: "POST",
|
|
@@ -2288,13 +2292,30 @@ const registerApplication = async (jwtToken, consumerId, applicationData) => {
|
|
|
2288
2292
|
};
|
|
2289
2293
|
const recordFaceVideo = async (options = {}) => {
|
|
2290
2294
|
ensureSecureContext();
|
|
2291
|
-
const { durationMs = 3e3,
|
|
2295
|
+
const { durationMs = 3e3, onProgress } = options;
|
|
2296
|
+
const getSupportedMimeType = () => {
|
|
2297
|
+
const types = [
|
|
2298
|
+
"video/mp4;codecs=avc1",
|
|
2299
|
+
// iOS Safari (prioritário quando disponível)
|
|
2300
|
+
"video/mp4",
|
|
2301
|
+
// iOS Safari fallback
|
|
2302
|
+
"video/webm;codecs=vp9",
|
|
2303
|
+
// Chrome/Firefox
|
|
2304
|
+
"video/webm;codecs=vp8",
|
|
2305
|
+
// Chrome/Firefox fallback
|
|
2306
|
+
"video/webm"
|
|
2307
|
+
// Android Chrome
|
|
2308
|
+
];
|
|
2309
|
+
for (const type of types) {
|
|
2310
|
+
if (MediaRecorder.isTypeSupported(type)) return type;
|
|
2311
|
+
}
|
|
2312
|
+
return "";
|
|
2313
|
+
};
|
|
2292
2314
|
return new Promise(async (resolve, reject) => {
|
|
2293
|
-
let
|
|
2294
|
-
let mediaRecorder = null;
|
|
2315
|
+
let cameraStream = null;
|
|
2295
2316
|
const chunks = [];
|
|
2296
2317
|
try {
|
|
2297
|
-
|
|
2318
|
+
cameraStream = await navigator.mediaDevices.getUserMedia({
|
|
2298
2319
|
video: {
|
|
2299
2320
|
facingMode: "user",
|
|
2300
2321
|
width: { ideal: 640 },
|
|
@@ -2302,38 +2323,36 @@ const recordFaceVideo = async (options = {}) => {
|
|
|
2302
2323
|
},
|
|
2303
2324
|
audio: false
|
|
2304
2325
|
});
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
selectedMimeType
|
|
2310
|
-
|
|
2311
|
-
}
|
|
2312
|
-
}
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
});
|
|
2318
|
-
mediaRecorder.ondataavailable = (event) => {
|
|
2326
|
+
const selectedMimeType = getSupportedMimeType();
|
|
2327
|
+
let recorder;
|
|
2328
|
+
try {
|
|
2329
|
+
recorder = selectedMimeType ? new MediaRecorder(cameraStream, {
|
|
2330
|
+
mimeType: selectedMimeType,
|
|
2331
|
+
videoBitsPerSecond: 1e6
|
|
2332
|
+
}) : new MediaRecorder(cameraStream, { videoBitsPerSecond: 1e6 });
|
|
2333
|
+
} catch {
|
|
2334
|
+
recorder = new MediaRecorder(cameraStream);
|
|
2335
|
+
}
|
|
2336
|
+
const finalMimeType = recorder.mimeType || selectedMimeType;
|
|
2337
|
+
recorder.ondataavailable = (event) => {
|
|
2319
2338
|
if (event.data.size > 0) {
|
|
2320
2339
|
chunks.push(event.data);
|
|
2321
2340
|
}
|
|
2322
2341
|
};
|
|
2323
|
-
|
|
2324
|
-
if (
|
|
2325
|
-
|
|
2342
|
+
recorder.onstop = () => {
|
|
2343
|
+
if (cameraStream) {
|
|
2344
|
+
cameraStream.getTracks().forEach((track) => track.stop());
|
|
2326
2345
|
}
|
|
2327
|
-
const videoBlob = new Blob(chunks, { type:
|
|
2346
|
+
const videoBlob = new Blob(chunks, { type: finalMimeType });
|
|
2328
2347
|
resolve(videoBlob);
|
|
2329
2348
|
};
|
|
2330
|
-
|
|
2331
|
-
if (
|
|
2332
|
-
|
|
2349
|
+
recorder.onerror = (event) => {
|
|
2350
|
+
if (cameraStream) {
|
|
2351
|
+
cameraStream.getTracks().forEach((track) => track.stop());
|
|
2333
2352
|
}
|
|
2334
2353
|
reject(new NeoFaceError(`Recording error: ${event}`, ErrorType.CAPTURE_ERROR));
|
|
2335
2354
|
};
|
|
2336
|
-
|
|
2355
|
+
recorder.start(100);
|
|
2337
2356
|
if (onProgress) {
|
|
2338
2357
|
const progressInterval = 100;
|
|
2339
2358
|
let elapsed = 0;
|
|
@@ -2347,13 +2366,13 @@ const recordFaceVideo = async (options = {}) => {
|
|
|
2347
2366
|
}, progressInterval);
|
|
2348
2367
|
}
|
|
2349
2368
|
setTimeout(() => {
|
|
2350
|
-
if (
|
|
2351
|
-
|
|
2369
|
+
if (recorder && recorder.state === "recording") {
|
|
2370
|
+
recorder.stop();
|
|
2352
2371
|
}
|
|
2353
2372
|
}, durationMs);
|
|
2354
2373
|
} catch (error) {
|
|
2355
|
-
if (
|
|
2356
|
-
|
|
2374
|
+
if (cameraStream) {
|
|
2375
|
+
cameraStream.getTracks().forEach((track) => track.stop());
|
|
2357
2376
|
}
|
|
2358
2377
|
if (error instanceof Error) {
|
|
2359
2378
|
if (error.name === "NotAllowedError") {
|
|
@@ -2483,6 +2502,68 @@ const videoToBase64 = async (videoBlob) => {
|
|
|
2483
2502
|
reader.readAsDataURL(videoBlob);
|
|
2484
2503
|
});
|
|
2485
2504
|
};
|
|
2505
|
+
const blobToBase64 = (blob) => new Promise((resolve, reject) => {
|
|
2506
|
+
const reader = new FileReader();
|
|
2507
|
+
reader.onload = () => {
|
|
2508
|
+
const result = reader.result;
|
|
2509
|
+
resolve(result.includes(",") ? result.split(",")[1] : result);
|
|
2510
|
+
};
|
|
2511
|
+
reader.onerror = () => reject(new NeoFaceError("Failed to convert image to base64", ErrorType.CAPTURE_ERROR));
|
|
2512
|
+
reader.readAsDataURL(blob);
|
|
2513
|
+
});
|
|
2514
|
+
const registerDocumentByImage = async (personId, jwtToken, images) => {
|
|
2515
|
+
var _a, _b;
|
|
2516
|
+
ensureSecureContext();
|
|
2517
|
+
if (!personId) {
|
|
2518
|
+
throw new NeoFaceError("personId is required", ErrorType.VALIDATION_ERROR);
|
|
2519
|
+
}
|
|
2520
|
+
if (!jwtToken) {
|
|
2521
|
+
throw new NeoFaceError("jwtToken is required", ErrorType.VALIDATION_ERROR);
|
|
2522
|
+
}
|
|
2523
|
+
if (!images || images.length === 0) {
|
|
2524
|
+
throw new NeoFaceError("At least one document image is required", ErrorType.VALIDATION_ERROR);
|
|
2525
|
+
}
|
|
2526
|
+
const base64Images = await Promise.all(
|
|
2527
|
+
images.map(async (img) => {
|
|
2528
|
+
const compressed = await compressDocumentImage(img);
|
|
2529
|
+
return blobToBase64(compressed);
|
|
2530
|
+
})
|
|
2531
|
+
);
|
|
2532
|
+
const controller = createTimeoutController();
|
|
2533
|
+
try {
|
|
2534
|
+
const response = await fetch(`${getApiBaseUrl()}/api/v1/donors/${personId}/documents/`, {
|
|
2535
|
+
method: "POST",
|
|
2536
|
+
headers: {
|
|
2537
|
+
"Content-Type": "application/json",
|
|
2538
|
+
Authorization: `Bearer ${jwtToken}`
|
|
2539
|
+
},
|
|
2540
|
+
body: JSON.stringify({ document_images: base64Images }),
|
|
2541
|
+
signal: controller.signal
|
|
2542
|
+
});
|
|
2543
|
+
const data = await response.json();
|
|
2544
|
+
if (!response.ok) {
|
|
2545
|
+
throw new NeoFaceError(
|
|
2546
|
+
(data == null ? void 0 : data.message) || `API Error ${response.status}`,
|
|
2547
|
+
ErrorType.NETWORK_ERROR
|
|
2548
|
+
);
|
|
2549
|
+
}
|
|
2550
|
+
return {
|
|
2551
|
+
success: true,
|
|
2552
|
+
taskId: ((_a = data.data) == null ? void 0 : _a.task_id) ?? "",
|
|
2553
|
+
status: ((_b = data.data) == null ? void 0 : _b.status) ?? "processing",
|
|
2554
|
+
message: data.message ?? "Documents submitted for processing"
|
|
2555
|
+
};
|
|
2556
|
+
} catch (error) {
|
|
2557
|
+
if (error instanceof NeoFaceError) throw error;
|
|
2558
|
+
if (error instanceof Error) {
|
|
2559
|
+
if (error.name === "AbortError") {
|
|
2560
|
+
throw new NeoFaceError("Request timeout", ErrorType.NETWORK_ERROR);
|
|
2561
|
+
}
|
|
2562
|
+
throw new NeoFaceError(error.message, ErrorType.NETWORK_ERROR);
|
|
2563
|
+
}
|
|
2564
|
+
throw new NeoFaceError("Unknown error occurred", ErrorType.NETWORK_ERROR);
|
|
2565
|
+
}
|
|
2566
|
+
};
|
|
2486
2567
|
const modalReducer$1 = (state, action) => {
|
|
2487
2568
|
switch (action.type) {
|
|
2488
2569
|
case "PERMISSION_GRANTED":
|
|
@@ -5321,14 +5402,15 @@ async function captureFaceSilently() {
|
|
|
5321
5402
|
video.style.width = "1px";
|
|
5322
5403
|
video.style.height = "1px";
|
|
5323
5404
|
video.style.opacity = "0";
|
|
5405
|
+
video.muted = true;
|
|
5406
|
+
video.playsInline = true;
|
|
5324
5407
|
video.setAttribute("autoplay", "");
|
|
5325
|
-
video.setAttribute("muted", "");
|
|
5326
5408
|
video.setAttribute("playsinline", "");
|
|
5327
5409
|
const canvas = document.createElement("canvas");
|
|
5328
5410
|
canvas.style.display = "none";
|
|
5329
5411
|
let stream = null;
|
|
5330
5412
|
let faceDetectionAttempts = 0;
|
|
5331
|
-
const MAX_FACE_DETECTION_ATTEMPTS =
|
|
5413
|
+
const MAX_FACE_DETECTION_ATTEMPTS = 30;
|
|
5332
5414
|
const cleanup = () => {
|
|
5333
5415
|
if (stream) {
|
|
5334
5416
|
stream.getTracks().forEach((track) => track.stop());
|
|
@@ -5342,22 +5424,27 @@ async function captureFaceSilently() {
|
|
|
5342
5424
|
};
|
|
5343
5425
|
document.body.appendChild(video);
|
|
5344
5426
|
document.body.appendChild(canvas);
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5427
|
+
const tryGetUserMedia = (withConstraints) => {
|
|
5428
|
+
if (withConstraints) {
|
|
5429
|
+
return navigator.mediaDevices.getUserMedia({
|
|
5430
|
+
video: {
|
|
5431
|
+
width: { ideal: 640 },
|
|
5432
|
+
height: { ideal: 480 },
|
|
5433
|
+
facingMode: "user"
|
|
5434
|
+
},
|
|
5435
|
+
audio: false
|
|
5436
|
+
});
|
|
5437
|
+
}
|
|
5438
|
+
return navigator.mediaDevices.getUserMedia({ video: { facingMode: "user" }, audio: false });
|
|
5439
|
+
};
|
|
5440
|
+
tryGetUserMedia(true).catch(() => tryGetUserMedia(false)).then((mediaStream) => {
|
|
5353
5441
|
stream = mediaStream;
|
|
5354
5442
|
video.srcObject = stream;
|
|
5355
|
-
video.play();
|
|
5356
5443
|
const tryCapture = () => {
|
|
5357
5444
|
if (!video.videoWidth || !video.videoHeight) {
|
|
5358
5445
|
if (faceDetectionAttempts < MAX_FACE_DETECTION_ATTEMPTS) {
|
|
5359
5446
|
faceDetectionAttempts++;
|
|
5360
|
-
setTimeout(tryCapture,
|
|
5447
|
+
setTimeout(tryCapture, 150);
|
|
5361
5448
|
return;
|
|
5362
5449
|
}
|
|
5363
5450
|
cleanup();
|
|
@@ -5387,7 +5474,7 @@ async function captureFaceSilently() {
|
|
|
5387
5474
|
detectFace2().then((hasFace) => {
|
|
5388
5475
|
if (!hasFace && faceDetectionAttempts < MAX_FACE_DETECTION_ATTEMPTS) {
|
|
5389
5476
|
faceDetectionAttempts++;
|
|
5390
|
-
setTimeout(tryCapture,
|
|
5477
|
+
setTimeout(tryCapture, 150);
|
|
5391
5478
|
return;
|
|
5392
5479
|
}
|
|
5393
5480
|
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
|
|
@@ -5405,9 +5492,26 @@ async function captureFaceSilently() {
|
|
|
5405
5492
|
);
|
|
5406
5493
|
});
|
|
5407
5494
|
};
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5495
|
+
const playPromise = video.play();
|
|
5496
|
+
if (playPromise !== void 0) {
|
|
5497
|
+
playPromise.then(() => {
|
|
5498
|
+
if (video.videoWidth && video.videoHeight) {
|
|
5499
|
+
setTimeout(tryCapture, CAMERA_READY_DELAY);
|
|
5500
|
+
} else {
|
|
5501
|
+
video.onloadedmetadata = () => setTimeout(tryCapture, CAMERA_READY_DELAY);
|
|
5502
|
+
setTimeout(() => {
|
|
5503
|
+
if (video.videoWidth && video.videoHeight) {
|
|
5504
|
+
tryCapture();
|
|
5505
|
+
}
|
|
5506
|
+
}, 1500);
|
|
5507
|
+
}
|
|
5508
|
+
}).catch((err) => {
|
|
5509
|
+
cleanup();
|
|
5510
|
+
reject(new NeoFaceError("Erro ao reproduzir câmera: " + err.message, ErrorType.CAMERA_ERROR));
|
|
5511
|
+
});
|
|
5512
|
+
} else {
|
|
5513
|
+
video.onloadedmetadata = () => setTimeout(tryCapture, CAMERA_READY_DELAY);
|
|
5514
|
+
}
|
|
5411
5515
|
video.onerror = () => {
|
|
5412
5516
|
cleanup();
|
|
5413
5517
|
reject(new NeoFaceError("Erro ao acessar câmera", ErrorType.CAMERA_ERROR));
|
|
@@ -5481,27 +5585,55 @@ async function attemptLogin(applicationToken, overlay, fastMode = false, isRetry
|
|
|
5481
5585
|
video.style.width = "1px";
|
|
5482
5586
|
video.style.height = "1px";
|
|
5483
5587
|
video.style.opacity = "0";
|
|
5588
|
+
video.muted = true;
|
|
5589
|
+
video.playsInline = true;
|
|
5484
5590
|
video.setAttribute("autoplay", "");
|
|
5485
|
-
video.setAttribute("muted", "");
|
|
5486
5591
|
video.setAttribute("playsinline", "");
|
|
5487
5592
|
document.body.appendChild(video);
|
|
5488
5593
|
let stream = null;
|
|
5489
5594
|
try {
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5595
|
+
try {
|
|
5596
|
+
stream = await navigator.mediaDevices.getUserMedia({
|
|
5597
|
+
video: {
|
|
5598
|
+
width: { ideal: 640 },
|
|
5599
|
+
height: { ideal: 480 },
|
|
5600
|
+
facingMode: "user"
|
|
5601
|
+
},
|
|
5602
|
+
audio: false
|
|
5603
|
+
});
|
|
5604
|
+
} catch {
|
|
5605
|
+
stream = await navigator.mediaDevices.getUserMedia({
|
|
5606
|
+
video: { facingMode: "user" },
|
|
5607
|
+
audio: false
|
|
5608
|
+
});
|
|
5609
|
+
}
|
|
5498
5610
|
video.srcObject = stream;
|
|
5611
|
+
await new Promise((resolve) => {
|
|
5612
|
+
if (video.readyState >= 1) {
|
|
5613
|
+
resolve();
|
|
5614
|
+
} else {
|
|
5615
|
+
const handler = () => {
|
|
5616
|
+
video.removeEventListener("loadedmetadata", handler);
|
|
5617
|
+
resolve();
|
|
5618
|
+
};
|
|
5619
|
+
video.addEventListener("loadedmetadata", handler);
|
|
5620
|
+
setTimeout(resolve, 2e3);
|
|
5621
|
+
}
|
|
5622
|
+
});
|
|
5499
5623
|
await video.play();
|
|
5500
5624
|
await new Promise((resolve) => {
|
|
5501
|
-
if (video.
|
|
5502
|
-
resolve(
|
|
5625
|
+
if (video.videoWidth && video.videoHeight) {
|
|
5626
|
+
resolve();
|
|
5503
5627
|
} else {
|
|
5504
|
-
|
|
5628
|
+
const checkSize = () => {
|
|
5629
|
+
if (video.videoWidth && video.videoHeight) {
|
|
5630
|
+
resolve();
|
|
5631
|
+
} else {
|
|
5632
|
+
setTimeout(checkSize, 100);
|
|
5633
|
+
}
|
|
5634
|
+
};
|
|
5635
|
+
setTimeout(resolve, 3e3);
|
|
5636
|
+
checkSize();
|
|
5505
5637
|
}
|
|
5506
5638
|
});
|
|
5507
5639
|
overlay.updateStatus("detecting");
|
|
@@ -5971,8 +6103,8 @@ const biometricDetection = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.
|
|
|
5971
6103
|
initializeBiometricDetection,
|
|
5972
6104
|
isAdvancedDetectionAvailable
|
|
5973
6105
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
5974
|
-
const VERSION = "1.
|
|
5975
|
-
const RELEASE_DATE = "2026-
|
|
6106
|
+
const VERSION = "1.14.0";
|
|
6107
|
+
const RELEASE_DATE = "2026-03-04";
|
|
5976
6108
|
class OnboardingCaptureModal {
|
|
5977
6109
|
constructor(options) {
|
|
5978
6110
|
__publicField(this, "overlay", null);
|
|
@@ -6023,7 +6155,7 @@ class OnboardingCaptureModal {
|
|
|
6023
6155
|
<div class="neofaceid-modal-body">
|
|
6024
6156
|
<p class="neofaceid-subtitle">${this.subtitle ?? "Vamos capturar sua face e documento"}</p>
|
|
6025
6157
|
<div class="neofaceid-camera-container">
|
|
6026
|
-
<video class="neofaceid-video" autoplay playsinline></video>
|
|
6158
|
+
<video class="neofaceid-video" autoplay muted playsinline></video>
|
|
6027
6159
|
<canvas class="neofaceid-canvas"></canvas>
|
|
6028
6160
|
<div class="neofaceid-overlay">
|
|
6029
6161
|
<div class="neofaceid-frame"></div>
|
|
@@ -6074,12 +6206,20 @@ class OnboardingCaptureModal {
|
|
|
6074
6206
|
* Inicia a câmera do usuário com resolução adequada.
|
|
6075
6207
|
*/
|
|
6076
6208
|
async startCamera() {
|
|
6077
|
-
const constraints = {
|
|
6078
|
-
video: { facingMode: "user", width: { ideal: 1280 }, height: { ideal: 720 } },
|
|
6079
|
-
audio: false
|
|
6080
|
-
};
|
|
6081
|
-
this.stream = await navigator.mediaDevices.getUserMedia(constraints);
|
|
6082
6209
|
if (!this.video) throw new Error("Elemento de vídeo não encontrado");
|
|
6210
|
+
this.video.muted = true;
|
|
6211
|
+
this.video.playsInline = true;
|
|
6212
|
+
try {
|
|
6213
|
+
this.stream = await navigator.mediaDevices.getUserMedia({
|
|
6214
|
+
video: { facingMode: "user", width: { ideal: 1280 }, height: { ideal: 720 } },
|
|
6215
|
+
audio: false
|
|
6216
|
+
});
|
|
6217
|
+
} catch {
|
|
6218
|
+
this.stream = await navigator.mediaDevices.getUserMedia({
|
|
6219
|
+
video: { facingMode: "user" },
|
|
6220
|
+
audio: false
|
|
6221
|
+
});
|
|
6222
|
+
}
|
|
6083
6223
|
this.video.srcObject = this.stream;
|
|
6084
6224
|
await this.video.play();
|
|
6085
6225
|
}
|
|
@@ -6423,6 +6563,47 @@ class NeoFaceID {
|
|
|
6423
6563
|
* }
|
|
6424
6564
|
* ```
|
|
6425
6565
|
*/
|
|
6566
|
+
/**
|
|
6567
|
+
* Registers document images for an already-registered donor person.
|
|
6568
|
+
*
|
|
6569
|
+
* Opens the document capture UI (front + optional back), then submits
|
|
6570
|
+
* the images to the backend for extraction via DocExt.
|
|
6571
|
+
* The backend processes this asynchronously — use the returned `taskId`
|
|
6572
|
+
* to poll status if needed.
|
|
6573
|
+
*
|
|
6574
|
+
* @param personId UUID of the donor's person record
|
|
6575
|
+
* @param jwtToken JWT Bearer token of the authenticated donor
|
|
6576
|
+
* @param options Optional capture configuration
|
|
6577
|
+
* @returns Promise with task_id and processing status
|
|
6578
|
+
* @throws NeoFaceError if capture is cancelled, validation fails, or API call fails
|
|
6579
|
+
*
|
|
6580
|
+
* @example
|
|
6581
|
+
* ```typescript
|
|
6582
|
+
* const sdk = new NeoFaceID({ appToken: 'your-token' });
|
|
6583
|
+
*
|
|
6584
|
+
* const result = await sdk.registerDocumentByImage(personId, userJwtToken);
|
|
6585
|
+
* console.log('Task ID:', result.taskId); // poll for completion
|
|
6586
|
+
* ```
|
|
6587
|
+
*/
|
|
6588
|
+
async registerDocumentByImage(personId, jwtToken, options = {}) {
|
|
6589
|
+
const { DocumentCaptureModal: DocumentCaptureModal2 } = await Promise.resolve().then(() => DocumentCaptureModal$1);
|
|
6590
|
+
const modal = new DocumentCaptureModal2({
|
|
6591
|
+
useBackCamera: options.useBackCamera ?? true,
|
|
6592
|
+
preSelectedDocument: options.preSelectedDocument
|
|
6593
|
+
});
|
|
6594
|
+
const captureResult = await modal.open();
|
|
6595
|
+
if (!captureResult.success || !captureResult.frontImage) {
|
|
6596
|
+
throw new NeoFaceError(
|
|
6597
|
+
captureResult.error === "cancelled" ? "Document capture was cancelled by the user" : `Document capture failed: ${captureResult.error ?? "unknown error"}`,
|
|
6598
|
+
ErrorType.CAPTURE_ERROR
|
|
6599
|
+
);
|
|
6600
|
+
}
|
|
6601
|
+
const images = [captureResult.frontImage];
|
|
6602
|
+
if (captureResult.backImage) {
|
|
6603
|
+
images.push(captureResult.backImage);
|
|
6604
|
+
}
|
|
6605
|
+
return registerDocumentByImage(personId, jwtToken, images);
|
|
6606
|
+
}
|
|
6426
6607
|
async proofOfLife(options = {}) {
|
|
6427
6608
|
const {
|
|
6428
6609
|
videoDurationMs = 3e3,
|
|
@@ -6759,7 +6940,7 @@ class DocumentCaptureModal {
|
|
|
6759
6940
|
|
|
6760
6941
|
<div class="neoface-doc-body">
|
|
6761
6942
|
<div class="neoface-doc-camera-container">
|
|
6762
|
-
<video class="neoface-doc-video" autoplay playsinline></video>
|
|
6943
|
+
<video class="neoface-doc-video" autoplay muted playsinline></video>
|
|
6763
6944
|
<canvas class="neoface-doc-canvas"></canvas>
|
|
6764
6945
|
|
|
6765
6946
|
<div class="neoface-doc-guide">
|
|
@@ -7011,6 +7192,8 @@ class DocumentCaptureModal {
|
|
|
7011
7192
|
this.video = (_a = this.overlay) == null ? void 0 : _a.querySelector(".neoface-doc-video");
|
|
7012
7193
|
this.canvas = (_b = this.overlay) == null ? void 0 : _b.querySelector(".neoface-doc-canvas");
|
|
7013
7194
|
if (this.video) {
|
|
7195
|
+
this.video.muted = true;
|
|
7196
|
+
this.video.playsInline = true;
|
|
7014
7197
|
this.video.srcObject = this.stream;
|
|
7015
7198
|
await this.video.play();
|
|
7016
7199
|
}
|
|
@@ -7599,6 +7782,11 @@ const startDocumentCapture = async (options) => {
|
|
|
7599
7782
|
const modal = new DocumentCaptureModal(options);
|
|
7600
7783
|
return modal.open();
|
|
7601
7784
|
};
|
|
7785
|
+
const DocumentCaptureModal$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
7786
|
+
__proto__: null,
|
|
7787
|
+
DocumentCaptureModal,
|
|
7788
|
+
startDocumentCapture
|
|
7789
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
7602
7790
|
function start(applicationToken, callbacks) {
|
|
7603
7791
|
const container = document.createElement("div");
|
|
7604
7792
|
container.id = "neoface-modal-container";
|