@waiting/bankcard-reader-bp8903
Version:
157 lines (139 loc) • 4.29 kB
JavaScript
/**
* @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 };