/* eslint-disable no-inner-declarations */ process.on('message', async (message, setHandle) => { try { const [dllPath, port] = require('path').join(message).split('|') process.send({ rescode: 0, msg: [dllPath, port] }) const ffi = require('ffi') const ref = require('ref') const Struct = require('ref-struct') const RefArray = require('ref-array') const bufferTrim = require('buffertrim') const rescode = { 65536: 'success', 65537: 'fail', 66306: 'timeout', 66305: 'cancel' } const Sodo_RequestCardAndQrcode = Struct({ transType: 'char', transDate: RefArray(ref.types.char, 3), transTime: RefArray(ref.types.char, 3), transAmt: 'int', transNo: RefArray(ref.types.char, 4), transOutBuf: RefArray(ref.types.char, 4096), lenTransOutbuf: 'int' }) const CardInfo = Struct({ recvBuf: RefArray(ref.types.char, 4096), lenRecv: 'int' }) const SfzInfo = Struct({ cmdOp1: ref.types.byte, cmdOp2: ref.types.byte, dataSend: RefArray(ref.types.char, 1024), lendataSend: 'int', recvBuf: RefArray(ref.types.byte, 4096), lenRecv: 'int' }) let program = ffi.Library(dllPath, { Sodo_InitSerialPort: ['void', ['int', 'int']], // Sodo_InitHttps: ["void", ["int"]], Sodo_Start: ['int', []], Sodo_Stop: ['int', []], // Sodo_Stop: ["int", []], Sodo_SB_Process: ['int', [ref.refType(CardInfo)]], Sodo_SB_Psam_Process_GetAllInfo: ['int', ['int*', 'int*', 'int']], '_Sodo_Sfz_Process@4': ['int', [ref.refType(SfzInfo)]], '_Sodo_RequestCardAndQrcode@4': [ 'int', [ref.refType(Sodo_RequestCardAndQrcode)] ] }) function search () { try { const cardAndQrcode = new Sodo_RequestCardAndQrcode() cardAndQrcode.transType = 0x60 cardAndQrcode.transDate = [0x20, 0x12, 0x12] cardAndQrcode.transNo = [0x11, 0x22, 0x33, 0x44] cardAndQrcode.transAmt = 1 const ret = program['_Sodo_RequestCardAndQrcode@4'](cardAndQrcode.ref()) if (rescode[ret] === 'timeout' || rescode[ret] === 'cancel') { process.send({ rescode: 0, msg: '连接超时或设备出错' }) exit() return } if (rescode[ret] === 'success') { process.send({ rescode: 0, ret, message: '查询成功' }) const transOutBuf = bufferTrim .trimEnd(Buffer.from(cardAndQrcode.transOutBuf)) .toString() process.send({ rescode: 2, ret, transOutBuf }) const res = isJSON(transOutBuf) ? JSON.parse(transOutBuf) : {} console.log('寻卡结果', res) process.send({ rescode: 2, msg: '寻卡结果', data: res }) let id switch (res.cardType) { case '1': // 社保卡 id = getSBCard() break case '2': // 身份证 id = getSFZCard() break case '187': // 扫码 id = getQRcode(res) break } console.log('id', id) } setTimeout(() => { search() }, 500) } catch (e) { process.send(e) } } function getSBCard () { // console.log("sb"); const cardInfo = new CardInfo() const ret0 = program.Sodo_SB_Process(cardInfo.ref()) console.log('[ ret0 ]', ret0) console.log('cardInfo', cardInfo, Buffer.from(cardInfo.recvBuf).toString()) const res = Buffer.alloc(512) const inp = Buffer.alloc(512) const ret = program.Sodo_SB_Psam_Process_GetAllInfo(res.ref(), inp.ref(), 4) if (rescode[ret] !== 'success') return const data = bufferTrim .trimEnd(Buffer.from(res)) .toString() .trim() .split('|') // 返回:卡片发行机构代码|社保卡卡号|卡片识别码|卡复位的信息|卡片版本|发行日期|有效日期 const params = { qrcode_info: data[2], // 必填,社保卡使用卡识别码,电子社保卡使用二维码原始字符串, (应该扫码或者读卡机自动获取) card_type: '01', // 社保卡01 , 二维码04 card_number: data[1], // 9位社保卡号(当介质类型为社保卡时必填) card_version: data[4], // 卡规范版本 publish_date: data[5], // 发卡日期 expiry_date: data[6], // 卡有效期 card_rest_info: data[3] // 卡复位信息 } console.log('[ params ]', params) process.send({ rescode: 1, msg: '社保卡', data: params, cardInfo: bufferTrim.trimEnd(Buffer.from(cardInfo.recvBuf)).toString() }) return params } function getSFZCard () { const cardInfo = new SfzInfo() cardInfo.cmdOp1 = 0x03 cardInfo.cmdOp2 = 0x00 const ret = program['_Sodo_Sfz_Process@4'](cardInfo.ref()) console.log('ret', ret) const idStr = Buffer.from(cardInfo.recvBuf) .slice(7, 263) .toString('ucs2') if ( !idStr .slice(61, 79) .trim() .replace(/\0/g, '').length ) { return } // if (!bufferTrim.trim()) return; console.log('%c [ idStr ]-109', idStr) const res = { name: idStr.slice(0, 15).trim(), sex: getSex(idStr.slice(15, 16)), nation: getNation(idStr.slice(16, 18)), idNum: idStr.slice(61, 79).trim(), address: idStr.slice(26, 61).trim(), begin: idStr.slice(94, 102).trim(), end: idStr.slice(102, 110).trim() } process.send({ rescode: 1, msg: '身份证', res }) console.log('%c [ res ]-112', res) } function getQRcode (res) { const qrcode = Buffer.from(res.ID, 'base64').toString() const params = { qrcode_info: qrcode, card_type: '04' } console.log('params', params) process.send({ rescode: 1, msg: '扫码', data: params }) return params } function isJSON (str) { try { JSON.parse(str) } catch (e) { return false } return true } function getSex (code) { switch (parseInt(code)) { case 0: return '未知的性别' case 1: return '男' case 2: return '女' case 9: return '未说明的性别' } return '未定义的性别' } function getNation (code) { switch (parseInt(code)) { case 1: return '汉' case 2: return '蒙古' case 3: return '回' case 4: return '藏' case 5: return '维吾尔' case 6: return '苗' case 7: return '彝' case 8: return '壮' case 9: return '布依' case 10: return '朝鲜' case 11: return '满' case 12: return '侗' case 13: return '瑶' case 14: return '白' case 15: return '土家' case 16: return '哈尼' case 17: return '哈萨克' case 18: return '傣' case 19: return '黎' case 20: return '傈僳' case 21: return '佤' case 22: return '畲' case 23: return '高山' case 24: return '拉祜' case 25: return '水' case 26: return '东乡' case 27: return '纳西' case 28: return '景颇' case 29: return '柯尔克孜' case 30: return '土' case 31: return '达斡尔' case 32: return '仫佬' case 33: return '羌' case 34: return '布朗' case 35: return '撒拉' case 36: return '毛难' case 37: return '仡佬' case 38: return '锡伯' case 39: return '阿昌' case 40: return '普米' case 41: return '塔吉克' case 42: return '怒' case 43: return '乌孜别克' case 44: return '俄罗斯' case 45: return '鄂温克' case 46: return '崩龙' case 47: return '保安' case 48: return '裕固' case 49: return '京' case 50: return '塔塔尔' case 51: return '独龙' case 52: return '鄂伦春' case 53: return '赫哲' case 54: return '门巴' case 55: return '珞巴' case 56: return '基诺' } } function exit () { process.kill(process.pid) process.exit(0) } return new Promise((resolve, reject) => { program.Sodo_InitSerialPort(parseInt(port), 115200) console.log('已执行初始化串口', port) const ret = program.Sodo_Start() if (rescode[ret] !== 'success') { console.log('打开串口失败') process.send({ rescode: 0, msg: '打开串口失败' }) exit() } else { process.send({ rescode: 0, ret }) try { search() } catch (e) { process.send(e) } } }) } catch (e) { process.send({ rescode: 0, e }) } })