/****************************************************************************** * 文件名称: CardReader.cs * 文件说明: 读卡的封装,包括社保卡,身份证,电子凭证等等 * 当前版本: V1.0 * 创建日期: 2022-06-20 * * * 2020-06-20: 增加 CardReader 类 * ***** 2020-06-20: 增加 CardReader 方法,获取URL地址,USER信息,地方版SSCard.dll使用 * ***** 2020-06-20: 增加 CardReader 方法重载,国家版电子凭证使用 * ***** 2020-06-20: 增加 Init 方法,SSCard环境初始化 * ***** 2020-06-20: 增加 ReadCardBas 方法,读社保卡 * ***** 2020-06-20: 增加 VerifyPIN 方法,验证密码 * ***** 2020-06-20: 增加 ChangePIN 方法,修改密码 * ***** 2020-06-20: 增加 ReadSFZ 方法,读身份证 * ***** 2020-06-20: 增加 GetQRBase 方法,读二维码 * ***** 2020-06-20: 增加 NationEcTrans 方法,读电子凭证(国家版) ******************************************************************************/ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using PTMedicalInsurance.Variables; using System; using System.Runtime.InteropServices; using System.Text; namespace PTMedicalInsurance.CardReaders { class CardReader { [DllImport("SSCard.dll", EntryPoint = "Init", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)] static extern int Init(IntPtr pURL, IntPtr pUser); //[DllImport(DllPath, EntryPoint = "Init", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)] //static extern int Init(StringBuilder pInitInfo, StringBuilder pErrMsg); [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); const string DllPath = @"SSCard.dll"; private static bool initilaized = false; private static string URL; private static string User; public CardReader() { } public CardReader(string URL, string User) { } public static int Init(string _URL, string _User) { URL = _URL; User = _User; if (initilaized) { Global.writeLog("Init", "检测到已初始化", ""); return 0; } string errMsg = ""; int result = -1; //Global.writeLog_debug(string.Format("读卡初始化:{0},{1}", URL, User)); // 将托管字符串转换为 ANSI 编码的字节数组 byte[] urlBytes = Encoding.ASCII.GetBytes(URL + '\0'); // 添加终止符 byte[] userBytes = Encoding.ASCII.GetBytes(User + '\0'); // 添加终止符 Global.writeLog("Init", URL, User); // 分配全局非托管内存并复制字符串数据 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); if (result == 0) { initilaized = true; } return result; } catch (Exception ex) { errMsg = ex.Message; return result; } finally { // 显式释放全局非托管内存 if (pUrl != IntPtr.Zero) Marshal.FreeHGlobal(pUrl); if (pUser != IntPtr.Zero) Marshal.FreeHGlobal(pUser); Global.writeLog("Init", result.ToString(), errMsg); } } //public int Init() //{ // string errMsg = ""; // int result = -1; // try // { // StringBuilder sbInitInfo = new StringBuilder(); // StringBuilder sbUSER = new StringBuilder(4096); // result = Init(sbInitInfo, sbUSER); // return result; // } // catch (Exception ex) // { // errMsg = ex.Message; // return result; // } // finally // { // Global.writeLog("初始化", "", result.ToString() + ":" + errMsg); // } //} /// /// 读社保卡 /// /// /// 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 = outString; 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 ReadCardBas(out string basInfo, out string signInfo) { basInfo = ""; signInfo = ""; int rtn = -1; // 分配全局非托管内存 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 = outString; signInfo = signString; Global.pat.card.BusinessCode = signString; } else { string outString = Marshal.PtrToStringAnsi(pOutBuff); string signString = Marshal.PtrToStringAnsi(pSignBuff); basInfo = outString; signInfo = signString; } return rtn; } catch (Exception ex) { basInfo = "ReadCardBas异常:" + ex.Message; return rtn; } finally { // 显式释放非托管内存 Marshal.FreeHGlobal(pOutBuff); Marshal.FreeHGlobal(pSignBuff); Global.writeLog("ReadCardBas", basInfo, signInfo); } } /// /// 读身份证 /// /// /// public int ReadSFZ(out string OutBuff) { OutBuff = ""; try { SFZReader reader = new SFZReader(); return reader.ReadSFZ(out OutBuff); } catch (Exception ex) { OutBuff = "ReadSFZ 异常:" + ex.Message; return -1; } } /// /// 6101 /// /// /// public int ReadEC(out string OutBuff) { OutBuff = ""; try { ECTokenData eCToken = new ECTokenData(); eCToken.orgId = Global.inf.hospitalNO; eCToken.operatorId = Global.user.ID; eCToken.operatorName = Global.user.name; eCToken.officeId = Global.user.officeID; eCToken.officeName = Global.user.officeName; eCToken.businessType = Global.businessType; //eCToken.outBizNo = bizNo; //eCToken.extData = ""; string tmp = JsonConvert.SerializeObject(eCToken); var inData = new { InData = JObject.Parse(tmp) }; JObject joInData = new JObject( new JProperty("InData", JObject.Parse(tmp)) ); ECReader reader = new ECReader(); return reader.Read(joInData,out OutBuff); } catch (Exception ex) { OutBuff = "ReadEC 异常:" + ex.Message; return -1; } } /// /// 6101 /// /// /// public int ECQuery(out string OutBuff) { OutBuff = ""; try { EcQueryData ecqueryData = new EcQueryData(); ecqueryData.orgId = Global.inf.hospitalNO; ecqueryData.operatorId = Global.user.ID; ecqueryData.operatorName = Global.user.name; ecqueryData.officeId = Global.user.officeID; ecqueryData.officeName = Global.user.officeName; ecqueryData.businessType = Global.businessType; //eCToken.outBizNo = bizNo; //eCToken.extData = ""; NationECInput nationECInput = new NationECInput(); nationECInput.data = ecqueryData; nationECInput.orgId = Global.inf.hospitalNO; nationECInput.transType = "ec.query"; nationECInput.extra = ""; //测试环境电子凭证动态库地址:http://igb.hsa.gdgov.cn/tst_nation_eccode/tst_eccode/localcfc/api/hsecfc/localQrCodeQuery //正式环境电子凭证动态库地址:http://hosp.gd.hsip.gov.cn/prd_nation_eccode/prd_eccode/localcfc/api/hsecfc/localQrCodeQuery NationECCodeAPI nationECCodeAPI = new NationECCodeAPI(Global.inf.ecURL); return nationECCodeAPI.NationEcTrans(nationECInput, out OutBuff); } catch (Exception ex) { OutBuff = "ECQuery 异常:" + ex.Message; return -1; } } } }