This commit is contained in:
cheney
2022-12-22 14:57:51 +08:00
parent 95f09d0ad7
commit 635587335b
2277 changed files with 408903 additions and 16 deletions
+339
View File
@@ -0,0 +1,339 @@
function check(v, re, msg) {
if (!re.test(v)) {
alert(msg)
}
}
function padPkcs7(data) {
var d = data.length % 16;
d = 16 - d;
var arr = Array.from(data)
for (var i = 0; i < d; i++) {
arr.push(d)
}
return arr;
}
function stripPcks7(data) {
var arr = Array.from(data)
var padder = arr[arr.length - 1];
return arr.slice(0, arr.length - padder);
}
function ecb(bytes, cb) {
var ret = []
for (var i = 0; i < bytes.length; i += 16) {
var d = bytes.slice(i, i + 16);
var en = cb(d)
ret = ret.concat(Array.from(en))
}
return ret;
}
class ActiveEpc {
constructor() {
this.server = "ws://127.0.0.1:12321/active";
this.waitMap = {}
}
__debug(...str) {
if (window.active_debug) {
console.log(...str)
}
}
connect() {
this.__debug("connect")
var _this = this;
try {
if (this.sock) {
this.sock.onclose = function () {
}
this.sock.close()
}
this.sock = new WebSocket(this.server);
this.__debug("sock")
this.sock.onopen = function () {
_this.__debug("open");
_this.sock.isopened = true;
_this.sock.onmessage = function (e) {
_this.__debug(e.data)
var ret = JSON.parse(e.data);
var cb = _this.waitMap[ret.id]
cb && cb(ret)
}
};
this.sock.onclose = function () {
_this.sock.isopened = false;
_this.__debug("close");
_this.reconnect();
};
// this.sock.onerror = function () {
// _this.sock.isopened = false;
// this.__debug("onerror");
// _this.reconnect();
// };
} catch (e) {
_this.__debug("onerror");
_this.reconnect();
}
}
reconnect() {
this.__debug("reconnect")
var _this = this;
if (_this.sock && _this.sock.isopened) {
this.__debug("miss")
return
}
setTimeout(function () {
_this.connect();
}, 3000);
}
__send(cmd, param, cb) {
var id = (Math.random() + "").substr(2);
this.sock.send(
JSON.stringify({
id: id,
cmd: cmd,
param: param
})
);
if (cb) {
this.waitMap[id] = cb;
}
}
__check(v, re, msg, reject) {
if (!re.test(v)) {
reject && reject({
msg,
code: "C0"
})
}
}
login(uid, utype, pwd) {
var _this = this;
return new Promise(function (resolve, reject) {
if (!_this.sock.isopened) {
reject({
code: "CB",
msg: "Active 通信失败"
})
}
_this.__check(uid, /\d{1,2}/g, "用户编号填写错误!", reject);
_this.__check(utype, /\d{1}/g, "用户类型填写错误!", reject);
_this.__check(pwd, /\d{6}/g, "密码填写错误!", reject);
_this.__send("login", {
uid, utype, pwd
}, function (ret) {
if (ret.code === "00" || ret.code === "33") {
resolve(ret)
} else {
reject(ret)
}
})
})
}
logout() {
var _this = this;
return new Promise(function (resolve, reject) {
if (!_this.sock.isopened) {
reject({
code: "CB",
msg: "Active 通信失败"
})
}
_this.__send("logout", {}, function (ret) {
if (ret.code === "00" || ret.code === "2E") {
resolve(ret)
} else {
reject(ret)
}
})
})
}
getSn() {
var _this = this;
return new Promise(function (resolve, reject) {
if (!_this.sock.isopened) {
reject({
code: "CB",
msg: "Active 通信失败"
})
}
_this.__send("getSn", {}, function (ret) {
if (ret.code === "00") {
resolve(ret)
} else {
reject(ret)
}
})
})
}
setAutoSleepTime(minutes) {
var _this = this;
return new Promise(function (resolve, reject) {
_this.__check(minutes, /\d{1,2}/g, "时间填写错误!", reject);
var v = parseInt(minutes, 10);
if( v > 20 || v < 2 ) {
reject({
code : "C0",
msg: "时间超出范围"
})
}
if (!_this.sock.isopened) {
reject({
code: "CB",
msg: "Active 通信失败"
})
}
_this.__send("setAutoSleepTime", { minutes }, function (ret) {
if (ret.code === "00") {
resolve(ret)
} else {
reject(ret)
}
})
})
}
modifyPassword(uid, utype, pwd) {
var _this = this;
return new Promise(function (resolve, reject) {
if (!_this.sock.isopened) {
reject({
code: "CB",
msg: "Active 通信失败"
})
}
_this.__check(uid, /\d{1,2}/g, "用户编号填写错误!", reject);
_this.__check(utype, /\d{1}/g, "用户类型填写错误!", reject);
_this.__check(pwd, /\d{6}/g, "密码填写错误!", reject);
_this.__send("modifyPassword", {
uid, utype, pwd
}, function (ret) {
if (ret.code === "00") {
resolve(ret)
} else {
reject(ret)
}
})
})
}
calcPaycode(accr, accu, ticketType, ticketNo, date, banlance) {
var _this = this;
return new Promise(function (resolve, reject) {
if (!_this.sock.isopened) {
reject({
code: "CB",
msg: "Active 通信失败"
})
}
_this.__check(accu, /\d{1,32}/g, "收方账户填写错误!", reject);
_this.__check(ticketType, /\d{1}/g, "票据类型填写错误!", reject);
_this.__check(ticketNo, /\d{1,8}/g, "票据编号填写错误!", reject);
_this.__check(date, /^(?:(?:1[6-9]|[2-9][0-9])[0-9]{2}([-/.]?)(?:(?:0?[1-9]|1[0-2])\1(?:0?[1-9]|1[0-9]|2[0-8])|(?:0?[13-9]|1[0-2])\1(?:29|30)|(?:0?[13578]|1[02])\1(?:31))|(?:(?:1[6-9]|[2-9][0-9])(?:0[48]|[2468][048]|[13579][26])|(?:16|[2468][048]|[3579][26])00)([-/.]?)0?2\2(?:29))$/g, "时间填写错误!", reject);
_this.__check(banlance, /\d{1,16}/g, "金额填写错误!", reject);
if ( '4' == ticketType || '5' == ticketType ) {
if ( undefined === accr || "" === accr ) {
reject({
code: "C0",
msg: "票据类型为汇兑和其他时,收方账号必填。"
})
}
}
if ( undefined === accr ) {
accr = ""
}
_this.__send("calcPaycode", {
accr, accu, ticketType, ticketNo, date, banlance
}, function (ret) {
if (ret.code === "00") {
resolve(ret)
} else {
reject(ret)
}
})
})
}
getAccountList() {
var _this = this;
return new Promise(function (resolve, reject) {
if (!_this.sock.isopened) {
reject({
code: "CB",
msg: "Active 通信失败"
})
}
_this.__send("getAccountList", {}, function (ret) {
if (ret.code === "00") {
resolve(ret)
} else {
reject(ret)
}
})
})
}
}
/**
* 检测通过返回 true
* 检测不通过返回 fase
*/
ActiveEpc.checkSupport = function () {
try {
if (!!window.WebSocket && window.WebSocket.prototype.send) {
return true;
} else {
console.error("您的浏览器不支持!")
return false;
}
} catch (e) {
console.error("当前环境不支持!", e)
return false;
}
}
+401
View File
@@ -0,0 +1,401 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>无线支付密码器 js 接口示例</title>
<style>
body {
width: 430px;
overflow-x: hidden;
color: sienna;
}
.step {
margin: 1rem;
border: silver dashed 1px;
padding: 0 1rem 1rem 1rem;
border-radius: 1rem;
}
.loading{
width: 80px;
height: 40px;
margin: 0 auto;
margin-top:100px;
}
.loading span{
display: inline-block;
width: 8px;
height: 100%;
border-radius: 4px;
background: lightgreen;
-webkit-animation: load 1s ease infinite;
}
@-webkit-keyframes load{
0%,100%{
height: 40px;
background: lightgreen;
}
50%{
height: 70px;
margin: -15px 0;
background: lightblue;
}
}
.loading span:nth-child(2){
-webkit-animation-delay:0.2s;
}
.loading span:nth-child(3){
-webkit-animation-delay:0.4s;
}
.loading span:nth-child(4){
-webkit-animation-delay:0.6s;
}
.loading span:nth-child(5){
-webkit-animation-delay:0.8s;
}
</style>
<link href="layx.min.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="title-warning" style="width: 100%; color:#f3b223; font-size: 2rem ;text-align: center"><span>您的浏览器不支持! </span></div>
<div style="text-align: center"><h2>功能测试</h2></div>
<div class="step">
<h3>基本功能</h3>
<div style="margin-bottom: 1rem">
<div style="margin-bottom: 1rem">
<div style="margin-bottom: 1rem; display: inline-block; margin-right: 1rem">当前状态: <span id="status">....</span>&emsp;&emsp;&emsp; <button id="logout">退&emsp;&emsp;出</button></div>
<div style="margin-bottom: 1rem">
<input id="uid" type="text" maxlength="2" placeholder="用户编号,1~2 个数字">
<select id="utype" style="height: 1.2rem">
<option value ="0">法人/授权人</option>
<option value ="1">主管/主管</option>
<option value ="2">会计/审核人</option>
<option value ="3">出纳/签发人</option>
</select>
</div>
<div style="margin-bottom: 1rem">
<input id="pwd1" type="password" maxlength="6" placeholder="口令,6 个数字">
<button id="login" style="margin-right: 1rem">登&emsp;&emsp;录</button></div>
</div>
</div>
<div><input id="pwd2" type="password" maxlength="6" placeholder="6 个数字"> <button id="modifyPassword">修改口令</button> </div>
</div>
<div class="step">
<h3>获取设备编号</h3>
<div>设备编号: <input id="sn" readonly type="text"></div>
<button id="getSn" style="margin-top:1rem; margin-left: 0rem;">获取</button>
</div>
<div class="step">
<h3>设置自动休眠时间</h3>
<div>分钟: <input id="minutes" type="text" maxlength="2"></div>
<button id="setAutoSleepTime" style="margin-top:1rem; margin-left: 0rem;">设置</button>
</div>
<div class="step">
<h3>支付密码计算</h3>
<div>收方账户: <input type="text" id="accr" maxlength="30" placeholder="30 个数字,汇兑凭证/其他必填"></div>
<div>付方账户: <input type="text" id="accu" maxlength="32" placeholder="8 ~ 32 个数字"></div>
<div>票据类型: <select id="ticketType" style="height: 1.2rem">
<option value ="1">支票</option>
<option value ="2">银行汇票</option>
<option value ="3">银行本票</option>
<option value ="4">汇兑凭证</option>
<option value ="5">其他</option>
</select>
</div>
<div>票据编号: <input id="ticketNo" type="text" maxlength="8" placeholder="最大 8 个数字"></div>
<div>时&emsp;&emsp;间: <input id="date" type="text" maxlength="8" placeholder="yyyyMMdd"></div>
<div>金&emsp;&emsp;额: <input id="banlance" type="text" maxlength="16" placeholder="最大 16 个数字,单位是“分”"></div>
<div>支付密码: <input id="paycode" readonly type="text"></div>
<button id="calcPaycode" style="margin-top:1rem; margin-left: 0rem;">计算支付密码</button>
</div>
<div class="step">
<h3>获取账户列表</h3>
<button id="getAccountList">获取所有账户</button> <span style="color: silver; font-size: 0.8rem">账户比较多时较慢,最长 30 秒。</span>
<div id="loadding-account-list" class="loading" style="margin-bottom: 2rem">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
<div id="account-list" style="margin-top: 1rem">
</div>
</div>
<!-- 仅此示例程序需要依赖 jquery -->
<script src="jquery.min.js"></script>
<script src="layx.min.js" type="text/javascript"></script>
<script src="active.epc.min.js"></script>
<script type="application/javascript">
function getyyyyMMdd(){
var d = new Date();
var curr_date = d.getDate();
var curr_month = d.getMonth() + 1;
var curr_year = d.getFullYear();
String(curr_month).length < 2 ? (curr_month = "0" + curr_month): curr_month;
String(curr_date).length < 2 ? (curr_date = "0" + curr_date): curr_date;
var yyyyMMdd = curr_year + "" + curr_month +""+ curr_date;
return yyyyMMdd;
}
// 覆盖默认行为
function success(msg){
layx.notice({
title: '成功',
type: 'success',
message: msg
});
}
// 覆盖默认行为
function warning(msg){
layx.notice({
title: '警告',
type: 'warning',
message: msg
});
}
// 覆盖默认行为
function alert(msg){
layx.notice({
title: '错误',
type: 'error',
message: msg
});
}
// init
$("#title-warning").hide();
$("#loadding-account-list").hide();
$("#date").val( getyyyyMMdd() );
$(function () {
if ( ! ActiveEpc.checkSupport() ) {
$("#title-warning").show();
} else {
$("#title-warning").hide();
}
// 建立连接
var api = new ActiveEpc();
api.connect()
$("#login").click(function (){
$(this).attr("disabled",true);
// 用户登录
var uid = $("#uid").val();
var utype = $("#utype").val();
var pwd1 = $("#pwd1").val();
api.login(uid, utype, pwd1)
.then(function ( ret ){
if ( ret.code === "00" ) {
success("登录成功")
} else {
warning("重复登录")
}
$("#status").text("已登录").css({ color : "green"});
})
.catch(function (e) {
alert("[" + e.code + "]" + "登录失败," + (e.data ? "剩余尝试次数" + e.data : e.msg) )
$("#status").text("...").css({ color : "sliver"})
}).finally(() => {
$(this).attr("disabled",false);
})
})
$("#logout").click(function (){
$(this).attr("disabled",true);
api.logout()
.then(function (ret){
if ( ret.code === "00" ) {
success("已退出")
} else {
warning("重复退出")
}
$("#status").text("已退出").css({ color : "orange"})
})
.catch(function (e) {
alert("[" + e.code + "]" + "退出失败," + e.msg)
$("#status").text("...").css({ color : "orange"})
}).finally(() => {
$(this).attr("disabled",false);
})
})
$("#getSn").click(function (){
api.getSn()
.then(function ( ret ){
success("获取芯片编号成功!")
$("#sn").val( ret.data )
})
.catch(function (e) {
alert("[" + e.code + "]" + "获取芯片编号失败," + e.msg)
if ( "2E" === e.code ) {
$("#status").text("未登录").css({ color : "sliver"})
}
}).finally(() => {
$(this).attr("disabled",false);
})
})
$("#setAutoSleepTime").click(function (){
var minutes = $("#minutes").val();
api.setAutoSleepTime( minutes )
.then(function ( ret ){
success("设置自动休眠时间成功!")
$("#minutes").val("")
})
.catch(function (e) {
alert("[" + e.code + "]" + "设置自动休眠时间失败," + e.msg)
if ( "2E" === e.code ) {
$("#status").text("未登录").css({ color : "sliver"})
}
}).finally(() => {
$(this).attr("disabled",false);
})
})
$("#modifyPassword").click(function (){
var uid = $("#uid").val();
var utype = $("#utype").val();
var pwd2 = $("#pwd2").val();
$(this).attr("disabled",true);
api.modifyPassword(uid, utype, pwd2)
.then(function (){
success("密码修改成功,请牢记!")
})
.catch(function (e) {
alert("[" + e.code + "]" + "修改密码失败," + e.msg)
if ( "2E" === e.code ) {
$("#status").text("未登录").css({ color : "sliver"})
}
}).finally(() => {
$(this).attr("disabled",false);
})
})
$("#calcPaycode").click(function (){
$(this).attr("disabled",true);
var accr = $("#accr").val();
var accu = $("#accu").val();
var ticketType = $("#ticketType").val();
var ticketNo = $("#ticketNo").val();
var date = $("#date").val();
var banlance = $("#banlance").val();
api.calcPaycode(accr, accu, ticketType, ticketNo, date, banlance)
.then(function (ret){
var v = ret.data;
if ( v.startsWith("FFFF") ) {
v = v.substr(4);
}
$("#paycode").val(v);
success("计算结束")
})
.catch(function (e) {
$("#paycode").val("");
alert("[" + e.code + "]" + "计算支付密码失败," + e.msg)
if ( "2E" === e.code ) {
$("#status").text("未登录").css({ color : "sliver"})
}
}).finally(() => {
$(this).attr("disabled",false);
})
})
$("#getAccountList").click(function (){
$(this).attr("disabled",true);
$("#account-list").hide();
$("#loadding-account-list").show();
api.getAccountList()
.then(function ( ret ){
var data = ret.data;
var table = " <table border=\"1\">\n" +
" <tr>\n" +
" <th>ID</th>\n" +
" <th>账户</th>\n" +
" <th>有效位</th>\n" +
" </tr>\n" +
"\n"
for ( var i = 0; i < data.length; i++) {
table += "<tr>\n" +
" <td>"+ data[i].id +"</td>\n" +
" <td>"+ data[i].acc +"</td>\n" +
" <td>"+ data[i].len +"</td>\n" +
" </tr>"
}
+ " </table>"
$("#account-list").html( table ).show();
})
.catch(function (e) {
alert("[" + e.code + "]" + "获取账号列表失败," + e.msg)
if ( "2E" === e.code ) {
$("#status").text("未登录").css({ color : "sliver"})
}
}).finally(() => {
$("#loadding-account-list").hide();
$(this).attr("disabled",false);
})
})
})
</script>
</body>
</html>
+2
View File
File diff suppressed because one or more lines are too long
+1
View File
File diff suppressed because one or more lines are too long
+5
View File
File diff suppressed because one or more lines are too long