CardReaderNew.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. using System;
  2. using System.Text;
  3. using System.Runtime.InteropServices;
  4. using PTMedicalInsurance.Variables;
  5. public class CardReaderNew
  6. {
  7. // ========== DLL 导入 ==========
  8. [DllImport("SSCard.dll", EntryPoint = "Init", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
  9. private static extern int InitDll(StringBuilder pURL, StringBuilder pUser);
  10. [DllImport("SSCard.dll", EntryPoint = "ReadCardBasGZ", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
  11. private static extern int ReadCardBasGZ(StringBuilder pOutBuff, int nOutBuffLen, StringBuilder pSignBuff, int nSignBuffLen);
  12. [DllImport("SSCard.dll", EntryPoint = "ReadMedicalCardGZ", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
  13. private static extern int ReadMedicalCardGZ(StringBuilder pOutBuff, int nOutBuffLen, StringBuilder pSignBuff, int nSignBuffLen);
  14. [DllImport("SSCard.dll", EntryPoint = "VerifyPIN", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
  15. private static extern int VerifyPIN(StringBuilder pOutBuff, int nOutBuffLen);
  16. [DllImport("SSCard.dll", EntryPoint = "ChangePIN", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
  17. private static extern int ChangePIN(StringBuilder pOutBuff, int nOutBuffLen);
  18. [DllImport("SSCard.dll", EntryPoint = "ReadIDCardGZ", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
  19. private static extern int ReadSFZ(StringBuilder pOutBuff, int nOutBuffLen, StringBuilder pSignBuff, int nSignBuffLen);
  20. [DllImport("SSCard.dll", EntryPoint = "GetTwoBarCodes", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
  21. private static extern int GetQRBase(int nTimeout, StringBuilder pOutBuff, int nOutBuffLen, StringBuilder pSignBuff, int nSignBuffLen);
  22. [DllImport("NationECCode.dll", EntryPoint = "NationEcTrans", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
  23. private static extern IntPtr NationEcTrans(StringBuilder strUrl, StringBuilder InData, StringBuilder OutData);
  24. [DllImport("SSCARDInterface.dll", EntryPoint = "SetAutoQRcode", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
  25. private static extern int SetAutoQRcode(StringBuilder pOutBuff);
  26. [DllImport("SSCARDInterface.dll", EntryPoint = "CloseAutoQRcode", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
  27. private static extern int CloseAutoQRcode(StringBuilder pOutBuff);
  28. [DllImport("SSCARDInterface.dll", EntryPoint = "iOpenPort", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
  29. private static extern int iOpenPort(StringBuilder pOutBuff);
  30. [DllImport("SSCARDInterface.dll", EntryPoint = "iClosePort", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
  31. private static extern int iClosePort(StringBuilder pOutBuff);
  32. // ========== 单例实现 ==========
  33. private static readonly Lazy<CardReaderNew> _instance = new Lazy<CardReaderNew>(() =>
  34. {
  35. string url = Global.inf.cardURL ?? throw new InvalidOperationException("Global.inf.cardURL 未初始化");
  36. string user = Global.inf.areaCode ?? throw new InvalidOperationException("Global.inf.areaCode 未初始化");
  37. var reader = new CardReaderNew(url, user);
  38. reader.Initialize();
  39. return reader;
  40. });
  41. public static CardReaderNew Instance => _instance.Value;
  42. // ========== 实例成员 ==========
  43. private readonly string _url;
  44. private readonly string _user;
  45. private bool _isInited = false;
  46. // 私有构造函数(禁止外部 new)
  47. private CardReaderNew(string url, string user)
  48. {
  49. _url = url;
  50. _user = user;
  51. }
  52. // 初始化(仅执行一次)
  53. private void Initialize()
  54. {
  55. if (_isInited) return;
  56. string errMsg = "";
  57. int result = -1;
  58. try
  59. {
  60. var sbURL = new StringBuilder(_url);
  61. var sbUser = new StringBuilder(_user);
  62. result = InitDll(sbURL, sbUser);
  63. if (result == 0)
  64. {
  65. _isInited = true;
  66. }
  67. else
  68. {
  69. errMsg = $"Init 返回错误码: {result}";
  70. }
  71. }
  72. catch (Exception ex)
  73. {
  74. errMsg = ex.Message;
  75. result = -1;
  76. }
  77. finally
  78. {
  79. Global.writeLog("初始化", $"{_url}:{_user}", $"{result}:{errMsg}");
  80. }
  81. if (!_isInited)
  82. {
  83. throw new InvalidOperationException($"CardReaderNew 初始化失败: {errMsg}");
  84. }
  85. }
  86. // ========== 业务方法(全部修正缓冲区长度)==========
  87. private const int DEFAULT_BUFFER_SIZE = 2048; // 统一使用 2048,更安全
  88. public int ReadCardBas(out string basInfo, out string regInfo)
  89. {
  90. if (!_isInited) { basInfo = "未初始化"; regInfo = ""; return -1; }
  91. basInfo = ""; regInfo = "";
  92. try
  93. {
  94. var sbBas = new StringBuilder(DEFAULT_BUFFER_SIZE);
  95. var sbReg = new StringBuilder(DEFAULT_BUFFER_SIZE);
  96. int rtn = ReadCardBasGZ(sbBas, DEFAULT_BUFFER_SIZE, sbReg, DEFAULT_BUFFER_SIZE);
  97. basInfo = sbBas.ToString();
  98. regInfo = sbReg.ToString();
  99. return rtn;
  100. }
  101. catch (Exception ex)
  102. {
  103. basInfo = "ReadCardBas异常: " + ex.Message;
  104. return -1;
  105. }
  106. finally
  107. {
  108. Global.writeLog("读社保卡(" + _url + ")", regInfo, basInfo);
  109. }
  110. }
  111. public int VerifyPIN(out string outBuff)
  112. {
  113. if (!_isInited) { outBuff = "未初始化"; return -1; }
  114. outBuff = "";
  115. try
  116. {
  117. var sb = new StringBuilder(DEFAULT_BUFFER_SIZE);
  118. int rtn = VerifyPIN(sb, DEFAULT_BUFFER_SIZE);
  119. outBuff = sb.ToString();
  120. return rtn;
  121. }
  122. catch (Exception ex)
  123. {
  124. outBuff = "VerifyPIN: " + ex.Message;
  125. return -1;
  126. }
  127. }
  128. public int ChangePIN(out string outBuff)
  129. {
  130. if (!_isInited) { outBuff = "未初始化"; return -1; }
  131. outBuff = "";
  132. try
  133. {
  134. var sb = new StringBuilder(DEFAULT_BUFFER_SIZE);
  135. int rtn = ChangePIN(sb, DEFAULT_BUFFER_SIZE);
  136. outBuff = sb.ToString();
  137. return rtn;
  138. }
  139. catch (Exception ex)
  140. {
  141. outBuff = "ChangePIN: " + ex.Message;
  142. return -1;
  143. }
  144. }
  145. public int ReadSFZ(out string OutBuff, out string SignBuff)
  146. {
  147. if (!_isInited) { OutBuff = "未初始化"; SignBuff = ""; return -1; }
  148. OutBuff = ""; SignBuff = "";
  149. try
  150. {
  151. var sbOut = new StringBuilder(DEFAULT_BUFFER_SIZE);
  152. var sbSign = new StringBuilder(DEFAULT_BUFFER_SIZE);
  153. int rtn = ReadSFZ(sbOut, DEFAULT_BUFFER_SIZE, sbSign, DEFAULT_BUFFER_SIZE);
  154. OutBuff = sbOut.ToString();
  155. SignBuff = sbSign.ToString();
  156. return rtn;
  157. }
  158. catch (Exception ex)
  159. {
  160. OutBuff = "ReadSFZ 异常: " + ex.Message;
  161. return -1;
  162. }
  163. }
  164. public int GetQRBase(out int timeout, out string OutBuff, out string SignBuff)
  165. {
  166. if (!_isInited) { OutBuff = "未初始化"; SignBuff = ""; timeout = 0; return -1; }
  167. OutBuff = ""; SignBuff = ""; timeout = 10;
  168. try
  169. {
  170. var sbOut = new StringBuilder(DEFAULT_BUFFER_SIZE);
  171. var sbSign = new StringBuilder(DEFAULT_BUFFER_SIZE);
  172. int rtn = GetQRBase(timeout, sbOut, DEFAULT_BUFFER_SIZE, sbSign, DEFAULT_BUFFER_SIZE);
  173. OutBuff = sbOut.ToString();
  174. SignBuff = sbSign.ToString();
  175. return rtn;
  176. }
  177. catch (Exception ex)
  178. {
  179. OutBuff = "GetQRBase 异常: " + ex.Message;
  180. return -1;
  181. }
  182. finally
  183. {
  184. Global.writeLog("GetQRBase", $"Timeout={timeout}", $"Out:{OutBuff}, Sign:{SignBuff}");
  185. }
  186. }
  187. public string NationEcTrans(string url, string inData, out string outData)
  188. {
  189. outData = "";
  190. try
  191. {
  192. var sbUrl = new StringBuilder(url);
  193. var sbIn = new StringBuilder(inData);
  194. var sbOut = new StringBuilder(10240); // 此处保持较大,因电子凭证可能较长
  195. IntPtr pRtn = NationEcTrans(sbUrl, sbIn, sbOut);
  196. outData = sbOut.ToString();
  197. return Marshal.PtrToStringAnsi(pRtn) ?? "-1";
  198. }
  199. catch (Exception ex)
  200. {
  201. outData = "NationEcTrans 异常: " + ex.Message;
  202. return "-1";
  203. }
  204. finally
  205. {
  206. Global.writeLog("电子凭证", inData, outData);
  207. }
  208. }
  209. public int SetAutoQRcode(out string errMsg)
  210. {
  211. errMsg = "";
  212. try
  213. {
  214. var sb = new StringBuilder(DEFAULT_BUFFER_SIZE);
  215. int rtn = SetAutoQRcode(sb);
  216. errMsg = sb.ToString();
  217. return rtn;
  218. }
  219. catch (Exception ex)
  220. {
  221. errMsg = "SetAutoQRcode 异常: " + ex.Message;
  222. return -1;
  223. }
  224. finally
  225. {
  226. Global.writeLog("SetAutoQRcode", "", errMsg);
  227. }
  228. }
  229. public int CloseAutoQRcode(out string errMsg)
  230. {
  231. errMsg = "";
  232. int rtn = -1;
  233. try
  234. {
  235. var sb = new StringBuilder(DEFAULT_BUFFER_SIZE);
  236. rtn = CloseAutoQRcode(sb);
  237. errMsg = sb.ToString();
  238. return rtn;
  239. }
  240. catch (Exception ex)
  241. {
  242. errMsg = "CloseAutoQRcode 异常: " + ex.Message;
  243. return -1;
  244. }
  245. finally
  246. {
  247. Global.writeLog("CloseAutoQRcode", rtn.ToString(), errMsg);
  248. }
  249. }
  250. public int iOpenPort(out string errMsg)
  251. {
  252. errMsg = "";
  253. int rtn = -1;
  254. try
  255. {
  256. var sb = new StringBuilder(DEFAULT_BUFFER_SIZE);
  257. rtn = iOpenPort(sb);
  258. errMsg = sb.ToString();
  259. return rtn;
  260. }
  261. catch (Exception ex)
  262. {
  263. errMsg = "iOpenPort 异常: " + ex.Message;
  264. return -1;
  265. }
  266. finally
  267. {
  268. Global.writeLog("iOpenPort", rtn.ToString(), errMsg);
  269. }
  270. }
  271. public int iClosePort(out string errMsg)
  272. {
  273. errMsg = "";
  274. int rtn = -1;
  275. try
  276. {
  277. var sb = new StringBuilder(DEFAULT_BUFFER_SIZE);
  278. rtn = iClosePort(sb);
  279. errMsg = sb.ToString();
  280. return rtn;
  281. }
  282. catch (Exception ex)
  283. {
  284. errMsg = "iClosePort 异常: " + ex.Message;
  285. return -1;
  286. }
  287. finally
  288. {
  289. Global.writeLog("iClosePort", rtn.ToString(), errMsg);
  290. }
  291. }
  292. }