如何在web浏览器页面使用IC卡读卡器并且兼容所有浏览器

2018-10-10 15:33:33 诺塔斯智能科技 94

    随着H5技术的不断发展与推广,H5技术被广泛用于移动设备,PC终端等众多领域。同时,越来越多的应用都基于B/S(浏览器/服务器)模式,降低开发难度的同时还能更好的普及和应用,突破了硬件设备的兼容性问题。然而,嵌入式开发的设备并没有跟上H5技术的脚步,现在很多嵌入式设备并不支持或者不能友好的支持浏览器应用。举个例子,如何在web浏览器页面使用IC卡读卡器并且兼容所有浏览器?针对这个问题,有人肯定会说利用active X控件就可以了啊!确实如果是基于IE或者IE内核的浏览器使用active X是没有任何问题,但是现在除了使用IE浏览器还有大部分使用Chrome和Firefox等多种内核和版本的浏览器,为了让嵌入式设备更好的兼容所有浏览器,我们提供了一套基于在嵌入式设备中内置WebSocket组件的方案,希望能帮助大家在解决使用浏览器集成嵌入式设备中遇到的难题,一下仅以我司智能卡读写器做详细介绍。

  传统的ActiveX组件,通过javascript页面与设备进行信息交互。

<HTML><HEAD><TITLE>第二代居民身份证网页ActiveX控件测试网页</TITLE>
<OBJECT ID=LotusCardDriver Visible=false WIDTH=0 HEIGHT=0
 CLASSID="CLSID:BD1874A5-3810-4639-8B70-3DDD607BAADB" CODEBASE="./lotus.CAB#version=1,0,0,4"> </OBJECT>
<SCRIPT language=JavaScript>
<!--


function ReadIDCard() {
	var nHandle = 0; //设备句柄
	var bResult = 0;
	var strTextInfo = "";
	var nErrorCode = 0;
	clearForm();
	nHandle	=	LotusCardDriver.OpenDevice("",0,0,0);
	if(nHandle <=0 ) 
	{
		alert("打开设备失败,或者你没有插入读卡器!购买读卡器,请点击 确定 ");
		window.location.href="https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-7912663678.8.HdHoCq&id=542822138758";
		return;
	}
	bResult = LotusCardDriver.Beep(nHandle,10);
  if(bResult!=1)
  {
  	alert("蜂鸣失败!");
  	LotusCardDriver.CloseDevice(nHandle);
  	return;
  }		
  bResult = LotusCardDriver.SetCardType(nHandle, 'B');
  if(bResult!=1)
  {
  	alert("设置卡类型失败!");
  	LotusCardDriver.CloseDevice(nHandle);
  	return;
  }		
  //使用1.0服务器
  //bResult = LotusCardDriver.GetTwoIdInfoByServer(nHandle, '120.24.253.33');
  //bResult = LotusCardDriver.GetTwoIdInfoByServer(nHandle, '192.168.1.101');
  //使用调度服务器
  bResult = LotusCardDriver.GetTwoIdInfoByMcuServer(nHandle, '112.124.37.59', 'UserName', 'Password', 2);
  if(bResult!=1)
  {
  	nErrorCode = LotusCardDriver.GetTwoIdErrorCode(nHandle);
  	alert("读取二代证信息失败!"+nErrorCode +LotusCardDriver.GetTwoIdErrorInfo(nHandle, nErrorCode));
  	LotusCardDriver.CloseDevice(nHandle);
  	return;
  }	
  //解析WL
  bResult = LotusCardDriver.WlDecodeByServer(nHandle, '120.24.249.49');//120.24.253.33 211.149.188.24
  
	LotusCardDriver.CloseDevice(nHandle);	
   
   fillForm();
/*   var ret = CVR_IDCard.ReadCard();
   if (ret == "0"){
      fillForm();
      return;
   } 

   alert("读卡错误,错误原因:" + ret);*/
}

function fillForm() {   
  var pName=LotusCardDriver.TwoId_Name; 
  var pSex=LotusCardDriver.TwoId_Sex;
  var pNation=LotusCardDriver.TwoId_Nation;
  var pBorn=LotusCardDriver.TwoId_Birthday;
  var pAddress=LotusCardDriver.TwoId_Address;
  var pCardNo=LotusCardDriver.TwoId_No;
  var pPolice=LotusCardDriver.TwoId_SignedDepartment;
  var pActivityLFrom=LotusCardDriver.TwoId_ValidityPeriodBegin; 
  var pActivityLTo=LotusCardDriver.TwoId_ValidityPeriodEnd; 
  var pDeviceNo=0;//LotusCardDriver.CardReaderId;
  var pPhotoBuffer=LotusCardDriver.TwoId_PhotoB64; 

  document.all['Name'].value = pName; 
  document.all['Sex'].value = pSex; 
  document.all['Nation'].value = pNation; 
  document.all['Born'].value = pBorn; 
  document.all['Address'].value = pAddress; 
  document.all['CardNo'].value = pCardNo; 
  document.all['Police'].value = pPolice;  
  document.all['ActivityLFrom'].value = pActivityLFrom; 
  document.all['DeviceNo'].value = pDeviceNo; 
  document.all['ActivityLTo'].value = pActivityLTo; 
  document.all['PhotoBuffer'].value = pPhotoBuffer; 
  document.all['PhotoDisplay'].src = 'data:image/jpg;base64,' + pPhotoBuffer; 
}

function clearForm() {
  document.all['Name'].value = ''; 
  document.all['Sex'].value = ''; 
  document.all['Nation'].value = ''; 
  document.all['Born'].value = ''; 
  document.all['Address'].value = ''; 
  document.all['CardNo'].value = ''; 
  document.all['Police'].value = '';  
  document.all['ActivityLFrom'].value = ''; 
  document.all['ActivityLTo'].value = ''; 
  document.all['PhotoBuffer'].value = ''; 
  document.all['PhotoDisplay'].src = ''; 
  document.all['DeviceNo'].value = ''; 

}

//-->
</SCRIPT>
<script>
 function gobackhome(){
 window.location.href="index.html";
}

这种方式在非IE浏览器模式下无法使用,更别提Android和IOS系统上的浏览器了。为了解决在非IE浏览器模式下将我们智能卡读写器嵌入在浏览器中,而且能兼容所有浏览器。我们将读写器单片机里面内置了Websocket组件,读写器采用TCP/IP网络通信,不管是PC浏览器还是Android、IOS浏览器均能实现完美兼容。

范例代码如下:

<!DOCTYPE html>    
<html>    
<head>    
<meta charset="utf-8" />    
<title>LotusCard WEB Socket演示页面</title>    
<meta name="apple-mobile-web-app-capable" content="yes">    
<meta name = "viewport" content = "width = 320, initial-scale = 1.0, user-scalable = yes">     
<script language="javascript" type="text/javascript">    
	function getNowFormatDate() {    
var date = new Date();    
var seperator1 = "-";    
var seperator2 = ":";    
var month = date.getMonth() + 1;    
var strDate = date.getDate();    
var socket = null;    
var nCommandIndex = 0;    
var strIp = "";    
var strPort = "";    
var wsUrl = "";    
if (month >= 1 && month <= 9) {    
month = "0" + month;    
}    
if (strDate >= 0 && strDate <= 9) {    
strDate = "0" + strDate;    
}    
var currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate    
+ " " + date.getHours() + seperator2 + date.getMinutes()    
+ seperator2 + date.getSeconds()    
+ seperator2 + date.getMilliseconds();    
return currentdate;    
	}		
    
		function ConnectServer(){    
			try {    
				nCommandIndex = 0;    
				strIp = document.getElementById('strLotusCardDeviceIp').value;    
				strPort = document.getElementById('strLotusCardDevicePort').value;    
				wsUrl = 'ws://'+ strIp +':'+strPort;    
				socket = new WebSocket(wsUrl);    
} catch (evt) {    
document.getElementById('log').innerHTML = '<li><b>'+getNowFormatDate()+'#new WebSocket error:'+ evt.data+'</b></li>' + document.getElementById('log').innerHTML;    
socket = null;    
if (typeof(connCb) != "undefined" && connCb != null)    
connCb("-1", "connect error!");    
return;    
}			
    
			socket.onopen = function ()    
				{    
					document.getElementById('log').innerHTML = '<li><b>'+getNowFormatDate()+'#连接服务器成功</b></li>' + document.getElementById('log').innerHTML;    
					document.getElementById('status').innerHTML = 'Socket Open';    
					document.getElementById('status').className = 'online';    
				};    
			socket.onclose =function(event)    
				{    
					document.getElementById('log').innerHTML = '<li><b>'+getNowFormatDate()+'#断开连接:' + event.wasClean + '</b></li>' + document.getElementById('log').innerHTML;    
					document.getElementById('status').innerHTML = 'Socket Closed';    
					document.getElementById('status').className = 'offline';    
				};    
			socket.onmessage = function(event)    
				{    
					var arrString;    
					strLastResult = event.data;    
					document.getElementById('log').innerHTML = '<li><b>'+getNowFormatDate()+'#收到数据:' + event.data + '</b></li>' + document.getElementById('log').innerHTML;    
//					arrString = strLastResult.split(',');    
//					if(COMMAND_OPEN_DEVICE == arrString[0])    
//					{    
//						if(arrString.length>2) m_nHandle = arrString[2];    
//						document.getElementById('log').innerHTML = '<li><b>#获取设备句柄:' + m_nHandle + '</b></li>' + document.getElementById('log').innerHTML;    
//					}					
    
					//document.getElementById('log').innerHTML = '<li><b>#received:' + arrString[0] + '</b></li>' + document.getElementById('log').innerHTML;    
					//document.getElementById('log').innerHTML = '<li><b>#received:' + arrString.length + '</b></li>' + document.getElementById('log').innerHTML;    
				};    
			socket.onerror = function(event)    
				{    
					document.getElementById('log').innerHTML = '<li><b>#disconnected:' + event.message + '</b></li>' + document.getElementById('log').innerHTML;    
					document.getElementById('status').innerHTML = 'Socket Error';    
					document.getElementById('status').className = 'error';    
				};			
    
		}    
