{"_id":"@dydydm/ekyc-sdk","_rev":"8-29f12d40bf583f2bdc96510e94373d19","name":"@dydydm/ekyc-sdk","dist-tags":{"latest":"0.3.2"},"versions":{"0.1.1":{"name":"@dydydm/ekyc-sdk","version":"0.1.1","keywords":["ekyc","kyc","verification","ocr","liveness","face-match"],"license":"MIT","_id":"@dydydm/ekyc-sdk@0.1.1","maintainers":[{"name":"tndvlue","email":"tungquyen2904x@gmail.com"}],"dist":{"shasum":"d865462f1e19aab75f254489e71b9911d72ff6ca","tarball":"https://registry.npmjs.org/@dydydm/ekyc-sdk/-/ekyc-sdk-0.1.1.tgz","fileCount":5,"integrity":"sha512-o91rzseSl+CxUlSEBWSGyWo9iCaZ9xmFBEGYES5wzbQI3vwbvUfbG/KsxyrV7XaUCxSfKqccjnWmqpEEEc+ssA==","signatures":[{"sig":"MEYCIQDz3SEvLFm7ei9xKyJ83oYhbDV6fr4YCwnd3ebnaORt4wIhANcIQdBSvsJVonAlWqpZ1e0ClVbxnv3eTw3/Ssx1hIOv","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":58371},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"22bd40e3496e4fac9d2c4c680bb7d5859dcee85b","scripts":{"dev":"tsup src/index.ts --format cjs,esm --dts --watch","lint":"tsc --noEmit","build":"tsup src/index.ts --format cjs,esm --dts","prepublishOnly":"npm run build"},"_npmUser":{"name":"tndvlue","email":"tungquyen2904x@gmail.com"},"_npmVersion":"10.9.0","description":"eKYC SDK - Client SDK for eKYC verification API","directories":{},"_nodeVersion":"22.11.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","typescript":"^5.3.0"},"_npmOperationalInternal":{"tmp":"tmp/ekyc-sdk_0.1.1_1773053229378_0.36667505036441694","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@dydydm/ekyc-sdk","version":"0.1.2","keywords":["ekyc","kyc","verification","ocr","liveness","face-match"],"license":"MIT","_id":"@dydydm/ekyc-sdk@0.1.2","maintainers":[{"name":"tndvlue","email":"tungquyen2904x@gmail.com"}],"dist":{"shasum":"40edaf0c6d06cf328b65ad29ab7686ebca3cdacd","tarball":"https://registry.npmjs.org/@dydydm/ekyc-sdk/-/ekyc-sdk-0.1.2.tgz","fileCount":5,"integrity":"sha512-oiRc3A9B1bzs2340XEJt9RtDtkjd6rs6fDN0GSsyTDd+kJzGGjf2ZZ2vMDZ0s+DRFLN0nQr5nLKZbev/m4EeVg==","signatures":[{"sig":"MEUCIQD1mqR4IXlIl14NEaPpI4Gu7Hf5q2PeNTB77lMUfeRsMQIgbrrADRLtRlCgyKWMsRd7iQfFYPBZG5QJGrxuYQ+xBLI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":58361},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"d0b71859d8f9a5a06522687da5db9dd684e46a7a","scripts":{"dev":"tsup src/index.ts --format cjs,esm --dts --watch","lint":"tsc --noEmit","build":"tsup src/index.ts --format cjs,esm --dts","prepublishOnly":"npm run build"},"_npmUser":{"name":"tndvlue","email":"tungquyen2904x@gmail.com"},"_npmVersion":"10.9.0","description":"eKYC SDK - Client SDK for eKYC verification API","directories":{},"_nodeVersion":"22.11.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","typescript":"^5.3.0"},"_npmOperationalInternal":{"tmp":"tmp/ekyc-sdk_0.1.2_1773116407013_0.2907738770389712","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@dydydm/ekyc-sdk","version":"0.1.3","keywords":["ekyc","kyc","verification","ocr","liveness","face-match"],"license":"MIT","_id":"@dydydm/ekyc-sdk@0.1.3","maintainers":[{"name":"tndvlue","email":"tungquyen2904x@gmail.com"}],"dist":{"shasum":"9a35a13785f078873ed50299574fa5c4f5e1ef2f","tarball":"https://registry.npmjs.org/@dydydm/ekyc-sdk/-/ekyc-sdk-0.1.3.tgz","fileCount":6,"integrity":"sha512-GmK1+V1mSJvB2s3nHHvvFiKocSZEVSGNbXzzMk720imrcNWMjK06MDp679UZY9HCfRR+64dEjfDeiLyiXlwTcQ==","signatures":[{"sig":"MEUCIFgdzsj5eJUiAb4Z9nSfX2qLzWjmia5qec4tp1yGW239AiEA4AEft4/LcRn8y7loiRXYntPxy6zhBwYzApry/mf8YNk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":63754},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"ada476e7594f013efed27b61420cc9d3ce38d74a","scripts":{"dev":"tsup src/index.ts --format cjs,esm --dts --watch","lint":"tsc --noEmit","build":"tsup src/index.ts --format cjs,esm --dts","prepublishOnly":"npm run build"},"_npmUser":{"name":"tndvlue","email":"tungquyen2904x@gmail.com"},"_npmVersion":"10.9.0","description":"eKYC SDK - Client SDK for eKYC verification API","directories":{},"_nodeVersion":"22.11.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","typescript":"^5.3.0"},"_npmOperationalInternal":{"tmp":"tmp/ekyc-sdk_0.1.3_1773213024680_0.3791635558034734","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@dydydm/ekyc-sdk","version":"0.2.0","keywords":["ekyc","kyc","verification","ocr","liveness","face-match"],"license":"MIT","_id":"@dydydm/ekyc-sdk@0.2.0","maintainers":[{"name":"tndvlue","email":"tungquyen2904x@gmail.com"}],"dist":{"shasum":"5adf1330cad88a8dd03ddcede4afc5a4ca910c1a","tarball":"https://registry.npmjs.org/@dydydm/ekyc-sdk/-/ekyc-sdk-0.2.0.tgz","fileCount":6,"integrity":"sha512-iLXyYXi2za3kybl/bvJnsqruDdpxOF/qegZSXhE50oEqQKqz/3LenHZjR9TvrJX77Qrtv+23AKXmihLJ3ZaUwQ==","signatures":[{"sig":"MEYCIQDFYGLLNx+nIZ5g9KJBQYGHHRAkioBr32hnihM+rjdQFwIhAPeac6UotT01U4wKuge4MAHuOqfeyBBEvN5PAwhyb3ev","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":97415},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"ada476e7594f013efed27b61420cc9d3ce38d74a","scripts":{"dev":"tsup src/index.ts --format cjs,esm --dts --watch","lint":"tsc --noEmit","build":"tsup src/index.ts --format cjs,esm --dts","prepublishOnly":"npm run build"},"_npmUser":{"name":"tndvlue","email":"tungquyen2904x@gmail.com"},"_npmVersion":"10.9.0","description":"eKYC SDK - Client SDK for eKYC verification API","directories":{},"_nodeVersion":"22.11.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","typescript":"^5.3.0"},"_npmOperationalInternal":{"tmp":"tmp/ekyc-sdk_0.2.0_1775791058381_0.767341085956305","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@dydydm/ekyc-sdk","version":"0.2.1","keywords":["ekyc","kyc","verification","ocr","liveness","face-match"],"license":"MIT","_id":"@dydydm/ekyc-sdk@0.2.1","maintainers":[{"name":"tndvlue","email":"tungquyen2904x@gmail.com"}],"dist":{"shasum":"beae62cf3be5eb10ddef2e49c3a6c2bfbd3740f4","tarball":"https://registry.npmjs.org/@dydydm/ekyc-sdk/-/ekyc-sdk-0.2.1.tgz","fileCount":6,"integrity":"sha512-nfgxmwPOR8dRmA+f9nYo+ir0gwBci7XPkkCQxv3rKnFYyJ58ihU0x5/Ot9OPQIJ1BrM97YTTSuC3AgZcr6EB1A==","signatures":[{"sig":"MEUCIEcBjLymAgUHEO0WfToiSSejwEXa0Fz1rERn9U/2VSA8AiEAs1y9a/Iqzoo1nHfe0C/CsUgE0thv+H1LChvqli3n/mo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":116827},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"ada476e7594f013efed27b61420cc9d3ce38d74a","scripts":{"dev":"tsup src/index.ts --format cjs,esm --dts --watch","lint":"tsc --noEmit","build":"tsup src/index.ts --format cjs,esm --dts","prepublishOnly":"npm run build"},"_npmUser":{"name":"tndvlue","email":"tungquyen2904x@gmail.com"},"_npmVersion":"10.9.0","description":"eKYC SDK - Client SDK for eKYC verification API","directories":{},"_nodeVersion":"22.11.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","typescript":"^5.3.0"},"_npmOperationalInternal":{"tmp":"tmp/ekyc-sdk_0.2.1_1776063383795_0.9367145056160024","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@dydydm/ekyc-sdk","version":"0.3.0","keywords":["ekyc","kyc","verification","ocr","liveness","face-match"],"license":"MIT","_id":"@dydydm/ekyc-sdk@0.3.0","maintainers":[{"name":"tndvlue","email":"tungquyen2904x@gmail.com"}],"dist":{"shasum":"e34c046ddeac52e8e7d8ca49b505e10a7f63b10d","tarball":"https://registry.npmjs.org/@dydydm/ekyc-sdk/-/ekyc-sdk-0.3.0.tgz","fileCount":6,"integrity":"sha512-bT0lwIuCF8xCmNHml7DstO/JBErev74bMpBTh8x+34IDUGyQXdvxzTXFkqxa+GxTaiXkIFy0mTs/whgigx6KYQ==","signatures":[{"sig":"MEYCIQDv6VfacTEHZY+fu7OBUwlcGytqMOWQ0RrTrXlveBtlYQIhAIhRBDSnPvRxJTLlAU7G/E33Ufxbe5ZX3lN/Da5jOz5r","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":119399},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"7506526c2b79e8c021de8f218ecf5c4dce68e1c1","scripts":{"dev":"tsup src/index.ts --format cjs,esm --dts --watch","lint":"tsc --noEmit","build":"tsup src/index.ts --format cjs,esm --dts","prepublishOnly":"npm run build"},"_npmUser":{"name":"tndvlue","email":"tungquyen2904x@gmail.com"},"_npmVersion":"10.9.0","description":"eKYC SDK - Client SDK for eKYC verification API","directories":{},"_nodeVersion":"22.11.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","typescript":"^5.3.0"},"_npmOperationalInternal":{"tmp":"tmp/ekyc-sdk_0.3.0_1776673261687_0.6869806700526868","host":"s3://npm-registry-packages-npm-production"}},"0.3.1":{"name":"@dydydm/ekyc-sdk","version":"0.3.1","keywords":["ekyc","kyc","verification","ocr","liveness","face-match"],"license":"MIT","_id":"@dydydm/ekyc-sdk@0.3.1","maintainers":[{"name":"tndvlue","email":"tungquyen2904x@gmail.com"}],"dist":{"shasum":"21a1a561e59504012206d9d33bb15df088477603","tarball":"https://registry.npmjs.org/@dydydm/ekyc-sdk/-/ekyc-sdk-0.3.1.tgz","fileCount":6,"integrity":"sha512-x2RZLhKKa51AIt6iMY5b8YraWb0cBm7+4oeY/U90IbYcq/Lnt+z+iIxggMpx9xh2iZjICO2QdHnQK+6GJj8PEA==","signatures":[{"sig":"MEUCIQC7adJGqCKwmuCye3TEcmgFyggiXoeQzQ6G6EG/HGKywAIgT2E5WN00uaxlLjZ739F80Rbr31ANgDwz5ZmXUZ/hs1Y=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":121273},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"7506526c2b79e8c021de8f218ecf5c4dce68e1c1","scripts":{"dev":"tsup src/index.ts --format cjs,esm --dts --watch","lint":"tsc --noEmit","build":"tsup src/index.ts --format cjs,esm --dts","prepublishOnly":"npm run build"},"_npmUser":{"name":"tndvlue","email":"tungquyen2904x@gmail.com"},"_npmVersion":"10.9.0","description":"eKYC SDK - Client SDK for eKYC verification API","directories":{},"_nodeVersion":"22.11.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","typescript":"^5.3.0"},"_npmOperationalInternal":{"tmp":"tmp/ekyc-sdk_0.3.1_1776674725712_0.4115414979739298","host":"s3://npm-registry-packages-npm-production"}},"0.3.2":{"name":"@dydydm/ekyc-sdk","version":"0.3.2","description":"eKYC SDK - Client SDK for eKYC verification API","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts","dev":"tsup src/index.ts --format cjs,esm --dts --watch","lint":"tsc --noEmit","prepublishOnly":"npm run build"},"keywords":["ekyc","kyc","verification","ocr","liveness","face-match"],"license":"MIT","publishConfig":{"access":"public"},"devDependencies":{"tsup":"^8.0.0","typescript":"^5.3.0"},"_id":"@dydydm/ekyc-sdk@0.3.2","gitHead":"7506526c2b79e8c021de8f218ecf5c4dce68e1c1","_nodeVersion":"22.11.0","_npmVersion":"10.9.0","dist":{"integrity":"sha512-jVPtqBTYTIxKyFe3X49RVuYeCD3I/dWde4KX+EMp0DUqb3I3qYWxSDKekYlTrB4lC6v+eFlDGksiGVNthKb9yg==","shasum":"a43416d9baf1e2e6ceaa09d0c39e02df47859aaf","tarball":"https://registry.npmjs.org/@dydydm/ekyc-sdk/-/ekyc-sdk-0.3.2.tgz","fileCount":6,"unpackedSize":123771,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIFe/C/olREipKNqD27XXjvvxlNHYkTEHFTAVceSJB/imAiA4FgMNu0UWV4TLM2lgXD6LepAfFgleDLIr2MJBga8cvQ=="}]},"_npmUser":{"name":"tndvlue","email":"tungquyen2904x@gmail.com"},"directories":{},"maintainers":[{"name":"tndvlue","email":"tungquyen2904x@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ekyc-sdk_0.3.2_1776737411356_0.23153866892004893"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-09T10:47:09.323Z","modified":"2026-04-21T02:10:11.641Z","0.1.1":"2026-03-09T10:47:09.510Z","0.1.2":"2026-03-10T04:20:07.167Z","0.1.3":"2026-03-11T07:10:24.816Z","0.2.0":"2026-04-10T03:17:38.504Z","0.2.1":"2026-04-13T06:56:23.928Z","0.3.0":"2026-04-20T08:21:01.817Z","0.3.1":"2026-04-20T08:45:25.841Z","0.3.2":"2026-04-21T02:10:11.483Z"},"license":"MIT","keywords":["ekyc","kyc","verification","ocr","liveness","face-match"],"description":"eKYC SDK - Client SDK for eKYC verification API","maintainers":[{"name":"tndvlue","email":"tungquyen2904x@gmail.com"}],"readme":"# @dydydm/ekyc-sdk\n\nSDK xác minh danh tính điện tử (eKYC) cho JavaScript/TypeScript — OCR giấy tờ, Liveness Detection, Face Match.\n\nAPI tương thích với VNPT eKYC SDK.\n\n---\n\n## I. TỔNG QUAN\n\n### 1. Mục đích\n\nTà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ử.\n\n### 2. Phạm vi\n\nSDK hỗ trợ các chức năng:\n\n- **OCR** — Bóc tách thông tin từ giấy tờ tùy thân (CMND/CCCD/Hộ chiếu/GPLX)\n- **Liveness Detection** — Kiểm tra chân dung chụp trực tiếp (chống giả mạo)\n- **Face Match** — So sánh khuôn mặt ảnh chân dung và ảnh trên giấy tờ\n\n### 3. Cài đặt\n\n```bash\nnpm install @dydydm/ekyc-sdk\n```\n\n---\n\n## II. TÍCH HỢP SDK VÀO DỰ ÁN\n\n### 1. Khởi tạo\n\n```ts\nimport { EkycClient } from '@dydydm/ekyc-sdk';\n\nconst client = new EkycClient({\n  baseUrl: 'https://api-dev.x-or.cloud/ekyc',\n  apiKey: 'your-api-key',\n});\n```\n\n**Khởi tạo kiểu VNPT (tokenId/tokenKey):**\n\n```ts\nconst client = new EkycClient({\n  baseUrl: 'https://api-dev.x-or.cloud/ekyc',\n  apiKey: '',\n  tokenId: 'your-token-id',\n  tokenKey: 'your-token-key',\n  authorization: 'Bearer your-access-token',\n});\n```\n\n### 2. Cách sử dụng\n\n- Khởi tạo `EkycClient` và cài đặt các thuộc tính\n- Gọi `client.start(files, options)` để thực hiện eKYC theo luồng\n- Dữ liệu sau khi xử lý được trả về qua kết quả `EkycResult`\n- Cấu trúc kết quả tương đương VNPT `icEkycGetResult`\n\n---\n\n## III. CÁC LUỒNG EKYC CHÍNH\n\n### 1. Luồng eKYC đầy đủ — `full`\n\n#### a. Mô tả\n\n- Bước 1: Tải ảnh giấy tờ mặt trước\n- Bước 2: Tải ảnh giấy tờ mặt sau\n- Bước 3: Tải ảnh chân dung\n- Bước 4: SDK thực hiện OCR, Liveness, Face Match → Trả kết quả\n\n**Lưu ý:**\n- Đối với Hộ chiếu và Bằng lái xe, bỏ qua ảnh mặt sau\n- Kết quả trả về qua `EkycResult` (tương đương VNPT `icEkycGetResult`)\n\n#### b. Mã nguồn tham khảo\n\n```ts\nconst result = await client.start(\n  {\n    idFront: idFrontFile,       // File | Blob — ảnh mặt trước (bắt buộc)\n    idBack: idBackFile,         // File | Blob — ảnh mặt sau (tuỳ chọn)\n    selfie: selfieFile,         // File | Blob — ảnh chân dung (bắt buộc)\n    livenessFrames: [           // Liveness frames (tuỳ chọn)\n      { file: frame1, action: 'center' },\n      { file: frame2, action: 'turn_left' },\n      { file: frame3, action: 'turn_right' },\n    ],\n  },\n  {\n    flowType: 'full',                       // Luồng đầy đủ\n    documentType: 'IdentityCard',           // Loại giấy tờ\n    isEnableCompare: true,                  // Bật so sánh khuôn mặt\n    checkLivenessFace: 'IBeta',             // Kiểm tra liveness chân dung\n    ocrEngine: 'surya',                     // Engine OCR\n    challengeCode: 'INNOVATIONCENTER',      // Mã challenge\n    onStep: (step, detail) => {\n      console.log(`[${step}]`, detail);\n    },\n  },\n);\n\n// Kết quả — tương đương VNPT icEkycGetResult\nconsole.log(result.ocrResult);              // Kết quả OCR\nconsole.log(result.compareFaceResult);      // Kết quả so sánh khuôn mặt\nconsole.log(result.livenessFaceResult);     // Kết quả liveness\nconsole.log(result.hashImageFront);         // Mã ảnh mặt trước\nconsole.log(result.hashImageBack);          // Mã ảnh mặt sau\nconsole.log(result.hashImageFace);          // Mã ảnh chân dung\nconsole.log(result.clientSessionResult);    // Session ID\nconsole.log(result.networkProblem);         // Lỗi mạng (rỗng = thành công)\n```\n\n### 2. Luồng OCR giấy tờ — `ocr`\n\n#### a. Mô tả\n\n- Bước 1: Tải ảnh giấy tờ mặt trước\n- Bước 2: Tải ảnh giấy tờ mặt sau\n- Bước 3: SDK thực hiện OCR → Trả kết quả\n\n**Lưu ý:** Đối với Hộ chiếu và Bằng lái xe, bỏ qua mặt sau.\n\n#### b. Mã nguồn tham khảo\n\n```ts\nconst result = await client.start(\n  {\n    idFront: idFrontFile,\n    idBack: idBackFile,\n  },\n  {\n    flowType: 'ocr',\n    documentType: 'IdentityCard',\n    ocrEngine: 'surya',\n  },\n);\n\nconsole.log(result.ocrResult);  // Kết quả OCR\n```\n\n### 3. Luồng OCR mặt trước — `ocrFront`\n\n#### a. Mô tả\n\n- Bước 1: Tải ảnh giấy tờ mặt trước\n- Bước 2: SDK thực hiện OCR mặt trước → Trả kết quả\n\n#### b. Mã nguồn tham khảo\n\n```ts\nconst result = await client.start(\n  { idFront: idFrontFile },\n  { flowType: 'ocrFront', ocrEngine: 'surya' },\n);\n```\n\n### 4. Luồng OCR mặt sau — `ocrBack`\n\n#### a. Mô tả\n\n- Bước 1: Tải ảnh giấy tờ mặt sau\n- Bước 2: SDK thực hiện OCR mặt sau → Trả kết quả\n\n#### b. Mã nguồn tham khảo\n\n```ts\nconst result = await client.start(\n  { idBack: idBackFile },\n  { flowType: 'ocrBack', ocrEngine: 'surya' },\n);\n```\n\n### 5. Luồng kiểm tra khuôn mặt — `face`\n\n#### a. Mô tả\n\n- Bước 1: Tải ảnh chân dung\n- Bước 2: SDK thực hiện Liveness + Face Match → Trả kết quả\n\n**Lưu ý:** Cần đã upload ảnh giấy tờ (ID_FRONT) trước đó trong cùng session nếu muốn Face Match.\n\n#### b. Mã nguồn tham khảo\n\n```ts\nconst result = await client.start(\n  {\n    selfie: selfieFile,\n    livenessFrames: [\n      { file: frame1, action: 'center' },\n      { file: frame2, action: 'turn_left' },\n    ],\n  },\n  {\n    flowType: 'face',\n    isEnableCompare: true,\n    checkLivenessFace: 'IBeta',\n  },\n);\n\nconsole.log(result.livenessFaceResult);   // Kết quả liveness\nconsole.log(result.compareFaceResult);    // Kết quả face match\n```\n\n---\n\n## IV. SỬ DỤNG TỪNG BƯỚC (Step-by-step)\n\nKhi cần kiểm soát chi tiết từng bước (ví dụ: webcam capture, upload từng frame).\n\n### 1. Tạo session\n\n```ts\nconst deviceContext = EkycClient.detectDevice();\nconst session = await client.session.create({\n  deviceContext,\n  challengeCode: 'INNOVATIONCENTER',\n  documentType: 'IdentityCard',\n  flowType: 'full',\n});\nconst sessionId = session.sessionId;\n```\n\n### 2. Upload ảnh\n\n```ts\n// Mặt trước\nconst front = await client.artifact.upload(sessionId, idFrontFile, 'ID_FRONT', {\n  onProgress: (p) => console.log(`${p.percent}%`),\n});\n\n// Mặt sau\nconst back = await client.artifact.upload(sessionId, idBackFile, 'ID_BACK');\n\n// Chân dung + liveness action\nconst selfie = await client.artifact.upload(sessionId, frameBlob, 'SELFIE', {\n  action: 'center',\n});\n```\n\n### 3. Chạy OCR\n\n```ts\nconst ocr = await client.task.ocr(sessionId, { ocrEngine: 'surya' });\n```\n\n### 4. Kiểm tra liveness từng frame\n\n```ts\nconst lv = await client.task.liveness(sessionId, selfie.artifactId, 'center');\nconsole.log(lv.passed, lv.decision, lv.score);\n```\n\n### 5. Kiểm tra liveness batch\n\n```ts\nconst lvBatch = await client.task.livenessBatch(sessionId);\n```\n\n### 6. So sánh khuôn mặt\n\n```ts\nconst fm = await client.task.faceMatch(sessionId);\n```\n\n### 7. Lấy tất cả kết quả\n\n```ts\nconst { data } = await client.task.getResults(sessionId);\n```\n\n---\n\n## V. CÁC THUỘC TÍNH ĐẦU VÀO\n\n### 1. Cấu hình SDK — `EkycConfig`\n\n| Thuộc tính | Kiểu dữ liệu | Bắt buộc | Mặc định | Mô tả |\n|---|---|---|---|---|\n| `baseUrl` | `string` | ✅ | — | Địa chỉ API server |\n| `apiKey` | `string` | ✅* | — | API Key xác thực. *Không bắt buộc nếu dùng tokenId/tokenKey |\n| `tokenId` | `string` | ❌ | `\"\"` | Token ID (VNPT-compatible) |\n| `tokenKey` | `string` | ❌ | `\"\"` | Token Key (VNPT-compatible) |\n| `authorization` | `string` | ❌ | `\"\"` | Authorization token (VNPT-compatible) |\n| `timeout` | `number` | ❌ | `30000` | Timeout mỗi request (ms) |\n| `debug` | `boolean` | ❌ | `false` | Bật log debug |\n| `retry` | `RetryConfig` | ❌ | *(xem bên dưới)* | Cấu hình retry |\n| `onEvent` | `EventCallback` | ❌ | — | Callback nhận event |\n\n### 2. Cấu hình retry — `RetryConfig`\n\n| Thuộc tính | Kiểu dữ liệu | Mặc định | Mô tả |\n|---|---|---|---|\n| `maxRetries` | `number` | `3` | Số lần retry tối đa |\n| `delay` | `number` | `1000` | Thời gian chờ (ms) |\n| `backoff` | `'fixed' \\| 'exponential'` | `'exponential'` | Chiến lược retry |\n| `retryOn` | `number[]` | `[408,429,500,502,503,504]` | HTTP status retry |\n\n### 3. Tuỳ chọn eKYC — `EkycOptions`\n\n| Thuộc tính | Kiểu dữ liệu | Mặc định | Mô tả |\n|---|---|---|---|\n| `flowType` | `FlowType` | `'full'` | Luồng eKYC: `full`, `ocr`, `ocrFront`, `ocrBack`, `face` |\n| `documentType` | `DocumentType` | `'IdentityCard'` | Loại giấy tờ |\n| `versionSdk` | `VersionSdk` | `'Normal'` | Phiên bản camera: `Normal`, `ProOval` |\n| `challengeCode` | `string` | `\"\"` | Mã challenge bảo mật |\n| `languageSdk` | `string` | `'vi'` | Ngôn ngữ |\n| `isEnableCompare` | `boolean` | `true` | Bật/Tắt so sánh khuôn mặt |\n| `checkLivenessFace` | `CheckLivenessFace` | `'NoneCheckFace'` | Chế độ liveness: `NoneCheckFace`, `IBeta`, `Standard` |\n| `isCheckLivenessCard` | `boolean` | `false` | Kiểm tra giấy tờ chụp trực tiếp |\n| `isCheckMaskedFace` | `boolean` | `false` | Kiểm tra che mặt |\n| `validateDocumentType` | `ValidateDocumentType` | `'None'` | Validate giấy tờ: `None`, `Basic`, `Medium`, `Advance` |\n| `ocrEngine` | `string` | `'surya'` | Engine OCR |\n| `deviceContext` | `DeviceContext` | auto-detect | Thông tin thiết bị |\n| `onStep` | `function` | — | Callback theo dõi tiến trình |\n\n### 4. Loại giấy tờ — `DocumentType`\n\n| Giá trị | Mô tả |\n|---|---|\n| `IdentityCard` | Chứng minh nhân dân / Căn cước công dân |\n| `IDCardChipBased` | Căn cước công dân gắn chip |\n| `Passport` | Hộ chiếu |\n| `DriverLicense` | Giấy phép lái xe |\n| `MilitaryIdCard` | Chứng minh quân đội |\n\n### 5. Luồng eKYC — `FlowType`\n\n| Giá trị | Mô tả |\n|---|---|\n| `full` | Chụp giấy tờ trước + sau + chân dung → OCR + Liveness + Face Match |\n| `ocr` | Chụp giấy tờ trước + sau → OCR |\n| `ocrFront` | Chỉ OCR mặt trước |\n| `ocrBack` | Chỉ OCR mặt sau |\n| `face` | Chụp chân dung → Liveness + Face Match |\n\n### 6. Liveness actions\n\n| Action | Mô tả |\n|---|---|\n| `center` | Nhìn thẳng vào camera |\n| `blink` | Chớp mắt |\n| `turn_left` | Quay mặt sang trái |\n| `turn_right` | Quay mặt sang phải |\n| `smile` | Mỉm cười |\n| `nod` | Gật đầu |\n\n---\n\n## VI. DỮ LIỆU TRẢ VỀ\n\n### 1. Kết quả eKYC — `EkycResult`\n\nTương đương VNPT `icEkycGetResult`:\n\n| Thuộc tính | Kiểu dữ liệu | Tương đương VNPT | Mô tả |\n|---|---|---|---|\n| `session` | `Session` | — | Thông tin phiên |\n| `ocrResult` | `TaskResult \\| null` | `ocrResult` | Kết quả OCR |\n| `compareFaceResult` | `TaskResult \\| null` | `compareFaceResult` | Kết quả so sánh khuôn mặt |\n| `livenessFaceResult` | `TaskResult \\| null` | `livenessFaceResult` | Kết quả liveness chân dung |\n| `hashImageFront` | `string` | `hashImageFront` | Mã ảnh giấy tờ mặt trước (artifactId) |\n| `hashImageBack` | `string` | `hashImageBack` | Mã ảnh giấy tờ mặt sau (artifactId) |\n| `hashImageFace` | `string` | `hashImageFace` | Mã ảnh chân dung (artifactId) |\n| `clientSessionResult` | `string` | `clientSessionResult` | Session ID |\n| `networkProblem` | `string` | `networkProblem` | Lỗi mạng (rỗng = thành công) |\n| `results` | `SessionResult[]` | — | Tất cả kết quả chi tiết |\n\n### 2. Kết quả task — `TaskResult`\n\n| Thuộc tính | Kiểu dữ liệu | Mô tả |\n|---|---|---|\n| `jobId` | `string` | ID job xử lý |\n| `taskType` | `'OCR' \\| 'LIVENESS' \\| 'FACE_MATCH'` | Loại task |\n| `status` | `'completed' \\| 'failed'` | Trạng thái |\n| `passed` | `boolean` | Pass hay fail |\n| `decision` | `string` | Quyết định: `success`, `real`, `spoofed`, `match`, `no_match` |\n| `score` | `number` | Điểm số |\n| `confidence` | `number` | Độ tin cậy |\n| `data` | `OcrData \\| LivenessData \\| FaceMatchData` | Dữ liệu chi tiết |\n\n### 3. Dữ liệu OCR — `OcrData`\n\n| Thuộc tính | Kiểu | Mô tả |\n|---|---|---|\n| `ocrEngine` | `string` | Engine OCR đã dùng |\n| `cardType` | `string` | Loại thẻ: `FRONT` / `BACK` |\n| `idNumber` | `string` | Số CMND/CCCD |\n| `name` | `string` | Họ và tên |\n| `dateOfBirth` | `string` | Ngày sinh |\n| `sex` | `string` | Giới tính |\n| `nationality` | `string` | Quốc tịch |\n| `placeOfOrigin` | `string` | Quê quán |\n| `placeOfResidence` | `string` | Nơi thường trú |\n| `expiryDate` | `string` | Ngày hết hạn |\n| `issueDate` | `string` | Ngày cấp |\n| `identifyingMarks` | `string` | Đặc điểm nhận dạng |\n| `mrz` | `string` | Machine Readable Zone |\n| `artifacts` | `object` | `{ idFront: artifactId, idBack: artifactId }` |\n| `idFront` | `OcrParsedSide` | Dữ liệu đầy đủ mặt trước (bao gồm `raw_text`) |\n| `idBack` | `OcrParsedSide` | Dữ liệu đầy đủ mặt sau (bao gồm `raw_text`) |\n| `merged` | `object` | Dữ liệu AI đã merge cả hai mặt |\n\n### 4. Dữ liệu Liveness — `LivenessData`\n\n| Thuộc tính | Kiểu | Mô tả |\n|---|---|---|\n| `isLive` | `boolean` | Người thật hay không |\n| `decision` | `string` | `real` / `spoofed` |\n| `livenessScore` | `number` | Điểm liveness (0–1) |\n| `summary` | `object` | `{ actionsPassed, totalActions, antiSpoofPassed, avgAntiSpoofScore }` |\n| `frameResults` | `FrameResult[]` | Kết quả từng frame |\n| `processingTime` | `string` | Thời gian xử lý |\n\n**FrameResult:**\n\n| Thuộc tính | Kiểu | Mô tả |\n|---|---|---|\n| `passed` | `boolean` | Frame pass hay không |\n| `action` | `string` | Action thực hiện |\n| `actionPassed` | `boolean` | Action đúng hay chưa |\n| `failReason` | `string` | Lý do thất bại |\n| `headPose` | `object` | `{ yaw, pitch, roll }` |\n| `antiSpoof` | `object` | `{ score, isReal }` |\n| `numFaces` | `number` | Số khuôn mặt |\n\n### 5. Dữ liệu Face Match — `FaceMatchData`\n\n| Thuộc tính | Kiểu | Mô tả |\n|---|---|---|\n| `verified` | `boolean` | Khuôn mặt khớp hay không |\n| `decision` | `string` | `match` / `no_match` / `review` |\n| `cosineSimilarity` | `number` | Cosine similarity |\n| `similarityPercentage` | `number` | Phần trăm tương đồng |\n| `euclideanDistance` | `number` | Khoảng cách Euclidean |\n| `artifacts` | `object` | `{ selfie: artifactId, idFront: artifactId }` |\n| `selfieQuality` | `ImageQuality` | Chất lượng ảnh chân dung |\n| `idCardQuality` | `ImageQuality` | Chất lượng ảnh giấy tờ |\n| `processingTime` | `string` | Thời gian xử lý |\n\n### 6. Upload result — `UploadResult`\n\n| Thuộc tính | Kiểu | Mô tả |\n|---|---|---|\n| `artifactId` | `string` | Mã ảnh (tương đương VNPT hashImage) |\n| `type` | `string` | `ID_FRONT` / `ID_BACK` / `SELFIE` |\n| `action` | `string` | Action liveness (nếu có) |\n| `checksum` | `string` | SHA-256 |\n| `size` | `number` | Dung lượng (bytes) |\n\n---\n\n## VII. SỰ KIỆN\n\n```ts\nconst client = new EkycClient({\n  baseUrl: '...',\n  apiKey: '...',\n  onEvent: (event) => {\n    console.log(event.type, event.data);\n  },\n});\n```\n\n| Event | Mô tả |\n|---|---|\n| `session.creating` / `session.created` | Tạo session |\n| `upload.start` / `upload.done` / `upload.failed` | Upload ảnh |\n| `task.start` / `task.done` / `task.failed` | Chạy task AI |\n| `verify.start` / `verify.step` / `verify.done` / `verify.failed` | Luồng eKYC |\n| `http.request` / `http.response` / `http.retry` | HTTP |\n\n---\n\n## VIII. XỬ LÝ LỖI\n\n```ts\nimport { EkycError } from '@dydydm/ekyc-sdk';\n\ntry {\n  const result = await client.start({ idFront, selfie }, { flowType: 'full' });\n} catch (err) {\n  if (err instanceof EkycError) {\n    console.error(err.message);     // Thông báo lỗi\n    console.error(err.statusCode);  // HTTP status: 400, 401, 404, 500...\n    console.error(err.code);        // Mã lỗi\n  }\n}\n```\n\n---\n\n## IX. SO SÁNH VỚI VNPT SDK\n\n| Tính năng | VNPT eKYC iOS | @dydydm/ekyc-sdk |\n|---|---|---|\n| Platform | iOS native | Web / Node.js |\n| Auth | `tokenId` + `tokenKey` + `authorization` | `apiKey` hoặc `tokenId` + `tokenKey` |\n| Flow types | `full`, `ocr`, `ocrFront`, `ocrBack`, `face` | ✅ Tương tự |\n| Document types | `IdentityCard`, `Passport`, `DriverLicense`... | ✅ Tương tự |\n| Camera / Capture | SDK tự chụp | App tự chụp, truyền File/Blob |\n| OCR | Tự động | `client.task.ocr()` hoặc tự động trong `start()` |\n| Liveness | ProOval xa gần | Upload frames + `client.task.liveness()` |\n| Face Match | Tự động | `client.task.faceMatch()` hoặc tự động trong `start()` |\n| Kết quả | `ICEKYCSavedData.shared()` | `EkycResult` |\n| `ocrResult` | ✅ | ✅ `result.ocrResult` |\n| `compareFaceResult` | ✅ | ✅ `result.compareFaceResult` |\n| `livenessFaceResult` | ✅ | ✅ `result.livenessFaceResult` |\n| `hashImageFront` | ✅ | ✅ `result.hashImageFront` |\n| `hashImageBack` | ✅ | ✅ `result.hashImageBack` |\n| `clientSessionResult` | ✅ | ✅ `result.clientSessionResult` |\n| `networkProblem` | ✅ | ✅ `result.networkProblem` |\n\n---\n\n## License\n\nMIT\n","readmeFilename":"README.md"}