精华内容
下载资源
问答
  • 多功能读写卡设备如何使用
    万次阅读
    2019-03-26 18:10:27

        因为公司需求最近研究了大量的NFC读写M1卡的资料,自己撸了一个相对完整DEMO,让大家一起学习学习。由于之前一直是使用复旦方案的读卡器进行读写卡的,不了解基本原理的请移步:

    1. M1卡存取控制字节规则详解

    2. android 非接触式M1卡改密码

        现在我们使用手机自带的NFC标准来进行读写M1卡,毕竟现在手机都这么先进了还插着读卡器来进行读写M1卡实在是过不去,过于Low逼了。至于什么是NFC标准,基于什么原理请各位自行百度吧,我懒得凑字数了,直接开始吧!

        首先我们先封装一个关于NFC的工具类,其中包括初始化NFC、检查NFC是否打开、初始化NFC设置、读取NFCID(UID)等等方法,上代码:

    public class NfcUtils {
        //nfc
        public static NfcAdapter mNfcAdapter;
        public static IntentFilter[] mIntentFilter = null;
        public static PendingIntent mPendingIntent = null;
        public static String[][] mTechList = null;
    
        /**
         * 构造函数,用于初始化nfc
         */
        public NfcUtils(Activity activity) {
            mNfcAdapter = NfcCheck(activity);
            NfcInit(activity);
        }
    
        /**
         * 检查NFC是否打开
         */
        public static NfcAdapter NfcCheck(Activity activity) {
            NfcAdapter mNfcAdapter = NfcAdapter.getDefaultAdapter(activity);
            if (mNfcAdapter == null) {
                return null;
            } else {
                if (!mNfcAdapter.isEnabled()) {
                    Intent setNfc = new Intent(Settings.ACTION_NFC_SETTINGS);
                    activity.startActivity(setNfc);
                }
            }
            return mNfcAdapter;
        }
    
        /**
         * 初始化nfc设置
         */
        public static void NfcInit(Activity activity) {
            mPendingIntent = PendingIntent.getActivity(activity, 0, new Intent(activity, activity.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
            IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
            IntentFilter filter2 = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
            try {
                filter.addDataType("*/*");
            } catch (IntentFilter.MalformedMimeTypeException e) {
                e.printStackTrace();
            }
            mIntentFilter = new IntentFilter[]{filter, filter2};
            mTechList = null;
        }
    
        /**
         * 读取NFC的数据
         */
        public static String readNFCFromTag(Intent intent) throws UnsupportedEncodingException {
            Parcelable[] rawArray = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
            if (rawArray != null) {
                NdefMessage mNdefMsg = (NdefMessage) rawArray[0];
                NdefRecord mNdefRecord = mNdefMsg.getRecords()[0];
                if (mNdefRecord != null) {
                    String readResult = new String(mNdefRecord.getPayload(), "UTF-8");
                    return readResult;
                }
            }
            return "数据为空";
        }
    
    
        /**
         * 往nfc写入数据
         */
        public static void writeNFCToTag(String data, Intent intent) throws IOException, FormatException {
            Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            Ndef ndef = Ndef.get(tag);
            ndef.connect();
            NdefRecord ndefRecord = NdefRecord.createTextRecord(null, data);
            NdefRecord[] records = {ndefRecord};
            NdefMessage ndefMessage = new NdefMessage(records);
            ndef.writeNdefMessage(ndefMessage);
        }
    
        /**
         * 读取nfcID
         */
        public static String readNFCId(Intent intent) throws UnsupportedEncodingException {
            Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            String id = ByteArrayToHexString(tag.getId());
            return id;
        }
    
        /**
         * 将字节数组转换为字符串
         */
        private static String ByteArrayToHexString(byte[] inarray) {
            int i, j, in;
            String[] hex = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};
            String out = "";
    
            for (j = 0; j < inarray.length; ++j) {
                in = (int) inarray[j] & 0xff;
                i = (in >> 4) & 0x0f;
                out += hex[i];
                i = in & 0x0f;
                out += hex[i];
            }
            return out;
        }
    }
    

            上面代码有不懂的可以看一下官方文档里面有详细的介绍NFCAPI,写完工具类后我们可以通过在任意你想实现NFC功能的Activity类里面重写onNewIntent这个方法。因为刷卡后会实例化一个新的Intent ,通过这个方法我们可以收集到该实例的Intent的Action是不是一个NFCAction。如果是,我们可以通过getParcelableExtra这个方法获取Intent对应的NFC的Tag数据。接着我们通过MifareClassic类里的get方法创建一个MifareClassic的对象,基于MifareClassic协议进行无握手式的连接M1卡。这个是射频技术,具体原理百度。连接后我们就可以对M1卡基于MifareClassic协议进行读写,代码如下:

         String action = intent.getAction();
           if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)){
               Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
               MifareClassic mifareClassic = MifareClassic.get(tag);
               try {
                   mifareClassic.connect();
                   //获取扇区数量
                   int count = mifareClassic.getSectorCount();
                   Log.e("onNewIntent:","扇区数量 ===" + count);
                   //用于判断时候有内容读取出来
                   for (int i = 0;i < count;i++){
                       boolean isOpen = mifareClassic.authenticateSectorWithKeyA(i,MifareClassic.KEY_DEFAULT);
                       if (isOpen){
                           //获取扇区里面块的数量
                           int bCount = mifareClassic.getBlockCountInSector(i);
                           Log.e("onNewIntent:","扇区里面块的数量 ===" + bCount);
                           //获取扇区第一个块对应芯片存储器的位置
                           //存储器的位置为第一扇区为0后面叠加4直到60为止
                           int bIndex = mifareClassic.sectorToBlock(i);
                           for (int j = 0; j < bCount; j++){
                               Log.e("onNewIntent:","存储器的位置 ===" + bIndex + "当前块 === "+ (bIndex+j));
                               byte[] data = mifareClassic.readBlock(bIndex+j);//进行了读卡
                               msgBuffer.append("块"+(bIndex+j)+"数据:").append(StringTool.byteHexToSting(data)).append("\r\n");
                               handler.sendEmptyMessage(0);
                               Log.e("数据","第"+(bIndex+j)+"块" + StringTool.byteHexToSting(data));
    
                           //修改KeyA和KeyB
                               if ((bIndex+j)==(4*i+3)){
                           //将所有扇区的最后一个Block修改为111111111111ff078069111111111111
                                   mifareClassic.writeBlock(bIndex+j,new byte[]{(byte) 0x11, (byte) 0x11, (byte) 0x11, (byte) 0x11, (byte) 0x11, (byte) 0x11, (byte) 0xff, 0x07, (byte) 0x80, (byte) 0x69,(byte) 0x11, (byte) 0x11, (byte) 0x11, (byte) 0x11, (byte) 0x11, (byte) 0x11});
                                   Log.e("onNewIntent:",(bIndex+j)+"块加密成功");
    
                               }
                                
                           }
                       }else {
                           msgBuffer.append("第"+(i+1)+"扇区"+"验证新卡密码失败\r\n");
                           handler.sendEmptyMessage(0);
                           Log.e("失败 ","验证密码");
                      }

           通过上面的操作基本是可以进行刷卡读写操作了,但是这还没有结束,我们还需要在这个Activity的生命周期对NFC进行开启和关闭前台调度系统。除此之外我们还要在这个Activity创建之时先检查我们的设备是否支持NFC功能,做到尽可能的完善,代码如下:

     @Override
        protected void onResume() {
            super.onResume();
            //开启前台调度系统
            if (mAdapter != null) {
                mAdapter.enableForegroundDispatch(this, mPendingIntent, null, null);
            }
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            //关闭前台调度系统
            mAdapter.disableForegroundDispatch(this);
        }
    
     @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            msgBuffer = new StringBuffer();
            mAdapter = NfcAdapter.getDefaultAdapter(this);
            mPendingIntent = PendingIntent.getActivity(this, 0,
                    new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
            IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
            try {
                ndef.addDataType("*/*");
    
            } catch (IntentFilter.MalformedMimeTypeException e) {
                throw new RuntimeException("fail", e);
            }
            mFilters = new IntentFilter[]{ndef,};
            mTechLists = new String[][]{{IsoDep.class.getName()}, {NfcA.class.getName()},};
            Log.d(" mTechLists", NfcF.class.getName() + mTechLists.length);
    
            if (mAdapter == null) {
                Toast.makeText(this, "设备不支持NFC!", Toast.LENGTH_LONG).show();
                msgBuffer.append("\r\n").append("设备不支持NFC!");
                handler.sendEmptyMessage(0);
                return;
            }else {
                msgBuffer.append("\r\n").append("设备支持NFC!");
                handler.sendEmptyMessage(0);
            }
            if (!mAdapter.isEnabled()) {
                Toast.makeText(this, "请在系统设置中先启用NFC功能!", Toast.LENGTH_LONG).show();
                return;
            }
    
    
        
    
        }

    这样我们的NFC读写卡功能就能实现了,如果有什么地方错误的话欢迎大家指正,互相探讨,这个领域好像很少人做。希望更多人一起来探讨。

    原创:https://blog.csdn.net/weixin_40600325/article/details/88824910

    更多相关内容
  • 摘要:介绍了指纹识别技术和非接触IC技术,给出了以C8051单片机为核心的具有指纹识别功能的IC卡读写器的设计方法,具体阐述了读写器的电路设计和软件开发。 关键词:指纹识别 IC 读写器 单片机随着IC技术的...
  • 华大多功能四合一HD-100多功能智能卡读写器配置使用教程一、简介二、配置使用三、代码分享 一、简介 华大HD-100多功能智能卡读写器作为IC系统集成必备的前端处理设备,极大地提高了系统的安全性和应用的方便性,能...

    华大多功能四合一HD-100多功能智能卡读写器OCX插件配置使用教程

    一、简介

    华大HD-100多功能智能卡读写器作为IC卡系统集成必备的前端处理设备,极大地提高了系统的安全性和应用的方便性,能更加优秀的服务于卫生、社保、二代证查询、工商、电信、邮政、税务、银行、保险、医疗以及各种收费、储值、查询等智能卡管理应用行业。

    1.HD-100有几种不同配置,功能分别如下:
    四合一:身份证、社保卡、磁条卡、就诊卡 (此次教程叫的就是四合一)
    三合一:社保卡、磁条卡、就诊卡

    2.华大HD-100多功能读卡器产品特点:

    • 支持 ISO/IEC 7816-1/2/3 标准 CPU 卡,T=0、T=1、逻辑加密卡及memory卡,社保卡、医保卡等

    • 支持 Mifare 卡和符合 ISO14443 标准的 A 类和 B 类卡,ISO 15693 等卡片, 通讯速率最高支持 424 Kbps

    • 支持身份证卡片

    • 支持 4个 PSAM 卡安全模块、支持高速 PSAM 卡安全交易认证,符合 ISO7816 标准

    • 安装方便,可靠性高,适合联机使用

    • 全速 USB 接口, RS232,以太网等

    • 人机界面:一个指示灯,指示电源和操作状态

    • 支持在线程序升级,提供 Windows/Linux/Unix 等各种平台下的应用程序标 准 DLL 动态库接口

    二、配置使用

    读卡器图片,如下图

    在这里插入图片描述


    注意:安装前先把360等杀毒软件退出,否则可能会影响读卡器的正常使用
    准备:先将读卡机设备连接到电脑usb接口,确定连接成功之后在进行一下操作

    1.以管理员点击运行(华大多合一控件安装.exe)文件,如下图

    在这里插入图片描述

    2. 安装时一直点击下一步即可,安装成功会显示以下页面

    在这里插入图片描述

    3.完成安装之后打开页面时需要使用 360浏览器或者IE浏览器 打开浏览器–>工具–>Internet选项–>自定义级别 (Internet和本地Internet都需要设置),如下图

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    4.选择启用

    在这里插入图片描述


    5.选择 是,之后打开页面之后选择兼容模式

    在这里插入图片描述

    6.选择允许阻止内容

    在这里插入图片描述

    7.选择 是

    在这里插入图片描述

    8.选择 是

    在这里插入图片描述

    9.硬件配置已完成接下来就可以使用啦!


    三、代码分享

    1.华大读卡器会给一套js代码,首先,需要引入到页面中进行调用。

    <script th:src="@{/js/common/hd_card.js}"></script>
    

    hd_card.js的代码内容如下:

    // version:2019011
    // 华大读卡器 head 中加 <OBJECT classid=clsid:A02C6AFF-89E7-41232-9DF3-508DD546543F9E2 width=0 height=0 align="center" id="bsHDdev" HSPACE=0 VSPACE=0></OBJECT>
    /** ***************基础工具*********************** */
    
    /**
     * 华大读卡器。读身份证或社保卡。返回:{type:类型, realname:姓名,gender:性别,nation:民族,brithday:出生日期,address:家庭住址,idCardNum:身份证号, sidCardNum:社保号, photoBase64: 照片base64字符串}
     */
    function tg_readCard4HD(deviceObjectId, slot) {
        var result = tg_readIdCard4HD(deviceObjectId); // 先读身份证
        if (!result.success) { // 身份证读取失败
            result = tg_readSidCard4HD(deviceObjectId, slot); // 读取社保卡
        }
        return result;
    }
    /**
     * 华大读卡器。读身份证 返回:{type:类型, realname:姓名,gender:性别,nation:民族,brithday:出生日期,address:家庭住址,idCardNum:身份证号, photoBase64: 照片base64字符串}<br>
     * 相片显示:document.getElementById("photo").src="https://img-blog.csdnimg.cn/2022010711192871364.png"+photoBase64;
     */
    function tg_readIdCard4HD(deviceObjectId) {
        var result = { // 返回结果
            type : 'idCard' // 身份证
        };
        var deviceObject = document.getElementById(deviceObjectId); // 得到设备控件 deviceObjectId
        var readResult = deviceObject.iReaderIDCard("C:\\zp.jpg"); // 读卡,传入照片路径
        if (readResult == 0) { // 读卡成功
            var cardInfo = deviceObject.pOutInfo;
            var base64Str = deviceObject.base64Data;
            var idCardInfo = cardInfo.split('|').slice(0, 6);
            result.success = true;
            result.realname = idCardInfo[0];
            result.gender = idCardInfo[1];
            result.nation = idCardInfo[2];
            result.brithday = idCardInfo[3];
            result.address = idCardInfo[4];
            result.idCardNum = idCardInfo[5];
            result.photoBase64 = base64Str;
        } else { // 读卡失败
            console.log(deviceObject.pMsgErr);
        }
        return result;
    }
    
    /**
     * 华大读卡器。读社保卡 返回:{type:类型, sidCardNum:社保号,idCardNum:身份证号,realname:姓名,gender:性别,nation:民族,brithday:生日}
     */
    function tg_readSidCard4HD(deviceObjectId, slotParm) {
        var result = { // 返回结果
            type : 'sidCard' // 社保卡
        };
        var deviceObject = document.getElementById(deviceObjectId); // 得到设备控件 deviceObjectId
        var slot = 17; // 传入卡座号 17 -20
        if (slotParm) {
            slot = slotParm;
        }
        var readResult = deviceObject.iReadSicard(slot); // 读卡
        if (readResult == 0) { // 读卡成功
            var cardInfo = deviceObject.pOutInfo;
            var scardInfo = cardInfo.split('|').slice(0, 6);
            result.success = true;
            result.sidCardNum = scardInfo[0];
            result.idCardNum = scardInfo[1];
            result.realname = scardInfo[2];
            result.gender = scardInfo[3];
            result.nation = scardInfo[4];
            result.brithday = scardInfo[5];
        } else { // 读卡失败
            console.log(deviceObject.pMsgErr);
        }
        return result;
    }
    
    

    2.会有一个object classid 需要引入,下面的是我乱写的classid,每个设备都不一样。

    <object classid="clsid:A02C6AFF-89E7-41232-9DF3-508DD546543F9E2" id="bsHDdev" width="0" height="0" hspace="0" vspace="0" />
    

    3.页面使用代码示例(会自带测试页面也可以使用)

    <div class="layui-card layadmin-header">
        <div class="layui-breadcrumb" lay-filter="breadcrumb">
            <a lay-href="">主页</a> <a><cite>会员业务</cite></a> <a href="#/manage/member/"><cite>挂号</cite></a>
        </div>
        <object classid="clsid:A02C6AFF-89E7-41232-9DF3-508DD546543F9E2" id="bsHDdev" width="0" height="0" hspace="0" vspace="0" />
    </div>
    <!--/*******页面内容*******/-->
    <div class="layui-fluid">
        <div class="layui-card">
            <div class="layui-card-body">
                <form id="tg_member_add_form" lay-filter="tg_member_add_form_filter" class="layui-form layui-form-pane">
                    <!--/*防止重复提交*/-->
                    <!--<input name="tgAvoidRepeatSubmitToken" th:value="" type="text" hidden="true" />-->
                    <div class="layui-form-item">
                        <div class="layui-inline">
                            <div class="layui-input-inline">
                                <img src="" id="photoBase64" />
                            </div>
                        </div>
                    </div>
                    <div class="layui-form-item">
                        <div class="layui-inline">
                            <label class="layui-form-label">姓名<span style="color: red"> *</span></label>
                            <div class="layui-input-inline">
                                <input name="realname" id="realname" disabled placeholder="请输入姓名"  required maxlength="31" autocomplete="off" autofocus="autofocus" class="layui-input" type="text" />
                            </div>
                        </div>
                    </div>
                    <div class="layui-form-item">
                        <div class="layui-inline">
                            <label class="layui-form-label">性别<span style="color: red"> *</span></label>
                            <div class="layui-input-inline">
                                <input id="genderStr" disabled placeholder="请输入性别"  required maxlength="31" autocomplete="off" autofocus="autofocus" class="layui-input" type="text" /> 
                                <input id="gender" name="gender" type="text" hidden="true" />
                            </div>
                        </div>
                    </div>
                    <div class="layui-form-item">
                        <div class="layui-inline">
                            <label class="layui-form-label">民族<span style="color: red"> *</span></label>
                            <div class="layui-input-inline">
                                <input name="nation" id="nation" disabled placeholder="请输入民族"  required maxlength="31" autocomplete="off" autofocus="autofocus" class="layui-input" type="text" />
                            </div>
                        </div>
                    </div>
                    <div class="layui-form-item">
                        <div class="layui-inline">
                            <label class="layui-form-label">出生日期<span style="color: red"> *</span></label>
                            <div class="layui-input-inline">
                                <input name="brithday" id="brithday" disabled placeholder="请输入出生日期"  required maxlength="31" autocomplete="off" autofocus="autofocus" class="layui-input" type="text" />
                            </div>
                        </div>
                    </div>
                    <div class="layui-form-item">
                        <div class="layui-inline">
                            <label class="layui-form-label">身份证号<span style="color: red"> *</span></label>
                            <div class="layui-input-inline">
                                <input name="idCardNum" id="idCardNum" disabled placeholder="请输入身份证号"  required maxlength="31" autocomplete="off" autofocus="autofocus" class="layui-input" type="text" />
                            </div>
                        </div>
                    </div>
                    <div class="layui-form-item">
                        <div class="layui-inline">
                            <label class="layui-form-label">社保号<span style="color: red"> *</span></label>
                            <div class="layui-input-inline">
                                <input name="sidCardNum" id="sidCardNum" disabled placeholder="请输入社保号"  required maxlength="31" autocomplete="off" autofocus="autofocus" class="layui-input" type="text" />
                            </div>
                        </div>
                    </div>
                    <div class="layui-form-item">
                        <label class="layui-form-label">地址<span style="color: red"> *</span></label>
                        <div class="layui-input-block">
                            <input name="address" id="address" disabled placeholder="请输入地址"  required maxlength="31" autocomplete="off" autofocus="autofocus" class="layui-input" type="text" />
                        </div>
                    </div>
                    <div class="layui-form-item">
                        <div class="layui-input-block">
                            <div class="layui-footer">
                                <input type="button" id="tg_readCard_add_submit_but" value="读卡" class="layui-btn layui-btn-lg layui-btn-normal" lay-submit="" lay-filter="tg_readCard_add_submit_but_filter">
                                <button id="tg_member_add_form_submit_but" lay-filter="tg_member_add_form_submit_but_filter" class="layui-btn layui-btn-lg" lay-submit="">挂号</button>
                            </div>
                        </div>
                    </div>
                </form>
            </div>
        </div>
    </div>
    <!--/*******当前页js*******/-->
    <script>
        layui.use([ 'member', 'form', 'layer' ], function() {
            var member = layui.member, form = layui.form, $ = layui.$, layer = layui.layer;
            form.render(null, 'tg_member_add_form_filter'); // 渲染该模板动态表单
            // 监听读卡 
            form.on('submit(tg_readCard_add_submit_but_filter)', function(data) {
                var result = tg_readCard4HD("bsHDdev", 17);
                if (result.success) {
                    // 设置input值
                    $("#realname").attr("value", result.realname); // 姓名
                    $("#genderStr").attr("value", result.gender); // 性别
                    if(result.gender == "男"){
                        $("#gender").attr("value", 1);
                    } else {
                        $("#gender").attr("value", 2);
                    }
                    var year = result.brithday.substr(0, 4);
                    var month = result.brithday.substr(4, 2);
                    var day = result.brithday.substr(6, 2);
                    $("#nation").attr("value", result.nation); // 民族
                    $("#brithday").attr("value", year + "-" + month + "-" + day); // 出生日期
                    $("#address").attr("value", result.address); // 地址
                    $("#idCardNum").attr("value", result.idCardNum); // 身份证号
                    $("#sidCardNum").attr("value", result.sidCardNum); // 社保号
                    if( result.photoBase64 != null ){
                        $("#photoBase64").attr("src", 'data:image/jpeg;base64,' + result.photoBase64); // 照片base6
                    }
                    // 读卡提交到后台的值
                    data.field.realname = result.realname; // 姓名
                    data.field.gender = $("#gender").val(); // 性别
                    data.field.nation = result.nation; // 民族
                    data.field.brithday = year + "-" + month + "-" + day; // 出生日期
                    data.field.address = result.address; // 地址
                    data.field.idCardNum = result.idCardNum; // 身份证号
                    data.field.sidCardNum = result.sidCardNum; // 社保号
                    data.field.photoBase64 = result.photoBase64; // 照片base6
                 tg_submitForm('tg_readCard_add_submit_but', BASE_URL + 'm/cardRecord/add.htm', data.field, function(d) {
                }); 
                return false; // 阻止form跳转
                }
            });
            // 监听提交 
            form.on('submit(tg_member_add_form_submit_but_filter)', function(data) {
                if(data.field.realname != ""){
                    tg_submitForm('tg_member_add_form_submit_but', BASE_URL + 'm/signRecord/add.htm', data.field, function(d) {
                        tg_alert_success_location('/manage/member/show/id=' + data.field.idCardNum); // 成功提醒并跳转
                    });
                }else{
                    layer.msg("请读取卡片");
                }
                return false; // 阻止form跳转
            }); 
        });
    </script>
    

    以上就是华大多功能四合一HD-100多功能智能卡读写器配置的使用教程,希望可以帮助到你,如有疑问欢迎私信探讨交流。

    展开全文
  • 精伦多功能读写器OCX插件配置使用教程一、简介二、配置使用三、接口文档说明四、代码示例 一、简介 精伦多功能射频读写器iDR210是最新推出销售的一款多功能、免装驱动程序的射频读写器,可根据需求配置不同部件...

    精伦多功能读写器OCX插件配置使用教程

    一、简介

    精伦多功能射频卡读写器iDR210是最新推出销售的一款多功能、免装驱动程序的射频卡读写器,可根据需求配置不同部件实现不同射频卡的读取和写入功能。当配置了专用身份证安全控制模块(SAM)时,可作为第二代居民身份证阅读器使用。

    产品内置部授权的专用身份证安全控制模块(SAM),采用国际上先进的TypeB非接触IC卡阅读技术,完成对身份证有效性验证和信息的实时读取,并通过通讯口将身份证信息上传到计算机进行解码、显示、存储和查询等处理。同时可兼容读写其他行业定制的基于Type A、Type B规范的行业非接触卡(包括但不限于公交卡、员工卡等),也可单独作为TYPE A卡的射频卡读写器使用。

    可选配两个内置PSAM卡座,实现自定义的卡片认证和管理方式。

    ■ 身份证信息的读取、显示和保存

    与随机阅读软件配合,可自动找卡、实时读取和显示第二代身份证的文字和照片信息,具有黑名单检索和实时报警功能。具备保存、查找、删除、导出、打印等多种功能,可灵活设置信息滞留时间、保存方式、相同记录保存时间间隔等。

    ■ 操作简单

    采用HID USB接口,无需安装驱动、无需外接电源,可直接使用。客户也可以根据需要定制使用RS232接口。
      随机阅读软件自动设置通讯口和通讯参数,自动找卡和读卡。

    ■ 行业应用扩展功能

    可根据不同行业应用需求提供WindowsXP、WindowsCE、Linux和UNIX等不同操作系统下的二次开发支持。可兼容读取其他行业定制的基于Type A、Type B规范的行业非接触卡(包括但不限于公交卡、员工卡等)。

    二、配置使用

    读卡器图片,如下图

    在这里插入图片描述


    注意:安装前先把360等杀毒软件退出,否则可能会影响读卡器的正常使用 准备:先将读卡机设备连接到电脑usb接口,确定连接成功之后在进行一下操作
    以管理员身份运行SetupOCXv4.1.0.5.exe,如下图

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    9.硬件配置已完成接下来就可以使用啦!


    三、接口文档说明

    1.概述 精伦电子股份有限公司开发的二代身份证读卡系列机具适用于相关行业的联机型应用。产品提供了完善的二次软件开发接口(API)。本手册针对提供的ActiveX控件,对开发接口的文件组成、方法定义格式、调用方法及返回值等进行了详细的说明。

    2.接口文件说明 接口文件包括: IdrControl.ocx Dewlt.dll Savephoto.dll Wltrs.dll
    适用开发语言: 网络脚本开发
    第一次使用时,需要以管理员身份运行SetupOCX.exe对控件进行安装注册。

    更新说明:
    V4.1.0.1增加了Routon_ReadForeignBaseInfos、Routon_DecideIDCardType、DecideReadCardType、GetenName、GetcnName、GetNation方法,修改了ReadCard方法,可读取外国人永久居留证。
    V4.0.1.0增加对编码设备支持,可设置日志文件。
    V4.0.0.6增加RepeatRead 方法,可设置后进行连续读身份证。
    V4.0.0.0增加对210-P的支持。
    V3.4.1.4解决和13002相关在20130726的读卡体管理号问题。
    V3.4.1.3解决一个潜在导致内存泄漏的问题。
    V3.4.1.2增加GetCardPhotobuf方法,用于获取身份证正反面图片JPG格式Base64编码信息。
    V3.4.1.0增加ExportPhoto方法,可在读卡结束后生成指定照片和卡图片文件名。

    3.接口方法说明

    3.1.身份证方法
    3.1.1.读身份证方法
    原 型:short ReadCard(long iPort,BSTR PhotoPath)
    说 明:本方法将打开端口、找卡、读卡等功能进行了集成,可用于打开串口或USB口,并判断卡片类型以读取二代证卡内信息和外国人居留证卡内信息。
    参 数:
    1、iPort: 设置串口、USB或iDR210免驱动 USB-HID。
    普通串口 1 – 16(十进制) 例如:
    1:串口1(COM1)
    2:串口2(COM2)
    USB
    USB-HID
    (iDR210) 1001 例如:
    1001:USB
    2、PhotoPath:生成图片文件的绝对路径,包括生成的照片文件photo.bmp,photo.jpg和指定文件名的照片文件,和身份证正反面图片card.jpg。该参数为"“时,默认将照片文件保存到Windows系统临时文件目录(GetTempPath())。也可自行设置保存的路径,比如: “d:\photos\photo.bmp”,注意文件参数必须设置正确,才能正确地将相片文件放在指定位置(相片文件夹若不存在,将会自动生成新文件夹)。
    返 回 值:
    值 说明
    1 正确
    -1 端口初始化失败
    -2 卡认证失败(请重新将卡放到读卡器)
    -3 读取数据失败
    -4 生成照片文件失败(请检查设定路径和磁盘空间)
    注:如果读卡机具连接的端口是确定的,可以直接使用相应端口号调用本方法。否则,可以采用循环查找的方式调用本方法。
    3.1.2.端口初始化方法 原 型:short InitComm(long iPort) 说 明:本方法用于打开串口或USB并检测读卡设备是否就绪。 参 数:iPort: 设置串口或USB(目前串口和USB都只支持16个,即串口1~16和USB1001-1016)
    普通串口 1 – 16(十进制) 例如: 1:串口1(COM1) 2:串口2(COM2) USB USB-HID (iDR210) 1001 例如: 1001:USB
    返 回 值:
    值 意义
    1 正确
    其它 错误
    注:如果读卡机具连接的端口是确定的,可以直接使用相应端口号调用本方法。否则,可以采用循环查找的方式调用本方法。
    3.1.3.端口关闭接口
    原 型:int CloseComm(void)
    说 明:本方法用于关闭已打开的端口,一般在调用InitComm成功并完成读卡任务后调用。
    参 数:无
    返 回 值:
    值 意义
    1 正确
    其它 错误
    3.1.4.卡认证接口
    原 型:short Authenticate (void)
    说 明:本方法用于发现身份证卡并选择卡。
    参 数:无
    返 回 值:
    值 意义
    1 正确
    0 错误
    注:认证卡时,需要将身份证放置于读卡机具上方并做稍许时间的停留。如果方法返回错误表示没有发现卡或者卡停留时间太短。
    3.1.5.读卡信息接口
    原 型:short ReadBaseMsg();
    说 明:本函数用于读取卡中基本信息,包括文字信息与图像信息。
    返 回 值:
    值 意义
    1 正确
    -1 错误,缺少照片解码DLL库文件
    -2 生成wlt文件错
    -4 读基本信息错
    -5 照片解码错
    注:读卡基本信息时,需要将身份证置于读卡机具上方做稍许时间的停留。
    调用返回正确后,可进行下一步获取身份证个人姓名、性别等信息获取调用,
    照片文件photo.bmp放置在当前系统的临时文件目录(GetTempPath())。
    3.1.6.读卡信息并设定照片文件接口
    原  型:short ReadBaseMsgP(BSTR photopath);
    说  明:本函数用于读取卡中基本信息,包括文字信息与图像信息。
    参  数:BSTR photopath 放置照片信息绝对路径名
    返 回 值:
    值 意义
    1 正确
    -1 缺少照片解码DLL库文件
    -2 生成wlt文件错
    -3 照片文件名错
    -4 读基本信息错
    -5 照片解码错
    -6 缺少生成正反面图片DLL库文件
    -7 生成正反面图片错
    注:和ReadBaseMsg功能相仿(读卡实现中两个函数只需调用一个),参数为相片信息文件绝对路径名,可根据开发人员需要放置相片为指定目录文件,如"d:\photos\photo.bmp”,注意文件参数必须设置正确,才能正确地将相片文件放在指定位置(相片文件夹若不存在,将会自动生成新文件夹)
    3.1.7.获得身份证信息个人姓名
    原 型:BSTR GetName();
    说 明:本方法用于获取身份证个人姓名信息。
    返 回 值:个人姓名信息
    注:必须在读卡方法或读卡信息方法调用并返回正确的情况下方能正确获得身份证个人姓名信息
    3.1.8.获得身份证个人性别信息(汉字)
    原 型:BSTR GetSex();
    说 明:本方法用于获取身份证个人性别信息。
    返 回 值:个人性别信息,“男"或"女”。
    注:必须在读卡方法或读卡信息方法调用并返回正确的情况下方能正确获得身份证个人性别信息
    3.1.9.获得身份证个人性别信息(数字)
    原 型:short GetSexN();
    说 明:本方法用于获取身份证个人性别代码。
    返 回 值:
    值 说明
    1 男
    2 女
    注:必须在读卡方法或读卡信息方法调用并返回正确的情况下方能正确获得身份证个人性别信息
    3.1.10.获得身份证信息个人民族(汉字)
    原 型:BSTR GetFolk();
    说 明:本方法用于获取身份证个人民族信息。
    返 回 值:个人民族信息
    注:必须在读卡方法或读卡信息方法调用并调用并返回正确的情况下方能正确获得身份证个人民族信息
    3.1.11.获得身份证信息个人民族(数字)
    原 型:Short GetFolkN();
    说 明:本方法用于获取身份证个人民族数字代码。
    返 回 值:个人民族信息数字代码
    返回值以代码表示,下列是民族编码顺序,汉族编码为1,蒙古为2,依次递推。
    “汉”,“蒙古”,“回”,“藏”,“维吾尔”,“苗”,“彝”,“壮”,“布依”,“朝鲜”,“满”,“侗”,“瑶”,“白”,“土家”,“哈尼”,“哈萨克”,“傣”,“黎”,“傈僳”,“佤”,“畲”,“高山”,“拉祜”,“水”,“东乡”,“纳西”,“景颇”,“柯尔克孜”,“土”,“达斡尔”,“仫佬”,“羌”,“布朗”,“撒拉”,“毛南”,“仡佬”,“锡伯”,“阿昌”,“普米”,“塔吉克”,“怒”,“乌孜别克”,“俄罗斯”,“鄂温克”,“德昂”,“保安”,“裕固”,“京”,“塔塔尔”,“独龙”,“鄂伦春”,“赫哲”,“门巴”,“珞巴”,“基诺”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“其他”,“芒人”,“摩梭人”,“革家人”,“穿青人”,“入籍”,“其他”
    注:必须在读卡方法或读卡信息方法调用并调用并返回正确的情况下方能正确获得身份证个人民族信息
    3.1.12.获得身份证个人身份证号信息
    原 型:BSTR GetCode();
    说 明:本方法用于获取身份证个人身份证号信息。
    返 回 值:个人身份证号信息
    注:必须在读卡方法或读卡信息方法调用并返回正确的情况下方能正确获得身份证个人身份证号信息
    3.1.13.获得身份证个人出生年信息
    原 型:BSTR GetBirthYear();
    说 明:本方法用于获取身份证个人出生年信息。
    返 回 值:个人出生年信息
    注:必须在读卡方法或读卡信息方法调用并返回正确的情况下方能正确获得身份证个人出生年信息
    3.1.14.获得身份证个人出生月信息
    原 型:BSTR GetBirthMonth();
    说 明:本方法用于获取身份证个人出生月信息。
    返 回 值:个人出生月信息
    注:必须在读卡方法或读卡信息方法调用并返回正确的情况下方能正确获得身份证个人出生月信息
    3.1.15.获得身份证个人获得出生日信息
    原 型:BSTR GetBirthDay();
    说 明:本方法用于获取身份证个人获得出生日信息。
    返 回 值:个人出生日信息
    注:必须在读卡方法或读卡信息方法调用并返回正确的情况下方能正确获得身份证个人获得出生日信息
    3.1.16.获得身份证个人地址信息
    粗体 型:BSTR GetAddress();
    说 明:本方法用于获取身份证个人地址信息。
    返 回 值:个人地址信息
    注:必须在读卡方法或读卡信息方法调用并返回正确的情况下方能正确获得身份证个人地址信息
    3.1.17.获得身份证个人发证机关信息
    原 型:BSTR GetAgency();
    说 明:本方法用于获取身份证个人发证机关信息。
    返 回 值:个人发证机关信息
    注:必须在读卡方法或读卡信息方法调用并返回正确的情况下方能正确获得身份证个人发证机关信息
    3.1.18.获得身份证个人有效日期信息
    原 型:BSTR GetValid();
    说 明:本方法用于获取身份证个人有效日期信息。
    返 回 值:个人有效日期信息
    注:必须在读卡方法或读卡信息方法调用并返回正确的情况下方能正确获得身份证个人有效日期信息
    3.1.19.读追加地址信息
    原 型:short ReadNewAppMsg();
    说 明:读附加地址信息。
    返 回 值:
    值 意义
    0-4 附加地址数目
    -1 错误
    注:读追加地址信息时,需要将身份证置于读卡机具上方做稍许时间的停留。附加地址数目一般有0-4个,获得具体哪个附加地址信息可在调用此方法获得附加地址数目后调用GetNewAddress(short i)获得
    3.1.20.获得身份证个人获得附加地址信息
    原 型:BSTR GetNewAddress(short i);
    说 明:本方法用于获取身份证个人附加地址信息。
    参数: i附加地址序号
    返 回 值:附加地址
    注:必须在读卡基本信息ReadNewAppMsg()方法调用并返回正确的情况下方能正确获得身份证个人附加地址信息
    3.1.21.获得身份证照片Base64编码
    原 型:BSTR GetPhotobuf ();
    说 明:本方法用于获取身份证照片Base64编码信息。
    参数: 无
    返 回 值:身份证照片Base64编码信息
    注:必须在读卡方法调用并返回正确的情况下方能正确获得身份证照片信息
    3.1.22.获得阅读器安全模块号
    原 型:BSTR GetSAMID ();
    说 明:本方法用于获取阅读器安全模块号。
    参数: 无
    返 回 值:阅读器安全模块号
    注:
    3.1.23.获得身份证照片JPG格式Base64编码
    原 型:BSTR GetJPGPhotobuf ();
    说 明:本方法用于获取身份证照片JPG格式Base64编码信息。
    参数: 无
    返 回 值:身份证照片Base64编码信息
    注:必须在读卡方法调用并返回正确的情况下方能正确获得身份证照片信息
    3.1.24.获得身份证正反面图片JPG格式Base64编码
    原 型:BSTR GetCardPhotobuf ();
    说 明:本方法用于获取身份证正反面图片JPG格式Base64编码信息。
    参数: 无
    返 回 值:身份证照片Base64编码信息
    注:必须在读卡方法调用并返回正确的情况下方能正确获得身份证照片信息
    3.1.25.获得身份证卡号
    原 型:BSTR GetIDCardSN();
    说 明:本方法用于获取身份证卡号。
    返 回 值:身份证卡号
    注:必须在读卡方法调用并返回正确的情况下方能正确获得身份证照片信息
    3.1.26.输出指定照片文件和正反面图片
    原 型:Short ExportPhoto(BSTR PhotoFile,BSTR CardFile);
    说 明:本方法用于生成指定的照片和正反面图片文件名。
    返 回 值:
    值 意义
    1 成功
    -3 未调用ReadCard指定照片文件名
    -1 生成照片文件错
    -2 生成正反面图片文件错
    注:必须在ReadCard读卡方法调用并返回正确的情况下方能正确获得身份证照片信息
    3.1.27.设置是否可连续读身份证
    原 型:short RepeatRead (short isRepeat);
    说  明:本函数用于设置在不从阅读器上移开身份证的情况下连续读身份证。
    参  数:short isRepeat,1为连续读,0为不连续读。
    返 回 值:
    值 意义
    1 正确
    其他 错误
    注:默认是不连续读身份证
    3.1.28. 判断卡片类型
    原 型:short Routon_DecideIDCardType();
    说 明:本函数用于判断当前证件类型是身份证,还是外国人居留证
    返 回 值:
    值 意义
    100 中国身份证
    101 外国人居留证
    其他 其他错误
    注:该函数需在调用Authenticate函数后再调用。
    3.1.29. 读外国人永久居留证信息
    原 型:short Routon_ReadForeignBaseInfos(char enName,char Gender,char Code, char Nation, char cnName,char BirthYear,char BirthMonth,char BirthDay,char Valid);
    说 明:本函数用于读取外国人永久居留证基本信息,包括文字信息和图像信息。
    参 数:
    char
    enName, 指向外国人英文姓名信息。需要在调用时分配内存,字节数不小120。
    char
    Gender, 指向外国人的性别信息。需要在调用时分配内存,字节数不小于3;
    char
    Code,指向外国人永久居留证号码信息。需要在调用时分配内存,字节数不小于30;
    char
    Nation,指向外国人国籍或所在地区代码。需要在调用时分配内存,字节数不小于6;
    char
    cnName,指向外国人中文姓名信息。需要在调用时分配内存,字节数不小于31;
    char
    BirthYear,指向出生年份信息。需要在调用时分配内存,字节数不小于5;
    char
    BirthMonth,指向出生月份信息。需要在调用时分配内存,字节数不小于3;
    char
    BirthDay,指向出生日信息。需要在调用时分配内存,字节数不小于3;
    char
    Valid,指向外国人居留证有效日期。需要在调用时分配内存,字节数不小于32。
    返 回 值:
    值 意义
    1 正确
    0 错误
    -4 缺少dewlt.dll、savephoto.dll等DLL
    已废弃,如需使用该功能,请使用3.1.35接口Routon_ReadAllForeignBaseInfos
    注:读卡基本信息时,需要将身份证置于读卡机具上方做稍许时间的停留。
    调用返回正确后,可进行下一步获取身份证个人姓名、性别等信息获取调用,
    照片文件photo.bmp放置在当前系统的临时文件目录(GetTempPath())。
    返回的有效日期是以“XXXX.XX.XX-XXXX.XX.XX”的格式存放的。
    3.1.30. 判断读取的卡片类型
    原 型:short DecideReadCardType()
    说 明:在卡片读取完成之后,返回一个卡片类型的标志。
    返 回 值:
    值 说明
    1 身份证
    2 外国人居留证
    注:调用该函数之前必须调用ReadCard()函数,读取卡片成功之后,在调用该函数以返回卡片类型。
    3.1.31. 获取外国人居留证信息英文名字
    原 型:BSTR GetenName();
    说 明:本方法用于获取外国人永久居留证个人英文姓名信息。
    返 回 值:个人英文姓名信息
    注:必须在读卡方法或读卡信息方法调用并返回正确的情况下方能正确获得身份证个人英文姓名信息
    3.1.32. 获取外国人居留证信息英文名字
    原 型:BSTR GetcnName();
    说 明:本方法用于获取外国人永久居留证个人中文姓名信息。
    返 回 值:个人中文姓名信息
    注:必须在读卡方法或读卡信息方法调用并返回正确的情况下方能正确获得身份证个人中文姓名信息
    3.1.33 获得外国人居留证国籍或所在地区代码
    原 型:Short GetNation();
    说 明:本方法用于获取外国人永久居留证国籍或所在地区代码。
    返 回 值:外国人国籍或所在地区代码。
    3.1.34. 读外国人永久居留证信息带照片路径
    原 型:short Routon_ReadForeignBaseInfosP(char enName,char Gender,char Code, char Nation, char cnName,char BirthYear,char BirthMonth,char BirthDay,char Valid,BSTR photopath);
    说 明:本函数用于读取外国人永久居留证基本信息,包括文字信息和图像信息,并保存到指定路径中。
    参 数:
    char
    enName, 指向外国人英文姓名信息。需要在调用时分配内存,字节数不小120。
    char
    Gender, 指向外国人的性别信息。需要在调用时分配内存,字节数不小于3;
    char
    Code,指向外国人永久居留证号码信息。需要在调用时分配内存,字节数不小于30;
    char
    Nation,指向外国人国籍或所在地区代码。需要在调用时分配内存,字节数不小于6;
    char
    cnName,指向外国人中文姓名信息。需要在调用时分配内存,字节数不小于31;
    char
    BirthYear,指向出生年份信息。需要在调用时分配内存,字节数不小于5;
    char
    BirthMonth,指向出生月份信息。需要在调用时分配内存,字节数不小于3;
    char
    BirthDay,指向出生日信息。需要在调用时分配内存,字节数不小于3;
    char
    Valid,指向外国人居留证有效日期。需要在调用时分配内存,字节数不小于32。
    BSTR photopath 放置照片信息绝对路径名。
    返 回 值:
    值 意义
    1 正确
    0 错误
    -4 缺少dewlt.dll、savephoto.dll等DLL
    已废弃,如需使用该功能,请使用3.1.36接口Routon_ReadAllForeignBaseInfosP
    注:读卡基本信息时,需要将身份证置于读卡机具上方做稍许时间的停留。
    调用返回正确后,可进行下一步获取身份证个人姓名、性别等信息获取调用,
    照片文件photo.bmp放置在当前系统的临时文件目录(GetTempPath())。
    返回的有效日期是以“XXXX.XX.XX-XXXX.XX.XX”的格式存放的。
    3.1.35读外国人永久居留证全部信息
    原 型:short Routon_ReadAllForeignBaseInfos(char EnName,char Gender,char Code, char Nation, char CnName,char BirthYear,char BirthMonth,char BirthDay,char Valid,char CardVersion,char Agency,char CardType, char FutureItem);
    说 明:本函数用于读取外国人永久居留证基本信息,包括文字信息和图像信息。
    参 数:
    char
    EnName, 指向外国人英文姓名信息。需要在调用时分配内存,字节数不小120。
    char
    Gender, 指向外国人的性别信息。需要在调用时分配内存,字节数不小于3;
    char
    Code,指向外国人永久居留证号码信息。需要在调用时分配内存,字节数不小于30;
    char
    Nation,指向外国人国籍或所在地区代码。需要在调用时分配内存,字节数不小于6;
    char
    CnName,指向外国人中文姓名信息。需要在调用时分配内存,字节数不小于31;
    char
    BirthYear,指向出生年份信息。需要在调用时分配内存,字节数不小于5;
    char
    BirthMonth,指向出生月份信息。需要在调用时分配内存,字节数不小于3;
    char
    BirthDay,指向出生日信息。需要在调用时分配内存,字节数不小于3;
    char
    Valid,指向外国人居留证有效日期。需要在调用时分配内存,字节数不小于32。
    char
    CardVersion,指向外国人居留证证件版本号。需要在调用时分配内存,字节数不小于5。
    char
    Agency,指向外国人居留证当次申请受理机关代码。需要在调用时分配内存,字节数不小于9。
    char
    CardType,指向外国人居留证证件类型标识。需要在调用时分配内存,字节数不小于2。
    char
    FutureItem,指向外国人居留证预留项。需要在调用时分配内存,字节数不小于7。
    返 回 值:
    值 意义
    1 正确
    0 错误
    -4 SDT_ReadBaseMsg读卡失败
    注:读卡基本信息时,需要将身份证置于读卡机具上方做稍许时间的停留。
    调用返回正确后,可进行下一步获取身份证个人姓名、性别等信息获取调用,
    照片文件photo.bmp放置在当前系统的临时文件目录(GetTempPath())。
    返回的有效日期是以“XXXX.XX.XX-XXXX.XX.XX”的格式存放的。
    补充说明:1、Agency是机关代码,其对应的机关全称未知。
    2、FutureItem是预留项,未存放实际内容。
    3.1.36. 读外国人永久居留证全部信息带照片路径
    原 型:short Routon_ReadAllForeignBaseInfosP(char EnName,char Gender,char Code, char Nation, char nName,char BirthYear,char BirthMonth,char BirthDay,char Validchar CardVersion,char Agency,char CardType, char FutureItem,LPCTSTR photopath);
    说 明:本函数用于读取外国人永久居留证基本信息,包括文字信息和图像信息,并保存到指定路径中。
    参 数:
    char
    EnName, 指向外国人英文姓名信息。需要在调用时分配内存,字节数不小120。
    char
    Gender, 指向外国人的性别信息。需要在调用时分配内存,字节数不小于3;
    char
    Code,指向外国人永久居留证号码信息。需要在调用时分配内存,字节数不小于30;
    char
    Nation,指向外国人国籍或所在地区代码。需要在调用时分配内存,字节数不小于6;
    char
    CnName,指向外国人中文姓名信息。需要在调用时分配内存,字节数不小于31;
    char
    BirthYear,指向出生年份信息。需要在调用时分配内存,字节数不小于5;
    char
    BirthMonth,指向出生月份信息。需要在调用时分配内存,字节数不小于3;
    char
    BirthDay,指向出生日信息。需要在调用时分配内存,字节数不小于3;
    char
    Valid,指向外国人居留证有效日期。需要在调用时分配内存,字节数不小于32。
    char
    CardVersion,指向外国人居留证证件版本号。需要在调用时分配内存,字节数不小于5。
    char
    Agency,指向外国人居留证当次申请受理机关代码。需要在调用时分配内存,字节数不小于9。
    char
    CardType,指向外国人居留证证件类型标识。需要在调用时分配内存,字节数不小于2。
    char
    FutureItem,指向外国人居留证预留项。需要在调用时分配内存,字节数不小于7。
    LPCTSTR photopath 放置照片信息绝对路径名。
    返 回 值:
    值 意义
    1 正确
    0 错误
    -4 缺少dewlt.dll、savephoto.dll等DLL
    -5 获取接口SaveForeignCardAllJPG地址失败
    -6 接口SaveForeignCardAllJPG调用失败
    注:读卡基本信息时,需要将身份证置于读卡机具上方做稍许时间的停留。
    调用返回正确后,可进行下一步获取身份证个人姓名、性别等信息获取调用,
    照片文件photo.bmp放置在当前系统的临时文件目录(GetTempPath())。
    返回的有效日期是以“XXXX.XX.XX-XXXX.XX.XX”的格式存放的。
    补充说明:1、Agency是机关代码,其对应的机关全称未知。
    2、FutureItem是预留项,未存放实际内容。
    3.2.TypeA 非接触IC卡方法
    3.2.1.读TypeA卡

    原 型:short ReadICCard(long iPort)
    说 明:本方法用于打开串口并读取卡内信息。
    参 数:
    1、iPort: 设置串口(目前串口只支持16个,即串口1~16)
    普通串口 1 – 16(十进制) 例如:
    1:串口1(COM1)
    2:串口2(COM2)
    USB-HID
    (iDR210) 8159(十进制)
    返 回 值:
    值 说明
    1 正确
    -1 端口初始化失败
    -2 读卡失败
    注:如果读卡机具连接的端口是确定的,可以直接使用相应端口号调用本方法。否则,可以采用循环查找的方式调用本方法。
    3.2.2.获得TypeA卡序列号
    原 型:BSTR GetICCardSN();
    说 明:本方法用于获取IC卡序列号。
    返 回 值:IC卡序列号
    注:必须在ReadICCard方法调用并返回正确的情况下方能使用
    3.2.3.读TypeA卡块内容
    原 型:BSTR ReadTypeABlock(short SID, short BID, short KeyType, LPCTSTR Key);
    说 明:本方法用于读取指定扇区的指定块的内容。
    参 数:
    SID为扇区号,0-15(对M1S50卡)。
    BID为块号,0-3。
    KeyType为密钥类型,两种:1 keyA,2 keyB。
    Key为密钥,12个字节的字符串。
    返 回 值:
    值 说明
    32个字节字符串 正确。每两个字节对应块内的一个字节内容。
    0 失败
    注:必须在ReadICCard方法调用并返回正确的情况下方能使用
    3.2.4.写TypeA卡块内容
    原 型:BSTR WriteTypeABlock(short SID, short BID, short KeyType, LPCTSTR Key, LPCTSTR Data);
    说 明:本方法用于写入指定扇区的指定块的内容。
    参 数:
    SID为扇区号,0-15(对M1S50卡)。
    BID为块号,0-3。注意:若写每个扇区的3号块的数据不正确,卡将无法正常读写。
    KeyType为密钥类型,两种:1 keyA,2 keyB。
    Key为密钥,12个字节的字符串。
    Data为写入的内容,32个字节的字符串。
    返 回 值:
    值 说明
    1 正确。
    0 失败
    注:必须在ReadICCard方法调用并返回正确的情况下方能使用
    3.3.CPU卡方法
    注意:在读市民卡信息和发送第一条APDU命令前,必须先找卡。
    3.3.1.找CPU卡
    原 型:int FindICCard (void)
    说 明:本方法用于查找当前卡片类型。在做CPU卡相关操作前(比如读市民卡信息、发APDU命令等),必须先调用本方法找到CPU卡。
    参 数:无
    返 回 值:
    值 意义
    1 M1-S50卡
    2 CPU卡
    3 M1-S70卡
    0 未找到卡
    其他 不明卡错误码
    3.3.2.读顺德市民卡信息
    原 型:int ReadCitizenCard (void)
    说 明:本方法用于读出顺德市民卡信息。在调用本方法前,必须先使用FindICCard找到CPU卡。
    参 数:无
    返 回 值:
    值 意义
    1 成功
    -1 解密失败
    -2 读数据错
    -3 设备类型错
    3.3.3.取顺德市民卡卡号信息
    原 型:BSTR GetCityCardNO (void)
    说 明:本方法用于读出顺德市民卡卡号信息。在调用本方法前,必须先使用ReadCitizenCard方法。
    参 数:无
    返 回 值:顺德市民卡卡号
    3.3.4.取顺德市民卡姓名信息
    原 型:BSTR GetCityCardName (void)
    说 明:本方法用于读出顺德市民卡姓名信息。在调用本方法前,必须先使用ReadCitizenCard方法。
    参 数:无
    返 回 值:顺德市民卡姓名
    3.3.5.取顺德市民卡证件类型信息
    原 型:BSTR GetCityCardIDType (void)
    说 明:本方法用于读出顺德市民卡证件类型信息。在调用本方法前,必须先使用ReadCitizenCard方法。
    参 数:无
    返 回 值:顺德市民卡证件类型
    3.3.6.取顺德市民卡证件号码信息
    原 型:BSTR GetCityCardIDCode(void)
    说 明:本方法用于读出顺德市民卡证件号码信息。在调用本方法前,必须先使用ReadCitizenCard方法。
    参 数:无
    返 回 值:顺德市民卡证件号码
    3.3.7.取顺德市民卡附加信息
    原 型:BSTR GetCityCardAppInfo(void) 说 明:本方法用于读出顺德市民卡附加信息。在调用本方法前,必须先使用ReadCitizenCard方法。 参 数:无 返 回 值:顺德市民卡附加信息
    3.3.8.APDU命令及应答
    原 型:BSTR Routon_APDU (BSTR APDU_CMD) 说 明:本方法用于CPU卡的APDU命令交互。 参 数:BSTR APDU_CMD,APDU命令字符串 返 回 值: 值 意义 字符串 成功 -1 APDU_CMD不正确 -2 读数据错
    4.接口使用流程及示例
    实现请参照例程 test.htm
    提示:
    一 例程只是控件开发的简单示范,具体二次开发功能实现,由开发人员进行设计和开发
    二 调试过程中请注意 找卡过程中包含选卡,目前公安部安全模块只支持一次选卡,因此如果找卡成功后,若想再次进行找卡读卡流程需将机具上卡拿开后再次放置到机具上
    三ActiveX控件在网页上运行以及下载受到安全级别的限制(开发人员请注意)

    四、代码示例

    jl_card.js的代码内容如下:

    /**
     * 精伦电子控件。读身份证 参数 deviceObjectId 控件id 必须 photonPath 头像输出路径 可为空 cardPath 身份证正反面输出路径 可为空<br>
     * 返回:{type:类型, idCardNum:身份证号,realname:姓名,gender:性别文字,genderNum:性别数字,<br>
     * nation:民族,address:地址,photoBase64:照片(Base64编码),cardPhotoBase64:身份证正反面照片(Base64编码), <br>
     * birthYear:生日年,birthMonth:生日月,birthDay:生日日,agency:签发机关,valid:有效日期,samId:安全模块号,idCardSN:身份证卡号 <br>
     * code = 1:正常,code = -1:端口初始化失败,code =-2:请重新将卡片放到读卡器上,code = -3:读取数据失败,code = -4:生成照片文件失败,请检查设定路径和磁盘空间,code = 500:控件未安装}
     */
    function tg_readIdCard4JLDZ(deviceObjectId, photonPath, cardPath) {
        var result = { // 返回结果
            code : 1,
            type : 'idCard' // 身份证
        };
        try {
            var ax = new ActiveXObject("IDRCONTROL.IdrControlCtrl.1");
        } catch (e) {
            console.log("控件未安装");
            result.code = 500;
        }
        var code = deviceObjectId.ReadCard("1001", ""); // 注意:第一个参数为对应的设备端口,USB型为1001,串口型为1至16
        result.code = code;
        if (code == 1) {
            var cardtype = deviceObjectId.DecideReadCardType(); // 判断卡类型 1-身份证 2-外国居留证
            if (cardtype == 1) {
                deviceObjectId.setMute(0); // 设置是否静音读卡 0-不静音 1-静音
                deviceObjectId.RepeatRead(1); // 设置是否重复读卡 0-不重复 1-重复
                result.success = true;
                result.realname = deviceObjectId.GetName(); // 姓名
                result.nation = deviceObjectId.GetFolk(); // 民族
                result.gender = deviceObjectId.GetSex(); // 性别 文字
                result.genderNum = deviceObjectId.GetSexN(); // 性别 数字
                result.birthYear = deviceObjectId.GetBirthYear(); // 出生日期 年
                result.birthMonth = deviceObjectId.GetBirthMonth() // 出生日期 月
                result.birthDay = deviceObjectId.GetBirthDay() // 出生日期 日
                result.idCardNum = deviceObjectId.GetCode(); // 公民身份证号码
                result.idCardSN = deviceObjectId.GetIDCardSN(); // 身份证卡号
                result.address = deviceObjectId.GetAddress(); // 地址
                result.agency = deviceObjectId.GetAgency(); // 签发机关
                result.valid = deviceObjectId.GetValid(); // 有效日期
                result.samId = deviceObjectId.GetSAMID(); // 安全模块号
                result.photoBase64 = deviceObjectId.GetJPGPhotobuf(); // 照片(Base64编码)
                result.cardPhotoBase64 = deviceObjectId.GetCardPhotobuf(); // 身份证正反面照片(Base64编码)
                result.returnMsg = 1;
                if (photonPath == null) {
                    photonPath = "d:\\idcard\\" + "Z" + "+" + deviceObjectId.GetIDCardSN() + deviceObjectId.GetName() + ".jpg"; // 照片输出路径
                    if (cardPath == null) {
                        cardPath = "d:\\idcard\\" + "Z" + "+" + deviceObjectId.GetIDCardSN() + deviceObjectId.GetName() + "card.jpg"; // 正反面输出路径
                    }
                    deviceObjectId.ExportPhoto(photonPath, cardPath); // 输出照片接口
                } else {
                    console.log("当前卡片不是身份证,请将身份证放到读卡器上!");
                }
            }
        } else if (code == -1) {
            result.returnMsg = -1;
            console.log("端口初始化失败!");
        } else if (code == -2) {
            result.returnMsg = -2;
            console.log("请重新将卡片放到读卡器上!");
        } else if (code == -3) {
            result.returnMsg = -3;
            console.log("读取数据失败!");
        } else if (code == -4) {
            result.returnMsg = -4;
            console.log("生成照片文件失败,请检查设定路径和磁盘空间!");
        }
        return result;
    }
    

    以上就是华大多功能四合一HD-100多功能智能卡读写器配置的使用教程,希望可以帮助到你,如有疑问欢迎私信探讨交流。

    展开全文
  • 相对于PB375,其增加了Uart接口,内置5V转3.3V LDO,保留SD卡功能拓展接口,让您的开发更加简单,功能更加强大。应用于嵌入式系统/单片机读写U 盘、闪盘、闪存盘、USB 移动硬盘、USB 读卡器、等。 2.2 模块主要特点...
  • 功能NFC是指具备三种模式的NFC,即点对点模式、读写模式、模拟模式。点对点模式无需配对、在两部 NFC 设备之间建立更安全的交互,实现两个设备近距离内的数据传输。使用条件:●两部设备需要同时支持 NFC 功能。...

    全功能NFC是小米手机最先炒起来的概念,之后各大友商纷纷借用,比如努比亚、华为荣耀等。全功能NFC其实和全面屏都属于一种营销噱头。

    全功能NFC是指具备三种模式的NFC,即点对点模式、读写模式、卡模拟模式。

    点对点模式

    无需配对、在两部 NFC 设备之间建立更安全的交互,实现两个设备近距离内的数据传输。

    使用条件:

    ●两部设备需要同时支持 NFC 功能。

    ●数据传输时,两部设备的距离请保持在 10 厘米以内。

    ●使用时,请保持手机亮屏解锁状态。

    使用场景:

    ●文件传输(如传输图片、应用、联系人等)。

    ●快速建立设备间的连接(如蓝牙配对、分享数据热点等)。

    读写模式

    支持读写 NFC标签。

    使用限制:

    ●被读写的卡片、商品等需要支持 NFC 标签。

    使用场景:

    ●使用充值应用为实体、虚拟交通卡充值,查询交通卡余额。

    ●查看带 NFC 标签的商品信息。

    卡模拟模式

    将手机模拟成一张智能卡片,实现交通刷卡、手机支付、门禁等功能。

    使用条件:

    ●SIM 卡模拟:请先联系您的运营商(如移动、联通、电信)获取支持 NFC 功能的 SIM 卡。

    ●eSE 模拟:需要在 Huawei Pay 中添加有 QuickPass 标识的银行卡,在支持云闪付(有 QuickPass 标识)的 POS 机上支付。

    ●HCE 模拟:即银联云闪付。您需要提前下载银行卡对应的应用程序并按照应用的提示绑定银行卡,具体支持情况请咨询银行卡发行方。使用时打开 NFC 开关,默认付款应用选择对应银行应用,并保持亮屏解锁状态。如需使用云闪付功能,还需要卡片和 POS 机支持 QuickPass功能(有 Quick Pass 标识)。

    使用场景:

    ●SIM 卡模拟:将运营商(如移动、联通、电信)的 SIM 卡模拟为交通卡。

    ●eSE 模拟:将内置安全单元模拟为卡片进行支付(如 HuaweiPay)。

    ●HCE 模拟:通过银行应用软件绑定实体银行卡,将手机模拟成银行卡闪付消费。

    (责任编辑:佚名)

    展开全文
  • 使用STM32在SPI模式下读写SD

    千次阅读 2021-12-22 17:18:57
    使用STM32在SPI模式下读写SD
  • ZYNQ-使用SD卡读写文本数据

    千次阅读 2021-04-28 13:55:28
    本文主要关于SD相关内容,然后使用SD进行TXT文本读写,并用串口打印出读写数据。 开发环境 vivado 18.3&SDK,PYNQ-Z2开发板。 SD简介 SD(Secure Digital Card):安全数字,又叫安全数码。有体积小...
  • SD卡读写

    千次阅读 2021-12-05 15:53:04
    1、SD (Secure Digital Memory Card) 在我们生活中已经非常普遍了,控制器对 SD 进行读写通信操作一般有两种通信接口可选,一种是 SPI 接口,另外一种就是 SDIO 接口。SDIO 全称是安全数字输入/输出接口,...
  • STM32——SDIO进行SD卡读写测试

    千次阅读 2022-03-12 15:08:05
    SD(Secure Digtial Memory Card)在我们生活中已经非常普遍了,控制器对SD进行读写通信操作一般有两种通信接口可选,一种是SPI接口,另一种就是是SDIO接口。SDIO全称是安全数字输入/输出接口,多媒体(MMC)...
  • android 读写sd的权限设置

    千次阅读 2021-05-27 04:11:52
    在Android中,要模拟SD,要首先使用adb的mksdcard命令来建立SD的镜像,如何建立,大家上网查一下吧,应该很容易找到,这里不说这个问题.但是在应用程序执行起来以后,我们可以看到sdcard的执行权限很有问题.懂...
  • SDIO——读写SD

    千次阅读 2021-04-12 19:29:22
    SDIO的设备分类: SD / IO:这不是一种,现在已经不常用了,用到时再查。 SD存储:分局容量不同有三种名字① <= 2GB 的叫SDSC;② >2GB <= 32GB的叫SDHC;>32GB < 2TB 的叫SDXC。 单片机...
  • ACR122U写软件是一款专业的IC卡读写...ACR122U写软件界面展示IC卡读写工具功能1. 操作dump文件 可直接读取导出的dump文件,还可以修改并保存dump文件2. 读 可以读取任意扇区(0扇区~15扇区)3. 写 可以写入...
  • IC卡读写器开发说明

    千次阅读 2018-09-15 15:41:32
    动态库简介 动态库OUR_MIFARE.dll用VC开发,编译成32位Release实体或64位...本动态库是本公司USB接口IC卡读写器的配套文件,必须和读写器一起使用。 OUR_MIFARE.dll支持在软件运行中可以随时更换USB接口。本公司免...
  • STM32F103对SD数的读写

    千次阅读 2021-12-22 16:21:02
    SD存储是一种基于半导体快闪记忆器的新一代记忆设备,由于它体积小、数据传输速度快、可热插拔等优良的特性,被广泛地于便携式装置上使用,例如数码相机、平板电脑和多媒体播放器等。 SD具有高记忆容量、快速...
  • 其实这个想法已经有人做了,使用手机自带的nfc模拟校园,是可以实现门禁进出功能的。经过实际测试,一下方案是可行的: 使用带NFC功能手机模拟 NFC读卡器 + 白卡 带NFC功能手机+手环 or NFC 读卡器+白卡+手环 ...
  • S3读写模块,可以嵌入到大型的设备中,比如POS终端、门禁设备以及自动... 接触式智能IC卡读写设备广泛应用于个人身份安全认证、访问控制、公交电子票务、水电表系统、医疗收费系统、停车场、物流以及供应链管理等领域。
  • 多媒体MMC(MultiMedia Card)是由美国SanDisk公司和德国Simens公司于1997年共同开发推出的一种多功能存储。内置控制电路,可以使用在手机、数码相机、MP3、PDA等多种数字设备上,可反复记录30万次。现在市场上的...
  • 本文主要讲M1扇区读写和芯片卡读写权限初始化1 onCreate( initNFC() )2 onResume( )3 onPause()4 NFC设备刷卡时触发 onNewIntent(Intent)1,标签读写2,扇区读写3 CPU卡读写 重头戏 NFC 读写分几种,本文主要讲M...
  • FM1208CPU卡读写函数说明

    千次阅读 2018-10-20 17:58:40
    动态库简介 动态库OUR_MIFARE.dll用VC开发,编译成32位Release实体或64位Release...本动态库是本公司USB接口FM1208CPU卡读写器的配套文件,必须和读写器一起使用。 OUR_MIFARE.dll支持在软件运行中可以随时更换USB...
  • 您可以使用一张Secure Digital或SD实现此功能。 SD是一种非易失性存储,广泛应用于手机、数码相机、GPS导航设备、手持控制台和平板电脑等便携式设备中。另一种类型的SD是Micro SD。尺寸仅为15毫米x 11毫米...
  • Android针对IC卡读写的NFC开发

    万次阅读 多人点赞 2018-04-26 10:37:19
    这两天研究了NFC功能,网上查了很的资料,不过感觉别人讲的都大同小异,但都缺了那么一点点火候,因为第一次接触有些概念是不清楚的,所以代码看上去很吃力,这个博客呢就是想整体的进行讲解一下,做一点点补充,...
  • 学习使用USB-TTL驱动PN532来读写IC

    万次阅读 热门讨论 2020-06-02 15:46:07
    芯片内集成了13.56MHz下通信用的非接触通信的协议,内部包含有8051的内核,说了这么就不来废话了,对于芯片的诸多功能以及原理说句实话,博主了解的也不,不过并不妨碍我们使用它来读写市面上普通的IC!...
  • 目标:将门禁、考勤、会员、停车、电梯等等各种模拟进手机里,模拟后可用手机代替刷卡,无需root,不用电脑 背景介绍: 1、前言   目前,IC已被广泛应用于身份识别、金融消费、安全认证等领域。...
  • IC卡读写

    千次阅读 2016-11-06 15:50:10
    IC(Integrated Circuit),也被称作智能(Smart Card),具有写入数据和存储数据的功能,IC内存储器的内容可以根据需要有条件地供外部读取,完成信息处理和判定。由于其内部具有集成电路,不但可以存储大量...
  • android OTG (USB读写,U盘读写)最全使用相关总结

    万次阅读 多人点赞 2018-04-29 10:36:49
    androidOTG (USB读写,U盘读写) 最全使用相关总结 简介 第一种读取方法:android推荐使用的通过endpoint的形式进行通信 第二种读取方法:像读你sdcard的形式来读你的U盘设备 注意注意注意 提示 博主:来自...
  • 先说下背景,公司的厂内物流系统,通过自助制,获取一张IC,该关联运输任务信息。然后司机携带这张IC去园区内进行装卸货。装卸货系统通过IC读取器,读取卡号,然后调用物流系统的接口,获取运输任务信息,...
  • Profinet协议以太网工业读写器CK-FR08-E02是一款13.56MHZ高频一体式读写设备,可节省时间、空间,与PROFINET网络无缝连接,采用可靠的锌压铸外壳,适合直接安装在金属上,防护等级为IP67,适用于恶劣的工作环境,可...
  • 目前大多数手机厂商使用的NFC芯片都是NXP,另一部分则是BRCM(博通)方案,均执行同一标准,这是手机读写M1的技术基础。 UID: 普通复制,可以反复擦写所有扇区,门禁有防火墙则失效。 CUID: 升级复制,...
  • SD读写和加解密

    千次阅读 2019-06-14 17:42:07
    SD全称为 Secrue Digital Memory Card,具有轻巧、可加密、传输速度高、适用于手持设备使用等优点。 二、总线接口 SD需要高速读写,同时也要使手持等嵌入式设备能方便使用,特设有两个访问接口中:SD模式接口...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 60,512
精华内容 24,204
热门标签
关键字:

多功能读写卡设备如何使用