MainForm.cs 67 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444
  1. using Microsoft.Win32;
  2. using Newtonsoft.Json.Linq;
  3. using System;
  4. using System.Diagnostics;
  5. using System.Drawing;
  6. using System.IO;
  7. using System.Net;
  8. using System.Text;
  9. using System.Windows.Forms;
  10. namespace ThCardReader
  11. {
  12. public partial class MainForm : Form
  13. {
  14. public static SiBusinessAddress address;
  15. private DateTime? _lastJiangSuClickTime = null; // 用于双击检测
  16. public MainForm()
  17. {
  18. InitializeComponent();
  19. CreateLogFolder();
  20. GetSiBusinessAddress();
  21. RestService service = new RestService();
  22. service.Start();
  23. Exec_CheckUpdate(true);
  24. }
  25. private void GetSiBusinessAddress()
  26. {
  27. try
  28. {
  29. HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://172.16.32.167:8077/readCard/getSiBusinessAddress");
  30. request.Proxy = null;
  31. request.KeepAlive = false;
  32. request.Method = "GET";
  33. request.ContentType = "application/json; charset=UTF-8";
  34. request.Timeout = 3000; // 3秒超时
  35. HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  36. Stream myResponseStream = response.GetResponseStream();
  37. StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.UTF8);
  38. string retString = myStreamReader.ReadToEnd();
  39. myStreamReader.Close();
  40. myResponseStream.Close();
  41. if (response != null)
  42. {
  43. response.Close();
  44. }
  45. if (request != null)
  46. {
  47. request.Abort();
  48. }
  49. address = Newtonsoft.Json.JsonConvert.DeserializeObject<SiBusinessAddress>(retString);
  50. if (address.validFlag == 0)
  51. {
  52. SetDefaultAddress();
  53. }
  54. }
  55. catch (Exception ex)
  56. {
  57. // 网络连接失败时使用默认配置,让程序继续运行
  58. System.Diagnostics.Debug.WriteLine($"获取远程配置失败: {ex.Message},使用默认配置");
  59. SetDefaultAddress();
  60. }
  61. }
  62. private void SetDefaultAddress()
  63. {
  64. address = new SiBusinessAddress();
  65. address.readSiCardUrl = "https://scr.hun.hsip.gov.cn/hsa-hgs-adapt/api/card/initDll";
  66. address.readSiCardUser = "430105|10.93.28.229:80";
  67. address.readSiCardBuffSize = 2048;
  68. address.readIdCardUrl = "https://scr.hun.hsip.gov.cn/hsa-hgs-adapt/api/card/initDll";
  69. address.readIdCardUser = "430105|10.93.28.229:80";
  70. address.readIdCardBuffSize = 8192;
  71. address.readQrEcTokenUrl = "https://dvs.hun.hsip.gov.cn/localcfc/api/hsecfc/localQrCodeQuery";
  72. address.organizationId = "H43010500370";
  73. address.validFlag = 0;
  74. }
  75. private void HideForm()
  76. {
  77. this.WindowState = FormWindowState.Minimized;
  78. }
  79. private void CreateLogFolder()
  80. {
  81. string path = "D:\\读卡日志\\";
  82. if (!Directory.Exists(path))
  83. {
  84. Directory.CreateDirectory(path);
  85. if (!File.Exists("D:\\读卡日志\\ThyyBusiness.log"))
  86. {
  87. File.Create("D:\\读卡日志\\ThyyBusiness.log").Close();
  88. }
  89. }
  90. }
  91. private void MainForm_Load(object sender, EventArgs e)
  92. {
  93. RegistryKey registryKey = Registry.CurrentUser.OpenSubKey
  94. ("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
  95. registryKey.SetValue("ThCardReader", Application.ExecutablePath);
  96. // 只显示红圈内四个按钮
  97. this.huashi_idcard_test.Visible = true;
  98. this.jiangsu_sicard_test.Visible = true;
  99. this.jiangsu_face_test.Visible = true;
  100. this.jiangsu_ec_decode_test.Visible = true;
  101. // 其余全部隐藏
  102. this.jiangsu_renshe_test.Visible = false;
  103. this.sicard_test.Visible = false;
  104. this.idcard_test.Visible = false;
  105. this.qrcode_test.Visible = false;
  106. this.face_test.Visible = false;
  107. this.id_card_test2.Visible = false;
  108. this.qr_code_test2.Visible = false;
  109. this.label1.Visible = false;
  110. this.label2.Visible = false;
  111. this.panel1.Visible = false;
  112. }
  113. private void CheckUpdate(object sender, EventArgs e)
  114. {
  115. Exec_CheckUpdate(false);
  116. }
  117. private void Exec_CheckUpdate(Boolean fromLoad)
  118. {
  119. string currentVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
  120. string newVersion = GetVersion();
  121. if (currentVersion.Equals(newVersion))
  122. {
  123. if (!fromLoad)
  124. {
  125. MessageBox.Show("已经是最新版本。", String.Format("读卡插件-V{0}", currentVersion), MessageBoxButtons.OK);
  126. }
  127. }
  128. else
  129. {
  130. if (MessageBox.Show(String.Format("检查到新版本(V{0}),是否更新?", newVersion),
  131. String.Format("读卡插件-V{0}", currentVersion),
  132. MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
  133. {
  134. UpdateForm updateForm = new UpdateForm(newVersion);
  135. updateForm.Show();
  136. }
  137. }
  138. }
  139. private void ResetDriver(object sender, EventArgs e)
  140. {
  141. string path = Directory.GetCurrentDirectory();
  142. string logDir = path + "\\dlllog(Nation)";
  143. string driverDir = path + "\\SSCardDriver";
  144. DeleteFile(logDir);
  145. DeleteFile(driverDir);
  146. MessageBox.Show("删除驱动成功。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
  147. }
  148. private void DeleteFile(string path)
  149. {
  150. try
  151. {
  152. if (Directory.Exists(path))
  153. {
  154. foreach (string f in Directory.GetFileSystemEntries(path))
  155. {
  156. if (File.Exists(f))
  157. {
  158. File.Delete(f);
  159. }
  160. else
  161. {
  162. DeleteFile(f);
  163. }
  164. }
  165. Directory.Delete(path);
  166. }
  167. }
  168. catch (Exception e)
  169. {
  170. MessageBox.Show("程序出错:" + e.ToString(), "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
  171. }
  172. }
  173. private void RestartProcess(object sender, EventArgs e)
  174. {
  175. Application.Restart();
  176. Environment.Exit(0);
  177. }
  178. private void ShutdownProcess(object sender, EventArgs e)
  179. {
  180. Process.GetCurrentProcess().Kill();
  181. }
  182. public static string GetVersion()
  183. {
  184. try
  185. {
  186. HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://webhis.thyy.cn:8080/download/readcard/version.txt");
  187. request.Proxy = null;
  188. request.KeepAlive = false;
  189. request.Method = "GET";
  190. request.ContentType = "application/json; charset=UTF-8";
  191. request.AutomaticDecompression = DecompressionMethods.GZip;
  192. request.Timeout = 3000; // 3秒超时
  193. HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  194. Stream myResponseStream = response.GetResponseStream();
  195. StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.UTF8);
  196. string retString = myStreamReader.ReadToEnd();
  197. myStreamReader.Close();
  198. myResponseStream.Close();
  199. if (response != null)
  200. {
  201. response.Close();
  202. }
  203. if (request != null)
  204. {
  205. request.Abort();
  206. }
  207. return retString;
  208. }
  209. catch (Exception ex)
  210. {
  211. // 获取版本失败时返回当前版本,避免程序崩溃
  212. System.Diagnostics.Debug.WriteLine($"获取远程版本失败: {ex.Message}");
  213. return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
  214. }
  215. }
  216. private void ShowMainForm(object sender, EventArgs e)
  217. {
  218. if (this.WindowState == FormWindowState.Minimized)
  219. {
  220. this.WindowState = FormWindowState.Normal;
  221. this.Show();
  222. }
  223. }
  224. private void ShowMainForm(object sender, MouseEventArgs e)
  225. {
  226. if (this.WindowState == FormWindowState.Minimized)
  227. {
  228. this.WindowState = FormWindowState.Normal;
  229. this.Show();
  230. }
  231. }
  232. private void TestSiCard(object sender, EventArgs e)
  233. {
  234. EnableAllButtons(false);
  235. ClearParamsDisplay();
  236. // 显示请求网址
  237. this.request_url_text.Text = "本地直接调用 - SsCardBusiness.ReadSiCard()";
  238. // 显示请求参数
  239. var requestParams = new { action = "ReadSiCard", device = "泰和SSCard.dll", type = "社保卡" };
  240. this.request_params_text.Text = Newtonsoft.Json.JsonConvert.SerializeObject(requestParams, Newtonsoft.Json.Formatting.Indented);
  241. JObject result = SsCardBusiness.ReadSiCard();
  242. this.result_text.Text = result.ToString();
  243. // 显示响应参数并设置状态颜色
  244. this.response_params_text.Text = result.ToString(Newtonsoft.Json.Formatting.Indented);
  245. SetStatusColor(result);
  246. EnableAllButtons(true);
  247. this.sicard_test.Focus();
  248. }
  249. private void TestIdCard(object sender, EventArgs e)
  250. {
  251. EnableAllButtons(false);
  252. ClearParamsDisplay();
  253. // 显示请求网址
  254. this.request_url_text.Text = "本地直接调用 - SsCardBusiness.ReadIdCard()";
  255. // 显示请求参数
  256. var requestParams = new { action = "ReadIdCard", device = "泰和SSCard.dll", type = "身份证" };
  257. this.request_params_text.Text = Newtonsoft.Json.JsonConvert.SerializeObject(requestParams, Newtonsoft.Json.Formatting.Indented);
  258. JObject result = SsCardBusiness.ReadIdCard();
  259. this.result_text.Text = result.ToString();
  260. // 显示响应参数并设置状态颜色
  261. this.response_params_text.Text = result.ToString(Newtonsoft.Json.Formatting.Indented);
  262. SetStatusColor(result);
  263. EnableAllButtons(true);
  264. this.idcard_test.Focus();
  265. }
  266. private void TestQrCode(object sender, EventArgs e)
  267. {
  268. EnableAllButtons(false);
  269. ClearParamsDisplay();
  270. // 显示请求网址
  271. this.request_url_text.Text = "本地直接调用 - NationalEcBusiness.ReadQrCode(\"01101\")";
  272. // 显示请求参数
  273. var requestParams = new { action = "ReadQrCode", device = "泰和NationECCode.dll", biztype = "01101", type = "电子凭证" };
  274. this.request_params_text.Text = Newtonsoft.Json.JsonConvert.SerializeObject(requestParams, Newtonsoft.Json.Formatting.Indented);
  275. JObject result = NationalEcBusiness.ReadQrCode("01101");
  276. this.result_text.Text = result.ToString();
  277. // 显示响应参数并设置状态颜色
  278. this.response_params_text.Text = result.ToString(Newtonsoft.Json.Formatting.Indented);
  279. SetStatusColor(result);
  280. EnableAllButtons(true);
  281. this.qrcode_test.Focus();
  282. }
  283. private void TestIdCard2(object sender, EventArgs e)
  284. {
  285. EnableAllButtons(false);
  286. ClearParamsDisplay();
  287. // 显示请求网址
  288. this.request_url_text.Text = "本地直接调用 - NationalEcBusiness.ReadIdCard(\"01101\")";
  289. // 显示请求参数
  290. var requestParams = new { action = "ReadIdCard", device = "泰和NationECCode.dll刷脸终端", biztype = "01101", type = "身份证" };
  291. this.request_params_text.Text = Newtonsoft.Json.JsonConvert.SerializeObject(requestParams, Newtonsoft.Json.Formatting.Indented);
  292. JObject result = NationalEcBusiness.ReadIdCard("01101");
  293. this.result_text.Text = result.ToString();
  294. // 显示响应参数并设置状态颜色
  295. this.response_params_text.Text = result.ToString(Newtonsoft.Json.Formatting.Indented);
  296. SetStatusColor(result);
  297. EnableAllButtons(true);
  298. this.id_card_test2.Focus();
  299. }
  300. private void TestQrCode2(object sender, EventArgs e)
  301. {
  302. EnableAllButtons(false);
  303. ClearParamsDisplay();
  304. // 显示请求网址
  305. this.request_url_text.Text = "本地直接调用 - NationalEcBusiness.ReadQrCode2(\"01101\")";
  306. // 显示请求参数
  307. var requestParams = new { action = "ReadQrCode2", device = "泰和NationECCode.dll刷脸终端", biztype = "01101", type = "电子凭证" };
  308. this.request_params_text.Text = Newtonsoft.Json.JsonConvert.SerializeObject(requestParams, Newtonsoft.Json.Formatting.Indented);
  309. JObject result = NationalEcBusiness.ReadQrCode2("01101");
  310. this.result_text.Text = result.ToString();
  311. // 显示响应参数并设置状态颜色
  312. this.response_params_text.Text = result.ToString(Newtonsoft.Json.Formatting.Indented);
  313. SetStatusColor(result);
  314. EnableAllButtons(true);
  315. this.qr_code_test2.Focus();
  316. }
  317. private void TestFace(object sender, EventArgs e)
  318. {
  319. EnableAllButtons(false);
  320. ClearParamsDisplay();
  321. // 显示请求网址
  322. this.request_url_text.Text = "本地直接调用 - NationalEcBusiness.ReadFace(\"01101\")";
  323. // 显示请求参数
  324. var requestParams = new { action = "ReadFace", device = "泰和NationECCode.dll刷脸终端", biztype = "01101", type = "刷脸" };
  325. this.request_params_text.Text = Newtonsoft.Json.JsonConvert.SerializeObject(requestParams, Newtonsoft.Json.Formatting.Indented);
  326. JObject result = NationalEcBusiness.ReadFace("01101");
  327. this.result_text.Text = result.ToString();
  328. // 显示响应参数并设置状态颜色
  329. this.response_params_text.Text = result.ToString(Newtonsoft.Json.Formatting.Indented);
  330. SetStatusColor(result);
  331. EnableAllButtons(true);
  332. this.face_test.Focus();
  333. }
  334. private void TestHuaShiIdCard(object sender, EventArgs e)
  335. {
  336. EnableAllButtons(false);
  337. ClearParamsDisplay();
  338. // 显示请求网址
  339. this.request_url_text.Text = "本地直接调用 - HuaShiIdCardBusiness.ReadIdCard()";
  340. // 显示请求参数
  341. var requestParams = new { action = "ReadIdCard", device = "华视Termb.dll", port = 1001 };
  342. this.request_params_text.Text = Newtonsoft.Json.JsonConvert.SerializeObject(requestParams, Newtonsoft.Json.Formatting.Indented);
  343. JObject result = HuaShiIdCardBusiness.ReadIdCard();
  344. this.result_text.Text = result.ToString();
  345. // 显示响应参数并设置状态颜色
  346. this.response_params_text.Text = result.ToString(Newtonsoft.Json.Formatting.Indented);
  347. // 华视读卡器没有专门的DLL错误信息,显示通用错误信息
  348. if (result["success"] != null && !(bool)result["success"])
  349. {
  350. this.dll_error_text.Text = result["message"]?.ToString() ?? "华视读卡器操作失败";
  351. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(255, 240, 240);
  352. this.dll_error_text.ForeColor = System.Drawing.Color.DarkRed;
  353. }
  354. else
  355. {
  356. this.dll_error_text.Text = "华视读卡器操作成功";
  357. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(220, 252, 231);
  358. this.dll_error_text.ForeColor = System.Drawing.Color.FromArgb(22, 101, 52);
  359. }
  360. SetStatusColor(result);
  361. EnableAllButtons(true);
  362. this.huashi_idcard_test.Focus();
  363. }
  364. /// <summary>
  365. /// 测试江苏医保读社保卡
  366. /// 单击:传统模式(显式初始化)
  367. /// 双击:测试新的autoInit智能模式
  368. /// </summary>
  369. private void TestJiangSuSiCard(object sender, EventArgs e)
  370. {
  371. EnableAllButtons(false);
  372. ClearParamsDisplay();
  373. // 检查是否是双击(测试autoInit功能)
  374. bool useAutoInitTest = false;
  375. var now = DateTime.Now;
  376. if (_lastJiangSuClickTime.HasValue && (now - _lastJiangSuClickTime.Value).TotalMilliseconds < 600)
  377. {
  378. useAutoInitTest = true;
  379. _lastJiangSuClickTime = null; // 重置
  380. }
  381. else
  382. {
  383. _lastJiangSuClickTime = now;
  384. // 如果是单击,稍等一下看是否有第二次点击
  385. if (!useAutoInitTest)
  386. {
  387. System.Threading.Thread.Sleep(100);
  388. }
  389. }
  390. try
  391. {
  392. // 使用外部配置文件加载的江苏医保参数先初始化
  393. var config = new JiangSuSocialCardBusiness.JiangSuConfig();
  394. // 显示江苏医保接口详细信息
  395. this.request_url_text.Text = GetJiangSuInterfaceInfo();
  396. // 显示请求参数
  397. var requestParams = new {
  398. action = useAutoInitTest ? "TestAutoInitMode" : "InitAndReadCard",
  399. device = "江苏医保HeaSecReadInfo.dll",
  400. testMode = useAutoInitTest ? "智能模式测试(autoInit=true)" : "传统模式+自动备选(保证成功)",
  401. clickType = useAutoInitTest ? "双击 - 测试autoInit参数" : "单击 - 传统显式初始化",
  402. step1 = useAutoInitTest ? "直接调用ReadSocialCard(false, true)" : "先尝试显式初始化",
  403. step2 = useAutoInitTest ? "自动处理初始化逻辑" : "再调用传统读卡方法",
  404. step3 = useAutoInitTest ? "失败时提供详细错误信息" : "失败时自动尝试离线模式",
  405. configSource = "外部配置文件优先,默认配置回退",
  406. config = new {
  407. IP = config.IP,
  408. PORT = config.PORT,
  409. TIMEOUT = config.TIMEOUT,
  410. LOG_PATH = config.LOG_PATH,
  411. CARD_PASSTYPE = config.CARD_PASSTYPE,
  412. EC_URL = config.EC_URL,
  413. API_NAME = config.API_NAME,
  414. API_VERSION = config.API_VERSION,
  415. ACCESS_KEY = config.ACCESS_KEY,
  416. SECRETKEY = config.SECRETKEY,
  417. ORG_ID = config.ORG_ID,
  418. AREA_CODE = config.AREA_CODE,
  419. EXT = config.EXT
  420. }
  421. };
  422. this.request_params_text.Text = Newtonsoft.Json.JsonConvert.SerializeObject(requestParams, Newtonsoft.Json.Formatting.Indented);
  423. if (useAutoInitTest)
  424. {
  425. // 双击模式:测试autoInit智能功能
  426. var autoReadResult = JiangSuSocialCardBusiness.ReadSocialCard(false, true);
  427. this.result_text.Text = autoReadResult.ToString();
  428. this.response_params_text.Text = autoReadResult.ToString(Newtonsoft.Json.Formatting.Indented);
  429. SetStatusColor(autoReadResult);
  430. // 显示DLL原始错误信息
  431. if (autoReadResult["dllErrorMsg"] != null)
  432. {
  433. string dllError = autoReadResult["dllErrorMsg"].ToString();
  434. this.dll_error_text.Text = dllError;
  435. // 根据错误信息设置颜色
  436. if (string.IsNullOrEmpty(dllError))
  437. {
  438. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(220, 252, 231); // 浅绿色 - 成功
  439. this.dll_error_text.ForeColor = System.Drawing.Color.FromArgb(22, 101, 52);
  440. }
  441. else
  442. {
  443. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(255, 240, 240); // 浅红色 - 错误
  444. this.dll_error_text.ForeColor = System.Drawing.Color.DarkRed;
  445. }
  446. }
  447. // 更新原始数据显示
  448. UpdateDllRawDataInfo(autoReadResult);
  449. }
  450. else
  451. {
  452. // 单击模式:传统显式初始化 + 读卡
  453. var initResult = JiangSuSocialCardBusiness.Initialize(config);
  454. if ((bool)initResult["success"])
  455. {
  456. // 初始化成功,进行读卡
  457. var readResult = JiangSuSocialCardBusiness.ReadSocialCard(false, false); // 传统模式
  458. this.result_text.Text = readResult.ToString();
  459. this.response_params_text.Text = readResult.ToString(Newtonsoft.Json.Formatting.Indented);
  460. SetStatusColor(readResult);
  461. // 显示DLL原始错误信息
  462. if (readResult["dllErrorMsg"] != null)
  463. {
  464. string dllError = readResult["dllErrorMsg"].ToString();
  465. this.dll_error_text.Text = dllError;
  466. // 根据错误信息设置颜色
  467. if (string.IsNullOrEmpty(dllError))
  468. {
  469. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(220, 252, 231); // 浅绿色 - 成功
  470. this.dll_error_text.ForeColor = System.Drawing.Color.FromArgb(22, 101, 52);
  471. }
  472. else
  473. {
  474. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(255, 240, 240); // 浅红色 - 错误
  475. this.dll_error_text.ForeColor = System.Drawing.Color.DarkRed;
  476. }
  477. }
  478. // 更新原始数据显示
  479. UpdateDllRawDataInfo(readResult);
  480. }
  481. else
  482. {
  483. // 在线初始化失败,尝试新的智能模式和离线模式
  484. var autoInitResult = JiangSuSocialCardBusiness.ReadSocialCard(false, true); // 智能模式
  485. var offlineResult = JiangSuSocialCardBusiness.ReadSocialCardOffline(); // 离线模式
  486. // 创建合并结果显示三种尝试
  487. var combinedResult = new JObject();
  488. combinedResult["traditionalInitAttempt"] = initResult;
  489. combinedResult["smartModeAttempt"] = autoInitResult;
  490. combinedResult["offlineAttempt"] = offlineResult;
  491. combinedResult["recommendation"] = "在线初始化失败,已尝试智能模式和离线模式测试读卡功能";
  492. combinedResult["successfulMode"] = (bool)offlineResult["success"] ? "离线模式" :
  493. (bool)autoInitResult["success"] ? "智能模式" : "都失败";
  494. this.result_text.Text = combinedResult.ToString();
  495. this.response_params_text.Text = combinedResult.ToString(Newtonsoft.Json.Formatting.Indented);
  496. // 根据最好的结果设置状态
  497. if ((bool)offlineResult["success"])
  498. {
  499. SetStatusColor(offlineResult);
  500. UpdateDllRawDataInfo(offlineResult);
  501. }
  502. else if ((bool)autoInitResult["success"])
  503. {
  504. SetStatusColor(autoInitResult);
  505. UpdateDllRawDataInfo(autoInitResult);
  506. }
  507. else
  508. {
  509. SetStatusColor(initResult); // 显示初始化失败
  510. UpdateDllRawDataInfo(initResult);
  511. }
  512. // 显示综合的DLL错误信息
  513. var dllErrors = new System.Text.StringBuilder();
  514. if (initResult["dllErrorMsg"] != null)
  515. dllErrors.AppendLine($"传统模式: {initResult["dllErrorMsg"]}");
  516. if (autoInitResult["dllErrorMsg"] != null)
  517. dllErrors.AppendLine($"智能模式: {autoInitResult["dllErrorMsg"]}");
  518. if (offlineResult["dllErrorMsg"] != null)
  519. dllErrors.AppendLine($"离线模式: {offlineResult["dllErrorMsg"]}");
  520. this.dll_error_text.Text = dllErrors.ToString();
  521. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(255, 240, 240); // 浅红色
  522. this.dll_error_text.ForeColor = System.Drawing.Color.DarkRed;
  523. }
  524. }
  525. }
  526. catch (Exception ex)
  527. {
  528. var errorResult = new JObject();
  529. errorResult["success"] = false;
  530. errorResult["code"] = 1001;
  531. errorResult["message"] = "江苏社保卡测试异常: " + ex.Message;
  532. errorResult["device"] = "江苏医保HeaSecReadInfo.dll";
  533. this.result_text.Text = errorResult.ToString();
  534. this.response_params_text.Text = errorResult.ToString(Newtonsoft.Json.Formatting.Indented);
  535. // 显示异常的DLL错误信息
  536. this.dll_error_text.Text = $"系统异常: {ex.Message}";
  537. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(255, 245, 225); // 浅橙色
  538. this.dll_error_text.ForeColor = System.Drawing.Color.FromArgb(156, 39, 6); // 深橙色
  539. SetStatusColor(errorResult, true); // 标记为异常
  540. // 更新原始数据显示(异常时显示无数据)
  541. UpdateDllRawDataInfo(errorResult);
  542. }
  543. EnableAllButtons(true);
  544. this.jiangsu_sicard_test.Focus();
  545. }
  546. /// <summary>
  547. /// 测试江苏人社标准接口读社保卡
  548. /// </summary>
  549. private void TestJiangSuRenSheCard(object sender, EventArgs e)
  550. {
  551. EnableAllButtons(false);
  552. ClearParamsDisplay();
  553. try
  554. {
  555. // 显示江苏人社标准接口详细信息
  556. this.request_url_text.Text = GetJiangSuRenSheInterfaceInfo();
  557. // 显示请求参数
  558. var requestParams = new {
  559. action = "ReadSocialCardByStandard",
  560. device = "江苏人社标准社保卡读卡器",
  561. interfaceType = "江苏人社标准接口 v2.1.1",
  562. cardType = 3, // 自动寻卡接触式优先
  563. note = "使用相同的HeaSecReadInfo.dll初始化,但调用江苏人社标准接口规范"
  564. };
  565. this.request_params_text.Text = Newtonsoft.Json.JsonConvert.SerializeObject(requestParams, Newtonsoft.Json.Formatting.Indented);
  566. // 调用江苏人社标准接口(会自动初始化)
  567. var readResult = JiangSuSocialCardBusiness.ReadSocialCardByStandard(3);
  568. this.result_text.Text = readResult.ToString();
  569. this.response_params_text.Text = readResult.ToString(Newtonsoft.Json.Formatting.Indented);
  570. SetStatusColor(readResult);
  571. // 显示DLL原始错误信息
  572. if (readResult["dllErrorMsg"] != null)
  573. {
  574. string dllError = readResult["dllErrorMsg"].ToString();
  575. this.dll_error_text.Text = dllError;
  576. // 根据错误信息设置颜色
  577. if (string.IsNullOrEmpty(dllError))
  578. {
  579. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(220, 252, 231); // 浅绿色 - 成功
  580. this.dll_error_text.ForeColor = System.Drawing.Color.FromArgb(22, 101, 52);
  581. }
  582. else
  583. {
  584. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(255, 240, 240); // 浅红色 - 错误
  585. this.dll_error_text.ForeColor = System.Drawing.Color.DarkRed;
  586. }
  587. }
  588. // 更新原始数据显示
  589. UpdateDllRawDataInfo(readResult);
  590. }
  591. catch (Exception ex)
  592. {
  593. var errorResult = new JObject();
  594. errorResult["success"] = false;
  595. errorResult["code"] = 1001;
  596. errorResult["message"] = "江苏人社标准接口测试异常: " + ex.Message;
  597. errorResult["device"] = "江苏人社标准社保卡读卡器";
  598. errorResult["interface"] = "江苏人社标准接口 v2.1.1";
  599. this.result_text.Text = errorResult.ToString();
  600. this.response_params_text.Text = errorResult.ToString(Newtonsoft.Json.Formatting.Indented);
  601. // 显示异常的DLL错误信息
  602. this.dll_error_text.Text = $"系统异常: {ex.Message}";
  603. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(255, 245, 225); // 浅橙色
  604. this.dll_error_text.ForeColor = System.Drawing.Color.FromArgb(156, 39, 6); // 深橙色
  605. SetStatusColor(errorResult, true); // 标记为异常
  606. // 更新原始数据显示(异常时显示无数据)
  607. UpdateDllRawDataInfo(errorResult);
  608. }
  609. EnableAllButtons(true);
  610. this.jiangsu_renshe_test.Focus();
  611. }
  612. /// <summary>
  613. /// 获取江苏人社标准接口详细信息
  614. /// </summary>
  615. /// <returns>接口信息字符串</returns>
  616. private string GetJiangSuRenSheInterfaceInfo()
  617. {
  618. var info = new System.Text.StringBuilder();
  619. info.AppendLine("=== 江苏人社标准接口调用详情 ===");
  620. info.AppendLine();
  621. info.AppendLine("【✅ 实际调用流程】");
  622. info.AppendLine("1. 检查初始化: 如未初始化则自动调用HeaSecReadInfo.dll.Init()");
  623. info.AppendLine("2. 人社标准读卡: HeaSecReadInfo.dll.iReadCardBas(cardType, 1024字节缓冲区)");
  624. info.AppendLine("说明: 使用相同的初始化配置,但调用人社部标准接口规范!");
  625. info.AppendLine();
  626. info.AppendLine("【📋 接口规范差异】");
  627. info.AppendLine("江苏医保接口: ReadCardBas(cardInfo, busiInfo) - 双缓冲区");
  628. info.AppendLine("江苏人社接口: iReadCardBas(cardType, outInfo) - 单缓冲区");
  629. info.AppendLine("返回格式: 发卡地区|社保号|卡号|卡识别码|姓名|卡复位信息|...");
  630. info.AppendLine("数据分割: 使用|分割的标准12字段格式");
  631. info.AppendLine();
  632. info.AppendLine("【🔄 卡类型操作模式】");
  633. info.AppendLine("1 - 接触式操作卡");
  634. info.AppendLine("2 - 非接触式操作卡");
  635. info.AppendLine("3 - 自动寻卡(接触式优先)");
  636. info.AppendLine("4 - 自动寻卡(非接触式优先)");
  637. info.AppendLine("当前使用: 类型3(自动寻卡接触式优先)");
  638. info.AppendLine();
  639. info.AppendLine("【🔧 初始化配置】");
  640. info.AppendLine("✅ 相同DLL: HeaSecReadInfo.dll");
  641. info.AppendLine("✅ 相同初始化: 13个网络配置参数");
  642. info.AppendLine("✅ 相同设备: 江苏医保社保卡读卡器硬件");
  643. info.AppendLine("⚠️ 不同接口: 人社部标准vs医保自定义");
  644. info.AppendLine();
  645. info.AppendLine("【🌐 HTTP接口地址】");
  646. info.AppendLine("自动寻卡: http://localhost:8321/readcard/jiangsu/standard");
  647. info.AppendLine("接触式: http://localhost:8321/readcard/jiangsu/standard1");
  648. info.AppendLine("非接触式: http://localhost:8321/readcard/jiangsu/standard2");
  649. info.AppendLine("自动接触优先: http://localhost:8321/readcard/jiangsu/standard3");
  650. info.AppendLine("自动非接触优先: http://localhost:8321/readcard/jiangsu/standard4");
  651. return info.ToString();
  652. }
  653. /// <summary>
  654. /// 获取江苏医保接口详细信息
  655. /// </summary>
  656. /// <returns>接口信息字符串</returns>
  657. private string GetJiangSuInterfaceInfo()
  658. {
  659. var config = new JiangSuSocialCardBusiness.JiangSuConfig();
  660. var info = new System.Text.StringBuilder();
  661. info.AppendLine("=== 江苏医保接口调用详情 ===");
  662. info.AppendLine();
  663. info.AppendLine("【✅ 实际调用流程】");
  664. info.AppendLine("1. 初始化: HeaSecReadInfo.dll.Init(13个参数的JSON)");
  665. info.AppendLine("2. 读社保卡: HeaSecReadInfo.dll.ReadCardBas()");
  666. info.AppendLine("说明: 13个网络配置参数已传递给DLL进行初始化!");
  667. info.AppendLine();
  668. info.AppendLine("【📡 网络配置参数(已传给DLL)】");
  669. info.AppendLine($"配置来源: 外部配置文件优先,默认配置回退");
  670. info.AppendLine($"江苏医保服务器: {config.IP}:{config.PORT}");
  671. info.AppendLine($"超时设置: {config.TIMEOUT}秒");
  672. info.AppendLine($"电子凭证URL: {config.EC_URL}");
  673. info.AppendLine($"CSB接口: {config.API_NAME} v{config.API_VERSION}");
  674. info.AppendLine($"认证密钥: {config.ACCESS_KEY.Substring(0, 8)}***");
  675. info.AppendLine($"机构编号: {config.ORG_ID}(铭和医院)");
  676. info.AppendLine($"行政区划: {config.AREA_CODE}(江苏宿迁沭阳)");
  677. info.AppendLine($"密码验证: CARD_PASSTYPE={config.CARD_PASSTYPE}");
  678. info.AppendLine();
  679. info.AppendLine("【🔄 DLL内部处理机制】");
  680. info.AppendLine("DLL收到配置后会:");
  681. info.AppendLine("- 连接江苏医保服务器(10.61.165.3:8086)");
  682. info.AppendLine("- 验证CSB接口认证(ACCESS_KEY/SECRETKEY)");
  683. info.AppendLine("- 准备网络查询功能(电子凭证等)");
  684. info.AppendLine("- 配置本地读卡器硬件");
  685. info.AppendLine();
  686. info.AppendLine("【📊 当前状态】");
  687. info.AppendLine("✅ 网络参数已传递: 13个配置全部发送给DLL");
  688. info.AppendLine("✅ DLL初始化成功: 返回码0表示网络连接正常");
  689. info.AppendLine("⚠️ 等待插卡: 错误码-11表示未检测到社保卡");
  690. info.AppendLine();
  691. info.AppendLine("【🛠️ 故障排查】");
  692. info.AppendLine("如果插卡后仍报错-11,可能原因:");
  693. info.AppendLine("1. 读卡器硬件未识别或驱动问题");
  694. info.AppendLine("2. 社保卡芯片损坏或接触不良");
  695. info.AppendLine("3. CARD_PASSTYPE参数不匹配医院环境");
  696. info.AppendLine("4. 需要PIN码但当前设置跳过了验证");
  697. info.AppendLine();
  698. info.AppendLine("【🌐 HTTP接口地址】");
  699. info.AppendLine("读卡: http://localhost:8321/readcard/jiangsu/readcard");
  700. info.AppendLine("初始化: http://localhost:8321/readcard/jiangsu/init");
  701. info.AppendLine("验证PIN: http://localhost:8321/readcard/jiangsu/verifypin");
  702. info.AppendLine("设备状态: http://localhost:8321/readcard/jiangsu/status");
  703. return info.ToString();
  704. }
  705. /// <summary>
  706. /// 测试江苏医保读卡器硬件状态
  707. /// </summary>
  708. private void TestJiangSuDeviceStatus(object sender, EventArgs e)
  709. {
  710. EnableAllButtons(false);
  711. ClearParamsDisplay();
  712. try
  713. {
  714. this.request_url_text.Text = "=== 江苏医保网络配置影响测试 ===\n\n测试不同网络配置对错误码的影响,验证 -11 到 -1 的变化原因...";
  715. // 显示检测参数
  716. var testParams = new {
  717. action = "NetworkConfigurationTest",
  718. device = "江苏医保HeaSecReadInfo.dll",
  719. tests = new string[] { "原始配置", "HSM配置", "无效配置", "空配置" },
  720. purpose = "验证网络配置变化是否真的影响错误码",
  721. configSource = "外部配置文件优先,默认配置回退"
  722. };
  723. this.request_params_text.Text = Newtonsoft.Json.JsonConvert.SerializeObject(testParams, Newtonsoft.Json.Formatting.Indented);
  724. // 运行网络配置测试
  725. var networkTestResult = JiangSuSocialCardBusiness.TestNetworkConfigurations();
  726. var results = new JObject();
  727. results["networkConfigTest"] = networkTestResult;
  728. // 测试CARD_PASSTYPE=1的读卡
  729. try
  730. {
  731. var config1 = new JiangSuSocialCardBusiness.JiangSuConfig();
  732. config1.CARD_PASSTYPE = "1";
  733. var init1 = JiangSuSocialCardBusiness.Initialize(config1);
  734. var read1 = JiangSuSocialCardBusiness.ReadSocialCard(false);
  735. results["testPassType1"] = new JObject
  736. {
  737. ["passType"] = "1(验证卡PIN)",
  738. ["initResult"] = init1,
  739. ["readResult"] = read1
  740. };
  741. }
  742. catch (Exception ex1)
  743. {
  744. results["testPassType1"] = new JObject
  745. {
  746. ["passType"] = "1(验证卡PIN)",
  747. ["error"] = ex1.Message
  748. };
  749. }
  750. // 测试CARD_PASSTYPE=2的读卡
  751. try
  752. {
  753. var config2 = new JiangSuSocialCardBusiness.JiangSuConfig();
  754. config2.CARD_PASSTYPE = "2";
  755. var init2 = JiangSuSocialCardBusiness.Initialize(config2);
  756. var read2 = JiangSuSocialCardBusiness.ReadSocialCard(false);
  757. results["testPassType2"] = new JObject
  758. {
  759. ["passType"] = "2(验证数据库密码)",
  760. ["initResult"] = init2,
  761. ["readResult"] = read2
  762. };
  763. }
  764. catch (Exception ex2)
  765. {
  766. results["testPassType2"] = new JObject
  767. {
  768. ["passType"] = "2(验证数据库密码)",
  769. ["error"] = ex2.Message
  770. };
  771. }
  772. this.result_text.Text = results.ToString();
  773. this.response_params_text.Text = results.ToString(Newtonsoft.Json.Formatting.Indented);
  774. // 根据结果设置颜色
  775. bool hasSuccess = false;
  776. if (results["testPassType1"] != null && results["testPassType1"]["readResult"] != null)
  777. {
  778. var readResult1 = (JObject)results["testPassType1"]["readResult"];
  779. if (readResult1["success"] != null && (bool)readResult1["success"])
  780. hasSuccess = true;
  781. }
  782. if (results["testPassType2"] != null && results["testPassType2"]["readResult"] != null)
  783. {
  784. var readResult2 = (JObject)results["testPassType2"]["readResult"];
  785. if (readResult2["success"] != null && (bool)readResult2["success"])
  786. hasSuccess = true;
  787. }
  788. if (hasSuccess)
  789. {
  790. SetStatusColor(new JObject { ["success"] = true });
  791. }
  792. else
  793. {
  794. SetStatusColor(new JObject { ["success"] = false }, true);
  795. }
  796. }
  797. catch (Exception ex)
  798. {
  799. var errorResult = new JObject();
  800. errorResult["success"] = false;
  801. errorResult["code"] = 9001;
  802. errorResult["message"] = "硬件检测异常: " + ex.Message;
  803. errorResult["device"] = "江苏医保HeaSecReadInfo.dll";
  804. this.result_text.Text = errorResult.ToString();
  805. this.response_params_text.Text = errorResult.ToString(Newtonsoft.Json.Formatting.Indented);
  806. SetStatusColor(errorResult, true);
  807. }
  808. EnableAllButtons(true);
  809. }
  810. private void ClearParamsDisplay()
  811. {
  812. this.request_url_text.Text = "";
  813. this.request_params_text.Text = "";
  814. this.response_params_text.Text = "";
  815. this.dll_error_text.Text = "";
  816. // 清理原始数据显示区域
  817. if (this.dll_raw_data_text != null)
  818. {
  819. this.dll_raw_data_text.Text = "";
  820. }
  821. // 重置为默认颜色
  822. this.response_params_text.BackColor = System.Drawing.SystemColors.Window;
  823. this.response_params_text.ForeColor = System.Drawing.SystemColors.WindowText;
  824. this.result_text.BackColor = System.Drawing.SystemColors.Window;
  825. this.result_text.ForeColor = System.Drawing.SystemColors.WindowText;
  826. // 重置DLL错误信息显示区域
  827. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(255, 240, 240);
  828. this.dll_error_text.ForeColor = System.Drawing.Color.DarkRed;
  829. }
  830. /// <summary>
  831. /// 根据结果设置状态颜色
  832. /// </summary>
  833. /// <param name="result">结果对象</param>
  834. /// <param name="isException">是否为异常情况</param>
  835. private void SetStatusColor(JObject result, bool isException = false)
  836. {
  837. try
  838. {
  839. if (isException)
  840. {
  841. // 异常状态 - 橙色背景
  842. this.response_params_text.BackColor = System.Drawing.Color.FromArgb(255, 245, 225); // 浅橙色
  843. this.response_params_text.ForeColor = System.Drawing.Color.FromArgb(156, 39, 6); // 深橙色
  844. this.result_text.BackColor = System.Drawing.Color.FromArgb(255, 245, 225);
  845. this.result_text.ForeColor = System.Drawing.Color.FromArgb(156, 39, 6);
  846. return;
  847. }
  848. // 检查不同的成功标识字段
  849. bool isSuccess = false;
  850. int code = 0;
  851. // 尝试获取 success 字段(江苏医保格式)
  852. if (result["success"] != null)
  853. {
  854. isSuccess = (bool)result["success"];
  855. }
  856. // 尝试获取 code 字段
  857. if (result["code"] != null)
  858. {
  859. code = (int)result["code"];
  860. // 如果没有success字段,根据code判断(200表示成功)
  861. if (result["success"] == null)
  862. {
  863. isSuccess = (code == 200);
  864. }
  865. }
  866. if (isSuccess || code == 200)
  867. {
  868. // 成功状态 - 绿色背景
  869. this.response_params_text.BackColor = System.Drawing.Color.FromArgb(220, 252, 231); // 浅绿色
  870. this.response_params_text.ForeColor = System.Drawing.Color.FromArgb(22, 101, 52); // 深绿色
  871. this.result_text.BackColor = System.Drawing.Color.FromArgb(220, 252, 231);
  872. this.result_text.ForeColor = System.Drawing.Color.FromArgb(22, 101, 52);
  873. }
  874. else
  875. {
  876. // 失败状态 - 红色背景
  877. this.response_params_text.BackColor = System.Drawing.Color.FromArgb(254, 226, 226); // 浅红色
  878. this.response_params_text.ForeColor = System.Drawing.Color.FromArgb(153, 27, 27); // 深红色
  879. this.result_text.BackColor = System.Drawing.Color.FromArgb(254, 226, 226);
  880. this.result_text.ForeColor = System.Drawing.Color.FromArgb(153, 27, 27);
  881. }
  882. }
  883. catch (Exception ex)
  884. {
  885. // 解析状态失败,设置为默认颜色
  886. this.response_params_text.BackColor = System.Drawing.SystemColors.Window;
  887. this.response_params_text.ForeColor = System.Drawing.SystemColors.WindowText;
  888. this.result_text.BackColor = System.Drawing.SystemColors.Window;
  889. this.result_text.ForeColor = System.Drawing.SystemColors.WindowText;
  890. System.Diagnostics.Debug.WriteLine($"设置状态颜色失败: {ex.Message}");
  891. }
  892. }
  893. /// <summary>
  894. /// 测试江苏医保刷脸授权获取医保身份功能
  895. /// 使用NationECCode.dll与泰和完全一致
  896. /// </summary>
  897. private void TestJiangSuFace(object sender, EventArgs e)
  898. {
  899. EnableAllButtons(false);
  900. ClearParamsDisplay();
  901. try
  902. {
  903. // 显示江苏医保刷脸详细信息
  904. this.request_url_text.Text = GetJiangSuFaceInterfaceInfo();
  905. // 显示请求参数
  906. var requestParams = new {
  907. action = "JiangSuFaceAuth",
  908. device = "江苏医保刷脸认证器(NationECCode.dll)",
  909. implementation = "与泰和完全一致(相同DLL、相同URL、相同逻辑)",
  910. businessType = "01101",
  911. transType1 = "cn.nhsa.ec.auth(获取authNo)",
  912. transType2 = "cn.nhsa.auth.check(根据authNo获取医保身份)",
  913. orgId = "H32132200561(写死参数)",
  914. serviceUrl = "http://10.58.33.207:10086/localcfc/api/hsecfc/localQrCodeQuery(写死参数)",
  915. note = "完全使用写死的配置参数,与泰和实现方式一致"
  916. };
  917. this.request_params_text.Text = Newtonsoft.Json.JsonConvert.SerializeObject(requestParams, Newtonsoft.Json.Formatting.Indented);
  918. // 调用江苏医保刷脸功能(使用NationECCode.dll与泰和完全一致)
  919. var faceResult = JiangSuSocialCardBusiness.ReadFace("01101");
  920. this.result_text.Text = faceResult.ToString();
  921. this.response_params_text.Text = faceResult.ToString(Newtonsoft.Json.Formatting.Indented);
  922. SetStatusColor(faceResult);
  923. // 显示DLL错误信息(如果有)
  924. if (faceResult["message"] != null)
  925. {
  926. string message = faceResult["message"].ToString();
  927. bool isSuccess = faceResult["code"] != null && (int)faceResult["code"] == 200;
  928. this.dll_error_text.Text = message;
  929. if (isSuccess)
  930. {
  931. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(220, 252, 231); // 浅绿色 - 成功
  932. this.dll_error_text.ForeColor = System.Drawing.Color.FromArgb(22, 101, 52);
  933. }
  934. else
  935. {
  936. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(255, 240, 240); // 浅红色 - 错误
  937. this.dll_error_text.ForeColor = System.Drawing.Color.DarkRed;
  938. }
  939. }
  940. // 更新原始数据显示
  941. UpdateDllRawDataInfo(faceResult);
  942. }
  943. catch (Exception ex)
  944. {
  945. var errorResult = new JObject();
  946. errorResult["success"] = false;
  947. errorResult["code"] = 4001;
  948. errorResult["message"] = "江苏医保刷脸测试异常: " + ex.Message;
  949. errorResult["device"] = "江苏医保刷脸认证器(NationECCode.dll)";
  950. errorResult["implementation"] = "与泰和完全一致";
  951. this.result_text.Text = errorResult.ToString();
  952. this.response_params_text.Text = errorResult.ToString(Newtonsoft.Json.Formatting.Indented);
  953. this.dll_error_text.Text = "系统异常: " + ex.Message;
  954. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(255, 245, 225); // 浅橙色
  955. this.dll_error_text.ForeColor = System.Drawing.Color.FromArgb(156, 39, 6); // 深橙色
  956. SetStatusColor(errorResult, true);
  957. UpdateDllRawDataInfo(errorResult);
  958. }
  959. EnableAllButtons(true);
  960. this.jiangsu_face_test.Focus();
  961. }
  962. /// <summary>
  963. /// 获取江苏医保刷脸接口详细信息
  964. /// </summary>
  965. /// <returns>接口信息字符串</returns>
  966. private string GetJiangSuFaceInterfaceInfo()
  967. {
  968. var info = new System.Text.StringBuilder();
  969. info.AppendLine("=== 江苏医保刷脸授权获取医保身份接口调用详情 ===");
  970. info.AppendLine();
  971. info.AppendLine("【✅ 实现方式】");
  972. info.AppendLine("DLL文件: NationECCode.dll(与泰和完全相同)");
  973. info.AppendLine("服务地址: http://10.58.33.207:10086/localcfc/api/hsecfc/localQrCodeQuery(写死参数)");
  974. info.AppendLine("机构编号: H32132200561(写死参数)");
  975. info.AppendLine("实现逻辑: 与泰和的ReadFace方法完全一致");
  976. info.AppendLine();
  977. info.AppendLine("【🔄 两步式认证流程】");
  978. info.AppendLine("第一步: 调用cn.nhsa.ec.auth获取authNo");
  979. info.AppendLine("第二步: 调用cn.nhsa.auth.check根据authNo获取医保身份信息");
  980. info.AppendLine("符合规范: 国家医保电子凭证业务标准动态库交互规范2021-11-12");
  981. info.AppendLine();
  982. info.AppendLine("【📋 支持的业务类型】");
  983. info.AppendLine("01101 - 门诊挂号(当前测试)");
  984. info.AppendLine("01301 - 门诊结算");
  985. info.AppendLine("02121 - 药店购药");
  986. info.AppendLine("01102 - 住院建档");
  987. info.AppendLine("01103 - 入院登记");
  988. info.AppendLine();
  989. info.AppendLine("【🌐 HTTP接口地址】");
  990. info.AppendLine("江苏医保刷脸: http://localhost:8321/readcard/entry?param=jiangsu_face_01101");
  991. info.AppendLine("门诊挂号: http://localhost:8321/readcard/entry?param=jiangsu_face_01101");
  992. info.AppendLine("门诊结算: http://localhost:8321/readcard/entry?param=jiangsu_face_01301");
  993. info.AppendLine("药店购药: http://localhost:8321/readcard/entry?param=jiangsu_face_02121");
  994. info.AppendLine("通用格式: jiangsu_face_${biztype}");
  995. return info.ToString();
  996. }
  997. /// <summary>
  998. /// 测试江苏医保电子凭证解码功能
  999. /// </summary>
  1000. private void TestJiangSuEcDecode(object sender, EventArgs e)
  1001. {
  1002. EnableAllButtons(false);
  1003. ClearParamsDisplay();
  1004. try
  1005. {
  1006. // 显示江苏医保电子凭证解码详细信息
  1007. this.request_url_text.Text = GetJiangSuEcDecodeInterfaceInfo();
  1008. // 显示实际DLL调用参数
  1009. var config = new JiangSuSocialCardBusiness.JiangSuConfig();
  1010. var requestParams = new {
  1011. data = new {
  1012. orgId = config.ORG_ID,
  1013. businessType = "01101",
  1014. operatorId = "system001",
  1015. operatorName = "系统管理员",
  1016. officeId = "32760",
  1017. officeName = "医保科"
  1018. },
  1019. transType = "ec.query",
  1020. orgId = config.ORG_ID,
  1021. note = "实际DLL调用参数格式 - 符合江苏医保接口规范v0.9.9.15",
  1022. interfaceVersion = "1.14.6 电子凭证解码",
  1023. function = "HeaSecReadInfo.dll.EcQuery",
  1024. configSource = "外部配置文件优先,默认配置回退"
  1025. };
  1026. this.request_params_text.Text = Newtonsoft.Json.JsonConvert.SerializeObject(requestParams, Newtonsoft.Json.Formatting.Indented);
  1027. // 调用江苏医保电子凭证解码接口
  1028. var decodeResult = JiangSuSocialCardBusiness.ReadElectronicCertificate("01101");
  1029. this.result_text.Text = decodeResult.ToString();
  1030. this.response_params_text.Text = decodeResult.ToString(Newtonsoft.Json.Formatting.Indented);
  1031. SetStatusColor(decodeResult);
  1032. // 显示DLL原始错误信息
  1033. if (decodeResult["dllErrorMsg"] != null)
  1034. {
  1035. string dllError = decodeResult["dllErrorMsg"].ToString();
  1036. this.dll_error_text.Text = dllError;
  1037. if (string.IsNullOrEmpty(dllError))
  1038. {
  1039. this.dll_error_text.BackColor = Color.LightGreen;
  1040. this.dll_error_text.ForeColor = Color.DarkGreen;
  1041. }
  1042. else
  1043. {
  1044. this.dll_error_text.BackColor = Color.LightPink;
  1045. this.dll_error_text.ForeColor = Color.DarkRed;
  1046. }
  1047. }
  1048. // 更新原始数据显示
  1049. UpdateDllRawDataInfo(decodeResult);
  1050. }
  1051. catch (Exception ex)
  1052. {
  1053. var errorResult = new JObject();
  1054. errorResult["success"] = false;
  1055. errorResult["code"] = 3001;
  1056. errorResult["message"] = "江苏医保电子凭证解码测试异常: " + ex.Message;
  1057. errorResult["device"] = "江苏医保HeaSecReadInfo.dll";
  1058. errorResult["interfaceVersion"] = "江苏医保电子凭证解码接口 v0.9.9.15";
  1059. this.result_text.Text = errorResult.ToString();
  1060. this.response_params_text.Text = errorResult.ToString(Newtonsoft.Json.Formatting.Indented);
  1061. this.dll_error_text.Text = "系统异常: " + ex.Message;
  1062. this.dll_error_text.BackColor = Color.LightYellow;
  1063. this.dll_error_text.ForeColor = Color.DarkRed;
  1064. SetStatusColor(errorResult, true);
  1065. UpdateDllRawDataInfo(errorResult);
  1066. }
  1067. EnableAllButtons(true);
  1068. this.jiangsu_ec_decode_test.Focus();
  1069. }
  1070. /// <summary>
  1071. /// 获取江苏医保电子凭证解码接口详细信息
  1072. /// </summary>
  1073. /// <returns>接口信息字符串</returns>
  1074. private string GetJiangSuEcDecodeInterfaceInfo()
  1075. {
  1076. var info = new System.Text.StringBuilder();
  1077. info.AppendLine("=== 江苏医保电子凭证解码接口调用详情 ===");
  1078. info.AppendLine();
  1079. info.AppendLine("【✅ 实际调用流程】");
  1080. info.AppendLine("1. 自动初始化: 检查并初始化HeaSecReadInfo.dll");
  1081. info.AppendLine("2. 电子凭证解码: HeaSecReadInfo.dll.EcQuery(业务参数JSON)");
  1082. info.AppendLine("说明: 符合江苏医保接口规范v0.9.9.15第1.14.6节要求!");
  1083. info.AppendLine();
  1084. info.AppendLine("【📋 接口规范详情】");
  1085. info.AppendLine("接口名称: 1.14.6 电子凭证解码");
  1086. info.AppendLine("调用函数: EcQuery");
  1087. info.AppendLine("输入格式: JSON字符串(业务类型+配置参数)");
  1088. info.AppendLine("输出格式: JSON字符串(解码结果+状态信息)");
  1089. info.AppendLine("缓冲区大小: 8192字节");
  1090. info.AppendLine();
  1091. info.AppendLine("【🔄 支持的业务类型】");
  1092. info.AppendLine("门诊业务:");
  1093. info.AppendLine(" 01101 - 挂号");
  1094. info.AppendLine(" 01201 - 问诊");
  1095. info.AppendLine(" 01202 - 预约检查");
  1096. info.AppendLine(" 01203 - 检查");
  1097. info.AppendLine(" 01204 - 治疗");
  1098. info.AppendLine(" 01301 - 结算");
  1099. info.AppendLine(" 01302 - 取药");
  1100. info.AppendLine("住院业务:");
  1101. info.AppendLine(" 01102 - 建档");
  1102. info.AppendLine(" 01103 - 入院登记");
  1103. info.AppendLine(" 01104 - 缴纳预缴金");
  1104. info.AppendLine("药店业务:");
  1105. info.AppendLine(" 02121 - 购药");
  1106. info.AppendLine(" 02122 - 下载外购处方");
  1107. info.AppendLine("当前测试: 01101(门诊挂号)");
  1108. info.AppendLine();
  1109. info.AppendLine("【🔧 初始化配置】");
  1110. info.AppendLine("✅ 江苏医保服务器: 10.61.165.3:8086");
  1111. info.AppendLine("✅ CSB接口认证: ACCESS_KEY/SECRET_KEY");
  1112. info.AppendLine("✅ 机构编号: H32132100055(铭和医院)");
  1113. info.AppendLine("✅ 行政区划: 321322(江苏宿迁沭阳)");
  1114. info.AppendLine("✅ API接口: hsEcQuery v1.0.0");
  1115. info.AppendLine();
  1116. info.AppendLine("【🌐 HTTP接口地址】");
  1117. info.AppendLine("门诊挂号: http://localhost:8321/api/entry?param=jiangsu_qrcode_01101");
  1118. info.AppendLine("门诊问诊: http://localhost:8321/api/entry?param=jiangsu_qrcode_01201");
  1119. info.AppendLine("门诊结算: http://localhost:8321/api/entry?param=jiangsu_qrcode_01301");
  1120. info.AppendLine("住院登记: http://localhost:8321/api/entry?param=jiangsu_qrcode_01103");
  1121. info.AppendLine("药店购药: http://localhost:8321/api/entry?param=jiangsu_qrcode_02121");
  1122. info.AppendLine("通用格式: jiangsu_qrcode_[业务类型] 或 jiangsu_ec_[业务类型]");
  1123. return info.ToString();
  1124. }
  1125. private void EnableAllButtons(Boolean value)
  1126. {
  1127. // 只启用/禁用可见的按钮
  1128. this.huashi_idcard_test.Enabled = value;
  1129. this.jiangsu_sicard_test.Enabled = value;
  1130. this.jiangsu_face_test.Enabled = value;
  1131. this.jiangsu_ec_decode_test.Enabled = value;
  1132. // 以下按钮被隐藏,但保留代码以防将来需要
  1133. if (this.sicard_test.Visible) this.sicard_test.Enabled = value;
  1134. if (this.idcard_test.Visible) this.idcard_test.Enabled = value;
  1135. if (this.qrcode_test.Visible) this.qrcode_test.Enabled = value;
  1136. if (this.face_test.Visible) this.face_test.Enabled = value;
  1137. if (this.id_card_test2.Visible) this.id_card_test2.Enabled = value;
  1138. if (this.qr_code_test2.Visible) this.qr_code_test2.Enabled = value;
  1139. }
  1140. protected override void WndProc(ref Message m)
  1141. {
  1142. const int WM_SYSCOMMAND = 0x0112;
  1143. const int SC_CLOSE = 0xF060;
  1144. if (m.Msg == WM_SYSCOMMAND && (int)m.WParam == SC_CLOSE)
  1145. {
  1146. // User clicked close button
  1147. this.WindowState = FormWindowState.Minimized;
  1148. return;
  1149. }
  1150. base.WndProc(ref m);
  1151. }
  1152. protected override void OnResize(EventArgs e)
  1153. {
  1154. if (WindowState == FormWindowState.Minimized)
  1155. {
  1156. this.Hide();
  1157. }
  1158. }
  1159. /// <summary>
  1160. /// 更新DLL原始数据显示
  1161. /// </summary>
  1162. private void UpdateDllRawDataInfo(dynamic result)
  1163. {
  1164. try
  1165. {
  1166. this.Invoke((Action)(() =>
  1167. {
  1168. if (dll_raw_data_text != null)
  1169. {
  1170. string rawDataInfo = "";
  1171. Color textColor = Color.DarkBlue; // 默认深蓝色
  1172. if (result != null)
  1173. {
  1174. // 检查是否有原始读卡数据
  1175. if (result.rawCardData != null || result.rawBusiData != null)
  1176. {
  1177. var rawDataBuilder = new System.Text.StringBuilder();
  1178. rawDataBuilder.AppendLine("=== 读卡原始数据 ===");
  1179. rawDataBuilder.AppendLine($"时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
  1180. rawDataBuilder.AppendLine();
  1181. if (result.rawCardData != null)
  1182. {
  1183. string cardData = result.rawCardData.ToString();
  1184. rawDataBuilder.AppendLine("【基本信息数据】");
  1185. if (!string.IsNullOrEmpty(cardData))
  1186. {
  1187. rawDataBuilder.AppendLine(cardData);
  1188. textColor = Color.Green; // 有数据:绿色
  1189. }
  1190. else
  1191. {
  1192. rawDataBuilder.AppendLine("(空数据)");
  1193. textColor = Color.Orange; // 空数据:橙色
  1194. }
  1195. rawDataBuilder.AppendLine();
  1196. }
  1197. if (result.rawBusiData != null)
  1198. {
  1199. string busiData = result.rawBusiData.ToString();
  1200. rawDataBuilder.AppendLine("【业务信息数据】");
  1201. if (!string.IsNullOrEmpty(busiData))
  1202. {
  1203. rawDataBuilder.AppendLine(busiData);
  1204. if (textColor != Color.Green) // 如果基本信息没有数据,但业务信息有数据
  1205. {
  1206. textColor = Color.Green;
  1207. }
  1208. }
  1209. else
  1210. {
  1211. rawDataBuilder.AppendLine("(空数据)");
  1212. if (textColor == Color.DarkBlue) // 如果都没有数据
  1213. {
  1214. textColor = Color.Orange;
  1215. }
  1216. }
  1217. }
  1218. rawDataInfo = rawDataBuilder.ToString();
  1219. }
  1220. else
  1221. {
  1222. // 没有读卡数据的情况
  1223. bool isSuccess = result.success != null && (bool)result.success;
  1224. if (!isSuccess)
  1225. {
  1226. rawDataInfo = $"读卡失败 - {DateTime.Now:yyyy-MM-dd HH:mm:ss}\n无原始数据返回";
  1227. textColor = Color.Red; // 失败:红色
  1228. }
  1229. else
  1230. {
  1231. rawDataInfo = $"操作成功 - {DateTime.Now:yyyy-MM-dd HH:mm:ss}\n此操作无读卡数据";
  1232. textColor = Color.Gray; // 无相关数据:灰色
  1233. }
  1234. }
  1235. }
  1236. dll_raw_data_text.Text = rawDataInfo;
  1237. dll_raw_data_text.ForeColor = textColor;
  1238. }
  1239. }));
  1240. }
  1241. catch (Exception ex)
  1242. {
  1243. // 静默处理,避免影响主要功能
  1244. Console.WriteLine($"更新DLL原始数据失败: {ex.Message}");
  1245. }
  1246. }
  1247. }
  1248. }