idcard-reader
Version:
通过二代身份证机具读取二代身份证信息
22 lines (20 loc) • 6.36 kB
JavaScript
/**
* idcard-reader
* 通过二代身份证机具读取二代身份证信息
*
* @version 5.0.0
* @author waiting
* @license MIT
* @link https://github.com/waitingsong/node-idcard-reader#readme
*/
/**
* idcard-reader
* 通过二代身份证机具读取二代身份证信息
*
* @version 5.0.0
* @author waiting
* @license MIT
* @link https://github.com/waitingsong/node-idcard-reader#readme
*/
import{join as e,tmpdir as t,dirname as r,isFileExists as i,fileExists as n,createFileAsync as o,normalize as s}from"@waiting/shared-core";import{parseDeviceOpts as p,parseCompositeOpts as a,validateDllFile as c,testWrite as d,composite as u,formatBaseData as f,initialIDData as l,initialDataBase as g}from"@waiting/idcard-reader-base";export{initialCompositeOpts,initialOpts,nationMap}from"@waiting/idcard-reader-base";import{info as m,error as S}from"@waiting/log";import{Library as D}from"ffi-napi";import{of as h,range as P,timer as b,iif as w,combineLatest as v}from"rxjs";import{mergeMap as T,timeout as M,tap as $,map as O,concatMap as _,filter as C,take as A,defaultIfEmpty as B,shareReplay as H,catchError as x}from"rxjs/operators";const I={appDir:"",tmpDir:e(t(),"idcard-reader")},E={SDT_OpenPort:["int",["int"]],SDT_ClosePort:["int",["int"]],SDT_StartFindIDCard:["int",["int","pointer","int"]],SDT_SelectIDCard:["int",["int","pointer","int"]],SDT_ReadBaseMsg:["int",["int","pointer","pointer","pointer","pointer","int"]],SDT_GetSAMStatus:["int",["int","int"]],SDT_GetSAMIDToStr:["int",["int","pointer","int"]],SDT_ReadNewAppMsg:["int",["int","pointer","pointer","int"]],SDT_ResetSAM:["int",["int","int"]]},R={GetBmp:["int",["string","int"]]};function y(e,t){if(e&&e.inUse)return e.deviceOpts.debug&&m("Cautiton: connectDevice() device in use"),0;const r=e.apib.SDT_OpenPort(t);return e.deviceOpts.debug&&m(`open device port ret: ${r}`),144===r?t:0}function U(e){const t=e.apib.SDT_ClosePort(e.openPort);return e.deviceOpts.debug&&m(`disconnectDevice at port: ${e.openPort}, ret: ${t} `),e.inUse=!1,144===t}function F(e,t){if(t&&t>0){const r=e.apib.SDT_ResetSAM(t,0);m(`reset ${t} ret: ${r}`)}else{for(let t=1;t<=16;t+=1){const r=e.apib.SDT_ResetSAM(t,0);m(`reset ${t} ret: ${r}`)}for(let t=1001;t<=1016;t+=1){const r=e.apib.SDT_ResetSAM(t,0);m(`reset ${t} ret: ${r}`)}}e.deviceOpts.debug&&m(`reset device at port: ${e.openPort}`),e.inUse=!1}function L(e,t,r){const i=[];if(e.port>0){const n=G(e.port,e,t,r,!0);n.openPort>0&&i.push(n)}else{for(let n=1001;n<=1016;n+=1){const o=G(n,e,t,r,!0);if(o.openPort>0&&(i.push(o),!e.searchAll))break}if(!e.searchAll&&i.length)return i;for(let n=1;n<=16;n+=1){const o=G(n,e,t,r,!1);if(o.openPort>0&&(i.push(o),!e.searchAll))break}}return i}function G(e,t,r,i,n){const o={apib:i,apii:null,deviceOpts:t,compositeOpts:r,inUse:!1,openPort:0,useUsb:n},s=y(o,e);return s>0&&(o.inUse=!0,o.openPort=s,t.debug&&m(`Found device at serial/usb port: ${s}`),U(o)),o}function j(e){const t=r(e.deviceOpts.dllTxt);process.env.PATH=`${process.env.PATH};${t}`,e.deviceOpts.debug&&m("starting reading readCard ");const i=y(e,e.openPort);if(!i)throw new Error(`打开端口失败 readDataBase() port: ${e.openPort}`);const n=k(e).pipe(T(t=>{if(t)return h(V(e)).pipe(M(1500));throw new Error("findCard() 未能找到指定设备")}),$(e=>{if(!e)throw new Error("二代证无效,请确保证件处于机具读卡区域内")})),o=n.pipe(O(()=>Y(e)),$(t=>{e.deviceOpts.debug&&(m("readDataBase ret"),m(t))}));return o}function k(e){const{findCardRetryTimes:t}=e.deviceOpts,r=P(0,t>0?t+1:1).pipe(_((r,i)=>{if(i>0&&i>=t)throw new Error(`findCard fail over ${t} times`);const n=b(0===i?0:1e3);return n.pipe(T(()=>h(N(e))))})),i=r.pipe($(t=>{e.deviceOpts.debug&&m(`findStatus: ${t}`)}),C(e=>159===e),A(1),B(0),O(e=>e>0));return i}function N(e){try{const t=Buffer.alloc(4);return e.apib.SDT_StartFindIDCard(e.openPort,t,1)}catch(t){return e.deviceOpts.debug&&S(t),0}}function V(e){const t=Buffer.alloc(4),r=e.apib.SDT_SelectIDCard(e.openPort,t,1);return 144===r}function Y(e){const t={pucCHMsg:Buffer.alloc(1024),puiCHMsgLen:Buffer.from([1024]),pucPHMsg:Buffer.alloc(1024),puiPHMsgLen:Buffer.from([1024])},r={err:1,code:0,text:t.pucCHMsg,image:t.pucPHMsg,imagePath:""};try{r.code=e.apib.SDT_ReadBaseMsg(e.openPort,t.pucCHMsg,t.puiCHMsgLen,t.pucPHMsg,t.puiPHMsgLen,1)}catch(e){console.error(e)}return 144===r.code?r.err=0:F(e,e.openPort),r}async function q(e){const t=p(e),r=a(e),{debug:n}=t;if(n&&(m(r),m(t)),await c(t.dllTxt),r.useComposite){if(!t.dllImage)throw new Error("Value of dellImage empty");if(!await i(t.dllImage))throw new Error("File not exists: "+t.dllImage)}await d(t.imgSaveDir);const o=D(t.dllTxt,E),s=L(t,r,o);if(s&&s.length)return n&&console.info("Found devices:",s),s;throw new Error("未找到读卡设备")}function z(e){if(e.openPort){U(e);const t=j(e).pipe(H(1)),r=t.pipe($(e=>{if(e.err)throw new Error("读卡失败:code:"+e.code.toString())}),O(e=>{const t=J(e&&e.text.byteLength?e.text.toString("ucs2"):"");return t}),H(1)),i=t.pipe(T(t=>K(t.image,e)),T(e=>n(e).pipe($(t=>{t||S(`解码头像文件失败 path: "${e}"`)})))),o=w(()=>!e.compositeOpts.useComposite,h({compositePath:"",imagePath:""}),v(r,i).pipe(T(([t,r])=>u(r,t,e.compositeOpts).pipe(O(e=>({compositePath:e,imagePath:r})))))),s=v(r,o).pipe($(()=>{U(e)}),O(([e,t])=>{const r={...l,...t,base:e};return r}),M(2e4),x(t=>{throw U(e),t}));return s.toPromise()}throw new Error("设备端口未指定")}function J(e){const t={...g};return e&&e.length?(t.name=e.slice(0,15).trim(),t.gender=+e.slice(15,16),t.nation=e.slice(16,18),t.birth=e.slice(18,26),t.address=e.slice(26,61).trim(),t.idc=e.slice(61,79),t.regorg=e.slice(79,94).trim(),t.startdate=e.slice(94,102),t.enddate=e.slice(102,110),f(t)):t}function K(e,t){const r=t.deviceOpts;return t.apii=D(r.dllImage,R),Q(t,e)}async function Q(t,r){const i=e(t.deviceOpts.imgSaveDir,W("idcrimage_")),n=i+".wlt";if(!t.apii)return"";await o(n,r);const p=t.apii.GetBmp(n,t.useUsb?2:1);if(t.deviceOpts.debug&&m(["resolve image res:",p]),1===p){const e=s(i+".bmp");return e}return""}function W(e){const t=new Date,r=t.getMonth(),i=t.getDate(),n=Math.random().toString().slice(-8);return`${e}${t.getFullYear()}${r>9?r:"0"+r.toString()}${i>9?i:"0"+i.toString()}_${n}`}I.appDir=e(__dirname,"/..");export{q as init,J as pickFields,z as read,K as retriveAvatar};
//# sourceMappingURL=index.esm.min.js.map