using Newtonsoft.Json.Linq; using PTMedicalInsurance.Entity; using PTMedicalInsurance.Helper; using PTMedicalInsurance.Variables; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; namespace PTMedicalInsurance.Common { class CardReaderNew { const string DllPath = @"SSCard.dll"; private bool initilaized = false; [DllImport("SSCard.dll", EntryPoint = "Init", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)] static extern int Init(IntPtr pURL, IntPtr pUser); [DllImport("SSCard.dll", EntryPoint = "ReadCardBas", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)] private static extern int ReadCardBas(IntPtr pOutBuff, int nOutBuffLen, IntPtr pSignBuff, int nSignBuffLen); [DllImport("SSCard.dll", EntryPoint = "VerifyPIN", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)] static extern int VerifyPIN(StringBuilder pOutBuff, int nOutBuffLen); [DllImport("SSCard.dll", EntryPoint = "ChangePIN", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)] static extern int ChangePIN(StringBuilder pOutBuff, int nOutBuffLen); [DllImport("SSCard.dll", EntryPoint = "ReadSFZ", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)] static extern int ReadSFZ(StringBuilder pOutBuff, int nOutBuffLen, StringBuilder pSignBuff, int nSignBuffLen); [DllImport("SSCard.dll", EntryPoint = "GetQRBase", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)] static extern int GetQRBase(int nTimeout, StringBuilder pOutBuff, int nOutBuffLen, StringBuilder pSignBuff, int nSignBuffLen); //电子凭证 [DllImport("NationECCode.dll", EntryPoint = "NationEcTrans", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)] static extern IntPtr NationEcTrans(StringBuilder strUrl, StringBuilder InData, StringBuilder OutData); private string URL; private string User; public CardReaderNew(string URL, string User) { this.URL = URL; this.User = User; // 获取当前线程 Thread currentThread = Thread.CurrentThread; Global.writeLog($"Current threadID: {currentThread.ManagedThreadId}"); //Global.writeLog($"Is this the main thread? {currentThread.IsBackground == false && currentThread.Name == null}"); //Global.writeLog($"Thread name: {currentThread.Name ?? "Unnamed"}"); } public int Init() { if (initilaized) return 0; string errMsg = ""; int result = -1; Global.writeLog(string.Format("读卡初始化:{0},{1}", URL, User)); // 将托管字符串转换为 ANSI 编码的字节数组 byte[] urlBytes = Encoding.ASCII.GetBytes(URL + '\0'); // 添加终止符 byte[] userBytes = Encoding.ASCII.GetBytes(User + '\0'); // 添加终止符 //// 分配非托管内存并复制字符串数据 //IntPtr pUrl = Marshal.AllocCoTaskMem(urlBytes.Length); //IntPtr pUser = Marshal.AllocCoTaskMem(userBytes.Length); // 分配全局非托管内存并复制字符串数据 IntPtr pUrl = Marshal.AllocHGlobal(urlBytes.Length); IntPtr pUser = Marshal.AllocHGlobal(userBytes.Length); try { // 将托管字节数组复制到非托管内存 Marshal.Copy(urlBytes, 0, pUrl, urlBytes.Length); Marshal.Copy(userBytes, 0, pUser, userBytes.Length); result = Init(pUrl, pUser); initilaized = true; return result; } catch (Exception ex) { errMsg = ex.Message; return result; } finally { Global.writeLog("初始化", "", result.ToString() + ":" + errMsg); //// 显式释放非托管内存 //if (pUrl != IntPtr.Zero) Marshal.FreeCoTaskMem(pUrl); //if (pUser != IntPtr.Zero) Marshal.FreeCoTaskMem(pUser); // 显式释放全局非托管内存 if (pUrl != IntPtr.Zero) Marshal.FreeHGlobal(pUrl); if (pUser != IntPtr.Zero) Marshal.FreeHGlobal(pUser); } } /// /// 读社保卡 /// /// /// public int ReadCardBas(out string basInfo) { basInfo = ""; int rtn = -1; // 分配非托管内存 //IntPtr pOutBuff = Marshal.AllocCoTaskMem(1024); //IntPtr pSignBuff = Marshal.AllocCoTaskMem(8192); // 分配全局非托管内存 IntPtr pOutBuff = Marshal.AllocHGlobal(1024); IntPtr pSignBuff = Marshal.AllocHGlobal(8192); try { rtn = ReadCardBas(pOutBuff, 1024, pSignBuff, 8192); if (rtn == 0) { // 解析返回读卡信息 string outString = Marshal.PtrToStringAnsi(pOutBuff); string signString = Marshal.PtrToStringAnsi(pSignBuff); basInfo = parseCardInfo(outString, 0); Global.pat.card.BusinessCode = signString; } else { string outString = Marshal.PtrToStringAnsi(pOutBuff); basInfo = outString; } return rtn; } catch (Exception ex) { basInfo = "ReadCardBas异常:" + ex.Message; return rtn; } finally { Global.writeLog("读社保卡", "", basInfo); //// 显式释放非托管内存 //Marshal.FreeCoTaskMem(pOutBuff); //Marshal.FreeCoTaskMem(pSignBuff); // 显式释放非托管内存 Marshal.FreeHGlobal(pOutBuff); Marshal.FreeHGlobal(pSignBuff); } } /// /// 读身份证 /// /// /// public int ReadSFZ(out string OutBuff) { OutBuff = ""; int rtn = -1; try { StringBuilder sbOutBuff = new StringBuilder(1024); StringBuilder sbBusiCardBuff = new StringBuilder(1024); rtn = ReadSFZ(sbOutBuff, 1024, sbBusiCardBuff, 1024); // 解析返回读卡信息 OutBuff = parseCardInfo(sbOutBuff.ToString(), 0); Global.pat.card.BusinessCode = sbBusiCardBuff.ToString(); return rtn; } catch (Exception ex) { OutBuff = "ReadSFZ 异常:" + ex.Message; return rtn; } } public int ReadECToken(string URL, string inputParam, out string sOutPar) { sOutPar = ""; StringBuilder sbURL = new StringBuilder(URL); StringBuilder sbInput = new StringBuilder(inputParam); StringBuilder sbOut = new StringBuilder(40960); IntPtr pInt = CardReaderNew.NationEcTrans(sbURL, sbInput, sbOut); string outputData = sbOut.ToString(); //sOutPar = parseECTokenOutput(outputData); sOutPar = outputData; if (JsonHelper.getDestValue(JObject.Parse(outputData), "code") != "0") { return -1; } return 0; } public static string parseECTokenOutput(string data) { JObject joRtn = JObject.Parse(data); Global.pat.ecToken = JsonHelper.getDestValue(joRtn, "data.ecToken"); Global.pat.certNO = JsonHelper.getDestValue(joRtn, "data.idNo"); //身份证 Global.pat.name = JsonHelper.getDestValue(joRtn, "data.userName"); Global.pat.certType = JsonHelper.getDestValue(joRtn, "data.idType"); Global.pat.insuplc_admdvs = JsonHelper.getDestValue(joRtn, "data.insuOrg"); // 令牌 Global.pat.mdtrtcertNO = Global.pat.ecToken; return data; } /// /// 解析读卡结果 /// /// /// private string parseCardInfo(string inBuff, int startIndex = 1) { // 360100 | 362502198603060820 | B04D4C6B2 | 360100D156000005B04D4C6BF99AC1BD | 李凌 | 0081544C9386841907267A0FD6 | 2.00 | 20200612 | 20300612 | 369900906440 || string[] data = inBuff.Split("|".ToCharArray()); CardInfo card = new CardInfo(); card.certno = data[startIndex + 1]; card.cardno = data[startIndex + 2]; card.card_sn = data[startIndex + 3]; card.psn_name = data[startIndex + 4]; Global.pat.insuplc_admdvs = data[startIndex]; //行政区划 Global.pat.card.SN = card.card_sn; Global.pat.certType = "01"; Global.pat.certNO = card.certno; Global.pat.name = card.psn_name; Global.pat.card.NO = card.cardno; Global.pat.mdtrtcertNO = card.certno; string outParam = JsonHelper.toJsonString(card); Global.writeLog("读卡返回:", inBuff, outParam); return outParam; } } }