2015年1月4日 星期日

[C#] C# 語取健保卡基本資料─晶片讀卡機

在網路上看到的原始碼,紀錄下來, 資料來源 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace ReadNHICard
{
    class Program
    {
        public struct SCARD_IO_REQUEST
        {
            public int dwProtocol;
            public int cbPciLength;
        }

        //引用 PC/SC(Personal Computer/Smart Card) API WinScard.dll
        [DllImport("WinScard.dll")]
        public static extern int SCardEstablishContext([In]Int32 dwScope,
            [In]int nNotUsed1, [In]int nNotUsed2, [In, Out]ref int phContext);
        [DllImport("WinScard.dll")]
        public static extern int SCardReleaseContext(int phContext);
        [DllImport("WinScard.dll")]
        public static extern int SCardConnect(int hContext, string cReaderName,
            uint dwShareMode, uint dwPrefProtocol, ref int phCard, ref int ActiveProtocol);
        [DllImport("WinScard.dll")]
        public static extern int SCardDisconnect(int hCard, int Disposition);
        [DllImport("WinScard.dll")]
        public static extern int SCardListReaders(int hContext, string cGroups,
            ref string cReaderLists, ref int nReaderCount);
        [DllImport("WinScard.dll")]
        public static extern int SCardTransmit(int hCard,
            ref SCARD_IO_REQUEST pioSendPci, byte[] pbSendBuffer, int cbSendLength,
            ref SCARD_IO_REQUEST pioRecvPci, ref byte pbRecvBuffer, ref int pcbRecvLength);
 

        static void Main(string[] args)
        {
            int ContextHandle = 0;
            int CardHandle = 0;
            int ActiveProtocol = 0;
            int ReaderCount = -1;
            string ReaderList = string.Empty; //讀卡機名稱列表
            SCARD_IO_REQUEST SendPci, RecvPci;
            byte[] SelectAPDU = { 0x00, 0xA4, 0x04, 0x00, 0x10, 0xD1, 0x58, 0x00, 0x00, 0x01, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00 };
            byte[] ReadProfileAPDU = { 0x00, 0xca, 0x11, 0x00, 0x02, 0x00, 0x00 };
            byte[] SelectRecvBytes = new byte[2]; //應回 90 00
            int SelectRecvLength = 2;
            byte[] ProfileRecvBytes = new byte[59]; //接收Profile的 Byte Array
            int ProfileRecvLength = 59;
           

            //建立 Smart Card API
            if (SCardEstablishContext(0, 0, 0, ref ContextHandle) == 0)
                //列出可用的 Smart Card 讀卡機
                if (SCardListReaders(0, null, ref ReaderList, ref ReaderCount) == 0)
                    //建立 Smart Card 連線
                    if (SCardConnect(ContextHandle, ReaderList, 1, 2, ref CardHandle, ref ActiveProtocol) == 0)
                    {
                        SendPci.dwProtocol = RecvPci.dwProtocol = ActiveProtocol;
                        SendPci.cbPciLength = RecvPci.cbPciLength = 8;
                        //下達 Select Profile 檔的 APDU
                        if (SCardTransmit(CardHandle, ref SendPci, SelectAPDU, SelectAPDU.Length,
                         ref RecvPci, ref SelectRecvBytes[0], ref SelectRecvLength) == 0)
                        //下達讀取Profile指令
                        {
                            if (SCardTransmit(CardHandle, ref SendPci, ReadProfileAPDU, ReadProfileAPDU.Length,
                              ref RecvPci, ref ProfileRecvBytes[0], ref ProfileRecvLength) == 0)
                                Console.WriteLine("健保卡ID:{0}\n姓名:{1}\n身份証字號:{2}\n生日:{3}/{4}/{5}\n姓別:{6}\n發卡日期:{7}/{8}/{9}",
                                  Encoding.Default.GetString(ProfileRecvBytes, 0, 12),
                                  Encoding.Default.GetString(ProfileRecvBytes, 12, 6),
                                  Encoding.Default.GetString(ProfileRecvBytes, 32, 10),
                                  Encoding.Default.GetString(ProfileRecvBytes, 43, 2),
                                  Encoding.Default.GetString(ProfileRecvBytes, 45, 2),
                                  Encoding.Default.GetString(ProfileRecvBytes, 47, 2),
                                  Encoding.Default.GetString(ProfileRecvBytes, 49, 1),
                                  Encoding.Default.GetString(ProfileRecvBytes, 51, 2),
                                  Encoding.Default.GetString(ProfileRecvBytes, 53, 2),
                                  Encoding.Default.GetString(ProfileRecvBytes, 55, 2)
                                  );
                        }
                    }
            Console.ReadKey();
        }
    }
}

沒有留言:

張貼留言