MainForm.cs 65 KB

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