通过明华读卡器读取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);  //读数据

三、源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
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

 

posted @   MrKing&  阅读(3060)  评论(9编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示