UNPKG

@waiting/bankcard-reader-bp8903

Version:
157 lines (139 loc) 4.29 kB
/** * @waiting/bankcard-reader-bp8903 * 南天 BP8903 读银行卡 * * @version 1.1.1 * @author waiting * @license MIT * @link https://github.com/waitingsong/node-bankcard-reader-bp8903#readme */ import { DTypes } from 'win32-def'; import { parseDeviceOpts } from '@waiting/bankcard-reader-base'; export { initialOpts } from '@waiting/bankcard-reader-base'; import { info } from '@waiting/log'; import { setPathDirectory, dirname, validateDllFile } from '@waiting/shared-core'; import { Library } from 'ffi'; import { of } from 'rxjs'; const dllFuncs = { OpenComPort: [DTypes.INT, [DTypes.INT, DTypes.POINT, DTypes.INT, DTypes.INT]], CloseComPort: [DTypes.INT, []], IsComOpen: [DTypes.INT, []], GetCardNumberFromDev: [DTypes.INT, [DTypes.INT, DTypes.POINT, DTypes.INT, DTypes.POINT]], }; function connectDevice(device, port) { if (device && device.inUse) { device.deviceOpts.debug && info('Cautiton: connectDevice() device in use'); return 0 } const openRet = device.apib.OpenComPort(port, Buffer.from(''), 9600, 1); device.deviceOpts.debug && info(`open com ret: ${openRet}`); return openRet === 0 ? port : 0 } function disconnectDevice(device) { const ret = device.apib.CloseComPort(); device.deviceOpts.debug && info(`disconnectDevice at port: ${device.openPort}, ret: ${ret} `); device.inUse = false; return true } /** 检查端口是否已打开 */ function isDevicePortOpen(device) { const ret = device.apib.IsComOpen(); device.deviceOpts.debug && info(`isPortOpen: ${ret}`); return ret === 1 ? true : false } function findDeviceList(deviceOpts, apib) { const arr = []; // 指定了端口 if (deviceOpts.port > 0) { const device = findDevice(deviceOpts.port, deviceOpts, apib); if (device.openPort > 0) { arr.push(device); } } else { // 检测串口. bp8903 为串口接口 for (let i = 1; i <= 16; i++) { const device = findDevice(i, deviceOpts, apib); if (device.openPort > 0) { arr.push(device); } } } return arr } function findDevice(openPort, deviceOpts, apib) { const device = { apib, deviceOpts, inUse: false, openPort: 0, }; const port = connectDevice(device, openPort); if (port > 0 && isDevicePortOpen(device)) { device.inUse = true; device.openPort = port; deviceOpts.debug && info(`Found device at serial/usb port: ${port}`); disconnectDevice(device); } return device } /** 读取银行卡 支持 接触、非接触、磁条 */ function readAll(device) { setPathDirectory(dirname(device.deviceOpts.dllTxt)); const buf = Buffer.alloc(64); if (device.deviceOpts.debug) { info('starting reading...'); } const ret = { cardno: '', }; const code = device.apib.GetCardNumberFromDev(device.openPort, // Buffer.from('124|A'), Buffer.from(''), 3, buf); if (code === 0) { // 卡号可能重复数字 ...1234557\u0000557 ret.cardno = buf.toString().replace(/\0+.*$/, ''); } if (device.deviceOpts.debug) { info(`readDataBase code: ${code}`); info(`readDataBase bufLen: ${buf.byteLength}`); info('readDataBase buf: '); info(buf); info(`readDataBase ret: ${ret}`); // info(buf.slice(80)) } return ret } async function init(options) { const deviceOpts = parseDeviceOpts(options); const { debug } = deviceOpts; if (debug) { info(deviceOpts); } await validateDllFile(deviceOpts.dllTxt); const apib = Library(deviceOpts.dllTxt, dllFuncs); const devices = findDeviceList(deviceOpts, apib); if (devices && devices.length) { return devices } else { throw new Error('未找到读卡设备') } } /** Read card data */ function read(device) { if (device.openPort) { try { disconnectDevice(device); } catch (ex) { throw ex } const ret$ = of(readAll(device)); return ret$.toPromise() } else { throw new Error('设备端口未指定') } } export { init, read };