function ExecStringCommand(strCommand) {    
				strLastResult = '';    
				nCommandIndex++;    
				if (socket.readyState == WebSocket.OPEN) {    
					socket.send(strCommand+','+nCommandIndex);    
} else {    
		document.getElementById('log').innerHTML = '<li><b>#send failed. websocket not open. please check.</b></li>' + document.getElementById('log').innerHTML;    
}				
    
}    
functionGetSocketStatus() {    
	if(null == socket) return "socket is null";    
switch (socket.readyState) {    
case socket.CONNECTING:    
return "connecting";    
break;    
case socket.OPEN:    
return "open";    
break;    
case socket.CLOSING:    
return "closing";    
break;    
case socket.CLOSED:    
return "closed";    
break;    
default:    
return "undefined";    
break    
}    
};    
</script>    
<style>    
body {    
	font-family:Verdana,Arial,"Times New Roman";    
}    
#status {    
padding: 5px;    
color: #fff;    
background: #ccc;    
}    
#status.error {    
background: #c00;    
font-weight: bold;    
}    
#status.offline {    
background: #c00;    
font-weight: bold;    
}    
#status.online {    
background: #0c0;    
font-weight: bold;    
}    
</style>    
</head>    
<body>    
<h1>LotusCard WEB Socket 演示页面</h1>    
<table width="100%">    
	<tr style="width:100px; height:40px;">    
		<td>    
			读卡器IP:    
		</td>		    
		<td>    
			<input type="text" value="192.168.1.252" id="strLotusCardDeviceIp" style="width:150px; height:30px;" />    
		</td>    
	</tr>    
	<tr style="width:100px; height:40px;">    
		<td>    
			读卡器PORT:    
		</td>		    
		<td>    
			<input type="text" value="31213" id="strLotusCardDevicePort" style="width:150px; height:30px;" />    
		</td>    
	</tr>    
	<tr style="width:100px; height:40px;">    
		<td>    
			状态    
		</td>    
		<td>    
			<p id="status"></p>    
		</td>    
	</tr>    
	<tr style="width:100px; height:40px;">    
		<td colspan="2">    
			<h3>通信函数:1、连接服务器 2、执行字符串函数并解析结果 3、断开连接</h3>    
		</td>    
	</tr>    
	<tr style="width:100px; height:40px;">    
		<td>    
			连接服务器:    
		</td>    
		<td>    
			<INPUT id = "ConnectServer"type=button value="ConnectServer" onclick="javascript:ConnectServer();" style="width:150px; height:30px;"/>			    
		</td>    
	</tr>    
	<tr style="width:100px; height:40px;">    
		<td>    
			关闭连接:    
		</td>		    
		<td>    
			<INPUT id = "CloseConnection"type=button value="CloseConnection" onclick="javascript:socket.close();" style="width:150px; height:30px;"/>    
		</td>    
	</tr>    
	<tr style="width:100px; height:40px;">    
		<td>    
			获取连接状态:    
		</td>    
		<td>    
			<INPUT id = "ConnectionStatus"type=button value="ConnectionStatus" onclick="javascript:document.getElementById('log').innerHTML = '<li><b>#status:' + GetSocketStatus() + '</b></li>' + document.getElementById('log').innerHTML;"    
			style="width:150px; height:30px;"/>    
		</td>    
	</tr>    
	<tr style="width:100px; height:40px;">    
		<td>    
			获取MCU序列号:    
		</td>		    
		<td>    
			<INPUT id = "OpenDevice"type=button value="GetMcuSerailNo" onclick="javascript:ExecStringCommand('GetMcuSerailNo')" style="width:150px; height:30px;"/>    
		</td>    
	</tr>    
	<tr style="width:100px; height:40px;">    
		<td>    
			蜂鸣:    
		</td>		    
		<td>    
			<INPUT id = "Beep"type=button value="Beep" onclick="javascript:ExecStringCommand('Beep,10');" style="width:150px; height:30px;"/>    
		</td>    
	</tr>    
	<tr style="width:100px; height:40px;">    
		<td>    
			获取M1卡号:    
		</td>		    
		<td>    
			<INPUT id = "GetCardNo"type=button value="GetCardNo" onclick="javascript:ExecStringCommand('GetCardNo,38');" style="width:150px; height:30px;"/>    
		</td>    
	</tr>    
	<tr style="width:100px; height:40px;">    
		<td>    
			装载密码:    
		</td>		    
		<td>    
			<INPUT id = "LoadKey"type=button value="LoadKey" onclick="javascript:ExecStringCommand('LoadKey,96,0,FFFFFFFFFFFF');" style="width:150px; height:30px;"/>    
		</td>    
	</tr>    
	<tr style="width:100px; height:40px;">    
		<td>    
			验证密码:    
		</td>		    
		<td>    
			<INPUT id = "Authentication"type=button value="Authentication" onclick="javascript:ExecStringCommand('Authentication,96,0');" style="width:150px; height:30px;"/>    
		</td>    
	</tr>    
	<tr style="width:100px; height:40px;">    
		<td>    
			读数据扇区0块1:    
		</td>		    
		<td>    
			<INPUT id = "M1Read"type=button value="M1Read" onclick="javascript:ExecStringCommand('Read,1');" style="width:150px; height:30px;"/>    
		</td>    
	</tr>    
	<tr style="width:100px; height:40px;">    
		<td>    
			写数据扇区0块1:    
		</td>		    
		<td>    
			<INPUT id = "M1Write"type=button value="M1Write" onclick="javascript:ExecStringCommand('Write,1,0123456789abcdef0123456789abcdef');" style="width:150px; height:30px;"/>    
		</td>    
	</tr>	    
	<tr style="width:100px; height:40px;">    
		<td>    
			中止M1卡片:    
		</td>		    
		<td>    
			<INPUT id = "M1Halt"type=button value="M1Halt" onclick="javascript:ExecStringCommand('Halt');" style="width:150px; height:30px;"/>    
		</td>    
	</tr>		    
	<tr style="width:100px; height:40px;">    
		<td>    
			清除日志:    
		</td>		    
		<td>    
			<INPUT id = "ClearLog"type=button value="ClearLog" onclick="javascript:document.getElementById('log').innerHTML = '';" style="width:150px; height:30px;"/>    
		</td>    
	</tr>		    
	<tr>    
		<td colspan="2">    
			<h3>日志</h3>    
		</td>    
	</tr>    
	<tr>    
		<td colspan="2">    
			<ul id="log" style="overflow: auto; list-style: none; padding:0; background:#ffffff; font-size:small; border-style:solid; border-color:#c0c0c0"></ul>    
		</td>    
	</tr>	    
</table>    
</body>    
</html>


  • 1
  • 2