CardReader.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /******************************************************************************
  2. * 文件名称: CardReader.cs
  3. * 文件说明: 读卡的封装,包括社保卡,身份证,电子凭证等等
  4. * 当前版本: V1.0
  5. * 创建日期: 2022-06-20
  6. *
  7. * * 2020-06-20: 增加 CardReader 类
  8. * ***** 2020-06-20: 增加 CardReader 方法,获取URL地址,USER信息,地方版SSCard.dll使用
  9. * ***** 2020-06-20: 增加 CardReader 方法重载,国家版电子凭证使用
  10. * ***** 2020-06-20: 增加 Init 方法,SSCard环境初始化
  11. * ***** 2020-06-20: 增加 ReadCardBas 方法,读社保卡
  12. * ***** 2020-06-20: 增加 VerifyPIN 方法,验证密码
  13. * ***** 2020-06-20: 增加 ChangePIN 方法,修改密码
  14. * ***** 2020-06-20: 增加 ReadSFZ 方法,读身份证
  15. * ***** 2020-06-20: 增加 GetQRBase 方法,读二维码
  16. * ***** 2020-06-20: 增加 NationEcTrans 方法,读电子凭证(国家版)
  17. ******************************************************************************/
  18. using Newtonsoft.Json;
  19. using Newtonsoft.Json.Linq;
  20. using PTMedicalInsurance.Variables;
  21. using System;
  22. using System.Runtime.InteropServices;
  23. using System.Text;
  24. namespace PTMedicalInsurance.CardReaders
  25. {
  26. class CardReader
  27. {
  28. [DllImport("SSCard.dll", EntryPoint = "Init", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
  29. static extern int Init(IntPtr pURL, IntPtr pUser);
  30. //[DllImport(DllPath, EntryPoint = "Init", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
  31. //static extern int Init(StringBuilder pInitInfo, StringBuilder pErrMsg);
  32. [DllImport("SSCard.dll", EntryPoint = "ReadCardBas", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
  33. private static extern int ReadCardBas(IntPtr pOutBuff, int nOutBuffLen, IntPtr pSignBuff, int nSignBuffLen);
  34. const string DllPath = @"SSCard.dll";
  35. private static bool initilaized = false;
  36. private static string URL;
  37. private static string User;
  38. public CardReader()
  39. {
  40. }
  41. public CardReader(string URL, string User)
  42. {
  43. }
  44. public static int Init(string _URL, string _User)
  45. {
  46. URL = _URL;
  47. User = _User;
  48. if (initilaized)
  49. {
  50. Global.writeLog("Init", "检测到已初始化", "");
  51. return 0;
  52. }
  53. string errMsg = "";
  54. int result = -1;
  55. //Global.writeLog_debug(string.Format("读卡初始化:{0},{1}", URL, User));
  56. // 将托管字符串转换为 ANSI 编码的字节数组
  57. byte[] urlBytes = Encoding.ASCII.GetBytes(URL + '\0'); // 添加终止符
  58. byte[] userBytes = Encoding.ASCII.GetBytes(User + '\0'); // 添加终止符
  59. Global.writeLog("Init", URL, User);
  60. // 分配全局非托管内存并复制字符串数据
  61. IntPtr pUrl = Marshal.AllocHGlobal(urlBytes.Length);
  62. IntPtr pUser = Marshal.AllocHGlobal(userBytes.Length);
  63. try
  64. {
  65. // 将托管字节数组复制到非托管内存
  66. Marshal.Copy(urlBytes, 0, pUrl, urlBytes.Length);
  67. Marshal.Copy(userBytes, 0, pUser, userBytes.Length);
  68. result = Init(pUrl, pUser);
  69. if (result == 0)
  70. {
  71. initilaized = true;
  72. }
  73. return result;
  74. }
  75. catch (Exception ex)
  76. {
  77. errMsg = ex.Message;
  78. return result;
  79. }
  80. finally
  81. {
  82. // 显式释放全局非托管内存
  83. if (pUrl != IntPtr.Zero) Marshal.FreeHGlobal(pUrl);
  84. if (pUser != IntPtr.Zero) Marshal.FreeHGlobal(pUser);
  85. Global.writeLog("Init", result.ToString(), errMsg);
  86. }
  87. }
  88. //public int Init()
  89. //{
  90. // string errMsg = "";
  91. // int result = -1;
  92. // try
  93. // {
  94. // StringBuilder sbInitInfo = new StringBuilder();
  95. // StringBuilder sbUSER = new StringBuilder(4096);
  96. // result = Init(sbInitInfo, sbUSER);
  97. // return result;
  98. // }
  99. // catch (Exception ex)
  100. // {
  101. // errMsg = ex.Message;
  102. // return result;
  103. // }
  104. // finally
  105. // {
  106. // Global.writeLog("初始化", "", result.ToString() + ":" + errMsg);
  107. // }
  108. //}
  109. /// <summary>
  110. /// 读社保卡
  111. /// </summary>
  112. /// <param name="basInfo"></param>
  113. /// <returns></returns>
  114. public int ReadCardBas(out string basInfo)
  115. {
  116. basInfo = "";
  117. int rtn = -1;
  118. // 分配非托管内存
  119. //IntPtr pOutBuff = Marshal.AllocCoTaskMem(1024);
  120. //IntPtr pSignBuff = Marshal.AllocCoTaskMem(8192);
  121. // 分配全局非托管内存
  122. IntPtr pOutBuff = Marshal.AllocHGlobal(1024);
  123. IntPtr pSignBuff = Marshal.AllocHGlobal(8192);
  124. try
  125. {
  126. rtn = ReadCardBas(pOutBuff, 1024, pSignBuff, 8192);
  127. if (rtn == 0)
  128. {
  129. // 解析返回读卡信息
  130. string outString = Marshal.PtrToStringAnsi(pOutBuff);
  131. string signString = Marshal.PtrToStringAnsi(pSignBuff);
  132. basInfo = outString;
  133. Global.pat.card.BusinessCode = signString;
  134. }
  135. else
  136. {
  137. string outString = Marshal.PtrToStringAnsi(pOutBuff);
  138. basInfo = outString;
  139. }
  140. return rtn;
  141. }
  142. catch (Exception ex)
  143. {
  144. basInfo = "ReadCardBas异常:" + ex.Message;
  145. return rtn;
  146. }
  147. finally
  148. {
  149. Global.writeLog("读社保卡", "", basInfo);
  150. //// 显式释放非托管内存
  151. //Marshal.FreeCoTaskMem(pOutBuff);
  152. //Marshal.FreeCoTaskMem(pSignBuff);
  153. // 显式释放非托管内存
  154. Marshal.FreeHGlobal(pOutBuff);
  155. Marshal.FreeHGlobal(pSignBuff);
  156. }
  157. }
  158. public int ReadCardBas(out string basInfo, out string signInfo)
  159. {
  160. basInfo = ""; signInfo = "";
  161. int rtn = -1;
  162. // 分配全局非托管内存
  163. IntPtr pOutBuff = Marshal.AllocHGlobal(1024);
  164. IntPtr pSignBuff = Marshal.AllocHGlobal(8192);
  165. try
  166. {
  167. rtn = ReadCardBas(pOutBuff, 1024, pSignBuff, 8192);
  168. if (rtn == 0)
  169. {
  170. // 解析返回读卡信息
  171. string outString = Marshal.PtrToStringAnsi(pOutBuff);
  172. string signString = Marshal.PtrToStringAnsi(pSignBuff);
  173. basInfo = outString;
  174. signInfo = signString;
  175. Global.pat.card.BusinessCode = signString;
  176. }
  177. else
  178. {
  179. string outString = Marshal.PtrToStringAnsi(pOutBuff);
  180. string signString = Marshal.PtrToStringAnsi(pSignBuff);
  181. basInfo = outString;
  182. signInfo = signString;
  183. }
  184. return rtn;
  185. }
  186. catch (Exception ex)
  187. {
  188. basInfo = "ReadCardBas异常:" + ex.Message;
  189. return rtn;
  190. }
  191. finally
  192. {
  193. // 显式释放非托管内存
  194. Marshal.FreeHGlobal(pOutBuff);
  195. Marshal.FreeHGlobal(pSignBuff);
  196. Global.writeLog("ReadCardBas", basInfo, signInfo);
  197. }
  198. }
  199. /// <summary>
  200. /// 读身份证
  201. /// </summary>
  202. /// <param name="OutBuff"></param>
  203. /// <returns></returns>
  204. public int ReadSFZ(out string OutBuff)
  205. {
  206. OutBuff = "";
  207. try
  208. {
  209. SFZReader reader = new SFZReader();
  210. return reader.ReadSFZ(out OutBuff);
  211. }
  212. catch (Exception ex)
  213. {
  214. OutBuff = "ReadSFZ 异常:" + ex.Message;
  215. return -1;
  216. }
  217. }
  218. /// <summary>
  219. /// 6101
  220. /// </summary>
  221. /// <param name="OutBuff"></param>
  222. /// <returns></returns>
  223. public int ReadEC(out string OutBuff)
  224. {
  225. OutBuff = "";
  226. try
  227. {
  228. ECTokenData eCToken = new ECTokenData();
  229. eCToken.orgId = Global.inf.hospitalNO;
  230. eCToken.operatorId = Global.user.ID;
  231. eCToken.operatorName = Global.user.name;
  232. eCToken.officeId = Global.user.officeID;
  233. eCToken.officeName = Global.user.officeName;
  234. eCToken.businessType = Global.businessType;
  235. //eCToken.outBizNo = bizNo;
  236. //eCToken.extData = "";
  237. string tmp = JsonConvert.SerializeObject(eCToken);
  238. var inData = new { InData = JObject.Parse(tmp) };
  239. JObject joInData = new JObject(
  240. new JProperty("InData", JObject.Parse(tmp))
  241. );
  242. ECReader reader = new ECReader();
  243. return reader.Read(joInData,out OutBuff);
  244. }
  245. catch (Exception ex)
  246. {
  247. OutBuff = "ReadEC 异常:" + ex.Message;
  248. return -1;
  249. }
  250. }
  251. /// <summary>
  252. /// 6101
  253. /// </summary>
  254. /// <param name="OutBuff"></param>
  255. /// <returns></returns>
  256. public int ECQuery(out string OutBuff)
  257. {
  258. OutBuff = "";
  259. try
  260. {
  261. EcQueryData ecqueryData = new EcQueryData();
  262. ecqueryData.orgId = Global.inf.hospitalNO;
  263. ecqueryData.operatorId = Global.user.ID;
  264. ecqueryData.operatorName = Global.user.name;
  265. ecqueryData.officeId = Global.user.officeID;
  266. ecqueryData.officeName = Global.user.officeName;
  267. ecqueryData.businessType = Global.businessType;
  268. //eCToken.outBizNo = bizNo;
  269. //eCToken.extData = "";
  270. NationECInput nationECInput = new NationECInput();
  271. nationECInput.data = ecqueryData;
  272. nationECInput.orgId = Global.inf.hospitalNO;
  273. nationECInput.transType = "ec.query";
  274. nationECInput.extra = "";
  275. //测试环境电子凭证动态库地址:http://igb.hsa.gdgov.cn/tst_nation_eccode/tst_eccode/localcfc/api/hsecfc/localQrCodeQuery
  276. //正式环境电子凭证动态库地址:http://hosp.gd.hsip.gov.cn/prd_nation_eccode/prd_eccode/localcfc/api/hsecfc/localQrCodeQuery
  277. NationECCodeAPI nationECCodeAPI = new NationECCodeAPI(Global.inf.ecURL);
  278. return nationECCodeAPI.NationEcTrans(nationECInput, out OutBuff);
  279. }
  280. catch (Exception ex)
  281. {
  282. OutBuff = "ECQuery 异常:" + ex.Message;
  283. return -1;
  284. }
  285. }
  286. }
  287. }