通過明華讀卡器讀取IC卡的數據,並將數據通過HTTP傳遞


    背景:Vue調用硬件比較麻煩,通過明華讀卡器讀取IC卡的數據,封裝成一個HTTP,其他人只需要調用HTTP就可以讀取IC卡。

Demo效果圖:

 

 

 

一.c# 通過HttpListener創建HTTP服務

在c#中可以利用HttpListener來自定義創建HTTP服務,通過http協議進行服務端與多個客戶端之間的信息傳遞,並且可以做成windows系統服務,而不用寄宿在IIS上。

二.使用明華讀卡器,需要把mwrf32.dll放在在根目錄里(與.exe同一目錄,可去官網下載)

1.讀IC卡數據需要五步

連接讀卡器、加載密碼,此密碼是用來驗證卡片的密碼、尋卡、驗證密碼、讀數據

2.一片對應四區,如果密碼驗證錯誤就會讀不出數據,比如2對應8

 var stcode = rf_authentication(icdev, 0, 2);  //驗證密碼

 var  st = rf_read_hex(icdev, 8, databuffer);  //讀數據

三、源碼

 public partial class MainWindow : Window
    {  //變量
        public static IntPtr icdev = IntPtr.Zero;
        static HttpListener httpobj;
        //static byte sector;  //扇區號
        public static string msg;
        public static string msg2;
        public static string msg3;
        public static string msg4;
        public MainWindow()
        {
            InitializeComponent();
            //提供一個簡單的、可通過編程方式控制的 HTTP 協議偵聽器。此類不能被繼承。
            httpobj = new HttpListener();
            //定義url及端口號,通常設置為配置文件
            httpobj.Prefixes.Add("http://127.0.0.1/ReadIC/");
            //啟動監聽器
            httpobj.Start();
            //異步監聽客戶端請求,當客戶端的網絡請求到來時會自動執行Result委托
            //該委托沒有返回值,有一個IAsyncResult接口的參數,可通過該參數獲取context對象
            httpobj.BeginGetContext(Result, null);
            bt1_Click();        
        }
        private static void Result(IAsyncResult ar)
        {
            //當接收到請求后程序流會走到這里
            //繼續異步監聽
            httpobj.BeginGetContext(Result, null);
            var guid = Guid.NewGuid().ToString();
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine($"接到新的請求:{guid},時間:{DateTime.Now.ToString()}");
            //獲得context對象
            var context = httpobj.EndGetContext(ar);
            var request = context.Request;
            var response = context.Response;
            ////如果是js的ajax請求,還可以設置跨域的ip地址與參數
            //context.Response.AppendHeader("Access-Control-Allow-Origin", "*");//后台跨域請求,通常設置為配置文件
            //context.Response.AppendHeader("Access-Control-Allow-Headers", "ID,PW");//后台跨域參數設置,通常設置為配置文件
            //context.Response.AppendHeader("Access-Control-Allow-Method", "post");//后台跨域請求設置,通常設置為配置文件
            context.Response.ContentType = "text/plain;charset=UTF-8";//告訴客戶端返回的ContentType類型為純文本格式,編碼為UTF-8
            context.Response.AddHeader("Content-type", "text/plain;charset=UTF-8");//添加響應頭信息
            context.Response.ContentEncoding = Encoding.UTF8;
            string returnObj = null;//定義返回客戶端的信息
            if (request.HttpMethod == "POST" && request.InputStream != null)
            {
                //處理客戶端發送的請求並返回處理信息
                returnObj = HandleRequest(request, response);
            }
            else
            {
                bt2_Click();
                bt3_Click();
                bt4_Click();
                returnObj = msg + "\r\n" + msg2 + "\r\n" + msg3 + "\r\n" + msg4;

            }
            var returnByteArr = Encoding.UTF8.GetBytes(returnObj);//設置客戶端返回信息的編碼
            try
            {
                using (var stream = response.OutputStream)
                {
                    //把處理信息返回到客戶端
                    stream.Write(returnByteArr, 0, returnByteArr.Length);
                }
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine($"網絡蹦了:{ex.ToString()}");
            }
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine($"請求處理完成:{guid},時間:{ DateTime.Now.ToString()}\r\n");
        }
        private static string HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
        {
            string data = null;
            try
            {
                var byteList = new List<byte>();
                var byteArr = new byte[2048];
                int readLen = 0;
                int len = 0;
                //接收客戶端傳過來的數據並轉成字符串類型
                do
                {
                    readLen = request.InputStream.Read(byteArr, 0, byteArr.Length);
                    len += readLen;
                    byteList.AddRange(byteArr);
                } while (readLen != 0);
                data = Encoding.UTF8.GetString(byteList.ToArray(), 0, len);
                //獲取得到數據data可以進行其他操作
            }
            catch (Exception ex)
            {
                response.StatusDescription = "404";
                response.StatusCode = 404;
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine($"在接收數據時發生錯誤:{ex.ToString()}");
                return $"在接收數據時發生錯誤:{ex.ToString()}";//把服務端錯誤信息直接返回可能會導致信息不安全,此處僅供參考
            }
            response.StatusDescription = "200";//獲取或設置返回給客戶端的 HTTP 狀態代碼的文本說明。
            response.StatusCode = 200;// 獲取或設置返回給客戶端的 HTTP 狀態代碼。
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine($"接收數據完成:{data.Trim()},時間:{DateTime.Now.ToString()}");
            return $"接收數據完成";
        }

        [DllImport("mwrf32.dll", EntryPoint = "rf_init", SetLastError = true,
                     CharSet = CharSet.Auto, ExactSpelling = false,
                     CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr rf_init(Int16 port, int baud);
        [DllImport("mwrf32.dll", EntryPoint = "usb_init", SetLastError = true,
            CharSet = CharSet.Auto, ExactSpelling = false,
            CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr usb_init();
        [DllImport("mwrf32.dll", EntryPoint = "rf_exit", SetLastError = true,
               CharSet = CharSet.Auto, ExactSpelling = false,
               CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_exit(IntPtr icdev);

        [DllImport("mwrf32.dll", EntryPoint = "rf_beep", SetLastError = true,
               CharSet = CharSet.Auto, ExactSpelling = false,
               CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_beep(IntPtr icdev, int msec);

        [DllImport("mwrf32.dll", EntryPoint = "rf_get_status", SetLastError = true,
              CharSet = CharSet.Auto, ExactSpelling = false,
              CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_get_status(IntPtr icdev, byte[] state);

        [DllImport("mwrf32.dll", EntryPoint = "rf_load_key", SetLastError = true,
             CharSet = CharSet.Auto, ExactSpelling = false,
             CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_load_key(IntPtr icdev, byte mode, byte secnr, byte[] keybuff);

        [DllImport("mwrf32.dll", EntryPoint = "rf_load_key_hex", SetLastError = true,
             CharSet = CharSet.Auto, ExactSpelling = false,
             CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_load_key_hex(IntPtr icdev, byte mode, byte secnr, byte[] keybuff);


        [DllImport("mwrf32.dll", EntryPoint = "a_hex", SetLastError = true,
             CharSet = CharSet.Auto, ExactSpelling = false,
             CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 a_hex(byte[] asc, byte[] hex, Int16 len);

        [DllImport("mwrf32.dll", EntryPoint = "hex_a", SetLastError = true,
             CharSet = CharSet.Auto, ExactSpelling = false,
             CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 hex_a(byte[] hex, byte[] asc, Int16 len);

        [DllImport("mwrf32.dll", EntryPoint = "rf_reset", SetLastError = true,
             CharSet = CharSet.Auto, ExactSpelling = false,
             CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_reset(IntPtr icdev, Int16 msec);

        [DllImport("mwrf32.dll", EntryPoint = "rf_request", SetLastError = true,
             CharSet = CharSet.Auto, ExactSpelling = false,
             CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_request(IntPtr icdev, byte mode, out UInt16 tagtype);


        [DllImport("mwrf32.dll", EntryPoint = "rf_anticoll", SetLastError = true,
             CharSet = CharSet.Auto, ExactSpelling = false,
             CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_anticoll(IntPtr icdev, byte bcnt, out UInt32 snr);

        [DllImport("mwrf32.dll", EntryPoint = "rf_select", SetLastError = true,
             CharSet = CharSet.Auto, ExactSpelling = false,
             CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_select(IntPtr icdev, UInt32 snr, out byte size);

        [DllImport("mwrf32.dll", EntryPoint = "rf_card", SetLastError = true,
            CharSet = CharSet.Auto, ExactSpelling = false,
            CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_card(IntPtr icdev, byte mode, byte[] snr); //這里將第三個參數設置為byte數組,以便直接返回16進制卡號
        //public static extern Int16 rf_card(IntPtr icdev, int mode, out UInt32 snr);

        [DllImport("mwrf32.dll", EntryPoint = "rf_authentication", SetLastError = true,
             CharSet = CharSet.Auto, ExactSpelling = false,
             CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_authentication(IntPtr icdev, byte mode, byte secnr);

        [DllImport("mwrf32.dll", EntryPoint = "rf_authentication_2", SetLastError = true,
             CharSet = CharSet.Auto, ExactSpelling = false,
             CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_authentication_2(IntPtr icdev, byte mode, byte keynr, byte blocknr);

        [DllImport("mwrf32.dll", EntryPoint = "rf_read", SetLastError = true,
             CharSet = CharSet.Auto, ExactSpelling = false,
             CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_read(IntPtr icdev, byte blocknr, byte[] databuff);

        [DllImport("mwrf32.dll", EntryPoint = "rf_read_hex", SetLastError = true,
          CharSet = CharSet.Auto, ExactSpelling = false,
          CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_read_hex(IntPtr icdev, byte blocknr, byte[] databuff);

        [DllImport("mwrf32.dll", EntryPoint = "rf_write_hex", SetLastError = true,
             CharSet = CharSet.Auto, ExactSpelling = false,
             CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_write_hex(IntPtr icdev, int blocknr, byte[] databuff);

        [DllImport("mwrf32.dll", EntryPoint = "rf_write", SetLastError = true,
             CharSet = CharSet.Auto, ExactSpelling = false,
             CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_write(IntPtr icdev, byte blocknr, byte[] databuff);

        [DllImport("mwrf32.dll", EntryPoint = "rf_halt", SetLastError = true,
             CharSet = CharSet.Auto, ExactSpelling = false,
             CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_halt(IntPtr icdev);

        [DllImport("mwrf32.dll", EntryPoint = "rf_changeb3", SetLastError = true,
            CharSet = CharSet.Auto, ExactSpelling = false,
            CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_changeb3(IntPtr icdev, byte sector, byte[] keya, byte B0, byte B1,
              byte B2, byte B3, byte Bk, byte[] keyb);

        [DllImport("mwrf32.dll", EntryPoint = "rf_pro_rst", SetLastError = true,
            CharSet = CharSet.Auto, ExactSpelling = false,
            CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_pro_rst(IntPtr icdev, byte[] _Data);

        [DllImport("mwrf32.dll", EntryPoint = "rf_pro_trn", SetLastError = true,
            CharSet = CharSet.Auto, ExactSpelling = false,
            CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_pro_trn(IntPtr icdev, byte[] problock, byte[] recv);

        [DllImport("mwrf32.dll", EntryPoint = "rf_ctl_mode", SetLastError = true,
            CharSet = CharSet.Auto, ExactSpelling = false,
            CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_ctl_mode(IntPtr icdev, byte mode);    //受控方式

        [DllImport("mwrf32.dll")]
        public static extern Int16 rf_setbright(IntPtr icdev, byte bright);

        [DllImport("mwrf32.dll")]
        public static extern Int16 rf_disp_mode(IntPtr icdev, byte mode);

        [DllImport("mwrf32.dll")]
        public static extern Int16 rf_settime(IntPtr icdev, byte[] time);

        [DllImport("mwrf32.dll", EntryPoint = "rf_ctl_mode", SetLastError = true,
            CharSet = CharSet.Ansi, ExactSpelling = false,
            CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_settimehex(IntPtr icdev, string time);


        [DllImport("mwrf32.dll", EntryPoint = "rf_CtlBackLight", SetLastError = true,
            CharSet = CharSet.Auto, ExactSpelling = false,
            CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_CtlBackLight(IntPtr icdev, byte cOpenFlag); //控制背光

        [DllImport("mwrf32.dll", EntryPoint = "rf_LcdClrScrn", SetLastError = true,
            CharSet = CharSet.Auto, ExactSpelling = false,
            CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_LcdClrScrn(IntPtr icdev, byte cLine);   //清LCD屏

        [DllImport("mwrf32.dll", EntryPoint = "rf_DispMainMenu", SetLastError = true,
            CharSet = CharSet.Auto, ExactSpelling = false,
            CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_DispMainMenu(IntPtr icdev);     //顯示歡迎光臨

        [DllImport("mwrf32.dll", EntryPoint = "rf_DispLcd", SetLastError = true,
            CharSet = CharSet.Auto, ExactSpelling = false,
            CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_DispLcd(IntPtr icdev, byte line, byte type);   //顯示系統內置操作

        [DllImport("mwrf32.dll", EntryPoint = "rf_DispInfo", SetLastError = true,
            CharSet = CharSet.Auto, ExactSpelling = false,
            CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_DispInfo(IntPtr icdev, byte line, byte offset, byte[] data);  //顯示信息,操作前需清屏

        [DllImport("mwrf32.dll", EntryPoint = "rf_disp8", SetLastError = true,
            CharSet = CharSet.Auto, ExactSpelling = false,
            CallingConvention = CallingConvention.StdCall)]
        public static extern Int16 rf_disp8(IntPtr icdev, Int16 disp_len, byte[] disp_str);  //在讀寫器數碼管上顯示數字

        public void bt1_Click()
        {
            icdev = usb_init();  //連接設備
            if (icdev.ToInt32() > 0)
            {

                this.txt2.Text = "讀卡器連接成功!";
                msg = "已連接到讀卡器.............";
                byte[] status = new byte[30];
                var st3 = rf_get_status(icdev, status);  //讀取硬件版本號
                //lbHardVer.Text=System.Text.Encoding.ASCII.GetString(status);
                Console.WriteLine(System.Text.Encoding.Default.GetString(status));
                rf_beep(icdev, 25);
            }
            else
            {
                this.txt2.Text = "未識別到到讀卡器,請檢查設備連接后重試!!!!!";
                msg = "未識別到到讀卡器,請檢查設備連接后重試!!!!";
            }
        }

        public static void bt2_Click()
        {
            byte[] key = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
            byte mode = 0;
            //加載密碼,此密碼是用來驗證卡片的密碼
            for (byte sector = 0; sector < 16; sector++)
            {
                var st1 = rf_load_key(icdev, mode, sector, key);
                if (st1 != 0)
                {
                    string s1 = Convert.ToString(sector);
                   // txt3.Text = s1 + " sector rf_load_key error!";
                  
                }
            }

            byte[] snr = new byte[5];  //卡片序列號
            var st = rf_card(icdev, 0, snr);    //尋卡
            if (st != 0)
            {
              //  txt3.Text = "未識別到IC卡!!!";
             
                msg2 = "未識別到IC卡!!!";
            }
            else
            {
                byte[] snr1 = new byte[8];
               // txt3.Text = "識別到IC卡!!!!!" ;
               
                hex_a(snr, snr1, 4); //將卡號轉換為16進制字符串
             
                msg2 = "識別到IC卡," + "IC卡號:" + System.Text.Encoding.Default.GetString(snr1);
            }
        }

        public static void bt3_Click()
        {
            var stcode = rf_authentication(icdev, 0, 2);  //驗證密碼
            if (stcode != 0)
            {
               // txt4.Text = "IC卡密碼錯誤!!!!!";
              
                msg3 = "IC卡密碼錯誤!!!";
            }
            else
            {
               // txt4.Text = "IC卡密碼正確!!!!!";
              
                msg3 = "IC卡密碼正確!!!";
            }

        }

        public static void bt4_Click()
        {
            byte[] databuffer = new byte[32];
            byte block = 8;
          var  st = rf_read_hex(icdev, block, databuffer);  //讀數據,此函數讀出來的是16進制字符串,也就是把每個字節數據的16進制A​S​C​Ⅱ碼以字符串形式輸出
            if (st != 0)
            {
               // txt5.Text = "讀取IC卡數據失敗!" + st.ToString();
              
                msg4 = "讀取IC卡數據失敗!   " + st.ToString();
            }
            else
            {
               // txt5.Text = "讀取IC卡數據成功!" + System.Text.Encoding.Default.GetString(databuffer);             
                msg4 = "讀取IC卡數據成功!" + System.Text.Encoding.Default.GetString(databuffer);
            } 
        }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            bt2_Click();
            bt3_Click();
            bt4_Click();
        }

       
    }  

 

參考:https://www.cnblogs.com/yijiayi/p/9867502.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM