读取代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>读身份证+M1卡示例</h1><br>
<div id="message"></div>
<div>
<button id="OcrRecognition" onclick="OcrRecognition()">连接服务</button>
<tr>
<td align="right">超时(毫秒ms):</td>
<td><input type="text" id="timeOut" size="49" style="width:100px;" value="10000"></td>
</tr>
<tr>
<td align="right">日志:</td>
<td><input type="text" id="partyLog" size="49" style="width:400px;" readonly="readonly"></td>
</tr>
</div>
<h1>M1卡</h1><br>
<div>
<tr>
<td align="right">块号:</td>
<td><input type="text" id="Block" size="49" style="width: 100px;" value="2"></td>
</tr>
<tr>
<td align="right">密码:</td>
<td><input type="text" id="KeyBuf" size="49" style="width:200px;" value="FF FF FF FF FF FF"></td>
</tr>
<tr>
<td align="right">写入值:</td>
<td><input type="text" id="WriteBuf" size="49" style="width:200px;" value="01 02 03 04 05 06"></td>
</tr>
</div>
<div>
<button id="RequestM1" onclick="Request()" style="width:160px;">M1卡认证</button>
<button id="ReadM1" onclick="ReadM1()" style="width:160px;">读M1卡</button>
<button id="WriteM1" onclick="WriteM1()" style="width:160px;">写M1卡</button>
<button id="GetFisCardID" onclick="GetFisCardID()" style="width:160px;">银行卡信息</button>
</div>
<h1>读身份证</h1><br>
<div>
<button id="TimeOutReadIDCard" onclick="TimeOutReadIDCard()">时间段内读取身份证</button>
<button id="ReadIDCard" onclick=" ReadIDCard()">读取身份证</button>
<button id="ReadIDCardNoJudge" onclick="ReadIDCardNoJudge()">不拿起读身份证</button>
<button id="ReadSAMID" onclick="ReadSAMID()">获取安全模块号</button>
</div>
<table border="0" width="100%" cellpadding="0" cellspacing="10">
<tr>
<td align="right">姓名:</td>
<td><input type="text" id="partyName" size="49" style="width:400px;" readonly="readonly"></td>
</tr>
<tr>
<td align="right">性别:</td>
<td><input type="text" id="gender" size="49" style="width:400px;" readonly="readonly"></td>
</tr>
<tr>
<td align="right">民族:</td>
<td><input type="text" id="nation" size="49" style="width:400px;" readonly="readonly"></td>
</tr>
<tr>
<td align="right">出生日期:</td>
<td><input type="text" id="bornDay" size="49" style="width:400px;" readonly="readonly">(要求格式为:yyyyMMdd,长度为8)</td>
</tr>
<tr>
<td align="right">住址:</td>
<td><input type="text" id="certAddress" size="49" style="width:400px;" readonly="readonly"></td>
</tr>
<tr>
<td align="right">身份证号:</td>
<td><input type="text" id="certNumber" size="49" style="width:400px;" readonly="readonly">(居民身份号码,长度18位)</td>
</tr>
<tr>
<td align="right">签发机关:</td>
<td><input type="text" id="certOrg" size="49" style="width:400px;" readonly="readonly"></td>
</tr>
<tr>
<td align="right">开始期限:</td>
<td><input type="text" id="effDate" size="49" style="width:400px;" readonly="readonly">(要求格式为:yyyyMMdd,长度为8)</td>
</tr>
<tr>
<td align="right">结束期限:</td>
<td><input type="text" id="expDate" size="49" style="width:400px;" readonly="readonly">(要求格式为:yyyyMMdd,长度为8,或者是“长期”)</td>
</tr>
<tr>
<td align=right>照片:</td>
<td><IMG style="WIDTH: 124px; HEIGHT: 150px" name=PhotoDisplay></td>
</tr>
</table>
</body>
<script type="text/javascript">
let websockets;
let isconncet = false;
let Command = 1;
//创建一个数组对象用于存放当前的连接的状态,以便在页面上实时展示出来当前的状态
let statusArr = [
{ state: 0, value: '正在连接' },
{ state: 1, value: '已建立连接' },
{ state: 2, value: '正在关闭连接' },
{ state: 3, value: '已关闭连接' },
]
/**
* 建立连接
*
*/
function OcrRecognition() {
if (!isconncet) {
// 1. 创建websockets对象,参数为服务器websockets地址
let hostname = location.hostname;
var url = "ws:127.0.0.1:9001"
websockets = new WebSocket(url);
// 2.监听websocket的状态变化,接收的信息,关闭时的状态
//监听连接状态的变化
websockets.onopen = (event) => socketChange();
//监听接收消息的情况
websockets.onmessage = (res) => {
if (res.data == "failed to obtain ID card information") {
document.querySelector("#message").innerHTML += `<p>接收数据: ${res.data}</p>`
return;
}
var alldata = res.data.split("|");
if (Command < 6) {
// 读身份证
if (alldata.length >= 17) {
document.getElementById("partyLog").value = "读卡成功";
document.getElementById("partyName").value = alldata[3];
document.getElementById("nation").value = alldata[5];
document.getElementById("gender").value = alldata[4];
document.getElementById("certAddress").value = alldata[7];
document.getElementById("bornDay").value = alldata[6];
document.getElementById("certNumber").value = alldata[8];
document.getElementById("certOrg").value = alldata[9];
document.getElementById("effDate").value = alldata[10];
document.getElementById("expDate").value = alldata[11];
document.all['PhotoDisplay'].src = 'data:image/bmp;base64,' + alldata[19];
}
else {
document.getElementById("partyLog").value = res.data;
}
}
else {
// 读M1卡
if (Command == 6) {
// 卡认证
if (alldata.length >= 2) {
document.getElementById("partyLog").value = "卡序列号:" + alldata[0] + " 卡类型:" + alldata[1];
}
else {
document.getElementById("partyLog").value = res.data;
}
}
if (Command == 7) {
// 读M1卡
if (alldata.length >= 2) {
document.getElementById("partyLog").value = "卡序列号:" + alldata[0] + " 块数据:" + alldata[1];
}
else {
document.getElementById("partyLog").value = res.data;
}
}
if (Command == 8) {
// 写M1卡
document.getElementById("partyLog").value = res.data;
}
if (Command == 9) {
// 读银行卡卡号和有效期
if (alldata.length >= 2) {
document.getElementById("partyLog").value = "银行卡卡号:" + alldata[0] + " 有效期:" + alldata[1];
}
else {
document.getElementById("partyLog").value = res.data;
}
}
}
}
//监听关闭时的状态变化
websockets.onclose = (event) => socketChange();
}
else {
closeConnect();
document.getElementById("OcrRecognition").innerHTML = "连接服务";
}
}
function TimeOutReadIDCard() {
if (!isconncet) {
document.getElementById("partyLog").value = "未连接服务";
} else {
Command = 2;
clear();
let paramTimeOut = document.querySelector("#timeOut").value;
paramTimeOut = "timeout=" + paramTimeOut;
var parameterAll = paramTimeOut;
let val = "02?" + parameterAll;
websockets.send(val);
}
}
function ReadIDCard() {
if (!isconncet) {
document.getElementById("partyLog").value = "未连接服务";
} else {
Command = 3;
clear();
let paramTimeOut = document.querySelector("#timeOut").value;
paramTimeOut = "timeout=" + paramTimeOut;
var parameterAll = paramTimeOut;
let val = "03?" + parameterAll;
websockets.send(val);
}
}
function ReadIDCardNoJudge() {
if (!isconncet) {
document.getElementById("partyLog").value = "未连接服务";
} else {
Command = 4;
clear();
let paramTimeOut = document.querySelector("#timeOut").value;
paramTimeOut = "timeout=" + paramTimeOut;
var parameterAll = paramTimeOut;
let val = "04?" + parameterAll;
websockets.send(val);
}
}
function ReadSAMID() {
if (!isconncet) {
document.getElementById("partyLog").value = "未连接服务";
} else {
Command = 5;
clear();
let paramTimeOut = document.querySelector("#timeOut").value;
paramTimeOut = "timeout=" + paramTimeOut;
var parameterAll = paramTimeOut;
let val = "05?" + parameterAll;
websockets.send(val);
}
}
function Request() {
if (!isconncet) {
document.getElementById("partyLog").value = "未连接服务";
} else {
Command = 6;
clear();
let paramTimeOut = document.querySelector("#timeOut").value;
paramTimeOut = "timeout=" + paramTimeOut;
var parameterAll = paramTimeOut;
let val = "06?" + parameterAll;
websockets.send(val);
}
}
function ReadM1() {
if (!isconncet) {
document.getElementById("partyLog").value = "未连接服务";
} else {
Command = 7;
clear();
var ValuesBlock = document.querySelector("#Block").value;
ValuesBlock = "Block=" + ValuesBlock;
var ValuesKey = document.querySelector("#KeyBuf").value;
ValuesKey = "Key=" + ValuesKey;
var val = "07?" + ValuesBlock + "|" + ValuesKey;
websockets.send(val);
}
}
function WriteM1() {
if (!isconncet) {
document.getElementById("partyLog").value = "未连接服务";
} else {
Command = 8;
clear();
var ValuesBlock = document.querySelector("#Block").value;
ValuesBlock = "Block=" + ValuesBlock;
var ValuesKey = document.querySelector("#KeyBuf").value;
ValuesKey = "Key=" + ValuesKey;
var ValuesWriteBuf = document.querySelector("#WriteBuf").value;
ValuesWriteBuf = "WriteBuf=" + ValuesWriteBuf;
var val = "08?" + ValuesBlock + "|" + ValuesKey + "|" + ValuesWriteBuf;
websockets.send(val);
}
}
function GetFisCardID() {
if (!isconncet) {
document.getElementById("partyLog").value = "未连接服务";
} else {
Command = 9;
clear();
let paramTimeOut = document.querySelector("#timeOut").value;
paramTimeOut = "timeout=" + paramTimeOut;
var parameterAll = paramTimeOut;
let val = "09?" + parameterAll;
websockets.send(val);
}
}
/**
* socket状态变化
*
*/
function socketChange() {
let state = websockets.readyState;
let val = statusArr.map((item) => {
if (item.state == state) {
return item.value
}
});
//实时显示状态的变化
document.getElementById("partyLog").value = val;
//读身份证
if (1 == state) {
isconncet = true;
document.getElementById("OcrRecognition").innerHTML = "断开服务";
}
if (3 == state) {
isconncet = false;
}
}
/**
* 关闭连接
*
*/
function closeConnect() {
websockets.close();
}
/**
* 关闭连接
*
*/
function clear() {
document.getElementById("partyLog").value = "";
document.getElementById("partyName").value = "";
document.getElementById("nation").value = "";
document.getElementById("gender").value = "";
document.getElementById("certAddress").value = "";
document.getElementById("bornDay").value = "";
document.getElementById("certNumber").value = "";
document.getElementById("certOrg").value = "";
document.getElementById("effDate").value = "";
document.getElementById("expDate").value = "";
document.all['PhotoDisplay'].src = "";
}
</script>
</html>
身份证与 M1 卡读取交互页面功能概述
在酒店、金融、政务等需要身份核验与卡证交互的场景中,便捷高效的读卡工具至关重要。以下介绍的 HTML 页面便是一款集成身份证与 M1 卡读取功能的交互界面,通过 WebSocket 技术实现前端与后端服务的实时通信,为各类场景下的卡证信息采集提供了完整解决方案。
核心功能架构
该页面以模块化设计整合了两类核心功能:身份证信息读取与 M1 卡交互。整体界面分为功能控制区与信息展示区,通过简洁的按钮操作触发不同的读卡指令,配合输入框配置参数,最终将读取结果实时显示在对应区域。
在身份证读取方面,页面提供了四种操作模式:时间段内读取、单次读取、不拿起持续读取以及获取安全模块号(SAMID)。这些功能覆盖了不同场景下的使用需求 —— 例如酒店前台可通过 “时间段内读取” 功能在规定时间内等待旅客放置身份证,而 “不拿起读身份证” 则适用于需要连续核验的场景。
M1 卡交互功能则包含认证、读取、写入及银行卡信息获取,支持自定义块号、密码与写入值,满足对 M1 卡进行数据读写的多样化需求。无论是会员系统的卡片信息更新,还是门禁卡的权限配置,都可通过这些功能实现。
技术实现逻辑
页面采用 WebSocket 协议建立前端与后端服务的实时连接,通过ws:127.0.0.1:9001
地址与本地服务通信。当用户点击 “连接服务” 按钮时,前端创建 WebSocket 实例,监听连接状态变化并同步显示在日志区域;连接建立后,所有操作指令(如读卡、写卡)通过特定格式的字符串(如03?timeout=10000
)发送至后端。
后端返回的数据经 “|” 符号分割后,由前端按预设规则解析并填充至对应字段。例如身份证信息包含姓名、性别、民族等 17 项以上数据,分别对应页面中的输入框;M1 卡数据则根据操作类型(认证、读写)显示序列号、块数据等内容。此外,身份证照片通过 Base64 编码格式实时渲染至页面,实现信息可视化展示。
应用场景价值
该页面的设计充分考虑了实际使用场景的需求:超时时间设置可避免因设备响应延迟导致的操作卡顿;日志区域实时反馈操作状态,便于快速排查连接或读卡失败问题;模块化的功能分区使操作人员能迅速定位所需功能,降低学习成本。
阿雪技术观
在科技发展浪潮中,我们不妨积极投身技术共享。不满足于做受益者,更要主动担当贡献者。无论是分享代码、撰写技术博客,还是参与开源项目维护改进,每一个微小举动都可能蕴含推动技术进步的巨大能量。东方仙盟是汇聚力量的天地,我们携手在此探索硅基生命,为科技进步添砖加瓦。
Hey folks, in this wild tech - driven world, why not dive headfirst into the whole tech - sharing scene? Don't just be the one reaping all the benefits; step up and be a contributor too. Whether you're tossing out your code snippets, hammering out some tech blogs, or getting your hands dirty with maintaining and sprucing up open - source projects, every little thing you do might just end up being a massive force that pushes tech forward. And guess what? The Eastern FairyAlliance is this awesome place where we all come together. We're gonna team up and explore the whole silicon - based life thing, and in the process, we'll be fueling the growth of technology.