@luoxiao123/bankcard-reader-start
Version:
187 lines (165 loc) • 5.35 kB
JavaScript
/**
* @luoxiao123/bankcard-reader-start
* 实达三合一读卡器 读银行卡
*
* @version 0.0.6
* @author luoxiao
* @license MIT
* @link https://github.com/luoxiao-xy/node-bankcard-reader-start#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 { validateDllFile, setPathDirectory } from '@waiting/shared-core';
import { Library } from 'ffi';
const config = {
appDir: '',
};
const dllFuncs = {
star_InitConnect: [DTypes.INT, [DTypes.INT, DTypes.INT, DTypes.CHAR, DTypes.CHAR, DTypes.INT]],
star_Open: [DTypes.INT, [DTypes.INT, DTypes.INT, DTypes.CHAR]],
star_Close: [DTypes.INT, []],
star_GetDevInfo: [DTypes.INT, [DTypes.PSTR, DTypes.LPINT]],
star_ICGetInfo: [DTypes.INT, [DTypes.INT, DTypes.PSTR, DTypes.PSTR, DTypes.INT]],
star_ReadMagCardNo: [DTypes.INT, [DTypes.INT, DTypes.INT, DTypes.PSTR, DTypes.LPINT, DTypes.INT]],
};
function connectDevice(device) {
if (device && device.inUse) {
device.deviceOpts.debug && info('Cautiton: connectDevice() device in use');
return false
}
const openRet = device.apib.star_Open(0, 9600, '0');
device.deviceOpts.debug && info(`open com ret: ${openRet}`);
return openRet === 0 ? true : false
}
function disconnectDevice(device) {
const closeRet = device.apib.star_Close();
device.deviceOpts.debug && info(`disconnectDevice at port: ${device.openPort}, ret: ${closeRet} `);
device.inUse = false;
return closeRet === 0 ? true : false
}
/** 检查端口是否已打开 */
function isDevicePortOpen(device) {
const szDevInfo = Buffer.alloc(64);
const iInfoLen = Buffer.alloc(64);
const ret = device.apib.star_GetDevInfo(szDevInfo, iInfoLen); // 使用获取设备信息接口来检查是否连接成功
device.deviceOpts.debug && info(`isPortOpen: ${ret}`);
info(`设备信息: ${szDevInfo}`);
info(`设备信息长度: ${iInfoLen}`);
return ret === 0 ? true : false
}
function findDeviceList(deviceOpts, apib) {
const arr = [];
info('开始获取实达设备列表');
const device = findDevice(deviceOpts, apib);
arr.push(device);
return arr
}
function findDevice(deviceOpts, apib) {
const device = {
apib,
deviceOpts,
inUse: false,
openPort: 0,
};
const openRet = connectDevice(device);
if (openRet && !isDevicePortOpen(device)) {
device.inUse = true;
device.openPort = 0;
deviceOpts.debug && info(`Found device at serial/usb port: ${0}`);
disconnectDevice(device);
}
return device
}
/** 读取银行卡 磁条卡 */
function readMC(device) {
const szCardNo = Buffer.alloc(64);
const iCardNoLen = Buffer.alloc(64);
if (device.deviceOpts.debug) {
info('starting reading 磁条卡 ...');
}
const code = device.apib.star_ReadMagCardNo(23, 0, szCardNo, iCardNoLen, 5);
let cardno = '';
if (code === 0) {
// 卡号可能重复数字 ...1234557\u0000557
cardno = parseBuffer(szCardNo);
}
if (device.deviceOpts.debug) {
info(`readDataBase code: ${code}`);
info(`readDataBase bufLen: ${szCardNo.byteLength}`);
info('readDataBase buf: ');
info(szCardNo);
info(`readDataBase cardno: ${cardno}`);
}
return cardno
}
/** 读取银行卡 支持 接触、非接触 IC卡 */
function readIC(device) {
const buf = Buffer.alloc(64);
if (device.deviceOpts.debug) {
info('starting reading IC卡 ...');
}
const code = device.apib.star_ICGetInfo(2, Buffer.from('124|A'), buf, 1);
let cardno = '';
if (code === 0) {
// 卡号可能重复数字 ...1234557\u0000557
const bufstr = parseBuffer(buf);
cardno = bufstr ? bufstr.substring(4) : '';
}
if (device.deviceOpts.debug) {
info(`readDataBase code: ${code}`);
info(`readDataBase bufLen: ${buf.byteLength}`);
info('readDataBase buf: ');
info(buf);
info(`readDataBase cardno: ${cardno}`);
}
return cardno
}
/** 转换Buffer */
function parseBuffer(buf) {
const bufstr = buf.toString('utf8').trim().replace(/\0+$/g, '');
return bufstr
}
async function init(options) {
const deviceOpts = parseDeviceOpts(options);
const { debug } = deviceOpts;
info('开始实达设备');
if (debug) {
info(deviceOpts);
}
await validateDllFile(deviceOpts.dllTxt);
if (deviceOpts.dllSearchPath) {
setPathDirectory(deviceOpts.dllSearchPath);
}
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) {
const ret = {
cardno: '',
};
try {
ret.cardno = readIC(device) || readMC(device) || '';
}
catch (err) {
ret.cardno = '';
}
try {
disconnectDevice(device);
}
catch (ex) {
throw ex
}
return Promise.resolve(ret)
}
// base directory of this module
config.appDir = __dirname + '/..';
export { init, read };