@dydydm/ekyc-sdk
v0.3.2
Published
eKYC SDK - Client SDK for eKYC verification API
Maintainers
Readme
@dydydm/ekyc-sdk
SDK xác minh danh tính điện tử (eKYC) cho JavaScript/TypeScript — OCR giấy tờ, Liveness Detection, Face Match.
API tương thích với VNPT eKYC SDK.
I. TỔNG QUAN
1. Mục đích
Tài liệu này mô tả chi tiết cách tích hợp SDK @dydydm/ekyc-sdk vào dự án Web hoặc Node.js để thực hiện xác minh danh tính điện tử.
2. Phạm vi
SDK hỗ trợ các chức năng:
- OCR — Bóc tách thông tin từ giấy tờ tùy thân (CMND/CCCD/Hộ chiếu/GPLX)
- Liveness Detection — Kiểm tra chân dung chụp trực tiếp (chống giả mạo)
- Face Match — So sánh khuôn mặt ảnh chân dung và ảnh trên giấy tờ
3. Cài đặt
npm install @dydydm/ekyc-sdkII. TÍCH HỢP SDK VÀO DỰ ÁN
1. Khởi tạo
import { EkycClient } from '@dydydm/ekyc-sdk';
const client = new EkycClient({
baseUrl: 'https://api-dev.x-or.cloud/ekyc',
apiKey: 'your-api-key',
});Khởi tạo kiểu VNPT (tokenId/tokenKey):
const client = new EkycClient({
baseUrl: 'https://api-dev.x-or.cloud/ekyc',
apiKey: '',
tokenId: 'your-token-id',
tokenKey: 'your-token-key',
authorization: 'Bearer your-access-token',
});2. Cách sử dụng
- Khởi tạo
EkycClientvà cài đặt các thuộc tính - Gọi
client.start(files, options)để thực hiện eKYC theo luồng - Dữ liệu sau khi xử lý được trả về qua kết quả
EkycResult - Cấu trúc kết quả tương đương VNPT
icEkycGetResult
III. CÁC LUỒNG EKYC CHÍNH
1. Luồng eKYC đầy đủ — full
a. Mô tả
- Bước 1: Tải ảnh giấy tờ mặt trước
- Bước 2: Tải ảnh giấy tờ mặt sau
- Bước 3: Tải ảnh chân dung
- Bước 4: SDK thực hiện OCR, Liveness, Face Match → Trả kết quả
Lưu ý:
- Đối với Hộ chiếu và Bằng lái xe, bỏ qua ảnh mặt sau
- Kết quả trả về qua
EkycResult(tương đương VNPTicEkycGetResult)
b. Mã nguồn tham khảo
const result = await client.start(
{
idFront: idFrontFile, // File | Blob — ảnh mặt trước (bắt buộc)
idBack: idBackFile, // File | Blob — ảnh mặt sau (tuỳ chọn)
selfie: selfieFile, // File | Blob — ảnh chân dung (bắt buộc)
livenessFrames: [ // Liveness frames (tuỳ chọn)
{ file: frame1, action: 'center' },
{ file: frame2, action: 'turn_left' },
{ file: frame3, action: 'turn_right' },
],
},
{
flowType: 'full', // Luồng đầy đủ
documentType: 'IdentityCard', // Loại giấy tờ
isEnableCompare: true, // Bật so sánh khuôn mặt
checkLivenessFace: 'IBeta', // Kiểm tra liveness chân dung
ocrEngine: 'surya', // Engine OCR
challengeCode: 'INNOVATIONCENTER', // Mã challenge
onStep: (step, detail) => {
console.log(`[${step}]`, detail);
},
},
);
// Kết quả — tương đương VNPT icEkycGetResult
console.log(result.ocrResult); // Kết quả OCR
console.log(result.compareFaceResult); // Kết quả so sánh khuôn mặt
console.log(result.livenessFaceResult); // Kết quả liveness
console.log(result.hashImageFront); // Mã ảnh mặt trước
console.log(result.hashImageBack); // Mã ảnh mặt sau
console.log(result.hashImageFace); // Mã ảnh chân dung
console.log(result.clientSessionResult); // Session ID
console.log(result.networkProblem); // Lỗi mạng (rỗng = thành công)2. Luồng OCR giấy tờ — ocr
a. Mô tả
- Bước 1: Tải ảnh giấy tờ mặt trước
- Bước 2: Tải ảnh giấy tờ mặt sau
- Bước 3: SDK thực hiện OCR → Trả kết quả
Lưu ý: Đối với Hộ chiếu và Bằng lái xe, bỏ qua mặt sau.
b. Mã nguồn tham khảo
const result = await client.start(
{
idFront: idFrontFile,
idBack: idBackFile,
},
{
flowType: 'ocr',
documentType: 'IdentityCard',
ocrEngine: 'surya',
},
);
console.log(result.ocrResult); // Kết quả OCR3. Luồng OCR mặt trước — ocrFront
a. Mô tả
- Bước 1: Tải ảnh giấy tờ mặt trước
- Bước 2: SDK thực hiện OCR mặt trước → Trả kết quả
b. Mã nguồn tham khảo
const result = await client.start(
{ idFront: idFrontFile },
{ flowType: 'ocrFront', ocrEngine: 'surya' },
);4. Luồng OCR mặt sau — ocrBack
a. Mô tả
- Bước 1: Tải ảnh giấy tờ mặt sau
- Bước 2: SDK thực hiện OCR mặt sau → Trả kết quả
b. Mã nguồn tham khảo
const result = await client.start(
{ idBack: idBackFile },
{ flowType: 'ocrBack', ocrEngine: 'surya' },
);5. Luồng kiểm tra khuôn mặt — face
a. Mô tả
- Bước 1: Tải ảnh chân dung
- Bước 2: SDK thực hiện Liveness + Face Match → Trả kết quả
Lưu ý: Cần đã upload ảnh giấy tờ (ID_FRONT) trước đó trong cùng session nếu muốn Face Match.
b. Mã nguồn tham khảo
const result = await client.start(
{
selfie: selfieFile,
livenessFrames: [
{ file: frame1, action: 'center' },
{ file: frame2, action: 'turn_left' },
],
},
{
flowType: 'face',
isEnableCompare: true,
checkLivenessFace: 'IBeta',
},
);
console.log(result.livenessFaceResult); // Kết quả liveness
console.log(result.compareFaceResult); // Kết quả face matchIV. SỬ DỤNG TỪNG BƯỚC (Step-by-step)
Khi cần kiểm soát chi tiết từng bước (ví dụ: webcam capture, upload từng frame).
1. Tạo session
const deviceContext = EkycClient.detectDevice();
const session = await client.session.create({
deviceContext,
challengeCode: 'INNOVATIONCENTER',
documentType: 'IdentityCard',
flowType: 'full',
});
const sessionId = session.sessionId;2. Upload ảnh
// Mặt trước
const front = await client.artifact.upload(sessionId, idFrontFile, 'ID_FRONT', {
onProgress: (p) => console.log(`${p.percent}%`),
});
// Mặt sau
const back = await client.artifact.upload(sessionId, idBackFile, 'ID_BACK');
// Chân dung + liveness action
const selfie = await client.artifact.upload(sessionId, frameBlob, 'SELFIE', {
action: 'center',
});3. Chạy OCR
const ocr = await client.task.ocr(sessionId, { ocrEngine: 'surya' });4. Kiểm tra liveness từng frame
const lv = await client.task.liveness(sessionId, selfie.artifactId, 'center');
console.log(lv.passed, lv.decision, lv.score);5. Kiểm tra liveness batch
const lvBatch = await client.task.livenessBatch(sessionId);6. So sánh khuôn mặt
const fm = await client.task.faceMatch(sessionId);7. Lấy tất cả kết quả
const { data } = await client.task.getResults(sessionId);V. CÁC THUỘC TÍNH ĐẦU VÀO
1. Cấu hình SDK — EkycConfig
| Thuộc tính | Kiểu dữ liệu | Bắt buộc | Mặc định | Mô tả |
|---|---|---|---|---|
| baseUrl | string | ✅ | — | Địa chỉ API server |
| apiKey | string | ✅* | — | API Key xác thực. *Không bắt buộc nếu dùng tokenId/tokenKey |
| tokenId | string | ❌ | "" | Token ID (VNPT-compatible) |
| tokenKey | string | ❌ | "" | Token Key (VNPT-compatible) |
| authorization | string | ❌ | "" | Authorization token (VNPT-compatible) |
| timeout | number | ❌ | 30000 | Timeout mỗi request (ms) |
| debug | boolean | ❌ | false | Bật log debug |
| retry | RetryConfig | ❌ | (xem bên dưới) | Cấu hình retry |
| onEvent | EventCallback | ❌ | — | Callback nhận event |
2. Cấu hình retry — RetryConfig
| Thuộc tính | Kiểu dữ liệu | Mặc định | Mô tả |
|---|---|---|---|
| maxRetries | number | 3 | Số lần retry tối đa |
| delay | number | 1000 | Thời gian chờ (ms) |
| backoff | 'fixed' \| 'exponential' | 'exponential' | Chiến lược retry |
| retryOn | number[] | [408,429,500,502,503,504] | HTTP status retry |
3. Tuỳ chọn eKYC — EkycOptions
| Thuộc tính | Kiểu dữ liệu | Mặc định | Mô tả |
|---|---|---|---|
| flowType | FlowType | 'full' | Luồng eKYC: full, ocr, ocrFront, ocrBack, face |
| documentType | DocumentType | 'IdentityCard' | Loại giấy tờ |
| versionSdk | VersionSdk | 'Normal' | Phiên bản camera: Normal, ProOval |
| challengeCode | string | "" | Mã challenge bảo mật |
| languageSdk | string | 'vi' | Ngôn ngữ |
| isEnableCompare | boolean | true | Bật/Tắt so sánh khuôn mặt |
| checkLivenessFace | CheckLivenessFace | 'NoneCheckFace' | Chế độ liveness: NoneCheckFace, IBeta, Standard |
| isCheckLivenessCard | boolean | false | Kiểm tra giấy tờ chụp trực tiếp |
| isCheckMaskedFace | boolean | false | Kiểm tra che mặt |
| validateDocumentType | ValidateDocumentType | 'None' | Validate giấy tờ: None, Basic, Medium, Advance |
| ocrEngine | string | 'surya' | Engine OCR |
| deviceContext | DeviceContext | auto-detect | Thông tin thiết bị |
| onStep | function | — | Callback theo dõi tiến trình |
4. Loại giấy tờ — DocumentType
| Giá trị | Mô tả |
|---|---|
| IdentityCard | Chứng minh nhân dân / Căn cước công dân |
| IDCardChipBased | Căn cước công dân gắn chip |
| Passport | Hộ chiếu |
| DriverLicense | Giấy phép lái xe |
| MilitaryIdCard | Chứng minh quân đội |
5. Luồng eKYC — FlowType
| Giá trị | Mô tả |
|---|---|
| full | Chụp giấy tờ trước + sau + chân dung → OCR + Liveness + Face Match |
| ocr | Chụp giấy tờ trước + sau → OCR |
| ocrFront | Chỉ OCR mặt trước |
| ocrBack | Chỉ OCR mặt sau |
| face | Chụp chân dung → Liveness + Face Match |
6. Liveness actions
| Action | Mô tả |
|---|---|
| center | Nhìn thẳng vào camera |
| blink | Chớp mắt |
| turn_left | Quay mặt sang trái |
| turn_right | Quay mặt sang phải |
| smile | Mỉm cười |
| nod | Gật đầu |
VI. DỮ LIỆU TRẢ VỀ
1. Kết quả eKYC — EkycResult
Tương đương VNPT icEkycGetResult:
| Thuộc tính | Kiểu dữ liệu | Tương đương VNPT | Mô tả |
|---|---|---|---|
| session | Session | — | Thông tin phiên |
| ocrResult | TaskResult \| null | ocrResult | Kết quả OCR |
| compareFaceResult | TaskResult \| null | compareFaceResult | Kết quả so sánh khuôn mặt |
| livenessFaceResult | TaskResult \| null | livenessFaceResult | Kết quả liveness chân dung |
| hashImageFront | string | hashImageFront | Mã ảnh giấy tờ mặt trước (artifactId) |
| hashImageBack | string | hashImageBack | Mã ảnh giấy tờ mặt sau (artifactId) |
| hashImageFace | string | hashImageFace | Mã ảnh chân dung (artifactId) |
| clientSessionResult | string | clientSessionResult | Session ID |
| networkProblem | string | networkProblem | Lỗi mạng (rỗng = thành công) |
| results | SessionResult[] | — | Tất cả kết quả chi tiết |
2. Kết quả task — TaskResult
| Thuộc tính | Kiểu dữ liệu | Mô tả |
|---|---|---|
| jobId | string | ID job xử lý |
| taskType | 'OCR' \| 'LIVENESS' \| 'FACE_MATCH' | Loại task |
| status | 'completed' \| 'failed' | Trạng thái |
| passed | boolean | Pass hay fail |
| decision | string | Quyết định: success, real, spoofed, match, no_match |
| score | number | Điểm số |
| confidence | number | Độ tin cậy |
| data | OcrData \| LivenessData \| FaceMatchData | Dữ liệu chi tiết |
3. Dữ liệu OCR — OcrData
| Thuộc tính | Kiểu | Mô tả |
|---|---|---|
| ocrEngine | string | Engine OCR đã dùng |
| cardType | string | Loại thẻ: FRONT / BACK |
| idNumber | string | Số CMND/CCCD |
| name | string | Họ và tên |
| dateOfBirth | string | Ngày sinh |
| sex | string | Giới tính |
| nationality | string | Quốc tịch |
| placeOfOrigin | string | Quê quán |
| placeOfResidence | string | Nơi thường trú |
| expiryDate | string | Ngày hết hạn |
| issueDate | string | Ngày cấp |
| identifyingMarks | string | Đặc điểm nhận dạng |
| mrz | string | Machine Readable Zone |
| artifacts | object | { idFront: artifactId, idBack: artifactId } |
| idFront | OcrParsedSide | Dữ liệu đầy đủ mặt trước (bao gồm raw_text) |
| idBack | OcrParsedSide | Dữ liệu đầy đủ mặt sau (bao gồm raw_text) |
| merged | object | Dữ liệu AI đã merge cả hai mặt |
4. Dữ liệu Liveness — LivenessData
| Thuộc tính | Kiểu | Mô tả |
|---|---|---|
| isLive | boolean | Người thật hay không |
| decision | string | real / spoofed |
| livenessScore | number | Điểm liveness (0–1) |
| summary | object | { actionsPassed, totalActions, antiSpoofPassed, avgAntiSpoofScore } |
| frameResults | FrameResult[] | Kết quả từng frame |
| processingTime | string | Thời gian xử lý |
FrameResult:
| Thuộc tính | Kiểu | Mô tả |
|---|---|---|
| passed | boolean | Frame pass hay không |
| action | string | Action thực hiện |
| actionPassed | boolean | Action đúng hay chưa |
| failReason | string | Lý do thất bại |
| headPose | object | { yaw, pitch, roll } |
| antiSpoof | object | { score, isReal } |
| numFaces | number | Số khuôn mặt |
5. Dữ liệu Face Match — FaceMatchData
| Thuộc tính | Kiểu | Mô tả |
|---|---|---|
| verified | boolean | Khuôn mặt khớp hay không |
| decision | string | match / no_match / review |
| cosineSimilarity | number | Cosine similarity |
| similarityPercentage | number | Phần trăm tương đồng |
| euclideanDistance | number | Khoảng cách Euclidean |
| artifacts | object | { selfie: artifactId, idFront: artifactId } |
| selfieQuality | ImageQuality | Chất lượng ảnh chân dung |
| idCardQuality | ImageQuality | Chất lượng ảnh giấy tờ |
| processingTime | string | Thời gian xử lý |
6. Upload result — UploadResult
| Thuộc tính | Kiểu | Mô tả |
|---|---|---|
| artifactId | string | Mã ảnh (tương đương VNPT hashImage) |
| type | string | ID_FRONT / ID_BACK / SELFIE |
| action | string | Action liveness (nếu có) |
| checksum | string | SHA-256 |
| size | number | Dung lượng (bytes) |
VII. SỰ KIỆN
const client = new EkycClient({
baseUrl: '...',
apiKey: '...',
onEvent: (event) => {
console.log(event.type, event.data);
},
});| Event | Mô tả |
|---|---|
| session.creating / session.created | Tạo session |
| upload.start / upload.done / upload.failed | Upload ảnh |
| task.start / task.done / task.failed | Chạy task AI |
| verify.start / verify.step / verify.done / verify.failed | Luồng eKYC |
| http.request / http.response / http.retry | HTTP |
VIII. XỬ LÝ LỖI
import { EkycError } from '@dydydm/ekyc-sdk';
try {
const result = await client.start({ idFront, selfie }, { flowType: 'full' });
} catch (err) {
if (err instanceof EkycError) {
console.error(err.message); // Thông báo lỗi
console.error(err.statusCode); // HTTP status: 400, 401, 404, 500...
console.error(err.code); // Mã lỗi
}
}IX. SO SÁNH VỚI VNPT SDK
| Tính năng | VNPT eKYC iOS | @dydydm/ekyc-sdk |
|---|---|---|
| Platform | iOS native | Web / Node.js |
| Auth | tokenId + tokenKey + authorization | apiKey hoặc tokenId + tokenKey |
| Flow types | full, ocr, ocrFront, ocrBack, face | ✅ Tương tự |
| Document types | IdentityCard, Passport, DriverLicense... | ✅ Tương tự |
| Camera / Capture | SDK tự chụp | App tự chụp, truyền File/Blob |
| OCR | Tự động | client.task.ocr() hoặc tự động trong start() |
| Liveness | ProOval xa gần | Upload frames + client.task.liveness() |
| Face Match | Tự động | client.task.faceMatch() hoặc tự động trong start() |
| Kết quả | ICEKYCSavedData.shared() | EkycResult |
| ocrResult | ✅ | ✅ result.ocrResult |
| compareFaceResult | ✅ | ✅ result.compareFaceResult |
| livenessFaceResult | ✅ | ✅ result.livenessFaceResult |
| hashImageFront | ✅ | ✅ result.hashImageFront |
| hashImageBack | ✅ | ✅ result.hashImageBack |
| clientSessionResult | ✅ | ✅ result.clientSessionResult |
| networkProblem | ✅ | ✅ result.networkProblem |
License
MIT
