biometry-sdk 1.3.7 → 2.0.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.
- package/dist/index.d.ts +2 -2
- package/dist/{sdk.d.ts → sdk/index.d.ts} +7 -7
- package/dist/sdk.js +286 -0
- package/dist/{components → ui}/biometry-enrollment.d.ts +3 -5
- package/dist/ui/index.d.ts +4 -0
- package/dist/{components → ui}/process-video.d.ts +3 -6
- package/dist/{biometry-sdk.esm.js → ui.js} +100 -380
- package/package.json +17 -5
- /package/dist/{sdk.test.d.ts → sdk/index.test.d.ts} +0 -0
- /package/dist/{components → ui}/types.d.ts +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export * from './sdk';
|
|
2
2
|
export * from './types/index';
|
|
3
|
-
export { BiometryEnrollment } from './
|
|
4
|
-
export { ProcessVideoComponent } from './
|
|
3
|
+
export { BiometryEnrollment } from './ui/biometry-enrollment';
|
|
4
|
+
export { ProcessVideoComponent } from './ui/process-video';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { ApiResponse } from "
|
|
2
|
-
import { DocAuthInfo } from "
|
|
3
|
-
import { ConsentResponse } from "
|
|
4
|
-
import { FaceEnrollmentResponse, VoiceEnrollmentResponse } from "
|
|
5
|
-
import { FaceMatchResponse } from "
|
|
6
|
-
import { ProcessVideoResponse } from "
|
|
7
|
-
import { SessionResponse } from "
|
|
1
|
+
import { ApiResponse } from "../types/internal";
|
|
2
|
+
import { DocAuthInfo } from "../types/biometry/doc-auth";
|
|
3
|
+
import { ConsentResponse } from "../types/biometry/consent";
|
|
4
|
+
import { FaceEnrollmentResponse, VoiceEnrollmentResponse } from "../types/biometry/enrollment";
|
|
5
|
+
import { FaceMatchResponse } from "../types/biometry/face-match";
|
|
6
|
+
import { ProcessVideoResponse } from "../types/biometry/process-video";
|
|
7
|
+
import { SessionResponse } from "../types/biometry/session";
|
|
8
8
|
export declare class BiometrySDK {
|
|
9
9
|
private apiKey;
|
|
10
10
|
private static readonly BASE_URL;
|
package/dist/sdk.js
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
class BiometrySDK {
|
|
2
|
+
constructor(apiKey) {
|
|
3
|
+
if (!apiKey) {
|
|
4
|
+
throw new Error('API Key is required to initialize the SDK.');
|
|
5
|
+
}
|
|
6
|
+
this.apiKey = apiKey;
|
|
7
|
+
}
|
|
8
|
+
async request(path, method, body, headers) {
|
|
9
|
+
const defaultHeaders = {
|
|
10
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
11
|
+
};
|
|
12
|
+
const requestHeaders = Object.assign(Object.assign({}, defaultHeaders), headers);
|
|
13
|
+
if (body && !(body instanceof FormData)) {
|
|
14
|
+
requestHeaders['Content-Type'] = 'application/json';
|
|
15
|
+
body = JSON.stringify(body);
|
|
16
|
+
}
|
|
17
|
+
const response = await fetch(`${BiometrySDK.BASE_URL}${path}`, {
|
|
18
|
+
method,
|
|
19
|
+
headers: requestHeaders,
|
|
20
|
+
body,
|
|
21
|
+
});
|
|
22
|
+
if (!response.ok) {
|
|
23
|
+
const errorData = await response.json().catch(() => ({}));
|
|
24
|
+
const errorMessage = (errorData === null || errorData === undefined ? undefined : errorData.error) || (errorData === null || errorData === undefined ? undefined : errorData.message) || 'Unknown error occurred';
|
|
25
|
+
throw new Error(`Error ${response.status}: ${errorMessage}`);
|
|
26
|
+
}
|
|
27
|
+
// Extract response headers
|
|
28
|
+
const responseHeaders = {};
|
|
29
|
+
const requestId = response.headers.get("X-Request-Id");
|
|
30
|
+
if (requestId) {
|
|
31
|
+
responseHeaders["X-Request-Id"] = requestId;
|
|
32
|
+
}
|
|
33
|
+
const responseBody = await response.json();
|
|
34
|
+
return {
|
|
35
|
+
body: responseBody,
|
|
36
|
+
headers: responseHeaders
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Starts a new Session for a user.
|
|
41
|
+
*
|
|
42
|
+
* @returns {Promise<ApiResponse<SessionResponse>>} A promise resolving to the session ID.
|
|
43
|
+
* @throws {Error} - If the request fails.
|
|
44
|
+
*/
|
|
45
|
+
async startSession() {
|
|
46
|
+
return await this.request('/api-gateway/sessions/start', 'POST');
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Submits Authorization consent for a user.
|
|
50
|
+
* Authorization Consent is required to use the services like Face and Voice recognition.
|
|
51
|
+
*
|
|
52
|
+
* @param {boolean} isConsentGiven - Indicates whether the user has given consent.
|
|
53
|
+
* @param {string} userFullName - The full name of the user giving consent.
|
|
54
|
+
* @param {Object} [props] - Optional properties for the consent request.
|
|
55
|
+
* @param {string} [props.sessionId] - Session ID to link this consent with a specific session group.
|
|
56
|
+
* @param {object} [props.deviceInfo] - Device information object containing details about the user's device.
|
|
57
|
+
* This can include properties like operating system, browser, etc.
|
|
58
|
+
* @returns {Promise<ApiResponse<ConsentResponse>>} A promise resolving to the consent response.
|
|
59
|
+
* @throws {Error} - If the user's full name is not provided or if the request fails.
|
|
60
|
+
*/
|
|
61
|
+
async giveAuthorizationConsent(isConsentGiven, userFullName, props) {
|
|
62
|
+
if (!userFullName) {
|
|
63
|
+
throw new Error('User Full Name is required to give consent.');
|
|
64
|
+
}
|
|
65
|
+
const body = {
|
|
66
|
+
is_consent_given: isConsentGiven,
|
|
67
|
+
user_fullname: userFullName,
|
|
68
|
+
};
|
|
69
|
+
const headers = {};
|
|
70
|
+
if (props === null || props === undefined ? undefined : props.sessionId) {
|
|
71
|
+
headers['X-Session-ID'] = props.sessionId;
|
|
72
|
+
}
|
|
73
|
+
if (props === null || props === undefined ? undefined : props.deviceInfo) {
|
|
74
|
+
headers['X-Device-Info'] = JSON.stringify(props.deviceInfo);
|
|
75
|
+
}
|
|
76
|
+
return await this.request('/api-consent/consent', 'POST', body, headers);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Submits Storage consent for a user.
|
|
80
|
+
* Storage consent is granted by users, allowing us to store their biometric data for future verification.
|
|
81
|
+
*
|
|
82
|
+
* @param {boolean} isStorageConsentGiven - Indicates whether the user has given storage consent.
|
|
83
|
+
* @param {string} userFullName - The full name of the user giving storage consent.
|
|
84
|
+
* @param {Object} [props] - Optional properties for the consent request.
|
|
85
|
+
* @param {string} [props.sessionId] - Session ID to link this consent with a specific session group.
|
|
86
|
+
* @param {object} [props.deviceInfo] - Device information object containing details about the user's device.
|
|
87
|
+
* This can include properties like operating system, browser, etc.
|
|
88
|
+
* @returns {Promise<ApiResponse<ConsentResponse>>} A promise resolving to the consent response.
|
|
89
|
+
* @throws {Error} - If the user's full name is not provided or if the request fails.
|
|
90
|
+
*/
|
|
91
|
+
async giveStorageConsent(isStorageConsentGiven, userFullName, props) {
|
|
92
|
+
if (!userFullName) {
|
|
93
|
+
throw new Error('User Full Name is required to give storage consent.');
|
|
94
|
+
}
|
|
95
|
+
const body = {
|
|
96
|
+
is_consent_given: isStorageConsentGiven,
|
|
97
|
+
user_fullname: userFullName,
|
|
98
|
+
};
|
|
99
|
+
const headers = {};
|
|
100
|
+
if (props === null || props === undefined ? undefined : props.sessionId) {
|
|
101
|
+
headers['X-Session-ID'] = props.sessionId;
|
|
102
|
+
}
|
|
103
|
+
if (props === null || props === undefined ? undefined : props.deviceInfo) {
|
|
104
|
+
headers['X-Device-Info'] = JSON.stringify(props.deviceInfo);
|
|
105
|
+
}
|
|
106
|
+
return await this.request('/api-consent/strg-consent', 'POST', body, headers);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Enrolls a user's voice for biometric authentication.
|
|
110
|
+
*
|
|
111
|
+
* @param {File} audio - The audio file containing the user's voice.
|
|
112
|
+
* @param {string} userFullName - The full name of the user being enrolled.
|
|
113
|
+
* @param {string} uniqueId - A unique identifier for the enrolling process.
|
|
114
|
+
* @param {string} phrase - The phrase spoken in the audio file.
|
|
115
|
+
* @param {Object} [props] - Optional properties for the enrollment request.
|
|
116
|
+
* @param {string} [props.sessionId] - Session ID to link this enrollment with a specific session group.
|
|
117
|
+
* @param {object} [props.deviceInfo] - Device information object containing details about the user's device.
|
|
118
|
+
* This can include properties like operating system, browser, etc.
|
|
119
|
+
* @returns {Promise<ApiResponse<VoiceEnrollmentResponse>>} - A promise resolving to the voice enrolling response.
|
|
120
|
+
* @throws {Error} - If required parameters are missing or the request fails.
|
|
121
|
+
*/
|
|
122
|
+
async enrollVoice(audio, userFullName, uniqueId, phrase, props) {
|
|
123
|
+
if (!userFullName)
|
|
124
|
+
throw new Error('User fullname is required.');
|
|
125
|
+
if (!uniqueId)
|
|
126
|
+
throw new Error('Unique ID is required.');
|
|
127
|
+
if (!phrase)
|
|
128
|
+
throw new Error('Phrase is required.');
|
|
129
|
+
if (!audio)
|
|
130
|
+
throw new Error('Audio file is required.');
|
|
131
|
+
const formData = new FormData();
|
|
132
|
+
formData.append('unique_id', uniqueId);
|
|
133
|
+
formData.append('phrase', phrase);
|
|
134
|
+
formData.append('voice', audio);
|
|
135
|
+
const headers = {
|
|
136
|
+
'X-User-Fullname': userFullName,
|
|
137
|
+
};
|
|
138
|
+
if (props === null || props === undefined ? undefined : props.sessionId) {
|
|
139
|
+
headers['X-Session-ID'] = props.sessionId;
|
|
140
|
+
}
|
|
141
|
+
if (props === null || props === undefined ? undefined : props.deviceInfo) {
|
|
142
|
+
headers['X-Device-Info'] = JSON.stringify(props.deviceInfo);
|
|
143
|
+
}
|
|
144
|
+
return await this.request('/api-gateway/enroll/voice', 'POST', formData, headers);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Enrolls a user's face for biometric authentication.
|
|
148
|
+
*
|
|
149
|
+
* @param {File} face - Image file that contains user's face.
|
|
150
|
+
* @param {string} userFullName - The full name of the user being enrolled.
|
|
151
|
+
* @param {string} isDocument - Indicates whether the image is a document.
|
|
152
|
+
* @param {Object} [props] - Optional properties for the enrollment request.
|
|
153
|
+
* @param {string} [props.sessionId] - Session ID to link this enrollment with a specific session group.
|
|
154
|
+
* @param {object} [props.deviceInfo] - Device information object containing details about the user's device.
|
|
155
|
+
* This can include properties like operating system, browser, etc.
|
|
156
|
+
* @returns {Promise<ApiResponse<FaceEnrollmentResponse>>} - A promise resolving to the voice enrolling response.
|
|
157
|
+
* @throws {Error} - If required parameters are missing or the request fails.
|
|
158
|
+
*/
|
|
159
|
+
async enrollFace(face, userFullName, isDocument, props) {
|
|
160
|
+
if (!userFullName)
|
|
161
|
+
throw new Error('User fullname is required.');
|
|
162
|
+
if (!face)
|
|
163
|
+
throw new Error('Face image is required.');
|
|
164
|
+
const formData = new FormData();
|
|
165
|
+
formData.append('face', face);
|
|
166
|
+
if (isDocument) {
|
|
167
|
+
formData.append('is_document', 'true');
|
|
168
|
+
}
|
|
169
|
+
const headers = {
|
|
170
|
+
'X-User-Fullname': userFullName,
|
|
171
|
+
};
|
|
172
|
+
if (props === null || props === undefined ? undefined : props.sessionId) {
|
|
173
|
+
headers['X-Session-ID'] = props.sessionId;
|
|
174
|
+
}
|
|
175
|
+
if (props === null || props === undefined ? undefined : props.deviceInfo) {
|
|
176
|
+
headers['X-Device-Info'] = JSON.stringify(props.deviceInfo);
|
|
177
|
+
}
|
|
178
|
+
return await this.request('/api-gateway/enroll/face', 'POST', formData, headers);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Check the validity of a documents.
|
|
182
|
+
*
|
|
183
|
+
* @param {File} document - Document image file.
|
|
184
|
+
* @param {string} userFullName - The full name of the user being checked.
|
|
185
|
+
* @param {Object} [props] - Optional properties for the enrollment request.
|
|
186
|
+
* @param {string} [props.sessionId] - Session ID to link this enrollment with a specific session group.
|
|
187
|
+
* @param {object} [props.deviceInfo] - Device information object containing details about the user's device.
|
|
188
|
+
* This can include properties like operating system, browser, etc.
|
|
189
|
+
* @returns {Promise<ApiResponse<DocAuthInfo>>} - A promise resolving to the document authentication information.
|
|
190
|
+
*/
|
|
191
|
+
async checkDocAuth(document, userFullName, props) {
|
|
192
|
+
if (!document)
|
|
193
|
+
throw new Error('Document image is required.');
|
|
194
|
+
if (!userFullName)
|
|
195
|
+
throw new Error('User fullname is required.');
|
|
196
|
+
const formData = new FormData();
|
|
197
|
+
formData.append('document', document);
|
|
198
|
+
const headers = {
|
|
199
|
+
'X-User-Fullname': userFullName,
|
|
200
|
+
};
|
|
201
|
+
if (props === null || props === undefined ? undefined : props.sessionId) {
|
|
202
|
+
headers['X-Session-ID'] = props.sessionId;
|
|
203
|
+
}
|
|
204
|
+
if (props === null || props === undefined ? undefined : props.deviceInfo) {
|
|
205
|
+
headers['X-Device-Info'] = JSON.stringify(props.deviceInfo);
|
|
206
|
+
}
|
|
207
|
+
return await this.request('/api-gateway/check-doc-auth', 'POST', formData, headers);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Matches a user's face from video against a reference image.
|
|
211
|
+
*
|
|
212
|
+
* @param {File} image - Reference image file that contains user's face.
|
|
213
|
+
* @param {string} video - Video file that contains user's face.
|
|
214
|
+
* @param {string} userFullName - Pass the full name of end-user to process Voice and Face recognition services.
|
|
215
|
+
* @param {string} processVideoRequestId - ID from the response header of /process-video endpoint.
|
|
216
|
+
* @param {boolean} usePrefilledVideo - Pass true to use the video from the process-video endpoint.
|
|
217
|
+
* @param {Object} [props] - Optional properties for the enrollment request.
|
|
218
|
+
* @param {string} [props.sessionId] - Session ID to link this enrollment with a specific session group.
|
|
219
|
+
* @param {object} [props.deviceInfo] - Device information object containing details about the user's device.
|
|
220
|
+
* This can include properties like operating system, browser, etc.
|
|
221
|
+
* @returns {Promise<FaceMatchResponse>} - A promise resolving to the voice enrolling response.
|
|
222
|
+
* @throws {Error} - If required parameters are missing or the request fails.
|
|
223
|
+
*/
|
|
224
|
+
async matchFaces(image, video, userFullName, usePrefilledVideo, props) {
|
|
225
|
+
if (!image)
|
|
226
|
+
throw new Error('Face image is required.');
|
|
227
|
+
if ((!usePrefilledVideo) && !video)
|
|
228
|
+
throw new Error('Video is required.');
|
|
229
|
+
if (usePrefilledVideo && !(props === null || props === undefined ? undefined : props.sessionId))
|
|
230
|
+
throw new Error('Session ID is required to use a video from the process-video endpoint.');
|
|
231
|
+
const formData = new FormData();
|
|
232
|
+
if (video) {
|
|
233
|
+
formData.append('video', video);
|
|
234
|
+
}
|
|
235
|
+
formData.append('image', image);
|
|
236
|
+
const headers = {};
|
|
237
|
+
if (userFullName) {
|
|
238
|
+
headers['X-User-Fullname'] = userFullName;
|
|
239
|
+
}
|
|
240
|
+
if (usePrefilledVideo) {
|
|
241
|
+
headers['X-Use-Prefilled-Video'] = 'true';
|
|
242
|
+
}
|
|
243
|
+
if (props === null || props === undefined ? undefined : props.sessionId) {
|
|
244
|
+
headers['X-Session-ID'] = props.sessionId;
|
|
245
|
+
}
|
|
246
|
+
if (props === null || props === undefined ? undefined : props.deviceInfo) {
|
|
247
|
+
headers['X-Device-Info'] = JSON.stringify(props.deviceInfo);
|
|
248
|
+
}
|
|
249
|
+
return await this.request('/api-gateway/match-faces', 'POST', formData, headers);
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Process the video through Biometry services to check liveness and authorize user
|
|
253
|
+
*
|
|
254
|
+
* @param {File} video - Video file that you want to process.
|
|
255
|
+
* @param {string} phrase - Set of numbers that user needs to say out loud in the video.
|
|
256
|
+
* @param {string} userFullName - Pass the full name of end-user to process Voice and Face recognition services.
|
|
257
|
+
* @param {Object} [props] - Optional properties for the enrollment request.
|
|
258
|
+
* @param {string} [props.sessionId] - Session ID to link this enrollment with a specific session group.
|
|
259
|
+
* @param {object} [props.deviceInfo] - Device information object containing details about the user's device.
|
|
260
|
+
* This can include properties like operating system, browser, etc.
|
|
261
|
+
* @returns {Promise<ApiResponse<ProcessVideoResponse>>} - A promise resolving to the process video response.
|
|
262
|
+
*/
|
|
263
|
+
async processVideo(video, phrase, userFullName, props) {
|
|
264
|
+
if (!video)
|
|
265
|
+
throw new Error('Video is required.');
|
|
266
|
+
if (!phrase)
|
|
267
|
+
throw new Error('Phrase is required.');
|
|
268
|
+
const formData = new FormData();
|
|
269
|
+
formData.append('phrase', phrase);
|
|
270
|
+
formData.append('video', video);
|
|
271
|
+
const headers = {};
|
|
272
|
+
if (userFullName) {
|
|
273
|
+
headers['X-User-Fullname'] = userFullName;
|
|
274
|
+
}
|
|
275
|
+
if (props === null || props === undefined ? undefined : props.sessionId) {
|
|
276
|
+
headers['X-Session-ID'] = props.sessionId;
|
|
277
|
+
}
|
|
278
|
+
if (props === null || props === undefined ? undefined : props.deviceInfo) {
|
|
279
|
+
headers['X-Device-Info'] = JSON.stringify(props.deviceInfo);
|
|
280
|
+
}
|
|
281
|
+
return await this.request('/api-gateway/process-video', 'POST', formData, headers);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
BiometrySDK.BASE_URL = 'https://api.biometrysolutions.com'; //'https://dev-console.biometrysolutions.com';
|
|
285
|
+
|
|
286
|
+
export { BiometrySDK };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export declare class BiometryEnrollment extends HTMLElement {
|
|
2
2
|
private readonly shadow;
|
|
3
|
-
private sdk;
|
|
4
3
|
private videoElement;
|
|
5
4
|
private canvasElement;
|
|
6
5
|
private captureButton;
|
|
@@ -8,8 +7,8 @@ export declare class BiometryEnrollment extends HTMLElement {
|
|
|
8
7
|
private description?;
|
|
9
8
|
constructor();
|
|
10
9
|
static get observedAttributes(): string[];
|
|
11
|
-
get
|
|
12
|
-
set
|
|
10
|
+
get endpoint(): string | null;
|
|
11
|
+
set endpoint(value: string | null);
|
|
13
12
|
get userFullname(): string | null;
|
|
14
13
|
set userFullname(value: string | null);
|
|
15
14
|
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
@@ -18,9 +17,8 @@ export declare class BiometryEnrollment extends HTMLElement {
|
|
|
18
17
|
validateAttributes(): void;
|
|
19
18
|
init(): void;
|
|
20
19
|
private cleanup;
|
|
21
|
-
private initializeSDK;
|
|
22
|
-
private toggleState;
|
|
23
20
|
private attachSlotListeners;
|
|
24
21
|
private setupCamera;
|
|
25
22
|
private capturePhoto;
|
|
23
|
+
private toggleState;
|
|
26
24
|
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
export declare class ProcessVideoComponent extends HTMLElement {
|
|
2
|
-
private sdk;
|
|
3
|
-
private apiKey;
|
|
4
2
|
private phrase;
|
|
5
3
|
private previewStream;
|
|
6
4
|
private recordedChunks;
|
|
@@ -17,10 +15,10 @@ export declare class ProcessVideoComponent extends HTMLElement {
|
|
|
17
15
|
private errorState;
|
|
18
16
|
private timeLimit;
|
|
19
17
|
constructor();
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
get endpoint(): string | null;
|
|
19
|
+
set endpoint(value: string | null);
|
|
22
20
|
disconnectedCallback(): void;
|
|
23
|
-
attributeChangedCallback(name: string,
|
|
21
|
+
attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void;
|
|
24
22
|
private generateDefaultPhrase;
|
|
25
23
|
initializeUI(): void;
|
|
26
24
|
private attachSlotListeners;
|
|
@@ -45,7 +43,6 @@ export declare class ProcessVideoComponent extends HTMLElement {
|
|
|
45
43
|
get videoDuration(): number | null;
|
|
46
44
|
get currentFile(): File | null;
|
|
47
45
|
get currentStream(): MediaStream | null;
|
|
48
|
-
set sdkInstance(newSdk: any);
|
|
49
46
|
get videoElementRef(): HTMLVideoElement;
|
|
50
47
|
get fileInputRef(): HTMLInputElement;
|
|
51
48
|
get recordingTimeLimit(): number;
|
|
@@ -1,288 +1,3 @@
|
|
|
1
|
-
class BiometrySDK {
|
|
2
|
-
constructor(apiKey) {
|
|
3
|
-
if (!apiKey) {
|
|
4
|
-
throw new Error('API Key is required to initialize the SDK.');
|
|
5
|
-
}
|
|
6
|
-
this.apiKey = apiKey;
|
|
7
|
-
}
|
|
8
|
-
async request(path, method, body, headers) {
|
|
9
|
-
const defaultHeaders = {
|
|
10
|
-
Authorization: `Bearer ${this.apiKey}`,
|
|
11
|
-
};
|
|
12
|
-
const requestHeaders = Object.assign(Object.assign({}, defaultHeaders), headers);
|
|
13
|
-
if (body && !(body instanceof FormData)) {
|
|
14
|
-
requestHeaders['Content-Type'] = 'application/json';
|
|
15
|
-
body = JSON.stringify(body);
|
|
16
|
-
}
|
|
17
|
-
const response = await fetch(`${BiometrySDK.BASE_URL}${path}`, {
|
|
18
|
-
method,
|
|
19
|
-
headers: requestHeaders,
|
|
20
|
-
body,
|
|
21
|
-
});
|
|
22
|
-
if (!response.ok) {
|
|
23
|
-
const errorData = await response.json().catch(() => ({}));
|
|
24
|
-
const errorMessage = (errorData === null || errorData === undefined ? undefined : errorData.error) || (errorData === null || errorData === undefined ? undefined : errorData.message) || 'Unknown error occurred';
|
|
25
|
-
throw new Error(`Error ${response.status}: ${errorMessage}`);
|
|
26
|
-
}
|
|
27
|
-
// Extract response headers
|
|
28
|
-
const responseHeaders = {};
|
|
29
|
-
const requestId = response.headers.get("X-Request-Id");
|
|
30
|
-
if (requestId) {
|
|
31
|
-
responseHeaders["X-Request-Id"] = requestId;
|
|
32
|
-
}
|
|
33
|
-
const responseBody = await response.json();
|
|
34
|
-
return {
|
|
35
|
-
body: responseBody,
|
|
36
|
-
headers: responseHeaders
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Starts a new Session for a user.
|
|
41
|
-
*
|
|
42
|
-
* @returns {Promise<ApiResponse<SessionResponse>>} A promise resolving to the session ID.
|
|
43
|
-
* @throws {Error} - If the request fails.
|
|
44
|
-
*/
|
|
45
|
-
async startSession() {
|
|
46
|
-
return await this.request('/api-gateway/sessions/start', 'POST');
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Submits Authorization consent for a user.
|
|
50
|
-
* Authorization Consent is required to use the services like Face and Voice recognition.
|
|
51
|
-
*
|
|
52
|
-
* @param {boolean} isConsentGiven - Indicates whether the user has given consent.
|
|
53
|
-
* @param {string} userFullName - The full name of the user giving consent.
|
|
54
|
-
* @param {Object} [props] - Optional properties for the consent request.
|
|
55
|
-
* @param {string} [props.sessionId] - Session ID to link this consent with a specific session group.
|
|
56
|
-
* @param {object} [props.deviceInfo] - Device information object containing details about the user's device.
|
|
57
|
-
* This can include properties like operating system, browser, etc.
|
|
58
|
-
* @returns {Promise<ApiResponse<ConsentResponse>>} A promise resolving to the consent response.
|
|
59
|
-
* @throws {Error} - If the user's full name is not provided or if the request fails.
|
|
60
|
-
*/
|
|
61
|
-
async giveAuthorizationConsent(isConsentGiven, userFullName, props) {
|
|
62
|
-
if (!userFullName) {
|
|
63
|
-
throw new Error('User Full Name is required to give consent.');
|
|
64
|
-
}
|
|
65
|
-
const body = {
|
|
66
|
-
is_consent_given: isConsentGiven,
|
|
67
|
-
user_fullname: userFullName,
|
|
68
|
-
};
|
|
69
|
-
const headers = {};
|
|
70
|
-
if (props === null || props === undefined ? undefined : props.sessionId) {
|
|
71
|
-
headers['X-Session-ID'] = props.sessionId;
|
|
72
|
-
}
|
|
73
|
-
if (props === null || props === undefined ? undefined : props.deviceInfo) {
|
|
74
|
-
headers['X-Device-Info'] = JSON.stringify(props.deviceInfo);
|
|
75
|
-
}
|
|
76
|
-
return await this.request('/api-consent/consent', 'POST', body, headers);
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Submits Storage consent for a user.
|
|
80
|
-
* Storage consent is granted by users, allowing us to store their biometric data for future verification.
|
|
81
|
-
*
|
|
82
|
-
* @param {boolean} isStorageConsentGiven - Indicates whether the user has given storage consent.
|
|
83
|
-
* @param {string} userFullName - The full name of the user giving storage consent.
|
|
84
|
-
* @param {Object} [props] - Optional properties for the consent request.
|
|
85
|
-
* @param {string} [props.sessionId] - Session ID to link this consent with a specific session group.
|
|
86
|
-
* @param {object} [props.deviceInfo] - Device information object containing details about the user's device.
|
|
87
|
-
* This can include properties like operating system, browser, etc.
|
|
88
|
-
* @returns {Promise<ApiResponse<ConsentResponse>>} A promise resolving to the consent response.
|
|
89
|
-
* @throws {Error} - If the user's full name is not provided or if the request fails.
|
|
90
|
-
*/
|
|
91
|
-
async giveStorageConsent(isStorageConsentGiven, userFullName, props) {
|
|
92
|
-
if (!userFullName) {
|
|
93
|
-
throw new Error('User Full Name is required to give storage consent.');
|
|
94
|
-
}
|
|
95
|
-
const body = {
|
|
96
|
-
is_consent_given: isStorageConsentGiven,
|
|
97
|
-
user_fullname: userFullName,
|
|
98
|
-
};
|
|
99
|
-
const headers = {};
|
|
100
|
-
if (props === null || props === undefined ? undefined : props.sessionId) {
|
|
101
|
-
headers['X-Session-ID'] = props.sessionId;
|
|
102
|
-
}
|
|
103
|
-
if (props === null || props === undefined ? undefined : props.deviceInfo) {
|
|
104
|
-
headers['X-Device-Info'] = JSON.stringify(props.deviceInfo);
|
|
105
|
-
}
|
|
106
|
-
return await this.request('/api-consent/strg-consent', 'POST', body, headers);
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Enrolls a user's voice for biometric authentication.
|
|
110
|
-
*
|
|
111
|
-
* @param {File} audio - The audio file containing the user's voice.
|
|
112
|
-
* @param {string} userFullName - The full name of the user being enrolled.
|
|
113
|
-
* @param {string} uniqueId - A unique identifier for the enrolling process.
|
|
114
|
-
* @param {string} phrase - The phrase spoken in the audio file.
|
|
115
|
-
* @param {Object} [props] - Optional properties for the enrollment request.
|
|
116
|
-
* @param {string} [props.sessionId] - Session ID to link this enrollment with a specific session group.
|
|
117
|
-
* @param {object} [props.deviceInfo] - Device information object containing details about the user's device.
|
|
118
|
-
* This can include properties like operating system, browser, etc.
|
|
119
|
-
* @returns {Promise<ApiResponse<VoiceEnrollmentResponse>>} - A promise resolving to the voice enrolling response.
|
|
120
|
-
* @throws {Error} - If required parameters are missing or the request fails.
|
|
121
|
-
*/
|
|
122
|
-
async enrollVoice(audio, userFullName, uniqueId, phrase, props) {
|
|
123
|
-
if (!userFullName)
|
|
124
|
-
throw new Error('User fullname is required.');
|
|
125
|
-
if (!uniqueId)
|
|
126
|
-
throw new Error('Unique ID is required.');
|
|
127
|
-
if (!phrase)
|
|
128
|
-
throw new Error('Phrase is required.');
|
|
129
|
-
if (!audio)
|
|
130
|
-
throw new Error('Audio file is required.');
|
|
131
|
-
const formData = new FormData();
|
|
132
|
-
formData.append('unique_id', uniqueId);
|
|
133
|
-
formData.append('phrase', phrase);
|
|
134
|
-
formData.append('voice', audio);
|
|
135
|
-
const headers = {
|
|
136
|
-
'X-User-Fullname': userFullName,
|
|
137
|
-
};
|
|
138
|
-
if (props === null || props === undefined ? undefined : props.sessionId) {
|
|
139
|
-
headers['X-Session-ID'] = props.sessionId;
|
|
140
|
-
}
|
|
141
|
-
if (props === null || props === undefined ? undefined : props.deviceInfo) {
|
|
142
|
-
headers['X-Device-Info'] = JSON.stringify(props.deviceInfo);
|
|
143
|
-
}
|
|
144
|
-
return await this.request('/api-gateway/enroll/voice', 'POST', formData, headers);
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Enrolls a user's face for biometric authentication.
|
|
148
|
-
*
|
|
149
|
-
* @param {File} face - Image file that contains user's face.
|
|
150
|
-
* @param {string} userFullName - The full name of the user being enrolled.
|
|
151
|
-
* @param {string} isDocument - Indicates whether the image is a document.
|
|
152
|
-
* @param {Object} [props] - Optional properties for the enrollment request.
|
|
153
|
-
* @param {string} [props.sessionId] - Session ID to link this enrollment with a specific session group.
|
|
154
|
-
* @param {object} [props.deviceInfo] - Device information object containing details about the user's device.
|
|
155
|
-
* This can include properties like operating system, browser, etc.
|
|
156
|
-
* @returns {Promise<ApiResponse<FaceEnrollmentResponse>>} - A promise resolving to the voice enrolling response.
|
|
157
|
-
* @throws {Error} - If required parameters are missing or the request fails.
|
|
158
|
-
*/
|
|
159
|
-
async enrollFace(face, userFullName, isDocument, props) {
|
|
160
|
-
if (!userFullName)
|
|
161
|
-
throw new Error('User fullname is required.');
|
|
162
|
-
if (!face)
|
|
163
|
-
throw new Error('Face image is required.');
|
|
164
|
-
const formData = new FormData();
|
|
165
|
-
formData.append('face', face);
|
|
166
|
-
if (isDocument) {
|
|
167
|
-
formData.append('is_document', 'true');
|
|
168
|
-
}
|
|
169
|
-
const headers = {
|
|
170
|
-
'X-User-Fullname': userFullName,
|
|
171
|
-
};
|
|
172
|
-
if (props === null || props === undefined ? undefined : props.sessionId) {
|
|
173
|
-
headers['X-Session-ID'] = props.sessionId;
|
|
174
|
-
}
|
|
175
|
-
if (props === null || props === undefined ? undefined : props.deviceInfo) {
|
|
176
|
-
headers['X-Device-Info'] = JSON.stringify(props.deviceInfo);
|
|
177
|
-
}
|
|
178
|
-
return await this.request('/api-gateway/enroll/face', 'POST', formData, headers);
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Check the validity of a documents.
|
|
182
|
-
*
|
|
183
|
-
* @param {File} document - Document image file.
|
|
184
|
-
* @param {string} userFullName - The full name of the user being checked.
|
|
185
|
-
* @param {Object} [props] - Optional properties for the enrollment request.
|
|
186
|
-
* @param {string} [props.sessionId] - Session ID to link this enrollment with a specific session group.
|
|
187
|
-
* @param {object} [props.deviceInfo] - Device information object containing details about the user's device.
|
|
188
|
-
* This can include properties like operating system, browser, etc.
|
|
189
|
-
* @returns {Promise<ApiResponse<DocAuthInfo>>} - A promise resolving to the document authentication information.
|
|
190
|
-
*/
|
|
191
|
-
async checkDocAuth(document, userFullName, props) {
|
|
192
|
-
if (!document)
|
|
193
|
-
throw new Error('Document image is required.');
|
|
194
|
-
if (!userFullName)
|
|
195
|
-
throw new Error('User fullname is required.');
|
|
196
|
-
const formData = new FormData();
|
|
197
|
-
formData.append('document', document);
|
|
198
|
-
const headers = {
|
|
199
|
-
'X-User-Fullname': userFullName,
|
|
200
|
-
};
|
|
201
|
-
if (props === null || props === undefined ? undefined : props.sessionId) {
|
|
202
|
-
headers['X-Session-ID'] = props.sessionId;
|
|
203
|
-
}
|
|
204
|
-
if (props === null || props === undefined ? undefined : props.deviceInfo) {
|
|
205
|
-
headers['X-Device-Info'] = JSON.stringify(props.deviceInfo);
|
|
206
|
-
}
|
|
207
|
-
return await this.request('/api-gateway/check-doc-auth', 'POST', formData, headers);
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Matches a user's face from video against a reference image.
|
|
211
|
-
*
|
|
212
|
-
* @param {File} image - Reference image file that contains user's face.
|
|
213
|
-
* @param {string} video - Video file that contains user's face.
|
|
214
|
-
* @param {string} userFullName - Pass the full name of end-user to process Voice and Face recognition services.
|
|
215
|
-
* @param {string} processVideoRequestId - ID from the response header of /process-video endpoint.
|
|
216
|
-
* @param {boolean} usePrefilledVideo - Pass true to use the video from the process-video endpoint.
|
|
217
|
-
* @param {Object} [props] - Optional properties for the enrollment request.
|
|
218
|
-
* @param {string} [props.sessionId] - Session ID to link this enrollment with a specific session group.
|
|
219
|
-
* @param {object} [props.deviceInfo] - Device information object containing details about the user's device.
|
|
220
|
-
* This can include properties like operating system, browser, etc.
|
|
221
|
-
* @returns {Promise<FaceMatchResponse>} - A promise resolving to the voice enrolling response.
|
|
222
|
-
* @throws {Error} - If required parameters are missing or the request fails.
|
|
223
|
-
*/
|
|
224
|
-
async matchFaces(image, video, userFullName, usePrefilledVideo, props) {
|
|
225
|
-
if (!image)
|
|
226
|
-
throw new Error('Face image is required.');
|
|
227
|
-
if ((!usePrefilledVideo) && !video)
|
|
228
|
-
throw new Error('Video is required.');
|
|
229
|
-
if (usePrefilledVideo && !(props === null || props === undefined ? undefined : props.sessionId))
|
|
230
|
-
throw new Error('Session ID is required to use a video from the process-video endpoint.');
|
|
231
|
-
const formData = new FormData();
|
|
232
|
-
if (video) {
|
|
233
|
-
formData.append('video', video);
|
|
234
|
-
}
|
|
235
|
-
formData.append('image', image);
|
|
236
|
-
const headers = {};
|
|
237
|
-
if (userFullName) {
|
|
238
|
-
headers['X-User-Fullname'] = userFullName;
|
|
239
|
-
}
|
|
240
|
-
if (usePrefilledVideo) {
|
|
241
|
-
headers['X-Use-Prefilled-Video'] = 'true';
|
|
242
|
-
}
|
|
243
|
-
if (props === null || props === undefined ? undefined : props.sessionId) {
|
|
244
|
-
headers['X-Session-ID'] = props.sessionId;
|
|
245
|
-
}
|
|
246
|
-
if (props === null || props === undefined ? undefined : props.deviceInfo) {
|
|
247
|
-
headers['X-Device-Info'] = JSON.stringify(props.deviceInfo);
|
|
248
|
-
}
|
|
249
|
-
return await this.request('/api-gateway/match-faces', 'POST', formData, headers);
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* Process the video through Biometry services to check liveness and authorize user
|
|
253
|
-
*
|
|
254
|
-
* @param {File} video - Video file that you want to process.
|
|
255
|
-
* @param {string} phrase - Set of numbers that user needs to say out loud in the video.
|
|
256
|
-
* @param {string} userFullName - Pass the full name of end-user to process Voice and Face recognition services.
|
|
257
|
-
* @param {Object} [props] - Optional properties for the enrollment request.
|
|
258
|
-
* @param {string} [props.sessionId] - Session ID to link this enrollment with a specific session group.
|
|
259
|
-
* @param {object} [props.deviceInfo] - Device information object containing details about the user's device.
|
|
260
|
-
* This can include properties like operating system, browser, etc.
|
|
261
|
-
* @returns {Promise<ApiResponse<ProcessVideoResponse>>} - A promise resolving to the process video response.
|
|
262
|
-
*/
|
|
263
|
-
async processVideo(video, phrase, userFullName, props) {
|
|
264
|
-
if (!video)
|
|
265
|
-
throw new Error('Video is required.');
|
|
266
|
-
if (!phrase)
|
|
267
|
-
throw new Error('Phrase is required.');
|
|
268
|
-
const formData = new FormData();
|
|
269
|
-
formData.append('phrase', phrase);
|
|
270
|
-
formData.append('video', video);
|
|
271
|
-
const headers = {};
|
|
272
|
-
if (userFullName) {
|
|
273
|
-
headers['X-User-Fullname'] = userFullName;
|
|
274
|
-
}
|
|
275
|
-
if (props === null || props === undefined ? undefined : props.sessionId) {
|
|
276
|
-
headers['X-Session-ID'] = props.sessionId;
|
|
277
|
-
}
|
|
278
|
-
if (props === null || props === undefined ? undefined : props.deviceInfo) {
|
|
279
|
-
headers['X-Device-Info'] = JSON.stringify(props.deviceInfo);
|
|
280
|
-
}
|
|
281
|
-
return await this.request('/api-gateway/process-video', 'POST', formData, headers);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
BiometrySDK.BASE_URL = 'https://api.biometrysolutions.com'; //'https://dev-console.biometrysolutions.com';
|
|
285
|
-
|
|
286
1
|
var BiometryAttributes;
|
|
287
2
|
(function (BiometryAttributes) {
|
|
288
3
|
BiometryAttributes["ApiKey"] = "api-key";
|
|
@@ -305,22 +20,22 @@ class BiometryEnrollment extends HTMLElement {
|
|
|
305
20
|
this.canvasElement = null;
|
|
306
21
|
this.captureButton = null;
|
|
307
22
|
this.shadow = this.attachShadow({ mode: "open" });
|
|
308
|
-
this.sdk = null;
|
|
309
23
|
this.toggleState = this.toggleState.bind(this);
|
|
310
24
|
this.capturePhoto = this.capturePhoto.bind(this);
|
|
311
25
|
}
|
|
312
26
|
static get observedAttributes() {
|
|
313
27
|
return Object.values(BiometryAttributes);
|
|
314
28
|
}
|
|
315
|
-
get
|
|
316
|
-
return this.getAttribute("
|
|
29
|
+
get endpoint() {
|
|
30
|
+
return this.getAttribute("endpoint");
|
|
317
31
|
}
|
|
318
|
-
set
|
|
319
|
-
|
|
320
|
-
|
|
32
|
+
set endpoint(value) {
|
|
33
|
+
const current = this.getAttribute("endpoint");
|
|
34
|
+
if (value !== null && value !== current) {
|
|
35
|
+
this.setAttribute("endpoint", value);
|
|
321
36
|
}
|
|
322
|
-
else {
|
|
323
|
-
this.removeAttribute("
|
|
37
|
+
else if (value === null && current !== null) {
|
|
38
|
+
this.removeAttribute("endpoint");
|
|
324
39
|
}
|
|
325
40
|
}
|
|
326
41
|
get userFullname() {
|
|
@@ -335,7 +50,13 @@ class BiometryEnrollment extends HTMLElement {
|
|
|
335
50
|
}
|
|
336
51
|
}
|
|
337
52
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
338
|
-
if (name === "
|
|
53
|
+
if (name === "endpoint" || name === "user-fullname") {
|
|
54
|
+
if (name === "endpoint") {
|
|
55
|
+
this.endpoint = newValue;
|
|
56
|
+
}
|
|
57
|
+
else if (name === "user-fullname") {
|
|
58
|
+
this.userFullname = newValue;
|
|
59
|
+
}
|
|
339
60
|
this.validateAttributes();
|
|
340
61
|
}
|
|
341
62
|
}
|
|
@@ -345,10 +66,13 @@ class BiometryEnrollment extends HTMLElement {
|
|
|
345
66
|
}
|
|
346
67
|
disconnectedCallback() {
|
|
347
68
|
this.cleanup();
|
|
69
|
+
if (this.captureButton) {
|
|
70
|
+
this.captureButton.removeEventListener("click", this.capturePhoto);
|
|
71
|
+
}
|
|
348
72
|
}
|
|
349
73
|
validateAttributes() {
|
|
350
|
-
if (!this.
|
|
351
|
-
console.error("
|
|
74
|
+
if (!this.endpoint) {
|
|
75
|
+
console.error("Endpoint is required.");
|
|
352
76
|
this.toggleState(BiometryEnrollmentState.ErrorOther);
|
|
353
77
|
return;
|
|
354
78
|
}
|
|
@@ -393,7 +117,6 @@ class BiometryEnrollment extends HTMLElement {
|
|
|
393
117
|
</div>
|
|
394
118
|
</div>
|
|
395
119
|
`;
|
|
396
|
-
this.initializeSDK();
|
|
397
120
|
this.attachSlotListeners();
|
|
398
121
|
this.setupCamera();
|
|
399
122
|
this.toggleState("");
|
|
@@ -408,31 +131,6 @@ class BiometryEnrollment extends HTMLElement {
|
|
|
408
131
|
this.videoElement.srcObject = null;
|
|
409
132
|
}
|
|
410
133
|
}
|
|
411
|
-
initializeSDK() {
|
|
412
|
-
if (this.apiKey) {
|
|
413
|
-
this.sdk = new BiometrySDK(this.apiKey);
|
|
414
|
-
}
|
|
415
|
-
else {
|
|
416
|
-
this.toggleState(BiometryEnrollmentState.ErrorOther);
|
|
417
|
-
console.error("API key is required to initialize the SDK.");
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
toggleState(state) {
|
|
421
|
-
const slots = [
|
|
422
|
-
BiometryEnrollmentState.Loading,
|
|
423
|
-
BiometryEnrollmentState.Success,
|
|
424
|
-
BiometryEnrollmentState.ErrorNoFace,
|
|
425
|
-
BiometryEnrollmentState.ErrorMultipleFaces,
|
|
426
|
-
BiometryEnrollmentState.ErrorNotCentered,
|
|
427
|
-
BiometryEnrollmentState.ErrorOther,
|
|
428
|
-
];
|
|
429
|
-
slots.forEach((slotName) => {
|
|
430
|
-
const slot = this.shadow.querySelector(`slot[name="${slotName}"]`);
|
|
431
|
-
if (slot) {
|
|
432
|
-
slot.style.display = slotName === state ? "block" : "none";
|
|
433
|
-
}
|
|
434
|
-
});
|
|
435
|
-
}
|
|
436
134
|
attachSlotListeners() {
|
|
437
135
|
const videoSlot = this.shadow.querySelector('slot[name="video"]');
|
|
438
136
|
const canvasSlot = this.shadow.querySelector('slot[name="canvas"]');
|
|
@@ -471,8 +169,8 @@ class BiometryEnrollment extends HTMLElement {
|
|
|
471
169
|
}
|
|
472
170
|
async capturePhoto() {
|
|
473
171
|
try {
|
|
474
|
-
if (!this.videoElement || !this.canvasElement
|
|
475
|
-
console.error("Essential elements
|
|
172
|
+
if (!this.videoElement || !this.canvasElement) {
|
|
173
|
+
console.error("Essential elements are not initialized.");
|
|
476
174
|
return;
|
|
477
175
|
}
|
|
478
176
|
const context = this.canvasElement.getContext("2d");
|
|
@@ -488,33 +186,36 @@ class BiometryEnrollment extends HTMLElement {
|
|
|
488
186
|
return;
|
|
489
187
|
}
|
|
490
188
|
const file = new File([blob], "onboard-face.jpg", { type: "image/jpeg" });
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
case 1:
|
|
501
|
-
this.toggleState(BiometryEnrollmentState.ErrorNoFace);
|
|
502
|
-
break;
|
|
503
|
-
case 2:
|
|
504
|
-
this.toggleState(BiometryEnrollmentState.ErrorMultipleFaces);
|
|
505
|
-
break;
|
|
506
|
-
case 3:
|
|
507
|
-
this.toggleState(BiometryEnrollmentState.ErrorNotCentered);
|
|
508
|
-
break;
|
|
509
|
-
default:
|
|
510
|
-
this.toggleState(BiometryEnrollmentState.ErrorOther);
|
|
511
|
-
}
|
|
512
|
-
console.log("Enrollment result:", result);
|
|
189
|
+
const formData = new FormData();
|
|
190
|
+
formData.append('photo', file);
|
|
191
|
+
formData.append('userFullname', this.userFullname || '');
|
|
192
|
+
const response = await fetch(this.endpoint, {
|
|
193
|
+
method: 'POST',
|
|
194
|
+
body: formData
|
|
195
|
+
});
|
|
196
|
+
if (!response.ok) {
|
|
197
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
513
198
|
}
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
199
|
+
const result = await response.json();
|
|
200
|
+
this.resultCode = result === null || result === void 0 ? void 0 : result.code;
|
|
201
|
+
this.description = (result === null || result === void 0 ? void 0 : result.description) || "Unknown error occurred.";
|
|
202
|
+
switch (this.resultCode) {
|
|
203
|
+
case 0:
|
|
204
|
+
this.toggleState(BiometryEnrollmentState.Success);
|
|
205
|
+
break;
|
|
206
|
+
case 1:
|
|
207
|
+
this.toggleState(BiometryEnrollmentState.ErrorNoFace);
|
|
208
|
+
break;
|
|
209
|
+
case 2:
|
|
210
|
+
this.toggleState(BiometryEnrollmentState.ErrorMultipleFaces);
|
|
211
|
+
break;
|
|
212
|
+
case 3:
|
|
213
|
+
this.toggleState(BiometryEnrollmentState.ErrorNotCentered);
|
|
214
|
+
break;
|
|
215
|
+
default:
|
|
216
|
+
this.toggleState(BiometryEnrollmentState.ErrorOther);
|
|
517
217
|
}
|
|
218
|
+
console.log("Enrollment result:", result);
|
|
518
219
|
}
|
|
519
220
|
catch (error) {
|
|
520
221
|
console.error("Error in toBlob callback:", error);
|
|
@@ -527,6 +228,22 @@ class BiometryEnrollment extends HTMLElement {
|
|
|
527
228
|
this.toggleState(BiometryEnrollmentState.ErrorOther);
|
|
528
229
|
}
|
|
529
230
|
}
|
|
231
|
+
toggleState(state) {
|
|
232
|
+
const slots = [
|
|
233
|
+
BiometryEnrollmentState.Loading,
|
|
234
|
+
BiometryEnrollmentState.Success,
|
|
235
|
+
BiometryEnrollmentState.ErrorNoFace,
|
|
236
|
+
BiometryEnrollmentState.ErrorMultipleFaces,
|
|
237
|
+
BiometryEnrollmentState.ErrorNotCentered,
|
|
238
|
+
BiometryEnrollmentState.ErrorOther,
|
|
239
|
+
];
|
|
240
|
+
slots.forEach((slotName) => {
|
|
241
|
+
const slot = this.shadow.querySelector(`slot[name="${slotName}"]`);
|
|
242
|
+
if (slot) {
|
|
243
|
+
slot.style.display = slotName === state ? "block" : "none";
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
}
|
|
530
247
|
}
|
|
531
248
|
customElements.define("biometry-enrollment", BiometryEnrollment);
|
|
532
249
|
|
|
@@ -1063,7 +780,6 @@ var ysFixWebmDuration = /*@__PURE__*/getDefaultExportFromCjs(fixWebmDurationExpo
|
|
|
1063
780
|
class ProcessVideoComponent extends HTMLElement {
|
|
1064
781
|
constructor() {
|
|
1065
782
|
super();
|
|
1066
|
-
this.apiKey = null;
|
|
1067
783
|
this.previewStream = null;
|
|
1068
784
|
this.recordedChunks = [];
|
|
1069
785
|
this.mediaRecorder = null;
|
|
@@ -1076,25 +792,18 @@ class ProcessVideoComponent extends HTMLElement {
|
|
|
1076
792
|
this.phrase = this.generateDefaultPhrase();
|
|
1077
793
|
// Attach shadow DOM and initialize UI
|
|
1078
794
|
this.attachShadow({ mode: 'open' });
|
|
1079
|
-
this.apiKey = this.getAttribute('api-key');
|
|
1080
|
-
this.initializeSDK();
|
|
1081
795
|
this.initializeUI();
|
|
1082
796
|
}
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
this.sdk = new BiometrySDK(this.apiKey);
|
|
1086
|
-
}
|
|
1087
|
-
else {
|
|
1088
|
-
this.toggleState('error');
|
|
1089
|
-
console.error('API key is required to initialize the SDK.');
|
|
1090
|
-
}
|
|
797
|
+
get endpoint() {
|
|
798
|
+
return this.getAttribute("endpoint");
|
|
1091
799
|
}
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
800
|
+
set endpoint(value) {
|
|
801
|
+
const current = this.getAttribute("endpoint");
|
|
802
|
+
if (value !== null && value !== current) {
|
|
803
|
+
this.setAttribute("endpoint", value);
|
|
1095
804
|
}
|
|
1096
|
-
else {
|
|
1097
|
-
|
|
805
|
+
else if (value === null && current !== null) {
|
|
806
|
+
this.removeAttribute("endpoint");
|
|
1098
807
|
}
|
|
1099
808
|
}
|
|
1100
809
|
disconnectedCallback() {
|
|
@@ -1103,10 +812,9 @@ class ProcessVideoComponent extends HTMLElement {
|
|
|
1103
812
|
this.previewStream.getTracks().forEach(track => track.stop());
|
|
1104
813
|
}
|
|
1105
814
|
}
|
|
1106
|
-
attributeChangedCallback(name,
|
|
1107
|
-
if (name === '
|
|
1108
|
-
this.
|
|
1109
|
-
this.initializeSDK();
|
|
815
|
+
attributeChangedCallback(name, _oldValue, newValue) {
|
|
816
|
+
if (name === 'endpoint' && newValue !== this.endpoint) {
|
|
817
|
+
this.endpoint = newValue;
|
|
1110
818
|
}
|
|
1111
819
|
}
|
|
1112
820
|
generateDefaultPhrase() {
|
|
@@ -1409,7 +1117,6 @@ class ProcessVideoComponent extends HTMLElement {
|
|
|
1409
1117
|
this.recordButton.disabled = false;
|
|
1410
1118
|
this.stopButton.disabled = true;
|
|
1411
1119
|
this.mediaRecorder = null;
|
|
1412
|
-
this.recordedChunks = [];
|
|
1413
1120
|
this.previewStream = null;
|
|
1414
1121
|
}
|
|
1415
1122
|
catch (error) {
|
|
@@ -1419,6 +1126,7 @@ class ProcessVideoComponent extends HTMLElement {
|
|
|
1419
1126
|
onStopMediaRecorder(blob) {
|
|
1420
1127
|
const videoURL = URL.createObjectURL(blob);
|
|
1421
1128
|
this.videoFile = new File([blob], 'recorded_video.webm', { type: 'video/webm' });
|
|
1129
|
+
this.recordedChunks = [];
|
|
1422
1130
|
this.videoElement.src = videoURL;
|
|
1423
1131
|
this.videoElement.controls = true;
|
|
1424
1132
|
this.videoElement.play();
|
|
@@ -1453,16 +1161,31 @@ class ProcessVideoComponent extends HTMLElement {
|
|
|
1453
1161
|
console.error('No video file to submit.');
|
|
1454
1162
|
return;
|
|
1455
1163
|
}
|
|
1456
|
-
if (!this.
|
|
1164
|
+
if (!this.endpoint) {
|
|
1457
1165
|
this.toggleState('error');
|
|
1458
|
-
console.error('
|
|
1166
|
+
console.error('Endpoint must be provided.');
|
|
1167
|
+
return;
|
|
1168
|
+
}
|
|
1169
|
+
if (!this.userFullname) {
|
|
1170
|
+
this.toggleState('error');
|
|
1171
|
+
console.error('User full name must be provided.');
|
|
1459
1172
|
return;
|
|
1460
1173
|
}
|
|
1461
1174
|
this.toggleState('loading');
|
|
1462
1175
|
try {
|
|
1463
|
-
const
|
|
1464
|
-
|
|
1465
|
-
|
|
1176
|
+
const formData = new FormData();
|
|
1177
|
+
formData.append('video', this.videoFile);
|
|
1178
|
+
formData.append('phrase', this.convertPhraseToWords(this.phrase));
|
|
1179
|
+
formData.append('userFullname', this.userFullname);
|
|
1180
|
+
const response = await fetch(this.endpoint, {
|
|
1181
|
+
method: 'POST',
|
|
1182
|
+
body: formData
|
|
1183
|
+
});
|
|
1184
|
+
if (!response.ok) {
|
|
1185
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
1186
|
+
}
|
|
1187
|
+
const result = await response.json();
|
|
1188
|
+
console.log('Response from endpoint:', result);
|
|
1466
1189
|
this.toggleState('success');
|
|
1467
1190
|
}
|
|
1468
1191
|
catch (error) {
|
|
@@ -1471,7 +1194,7 @@ class ProcessVideoComponent extends HTMLElement {
|
|
|
1471
1194
|
}
|
|
1472
1195
|
}
|
|
1473
1196
|
static get observedAttributes() {
|
|
1474
|
-
return ['
|
|
1197
|
+
return ['endpoint', 'user-fullname'];
|
|
1475
1198
|
}
|
|
1476
1199
|
get userFullname() {
|
|
1477
1200
|
return this.getAttribute('user-fullname');
|
|
@@ -1501,9 +1224,6 @@ class ProcessVideoComponent extends HTMLElement {
|
|
|
1501
1224
|
get currentStream() {
|
|
1502
1225
|
return this.previewStream;
|
|
1503
1226
|
}
|
|
1504
|
-
set sdkInstance(newSdk) {
|
|
1505
|
-
this.sdk = newSdk;
|
|
1506
|
-
}
|
|
1507
1227
|
get videoElementRef() {
|
|
1508
1228
|
return this.videoElement;
|
|
1509
1229
|
}
|
|
@@ -1525,4 +1245,4 @@ class ProcessVideoComponent extends HTMLElement {
|
|
|
1525
1245
|
}
|
|
1526
1246
|
customElements.define('process-video', ProcessVideoComponent);
|
|
1527
1247
|
|
|
1528
|
-
export { BiometryEnrollment,
|
|
1248
|
+
export { BiometryEnrollment, ProcessVideoComponent };
|
package/package.json
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "biometry-sdk",
|
|
3
|
-
"version": "
|
|
4
|
-
"main": "dist/biometry-sdk.esm.js",
|
|
5
|
-
"types": "dist/index.d.ts",
|
|
6
|
-
"module": "dist/biometry-sdk.esm.js",
|
|
7
|
-
"browser": "dist/biometry-sdk.esm.js",
|
|
3
|
+
"version": "2.0.0",
|
|
8
4
|
"type": "module",
|
|
5
|
+
"main": "dist/sdk.js",
|
|
6
|
+
"module": "dist/sdk.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/sdk.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
},
|
|
13
|
+
"./sdk": {
|
|
14
|
+
"import": "./dist/sdk.js",
|
|
15
|
+
"types": "./dist/index.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"./ui": {
|
|
18
|
+
"import": "./dist/ui.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
9
21
|
"files": [
|
|
10
22
|
"dist/**/*",
|
|
11
23
|
"README.md"
|
|
File without changes
|
|
File without changes
|