MainForm.cs 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440
  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. config = new {
  406. IP = config.IP,
  407. PORT = config.PORT,
  408. TIMEOUT = config.TIMEOUT,
  409. LOG_PATH = config.LOG_PATH,
  410. CARD_PASSTYPE = config.CARD_PASSTYPE,
  411. EC_URL = config.EC_URL,
  412. API_NAME = config.API_NAME,
  413. API_VERSION = config.API_VERSION,
  414. ACCESS_KEY = config.ACCESS_KEY,
  415. SECRETKEY = config.SECRETKEY,
  416. ORG_ID = config.ORG_ID,
  417. AREA_CODE = config.AREA_CODE,
  418. EXT = config.EXT
  419. }
  420. };
  421. this.request_params_text.Text = Newtonsoft.Json.JsonConvert.SerializeObject(requestParams, Newtonsoft.Json.Formatting.Indented);
  422. if (useAutoInitTest)
  423. {
  424. // 双击模式:测试autoInit智能功能
  425. var autoReadResult = JiangSuSocialCardBusiness.ReadSocialCard(false, true);
  426. this.result_text.Text = autoReadResult.ToString();
  427. this.response_params_text.Text = autoReadResult.ToString(Newtonsoft.Json.Formatting.Indented);
  428. SetStatusColor(autoReadResult);
  429. // 显示DLL原始错误信息
  430. if (autoReadResult["dllErrorMsg"] != null)
  431. {
  432. string dllError = autoReadResult["dllErrorMsg"].ToString();
  433. this.dll_error_text.Text = dllError;
  434. // 根据错误信息设置颜色
  435. if (string.IsNullOrEmpty(dllError))
  436. {
  437. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(220, 252, 231); // 浅绿色 - 成功
  438. this.dll_error_text.ForeColor = System.Drawing.Color.FromArgb(22, 101, 52);
  439. }
  440. else
  441. {
  442. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(255, 240, 240); // 浅红色 - 错误
  443. this.dll_error_text.ForeColor = System.Drawing.Color.DarkRed;
  444. }
  445. }
  446. // 更新原始数据显示
  447. UpdateDllRawDataInfo(autoReadResult);
  448. }
  449. else
  450. {
  451. // 单击模式:传统显式初始化 + 读卡
  452. var initResult = JiangSuSocialCardBusiness.Initialize(config);
  453. if ((bool)initResult["success"])
  454. {
  455. // 初始化成功,进行读卡
  456. var readResult = JiangSuSocialCardBusiness.ReadSocialCard(false, false); // 传统模式
  457. this.result_text.Text = readResult.ToString();
  458. this.response_params_text.Text = readResult.ToString(Newtonsoft.Json.Formatting.Indented);
  459. SetStatusColor(readResult);
  460. // 显示DLL原始错误信息
  461. if (readResult["dllErrorMsg"] != null)
  462. {
  463. string dllError = readResult["dllErrorMsg"].ToString();
  464. this.dll_error_text.Text = dllError;
  465. // 根据错误信息设置颜色
  466. if (string.IsNullOrEmpty(dllError))
  467. {
  468. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(220, 252, 231); // 浅绿色 - 成功
  469. this.dll_error_text.ForeColor = System.Drawing.Color.FromArgb(22, 101, 52);
  470. }
  471. else
  472. {
  473. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(255, 240, 240); // 浅红色 - 错误
  474. this.dll_error_text.ForeColor = System.Drawing.Color.DarkRed;
  475. }
  476. }
  477. // 更新原始数据显示
  478. UpdateDllRawDataInfo(readResult);
  479. }
  480. else
  481. {
  482. // 在线初始化失败,尝试新的智能模式和离线模式
  483. var autoInitResult = JiangSuSocialCardBusiness.ReadSocialCard(false, true); // 智能模式
  484. var offlineResult = JiangSuSocialCardBusiness.ReadSocialCardOffline(); // 离线模式
  485. // 创建合并结果显示三种尝试
  486. var combinedResult = new JObject();
  487. combinedResult["traditionalInitAttempt"] = initResult;
  488. combinedResult["smartModeAttempt"] = autoInitResult;
  489. combinedResult["offlineAttempt"] = offlineResult;
  490. combinedResult["recommendation"] = "在线初始化失败,已尝试智能模式和离线模式测试读卡功能";
  491. combinedResult["successfulMode"] = (bool)offlineResult["success"] ? "离线模式" :
  492. (bool)autoInitResult["success"] ? "智能模式" : "都失败";
  493. this.result_text.Text = combinedResult.ToString();
  494. this.response_params_text.Text = combinedResult.ToString(Newtonsoft.Json.Formatting.Indented);
  495. // 根据最好的结果设置状态
  496. if ((bool)offlineResult["success"])
  497. {
  498. SetStatusColor(offlineResult);
  499. UpdateDllRawDataInfo(offlineResult);
  500. }
  501. else if ((bool)autoInitResult["success"])
  502. {
  503. SetStatusColor(autoInitResult);
  504. UpdateDllRawDataInfo(autoInitResult);
  505. }
  506. else
  507. {
  508. SetStatusColor(initResult); // 显示初始化失败
  509. UpdateDllRawDataInfo(initResult);
  510. }
  511. // 显示综合的DLL错误信息
  512. var dllErrors = new System.Text.StringBuilder();
  513. if (initResult["dllErrorMsg"] != null)
  514. dllErrors.AppendLine($"传统模式: {initResult["dllErrorMsg"]}");
  515. if (autoInitResult["dllErrorMsg"] != null)
  516. dllErrors.AppendLine($"智能模式: {autoInitResult["dllErrorMsg"]}");
  517. if (offlineResult["dllErrorMsg"] != null)
  518. dllErrors.AppendLine($"离线模式: {offlineResult["dllErrorMsg"]}");
  519. this.dll_error_text.Text = dllErrors.ToString();
  520. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(255, 240, 240); // 浅红色
  521. this.dll_error_text.ForeColor = System.Drawing.Color.DarkRed;
  522. }
  523. }
  524. }
  525. catch (Exception ex)
  526. {
  527. var errorResult = new JObject();
  528. errorResult["success"] = false;
  529. errorResult["code"] = 1001;
  530. errorResult["message"] = "江苏社保卡测试异常: " + ex.Message;
  531. errorResult["device"] = "江苏医保HeaSecReadInfo.dll";
  532. this.result_text.Text = errorResult.ToString();
  533. this.response_params_text.Text = errorResult.ToString(Newtonsoft.Json.Formatting.Indented);
  534. // 显示异常的DLL错误信息
  535. this.dll_error_text.Text = $"系统异常: {ex.Message}";
  536. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(255, 245, 225); // 浅橙色
  537. this.dll_error_text.ForeColor = System.Drawing.Color.FromArgb(156, 39, 6); // 深橙色
  538. SetStatusColor(errorResult, true); // 标记为异常
  539. // 更新原始数据显示(异常时显示无数据)
  540. UpdateDllRawDataInfo(errorResult);
  541. }
  542. EnableAllButtons(true);
  543. this.jiangsu_sicard_test.Focus();
  544. }
  545. /// <summary>
  546. /// 测试江苏人社标准接口读社保卡
  547. /// </summary>
  548. private void TestJiangSuRenSheCard(object sender, EventArgs e)
  549. {
  550. EnableAllButtons(false);
  551. ClearParamsDisplay();
  552. try
  553. {
  554. // 显示江苏人社标准接口详细信息
  555. this.request_url_text.Text = GetJiangSuRenSheInterfaceInfo();
  556. // 显示请求参数
  557. var requestParams = new {
  558. action = "ReadSocialCardByStandard",
  559. device = "江苏人社标准社保卡读卡器",
  560. interfaceType = "江苏人社标准接口 v2.1.1",
  561. cardType = 3, // 自动寻卡接触式优先
  562. note = "使用相同的HeaSecReadInfo.dll初始化,但调用江苏人社标准接口规范"
  563. };
  564. this.request_params_text.Text = Newtonsoft.Json.JsonConvert.SerializeObject(requestParams, Newtonsoft.Json.Formatting.Indented);
  565. // 调用江苏人社标准接口(会自动初始化)
  566. var readResult = JiangSuSocialCardBusiness.ReadSocialCardByStandard(3);
  567. this.result_text.Text = readResult.ToString();
  568. this.response_params_text.Text = readResult.ToString(Newtonsoft.Json.Formatting.Indented);
  569. SetStatusColor(readResult);
  570. // 显示DLL原始错误信息
  571. if (readResult["dllErrorMsg"] != null)
  572. {
  573. string dllError = readResult["dllErrorMsg"].ToString();
  574. this.dll_error_text.Text = dllError;
  575. // 根据错误信息设置颜色
  576. if (string.IsNullOrEmpty(dllError))
  577. {
  578. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(220, 252, 231); // 浅绿色 - 成功
  579. this.dll_error_text.ForeColor = System.Drawing.Color.FromArgb(22, 101, 52);
  580. }
  581. else
  582. {
  583. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(255, 240, 240); // 浅红色 - 错误
  584. this.dll_error_text.ForeColor = System.Drawing.Color.DarkRed;
  585. }
  586. }
  587. // 更新原始数据显示
  588. UpdateDllRawDataInfo(readResult);
  589. }
  590. catch (Exception ex)
  591. {
  592. var errorResult = new JObject();
  593. errorResult["success"] = false;
  594. errorResult["code"] = 1001;
  595. errorResult["message"] = "江苏人社标准接口测试异常: " + ex.Message;
  596. errorResult["device"] = "江苏人社标准社保卡读卡器";
  597. errorResult["interface"] = "江苏人社标准接口 v2.1.1";
  598. this.result_text.Text = errorResult.ToString();
  599. this.response_params_text.Text = errorResult.ToString(Newtonsoft.Json.Formatting.Indented);
  600. // 显示异常的DLL错误信息
  601. this.dll_error_text.Text = $"系统异常: {ex.Message}";
  602. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(255, 245, 225); // 浅橙色
  603. this.dll_error_text.ForeColor = System.Drawing.Color.FromArgb(156, 39, 6); // 深橙色
  604. SetStatusColor(errorResult, true); // 标记为异常
  605. // 更新原始数据显示(异常时显示无数据)
  606. UpdateDllRawDataInfo(errorResult);
  607. }
  608. EnableAllButtons(true);
  609. this.jiangsu_renshe_test.Focus();
  610. }
  611. /// <summary>
  612. /// 获取江苏人社标准接口详细信息
  613. /// </summary>
  614. /// <returns>接口信息字符串</returns>
  615. private string GetJiangSuRenSheInterfaceInfo()
  616. {
  617. var info = new System.Text.StringBuilder();
  618. info.AppendLine("=== 江苏人社标准接口调用详情 ===");
  619. info.AppendLine();
  620. info.AppendLine("【✅ 实际调用流程】");
  621. info.AppendLine("1. 检查初始化: 如未初始化则自动调用HeaSecReadInfo.dll.Init()");
  622. info.AppendLine("2. 人社标准读卡: HeaSecReadInfo.dll.iReadCardBas(cardType, 1024字节缓冲区)");
  623. info.AppendLine("说明: 使用相同的初始化配置,但调用人社部标准接口规范!");
  624. info.AppendLine();
  625. info.AppendLine("【📋 接口规范差异】");
  626. info.AppendLine("江苏医保接口: ReadCardBas(cardInfo, busiInfo) - 双缓冲区");
  627. info.AppendLine("江苏人社接口: iReadCardBas(cardType, outInfo) - 单缓冲区");
  628. info.AppendLine("返回格式: 发卡地区|社保号|卡号|卡识别码|姓名|卡复位信息|...");
  629. info.AppendLine("数据分割: 使用|分割的标准12字段格式");
  630. info.AppendLine();
  631. info.AppendLine("【🔄 卡类型操作模式】");
  632. info.AppendLine("1 - 接触式操作卡");
  633. info.AppendLine("2 - 非接触式操作卡");
  634. info.AppendLine("3 - 自动寻卡(接触式优先)");
  635. info.AppendLine("4 - 自动寻卡(非接触式优先)");
  636. info.AppendLine("当前使用: 类型3(自动寻卡接触式优先)");
  637. info.AppendLine();
  638. info.AppendLine("【🔧 初始化配置】");
  639. info.AppendLine("✅ 相同DLL: HeaSecReadInfo.dll");
  640. info.AppendLine("✅ 相同初始化: 13个网络配置参数");
  641. info.AppendLine("✅ 相同设备: 江苏医保社保卡读卡器硬件");
  642. info.AppendLine("⚠️ 不同接口: 人社部标准vs医保自定义");
  643. info.AppendLine();
  644. info.AppendLine("【🌐 HTTP接口地址】");
  645. info.AppendLine("自动寻卡: http://localhost:8321/readcard/jiangsu/standard");
  646. info.AppendLine("接触式: http://localhost:8321/readcard/jiangsu/standard1");
  647. info.AppendLine("非接触式: http://localhost:8321/readcard/jiangsu/standard2");
  648. info.AppendLine("自动接触优先: http://localhost:8321/readcard/jiangsu/standard3");
  649. info.AppendLine("自动非接触优先: http://localhost:8321/readcard/jiangsu/standard4");
  650. return info.ToString();
  651. }
  652. /// <summary>
  653. /// 获取江苏医保接口详细信息
  654. /// </summary>
  655. /// <returns>接口信息字符串</returns>
  656. private string GetJiangSuInterfaceInfo()
  657. {
  658. var config = new JiangSuSocialCardBusiness.JiangSuConfig();
  659. var info = new System.Text.StringBuilder();
  660. info.AppendLine("=== 江苏医保接口调用详情 ===");
  661. info.AppendLine();
  662. info.AppendLine("【✅ 实际调用流程】");
  663. info.AppendLine("1. 初始化: HeaSecReadInfo.dll.Init(13个参数的JSON)");
  664. info.AppendLine("2. 读社保卡: HeaSecReadInfo.dll.ReadCardBas()");
  665. info.AppendLine("说明: 13个网络配置参数已传递给DLL进行初始化!");
  666. info.AppendLine();
  667. info.AppendLine("【📡 网络配置参数(已传给DLL)】");
  668. info.AppendLine($"江苏医保服务器: {config.IP}:{config.PORT}");
  669. info.AppendLine($"超时设置: {config.TIMEOUT}秒");
  670. info.AppendLine($"电子凭证URL: {config.EC_URL}");
  671. info.AppendLine($"CSB接口: {config.API_NAME} v{config.API_VERSION}");
  672. info.AppendLine($"认证密钥: {config.ACCESS_KEY.Substring(0, 8)}***");
  673. info.AppendLine($"机构编号: {config.ORG_ID}(铭和医院)");
  674. info.AppendLine($"行政区划: {config.AREA_CODE}(江苏宿迁沭阳)");
  675. info.AppendLine($"密码验证: CARD_PASSTYPE={config.CARD_PASSTYPE}");
  676. info.AppendLine();
  677. info.AppendLine("【🔄 DLL内部处理机制】");
  678. info.AppendLine("DLL收到配置后会:");
  679. info.AppendLine("- 连接江苏医保服务器(10.61.165.3:8086)");
  680. info.AppendLine("- 验证CSB接口认证(ACCESS_KEY/SECRETKEY)");
  681. info.AppendLine("- 准备网络查询功能(电子凭证等)");
  682. info.AppendLine("- 配置本地读卡器硬件");
  683. info.AppendLine();
  684. info.AppendLine("【📊 当前状态】");
  685. info.AppendLine("✅ 网络参数已传递: 13个配置全部发送给DLL");
  686. info.AppendLine("✅ DLL初始化成功: 返回码0表示网络连接正常");
  687. info.AppendLine("⚠️ 等待插卡: 错误码-11表示未检测到社保卡");
  688. info.AppendLine();
  689. info.AppendLine("【🛠️ 故障排查】");
  690. info.AppendLine("如果插卡后仍报错-11,可能原因:");
  691. info.AppendLine("1. 读卡器硬件未识别或驱动问题");
  692. info.AppendLine("2. 社保卡芯片损坏或接触不良");
  693. info.AppendLine("3. CARD_PASSTYPE参数不匹配医院环境");
  694. info.AppendLine("4. 需要PIN码但当前设置跳过了验证");
  695. info.AppendLine();
  696. info.AppendLine("【🌐 HTTP接口地址】");
  697. info.AppendLine("读卡: http://localhost:8321/readcard/jiangsu/readcard");
  698. info.AppendLine("初始化: http://localhost:8321/readcard/jiangsu/init");
  699. info.AppendLine("验证PIN: http://localhost:8321/readcard/jiangsu/verifypin");
  700. info.AppendLine("设备状态: http://localhost:8321/readcard/jiangsu/status");
  701. return info.ToString();
  702. }
  703. /// <summary>
  704. /// 测试江苏医保读卡器硬件状态
  705. /// </summary>
  706. private void TestJiangSuDeviceStatus(object sender, EventArgs e)
  707. {
  708. EnableAllButtons(false);
  709. ClearParamsDisplay();
  710. try
  711. {
  712. this.request_url_text.Text = "=== 江苏医保网络配置影响测试 ===\n\n测试不同网络配置对错误码的影响,验证 -11 到 -1 的变化原因...";
  713. // 显示检测参数
  714. var testParams = new {
  715. action = "NetworkConfigurationTest",
  716. device = "江苏医保HeaSecReadInfo.dll",
  717. tests = new string[] { "原始配置", "HSM配置", "无效配置", "空配置" },
  718. purpose = "验证网络配置变化是否真的影响错误码"
  719. };
  720. this.request_params_text.Text = Newtonsoft.Json.JsonConvert.SerializeObject(testParams, Newtonsoft.Json.Formatting.Indented);
  721. // 运行网络配置测试
  722. var networkTestResult = JiangSuSocialCardBusiness.TestNetworkConfigurations();
  723. var results = new JObject();
  724. results["networkConfigTest"] = networkTestResult;
  725. // 测试CARD_PASSTYPE=1的读卡
  726. try
  727. {
  728. var config1 = new JiangSuSocialCardBusiness.JiangSuConfig();
  729. config1.CARD_PASSTYPE = "1";
  730. var init1 = JiangSuSocialCardBusiness.Initialize(config1);
  731. var read1 = JiangSuSocialCardBusiness.ReadSocialCard(false);
  732. results["testPassType1"] = new JObject
  733. {
  734. ["passType"] = "1(验证卡PIN)",
  735. ["initResult"] = init1,
  736. ["readResult"] = read1
  737. };
  738. }
  739. catch (Exception ex1)
  740. {
  741. results["testPassType1"] = new JObject
  742. {
  743. ["passType"] = "1(验证卡PIN)",
  744. ["error"] = ex1.Message
  745. };
  746. }
  747. // 测试CARD_PASSTYPE=2的读卡
  748. try
  749. {
  750. var config2 = new JiangSuSocialCardBusiness.JiangSuConfig();
  751. config2.CARD_PASSTYPE = "2";
  752. var init2 = JiangSuSocialCardBusiness.Initialize(config2);
  753. var read2 = JiangSuSocialCardBusiness.ReadSocialCard(false);
  754. results["testPassType2"] = new JObject
  755. {
  756. ["passType"] = "2(验证数据库密码)",
  757. ["initResult"] = init2,
  758. ["readResult"] = read2
  759. };
  760. }
  761. catch (Exception ex2)
  762. {
  763. results["testPassType2"] = new JObject
  764. {
  765. ["passType"] = "2(验证数据库密码)",
  766. ["error"] = ex2.Message
  767. };
  768. }
  769. this.result_text.Text = results.ToString();
  770. this.response_params_text.Text = results.ToString(Newtonsoft.Json.Formatting.Indented);
  771. // 根据结果设置颜色
  772. bool hasSuccess = false;
  773. if (results["testPassType1"] != null && results["testPassType1"]["readResult"] != null)
  774. {
  775. var readResult1 = (JObject)results["testPassType1"]["readResult"];
  776. if (readResult1["success"] != null && (bool)readResult1["success"])
  777. hasSuccess = true;
  778. }
  779. if (results["testPassType2"] != null && results["testPassType2"]["readResult"] != null)
  780. {
  781. var readResult2 = (JObject)results["testPassType2"]["readResult"];
  782. if (readResult2["success"] != null && (bool)readResult2["success"])
  783. hasSuccess = true;
  784. }
  785. if (hasSuccess)
  786. {
  787. SetStatusColor(new JObject { ["success"] = true });
  788. }
  789. else
  790. {
  791. SetStatusColor(new JObject { ["success"] = false }, true);
  792. }
  793. }
  794. catch (Exception ex)
  795. {
  796. var errorResult = new JObject();
  797. errorResult["success"] = false;
  798. errorResult["code"] = 9001;
  799. errorResult["message"] = "硬件检测异常: " + ex.Message;
  800. errorResult["device"] = "江苏医保HeaSecReadInfo.dll";
  801. this.result_text.Text = errorResult.ToString();
  802. this.response_params_text.Text = errorResult.ToString(Newtonsoft.Json.Formatting.Indented);
  803. SetStatusColor(errorResult, true);
  804. }
  805. EnableAllButtons(true);
  806. }
  807. private void ClearParamsDisplay()
  808. {
  809. this.request_url_text.Text = "";
  810. this.request_params_text.Text = "";
  811. this.response_params_text.Text = "";
  812. this.dll_error_text.Text = "";
  813. // 清理原始数据显示区域
  814. if (this.dll_raw_data_text != null)
  815. {
  816. this.dll_raw_data_text.Text = "";
  817. }
  818. // 重置为默认颜色
  819. this.response_params_text.BackColor = System.Drawing.SystemColors.Window;
  820. this.response_params_text.ForeColor = System.Drawing.SystemColors.WindowText;
  821. this.result_text.BackColor = System.Drawing.SystemColors.Window;
  822. this.result_text.ForeColor = System.Drawing.SystemColors.WindowText;
  823. // 重置DLL错误信息显示区域
  824. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(255, 240, 240);
  825. this.dll_error_text.ForeColor = System.Drawing.Color.DarkRed;
  826. }
  827. /// <summary>
  828. /// 根据结果设置状态颜色
  829. /// </summary>
  830. /// <param name="result">结果对象</param>
  831. /// <param name="isException">是否为异常情况</param>
  832. private void SetStatusColor(JObject result, bool isException = false)
  833. {
  834. try
  835. {
  836. if (isException)
  837. {
  838. // 异常状态 - 橙色背景
  839. this.response_params_text.BackColor = System.Drawing.Color.FromArgb(255, 245, 225); // 浅橙色
  840. this.response_params_text.ForeColor = System.Drawing.Color.FromArgb(156, 39, 6); // 深橙色
  841. this.result_text.BackColor = System.Drawing.Color.FromArgb(255, 245, 225);
  842. this.result_text.ForeColor = System.Drawing.Color.FromArgb(156, 39, 6);
  843. return;
  844. }
  845. // 检查不同的成功标识字段
  846. bool isSuccess = false;
  847. int code = 0;
  848. // 尝试获取 success 字段(江苏医保格式)
  849. if (result["success"] != null)
  850. {
  851. isSuccess = (bool)result["success"];
  852. }
  853. // 尝试获取 code 字段
  854. if (result["code"] != null)
  855. {
  856. code = (int)result["code"];
  857. // 如果没有success字段,根据code判断(200表示成功)
  858. if (result["success"] == null)
  859. {
  860. isSuccess = (code == 200);
  861. }
  862. }
  863. if (isSuccess || code == 200)
  864. {
  865. // 成功状态 - 绿色背景
  866. this.response_params_text.BackColor = System.Drawing.Color.FromArgb(220, 252, 231); // 浅绿色
  867. this.response_params_text.ForeColor = System.Drawing.Color.FromArgb(22, 101, 52); // 深绿色
  868. this.result_text.BackColor = System.Drawing.Color.FromArgb(220, 252, 231);
  869. this.result_text.ForeColor = System.Drawing.Color.FromArgb(22, 101, 52);
  870. }
  871. else
  872. {
  873. // 失败状态 - 红色背景
  874. this.response_params_text.BackColor = System.Drawing.Color.FromArgb(254, 226, 226); // 浅红色
  875. this.response_params_text.ForeColor = System.Drawing.Color.FromArgb(153, 27, 27); // 深红色
  876. this.result_text.BackColor = System.Drawing.Color.FromArgb(254, 226, 226);
  877. this.result_text.ForeColor = System.Drawing.Color.FromArgb(153, 27, 27);
  878. }
  879. }
  880. catch (Exception ex)
  881. {
  882. // 解析状态失败,设置为默认颜色
  883. this.response_params_text.BackColor = System.Drawing.SystemColors.Window;
  884. this.response_params_text.ForeColor = System.Drawing.SystemColors.WindowText;
  885. this.result_text.BackColor = System.Drawing.SystemColors.Window;
  886. this.result_text.ForeColor = System.Drawing.SystemColors.WindowText;
  887. System.Diagnostics.Debug.WriteLine($"设置状态颜色失败: {ex.Message}");
  888. }
  889. }
  890. /// <summary>
  891. /// 测试江苏医保刷脸授权获取医保身份功能
  892. /// 使用NationECCode.dll与泰和完全一致
  893. /// </summary>
  894. private void TestJiangSuFace(object sender, EventArgs e)
  895. {
  896. EnableAllButtons(false);
  897. ClearParamsDisplay();
  898. try
  899. {
  900. // 显示江苏医保刷脸详细信息
  901. this.request_url_text.Text = GetJiangSuFaceInterfaceInfo();
  902. // 显示请求参数
  903. var requestParams = new {
  904. action = "JiangSuFaceAuth",
  905. device = "江苏医保刷脸认证器(NationECCode.dll)",
  906. implementation = "与泰和完全一致(相同DLL、相同URL、相同逻辑)",
  907. businessType = "01101",
  908. transType1 = "cn.nhsa.ec.auth(获取authNo)",
  909. transType2 = "cn.nhsa.auth.check(根据authNo获取医保身份)",
  910. orgId = "H32132200561(写死参数)",
  911. serviceUrl = "http://10.58.33.207:10086/localcfc/api/hsecfc/localQrCodeQuery(写死参数)",
  912. note = "完全使用写死的配置参数,与泰和实现方式一致"
  913. };
  914. this.request_params_text.Text = Newtonsoft.Json.JsonConvert.SerializeObject(requestParams, Newtonsoft.Json.Formatting.Indented);
  915. // 调用江苏医保刷脸功能(使用NationECCode.dll与泰和完全一致)
  916. var faceResult = JiangSuSocialCardBusiness.ReadFace("01101");
  917. this.result_text.Text = faceResult.ToString();
  918. this.response_params_text.Text = faceResult.ToString(Newtonsoft.Json.Formatting.Indented);
  919. SetStatusColor(faceResult);
  920. // 显示DLL错误信息(如果有)
  921. if (faceResult["message"] != null)
  922. {
  923. string message = faceResult["message"].ToString();
  924. bool isSuccess = faceResult["code"] != null && (int)faceResult["code"] == 200;
  925. this.dll_error_text.Text = message;
  926. if (isSuccess)
  927. {
  928. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(220, 252, 231); // 浅绿色 - 成功
  929. this.dll_error_text.ForeColor = System.Drawing.Color.FromArgb(22, 101, 52);
  930. }
  931. else
  932. {
  933. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(255, 240, 240); // 浅红色 - 错误
  934. this.dll_error_text.ForeColor = System.Drawing.Color.DarkRed;
  935. }
  936. }
  937. // 更新原始数据显示
  938. UpdateDllRawDataInfo(faceResult);
  939. }
  940. catch (Exception ex)
  941. {
  942. var errorResult = new JObject();
  943. errorResult["success"] = false;
  944. errorResult["code"] = 4001;
  945. errorResult["message"] = "江苏医保刷脸测试异常: " + ex.Message;
  946. errorResult["device"] = "江苏医保刷脸认证器(NationECCode.dll)";
  947. errorResult["implementation"] = "与泰和完全一致";
  948. this.result_text.Text = errorResult.ToString();
  949. this.response_params_text.Text = errorResult.ToString(Newtonsoft.Json.Formatting.Indented);
  950. this.dll_error_text.Text = "系统异常: " + ex.Message;
  951. this.dll_error_text.BackColor = System.Drawing.Color.FromArgb(255, 245, 225); // 浅橙色
  952. this.dll_error_text.ForeColor = System.Drawing.Color.FromArgb(156, 39, 6); // 深橙色
  953. SetStatusColor(errorResult, true);
  954. UpdateDllRawDataInfo(errorResult);
  955. }
  956. EnableAllButtons(true);
  957. this.jiangsu_face_test.Focus();
  958. }
  959. /// <summary>
  960. /// 获取江苏医保刷脸接口详细信息
  961. /// </summary>
  962. /// <returns>接口信息字符串</returns>
  963. private string GetJiangSuFaceInterfaceInfo()
  964. {
  965. var info = new System.Text.StringBuilder();
  966. info.AppendLine("=== 江苏医保刷脸授权获取医保身份接口调用详情 ===");
  967. info.AppendLine();
  968. info.AppendLine("【✅ 实现方式】");
  969. info.AppendLine("DLL文件: NationECCode.dll(与泰和完全相同)");
  970. info.AppendLine("服务地址: http://10.58.33.207:10086/localcfc/api/hsecfc/localQrCodeQuery(写死参数)");
  971. info.AppendLine("机构编号: H32132200561(写死参数)");
  972. info.AppendLine("实现逻辑: 与泰和的ReadFace方法完全一致");
  973. info.AppendLine();
  974. info.AppendLine("【🔄 两步式认证流程】");
  975. info.AppendLine("第一步: 调用cn.nhsa.ec.auth获取authNo");
  976. info.AppendLine("第二步: 调用cn.nhsa.auth.check根据authNo获取医保身份信息");
  977. info.AppendLine("符合规范: 国家医保电子凭证业务标准动态库交互规范2021-11-12");
  978. info.AppendLine();
  979. info.AppendLine("【📋 支持的业务类型】");
  980. info.AppendLine("01101 - 门诊挂号(当前测试)");
  981. info.AppendLine("01301 - 门诊结算");
  982. info.AppendLine("02121 - 药店购药");
  983. info.AppendLine("01102 - 住院建档");
  984. info.AppendLine("01103 - 入院登记");
  985. info.AppendLine();
  986. info.AppendLine("【🌐 HTTP接口地址】");
  987. info.AppendLine("江苏医保刷脸: http://localhost:8321/readcard/entry?param=jiangsu_face_01101");
  988. info.AppendLine("门诊挂号: http://localhost:8321/readcard/entry?param=jiangsu_face_01101");
  989. info.AppendLine("门诊结算: http://localhost:8321/readcard/entry?param=jiangsu_face_01301");
  990. info.AppendLine("药店购药: http://localhost:8321/readcard/entry?param=jiangsu_face_02121");
  991. info.AppendLine("通用格式: jiangsu_face_${biztype}");
  992. return info.ToString();
  993. }
  994. /// <summary>
  995. /// 测试江苏医保电子凭证解码功能
  996. /// </summary>
  997. private void TestJiangSuEcDecode(object sender, EventArgs e)
  998. {
  999. EnableAllButtons(false);
  1000. ClearParamsDisplay();
  1001. try
  1002. {
  1003. // 显示江苏医保电子凭证解码详细信息
  1004. this.request_url_text.Text = GetJiangSuEcDecodeInterfaceInfo();
  1005. // 显示实际DLL调用参数
  1006. var config = new JiangSuSocialCardBusiness.JiangSuConfig();
  1007. var requestParams = new {
  1008. data = new {
  1009. orgId = config.ORG_ID,
  1010. businessType = "01101",
  1011. operatorId = "system001",
  1012. operatorName = "系统管理员",
  1013. officeId = "32760",
  1014. officeName = "医保科"
  1015. },
  1016. transType = "ec.query",
  1017. orgId = config.ORG_ID,
  1018. note = "实际DLL调用参数格式 - 符合江苏医保接口规范v0.9.9.15",
  1019. interfaceVersion = "1.14.6 电子凭证解码",
  1020. function = "HeaSecReadInfo.dll.EcQuery"
  1021. };
  1022. this.request_params_text.Text = Newtonsoft.Json.JsonConvert.SerializeObject(requestParams, Newtonsoft.Json.Formatting.Indented);
  1023. // 调用江苏医保电子凭证解码接口
  1024. var decodeResult = JiangSuSocialCardBusiness.ReadElectronicCertificate("01101");
  1025. this.result_text.Text = decodeResult.ToString();
  1026. this.response_params_text.Text = decodeResult.ToString(Newtonsoft.Json.Formatting.Indented);
  1027. SetStatusColor(decodeResult);
  1028. // 显示DLL原始错误信息
  1029. if (decodeResult["dllErrorMsg"] != null)
  1030. {
  1031. string dllError = decodeResult["dllErrorMsg"].ToString();
  1032. this.dll_error_text.Text = dllError;
  1033. if (string.IsNullOrEmpty(dllError))
  1034. {
  1035. this.dll_error_text.BackColor = Color.LightGreen;
  1036. this.dll_error_text.ForeColor = Color.DarkGreen;
  1037. }
  1038. else
  1039. {
  1040. this.dll_error_text.BackColor = Color.LightPink;
  1041. this.dll_error_text.ForeColor = Color.DarkRed;
  1042. }
  1043. }
  1044. // 更新原始数据显示
  1045. UpdateDllRawDataInfo(decodeResult);
  1046. }
  1047. catch (Exception ex)
  1048. {
  1049. var errorResult = new JObject();
  1050. errorResult["success"] = false;
  1051. errorResult["code"] = 3001;
  1052. errorResult["message"] = "江苏医保电子凭证解码测试异常: " + ex.Message;
  1053. errorResult["device"] = "江苏医保HeaSecReadInfo.dll";
  1054. errorResult["interfaceVersion"] = "江苏医保电子凭证解码接口 v0.9.9.15";
  1055. this.result_text.Text = errorResult.ToString();
  1056. this.response_params_text.Text = errorResult.ToString(Newtonsoft.Json.Formatting.Indented);
  1057. this.dll_error_text.Text = "系统异常: " + ex.Message;
  1058. this.dll_error_text.BackColor = Color.LightYellow;
  1059. this.dll_error_text.ForeColor = Color.DarkRed;
  1060. SetStatusColor(errorResult, true);
  1061. UpdateDllRawDataInfo(errorResult);
  1062. }
  1063. EnableAllButtons(true);
  1064. this.jiangsu_ec_decode_test.Focus();
  1065. }
  1066. /// <summary>
  1067. /// 获取江苏医保电子凭证解码接口详细信息
  1068. /// </summary>
  1069. /// <returns>接口信息字符串</returns>
  1070. private string GetJiangSuEcDecodeInterfaceInfo()
  1071. {
  1072. var info = new System.Text.StringBuilder();
  1073. info.AppendLine("=== 江苏医保电子凭证解码接口调用详情 ===");
  1074. info.AppendLine();
  1075. info.AppendLine("【✅ 实际调用流程】");
  1076. info.AppendLine("1. 自动初始化: 检查并初始化HeaSecReadInfo.dll");
  1077. info.AppendLine("2. 电子凭证解码: HeaSecReadInfo.dll.EcQuery(业务参数JSON)");
  1078. info.AppendLine("说明: 符合江苏医保接口规范v0.9.9.15第1.14.6节要求!");
  1079. info.AppendLine();
  1080. info.AppendLine("【📋 接口规范详情】");
  1081. info.AppendLine("接口名称: 1.14.6 电子凭证解码");
  1082. info.AppendLine("调用函数: EcQuery");
  1083. info.AppendLine("输入格式: JSON字符串(业务类型+配置参数)");
  1084. info.AppendLine("输出格式: JSON字符串(解码结果+状态信息)");
  1085. info.AppendLine("缓冲区大小: 8192字节");
  1086. info.AppendLine();
  1087. info.AppendLine("【🔄 支持的业务类型】");
  1088. info.AppendLine("门诊业务:");
  1089. info.AppendLine(" 01101 - 挂号");
  1090. info.AppendLine(" 01201 - 问诊");
  1091. info.AppendLine(" 01202 - 预约检查");
  1092. info.AppendLine(" 01203 - 检查");
  1093. info.AppendLine(" 01204 - 治疗");
  1094. info.AppendLine(" 01301 - 结算");
  1095. info.AppendLine(" 01302 - 取药");
  1096. info.AppendLine("住院业务:");
  1097. info.AppendLine(" 01102 - 建档");
  1098. info.AppendLine(" 01103 - 入院登记");
  1099. info.AppendLine(" 01104 - 缴纳预缴金");
  1100. info.AppendLine("药店业务:");
  1101. info.AppendLine(" 02121 - 购药");
  1102. info.AppendLine(" 02122 - 下载外购处方");
  1103. info.AppendLine("当前测试: 01101(门诊挂号)");
  1104. info.AppendLine();
  1105. info.AppendLine("【🔧 初始化配置】");
  1106. info.AppendLine("✅ 江苏医保服务器: 10.61.165.3:8086");
  1107. info.AppendLine("✅ CSB接口认证: ACCESS_KEY/SECRET_KEY");
  1108. info.AppendLine("✅ 机构编号: H32132100055(铭和医院)");
  1109. info.AppendLine("✅ 行政区划: 321322(江苏宿迁沭阳)");
  1110. info.AppendLine("✅ API接口: hsEcQuery v1.0.0");
  1111. info.AppendLine();
  1112. info.AppendLine("【🌐 HTTP接口地址】");
  1113. info.AppendLine("门诊挂号: http://localhost:8321/api/entry?param=jiangsu_qrcode_01101");
  1114. info.AppendLine("门诊问诊: http://localhost:8321/api/entry?param=jiangsu_qrcode_01201");
  1115. info.AppendLine("门诊结算: http://localhost:8321/api/entry?param=jiangsu_qrcode_01301");
  1116. info.AppendLine("住院登记: http://localhost:8321/api/entry?param=jiangsu_qrcode_01103");
  1117. info.AppendLine("药店购药: http://localhost:8321/api/entry?param=jiangsu_qrcode_02121");
  1118. info.AppendLine("通用格式: jiangsu_qrcode_[业务类型] 或 jiangsu_ec_[业务类型]");
  1119. return info.ToString();
  1120. }
  1121. private void EnableAllButtons(Boolean value)
  1122. {
  1123. // 只启用/禁用可见的按钮
  1124. this.huashi_idcard_test.Enabled = value;
  1125. this.jiangsu_sicard_test.Enabled = value;
  1126. this.jiangsu_face_test.Enabled = value;
  1127. this.jiangsu_ec_decode_test.Enabled = value;
  1128. // 以下按钮被隐藏,但保留代码以防将来需要
  1129. if (this.sicard_test.Visible) this.sicard_test.Enabled = value;
  1130. if (this.idcard_test.Visible) this.idcard_test.Enabled = value;
  1131. if (this.qrcode_test.Visible) this.qrcode_test.Enabled = value;
  1132. if (this.face_test.Visible) this.face_test.Enabled = value;
  1133. if (this.id_card_test2.Visible) this.id_card_test2.Enabled = value;
  1134. if (this.qr_code_test2.Visible) this.qr_code_test2.Enabled = value;
  1135. }
  1136. protected override void WndProc(ref Message m)
  1137. {
  1138. const int WM_SYSCOMMAND = 0x0112;
  1139. const int SC_CLOSE = 0xF060;
  1140. if (m.Msg == WM_SYSCOMMAND && (int)m.WParam == SC_CLOSE)
  1141. {
  1142. // User clicked close button
  1143. this.WindowState = FormWindowState.Minimized;
  1144. return;
  1145. }
  1146. base.WndProc(ref m);
  1147. }
  1148. protected override void OnResize(EventArgs e)
  1149. {
  1150. if (WindowState == FormWindowState.Minimized)
  1151. {
  1152. this.Hide();
  1153. }
  1154. }
  1155. /// <summary>
  1156. /// 更新DLL原始数据显示
  1157. /// </summary>
  1158. private void UpdateDllRawDataInfo(dynamic result)
  1159. {
  1160. try
  1161. {
  1162. this.Invoke((Action)(() =>
  1163. {
  1164. if (dll_raw_data_text != null)
  1165. {
  1166. string rawDataInfo = "";
  1167. Color textColor = Color.DarkBlue; // 默认深蓝色
  1168. if (result != null)
  1169. {
  1170. // 检查是否有原始读卡数据
  1171. if (result.rawCardData != null || result.rawBusiData != null)
  1172. {
  1173. var rawDataBuilder = new System.Text.StringBuilder();
  1174. rawDataBuilder.AppendLine("=== 读卡原始数据 ===");
  1175. rawDataBuilder.AppendLine($"时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
  1176. rawDataBuilder.AppendLine();
  1177. if (result.rawCardData != null)
  1178. {
  1179. string cardData = result.rawCardData.ToString();
  1180. rawDataBuilder.AppendLine("【基本信息数据】");
  1181. if (!string.IsNullOrEmpty(cardData))
  1182. {
  1183. rawDataBuilder.AppendLine(cardData);
  1184. textColor = Color.Green; // 有数据:绿色
  1185. }
  1186. else
  1187. {
  1188. rawDataBuilder.AppendLine("(空数据)");
  1189. textColor = Color.Orange; // 空数据:橙色
  1190. }
  1191. rawDataBuilder.AppendLine();
  1192. }
  1193. if (result.rawBusiData != null)
  1194. {
  1195. string busiData = result.rawBusiData.ToString();
  1196. rawDataBuilder.AppendLine("【业务信息数据】");
  1197. if (!string.IsNullOrEmpty(busiData))
  1198. {
  1199. rawDataBuilder.AppendLine(busiData);
  1200. if (textColor != Color.Green) // 如果基本信息没有数据,但业务信息有数据
  1201. {
  1202. textColor = Color.Green;
  1203. }
  1204. }
  1205. else
  1206. {
  1207. rawDataBuilder.AppendLine("(空数据)");
  1208. if (textColor == Color.DarkBlue) // 如果都没有数据
  1209. {
  1210. textColor = Color.Orange;
  1211. }
  1212. }
  1213. }
  1214. rawDataInfo = rawDataBuilder.ToString();
  1215. }
  1216. else
  1217. {
  1218. // 没有读卡数据的情况
  1219. bool isSuccess = result.success != null && (bool)result.success;
  1220. if (!isSuccess)
  1221. {
  1222. rawDataInfo = $"读卡失败 - {DateTime.Now:yyyy-MM-dd HH:mm:ss}\n无原始数据返回";
  1223. textColor = Color.Red; // 失败:红色
  1224. }
  1225. else
  1226. {
  1227. rawDataInfo = $"操作成功 - {DateTime.Now:yyyy-MM-dd HH:mm:ss}\n此操作无读卡数据";
  1228. textColor = Color.Gray; // 无相关数据:灰色
  1229. }
  1230. }
  1231. }
  1232. dll_raw_data_text.Text = rawDataInfo;
  1233. dll_raw_data_text.ForeColor = textColor;
  1234. }
  1235. }));
  1236. }
  1237. catch (Exception ex)
  1238. {
  1239. // 静默处理,避免影响主要功能
  1240. Console.WriteLine($"更新DLL原始数据失败: {ex.Message}");
  1241. }
  1242. }
  1243. }
  1244. }