You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

556 lines
23 KiB

4 weeks ago
  1. using Azure.Core;
  2. using Dapper;
  3. using Microsoft.Extensions.Configuration;
  4. using Newtonsoft.Json;
  5. using Newtonsoft.Json.Converters;
  6. using Npgsql;
  7. using Shentun.Peis.ImportLisResults;
  8. using Shentun.Peis.PlugIns.Extensions.ChargeRequests.YinHai;
  9. using Shentun.Peis.PlugIns.Extensions.ChargeRequests.YinHai.FeeBacks;
  10. using Shentun.Peis.PlugIns.Extensions.ImportLisResults.YinHai.ResultCalls;
  11. using Shentun.Peis.PlugIns.Extensions.LisRequests.YinHai;
  12. using Shentun.Peis.ThirdInterfaces;
  13. using Shentun.Utilities;
  14. using System;
  15. using System.Collections.Generic;
  16. using System.Data.Common;
  17. using System.IdentityModel.Tokens.Jwt;
  18. using System.Linq;
  19. using System.Net.Http.Headers;
  20. using System.Text;
  21. using System.Threading.Tasks;
  22. using System.Xml;
  23. using Volo.Abp.Application.Dtos;
  24. namespace Shentun.Peis.PlugIns.Extensions.ImportLisResults.YinHai
  25. {
  26. public class ImportLisResultPlugInsYinHai
  27. {
  28. protected IConfiguration? AppConfig;
  29. private readonly string AppConnctionStr;
  30. private readonly IConfiguration? InterfaceConfig;
  31. private readonly ThirdInterfaceDto? _thirdInterfaceDto;
  32. private readonly PluginLogger _logger; // 添加日志实例
  33. private string? _appBaseAddress;
  34. private static string? _accesToken;
  35. protected string? AppUser;
  36. protected string? AppPassword;
  37. static ImportLisResultPlugInsYinHai()
  38. {
  39. Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;
  40. }
  41. public ImportLisResultPlugInsYinHai(Guid thirdInterfaceId)
  42. {
  43. _logger = new PluginLogger();
  44. AppConfig = new ConfigurationBuilder()
  45. .SetBasePath(DirectoryHelper.GetAppDirectory()) // 设置基础路径为当前目录
  46. .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
  47. .Build();
  48. AppConnctionStr = AppConfig.GetSection("ConnectionStrings")
  49. .GetSection("Default").Value;
  50. using (DbConnection conn = new NpgsqlConnection(AppConnctionStr))
  51. {
  52. string sql;
  53. sql = @"
  54. SELECT *
  55. from third_interface
  56. where id =@ThirdInterfaceId
  57. ";
  58. _thirdInterfaceDto = (conn.Query<ThirdInterfaceDto>(sql,
  59. new { ThirdInterfaceId = thirdInterfaceId })).Single();
  60. }
  61. var configurationBuilder = new ConfigurationBuilder()
  62. .AddJsonStream(new MemoryStream(System.Text.Encoding.UTF8.GetBytes(_thirdInterfaceDto.ParmValue)));
  63. InterfaceConfig = configurationBuilder.Build();
  64. _appBaseAddress = AppConfig.GetSection("App")
  65. .GetSection("SelfUrl").Value;
  66. AppUser = AppConfig.GetSection("App")
  67. .GetSection("SelfUser").Value;
  68. AppPassword = AppConfig.GetSection("App")
  69. .GetSection("SelfPassword").Value;
  70. }
  71. public ImportLisResultPlugInsYinHai(string parmValue)
  72. {
  73. _logger = new PluginLogger();
  74. AppConfig = new ConfigurationBuilder()
  75. .SetBasePath(DirectoryHelper.GetAppDirectory()) // 设置基础路径为当前目录
  76. .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
  77. .Build();
  78. AppConnctionStr = AppConfig.GetSection("ConnectionStrings")
  79. .GetSection("Default").Value;
  80. var configurationBuilder = new ConfigurationBuilder()
  81. .AddJsonStream(new MemoryStream(System.Text.Encoding.UTF8.GetBytes(parmValue)));
  82. InterfaceConfig = configurationBuilder.Build();
  83. _appBaseAddress = AppConfig.GetSection("App")
  84. .GetSection("SelfUrl").Value;
  85. AppUser = AppConfig.GetSection("App")
  86. .GetSection("SelfUser").Value;
  87. AppPassword = AppConfig.GetSection("App")
  88. .GetSection("SelfPassword").Value;
  89. }
  90. /// <summary>
  91. /// 接收lis检查结果
  92. /// </summary>
  93. /// <param name="input"></param>
  94. /// <returns></returns>
  95. /// <exception cref="Exception"></exception>
  96. public async Task<CallBussinessResponseDetailDto> SendResultRequestAsync(InferfaceXmlDataDto input)
  97. {
  98. var res = new CallBussinessResponseDetailDto
  99. {
  100. msg = "失败",
  101. status_code = "-1"
  102. };
  103. #region 解析xml
  104. var lisResultCallRequestData = GetLisResultCallRequestData(input.message);
  105. #endregion
  106. _logger.LogResult("银海接收lis检查结果", $"请求数据:{input.message}");
  107. try
  108. {
  109. var execDoctorUser = InterfaceConfig.GetValue("Interface:ExecDoctorUser", "");
  110. var commonTableTypeId = InterfaceConfig.GetValue("Interface:CommonTableTypeId", "");
  111. var execOrganizationUnitId = InterfaceConfig.GetValue("Interface:ExecOrganizationUnitId", "");
  112. var checkDoctorName = InterfaceConfig.GetValue("Interface:CheckDoctorName", "");
  113. string actionName = "result_call";
  114. string codeName = "lis_server";
  115. var bodyData = lisResultCallRequestData.body.data.request_details;
  116. var createImportLisResultDtos = new List<CreateImportLisResultDto>();
  117. if (bodyData.detail.Any())
  118. {
  119. var lisItemCommonTableList = await GetCommonTableByTypeId(commonTableTypeId);
  120. foreach (var item in bodyData.detail)
  121. {
  122. var dzFirst = lisItemCommonTableList.FirstOrDefault(f => f.ThirdCode == item.examine_code.ToString());
  123. if (dzFirst == null)
  124. {
  125. throw new Exception($"Lis明细项目【{item.examine_name},编码:{item.examine_code}】没有对照");
  126. }
  127. var createImportLisResultDto = new CreateImportLisResultDto()
  128. {
  129. LisRequestNo = item.request_no,
  130. ItemId = Guid.Parse(dzFirst.DisplayName),
  131. ItemName = item.examine_name,
  132. Result = item.examine_result,
  133. Unit = item.computing_unit,
  134. ReferenceRangeValue = item.reference_range,
  135. //CriticalRangeValue = "",
  136. //ResultStatusId = "",
  137. //ReportPrompt = "",
  138. CheckDoctorName = checkDoctorName,
  139. //CheckDate = lisResult.CheckDate,
  140. ExecOrganizationUnitId = Guid.Parse(execOrganizationUnitId)
  141. };
  142. createImportLisResultDtos.Add(createImportLisResultDto);
  143. }
  144. }
  145. else
  146. {
  147. throw new Exception("无结果数据");
  148. }
  149. //发送数据
  150. var callResult = await CallAppServiceAsync<List<CreateImportLisResultDto>, object>("api/app/ImportLisResult/ImportResult", createImportLisResultDtos);
  151. _logger.LogResult("银海接收lis检查结果", $"处理成功,Lis申请单号【{createImportLisResultDtos.FirstOrDefault().LisRequestNo}】");
  152. var yinHaiSendInterfaceLogDto = new YinHaiSendInterfaceLogDto
  153. {
  154. LogName = "接收lis检查结果",
  155. ExecDoctorUser = Guid.Parse(execDoctorUser),
  156. InterfaceName = $"{codeName}_{actionName}",
  157. ParaValue = input.message,
  158. RequestNo = createImportLisResultDtos.FirstOrDefault().LisRequestNo,
  159. ReturnParaValue = ""
  160. };
  161. await AddSendLog(yinHaiSendInterfaceLogDto);
  162. res = new CallBussinessResponseDetailDto
  163. {
  164. status_code = "1",
  165. msg = "成功"
  166. };
  167. }
  168. catch (Exception ex)
  169. {
  170. _logger.LogResult("银海接收lis检查结果", ex, $"接收lis检查结果异常");
  171. }
  172. return res;
  173. }
  174. /// <summary>
  175. /// 获取对照数据
  176. /// </summary>
  177. /// <param name="commonTableTypeId"></param>
  178. /// <returns></returns>
  179. private async Task<List<YinHaiItemCommonTableDto>> GetCommonTableByTypeId(string commonTableTypeId)
  180. {
  181. var thirdCode = InterfaceConfig.GetValue("Interface:ThirdCode", "");
  182. using (DbConnection conn = new NpgsqlConnection(AppConnctionStr))
  183. {
  184. string sql;
  185. sql = $@"select display_name,{thirdCode} as thirdCode from common_table where common_table_type_id='{commonTableTypeId}' ";
  186. var yinHaiAsbitemCommonTableList = (await conn.QueryAsync<YinHaiItemCommonTableDto>(sql)).ToList();
  187. return yinHaiAsbitemCommonTableList;
  188. }
  189. }
  190. /// <summary>
  191. /// 添加日志
  192. /// </summary>
  193. /// <param name="input"></param>
  194. /// <returns></returns>
  195. private async Task AddSendLog(YinHaiSendInterfaceLogDto input)
  196. {
  197. using (DbConnection conn = new NpgsqlConnection(AppConnctionStr))
  198. {
  199. string sql;
  200. sql = $@" insert into interface_send_log (id,log_name,request_no,interface_name,para_value,return_para_value,concurrency_stamp,
  201. creation_time,creator_id,last_modification_time,last_modifier_id) values
  202. (@id,@log_name,@request_no,@interface_name,@para_value,@return_para_value,@concurrency_stamp,
  203. @creation_time,@creator_id,@last_modification_time,@last_modifier_id)
  204. ";
  205. await conn.ExecuteAsync(sql,
  206. new
  207. {
  208. id = Guid.NewGuid(),
  209. log_name = input.LogName,
  210. request_no = input.RequestNo,
  211. interface_name = input.InterfaceName,
  212. para_value = input.ParaValue,
  213. return_para_value = input.ReturnParaValue,
  214. concurrency_stamp = Guid.NewGuid().ToString("N"),
  215. creation_time = DateTime.Now,
  216. creator_id = input.ExecDoctorUser,
  217. last_modification_time = DateTime.Now,
  218. last_modifier_id = input.ExecDoctorUser
  219. });
  220. }
  221. }
  222. #region 解析xml
  223. private LisResultCallRequestDto GetLisResultCallRequestData(string message)
  224. {
  225. try
  226. {
  227. var doc = new XmlDocument();
  228. doc.LoadXml(message);
  229. var request = new LisResultCallRequestDto();
  230. var root = doc.DocumentElement;
  231. if (root == null) return null;
  232. // 解析 head
  233. var headNode = root.SelectSingleNode("head");
  234. if (headNode != null)
  235. {
  236. request.head = new CallBussinessRequestHeadDto
  237. {
  238. version = GetNodeValue(headNode, "version"),
  239. timestamp = GetNodeValue(headNode, "timestamp"),
  240. sign = GetNodeValue(headNode, "sign"),
  241. request_id = GetNodeValue(headNode, "request_id"),
  242. source_system = GetNodeValue(headNode, "source_system"),
  243. object_system = GetNodeValue(headNode, "object_system"),
  244. action = GetNodeValue(headNode, "action"),
  245. code = GetNodeValue(headNode, "code")
  246. };
  247. }
  248. // 解析 body
  249. var bodyNode = root.SelectSingleNode("body");
  250. if (bodyNode != null)
  251. {
  252. request.body = new LisResultCallRequestBodyDto();
  253. var dataNode = bodyNode.SelectSingleNode("data");
  254. if (dataNode != null)
  255. {
  256. request.body.data = new LisResultCallRequestBodyDataDto();
  257. var requestDetailsNode = dataNode.SelectSingleNode("request_details");
  258. if (requestDetailsNode != null)
  259. {
  260. // 创建 detail 列表
  261. request.body.data.request_details = new LisResultCallRequestBodyDataRequestDetails
  262. {
  263. detail = new List<LisResultCallRequestBodyDataRequestDetail>()
  264. };
  265. // 获取所有 detail 节点
  266. var detailNodes = requestDetailsNode.SelectNodes("detail");
  267. if (detailNodes != null)
  268. {
  269. foreach (XmlNode detailNode in detailNodes)
  270. {
  271. var detail = new LisResultCallRequestBodyDataRequestDetail
  272. {
  273. hos_id = GetNodeValue(detailNode, "hos_id"),
  274. request_no = GetNodeValue(detailNode, "request_no"),
  275. patient_type = GetNodeValue(detailNode, "patient_type"),
  276. report_serial_no = GetNodeValue(detailNode, "report_serial_no"),
  277. org_code = GetNodeValue(detailNode, "org_code"),
  278. system_source = GetNodeValue(detailNode, "system_source"),
  279. org_name = GetNodeValue(detailNode, "org_name"),
  280. patient_id = GetNodeValue(detailNode, "patient_id"),
  281. visit_id = GetNodeValue(detailNode, "visit_id"),
  282. order_id = GetNodeValue(detailNode, "order_id"),
  283. item_serial_no = GetNodeValue(detailNode, "item_serial_no"),
  284. print_no = GetNodeValue(detailNode, "print_no"),
  285. examine_way_name = GetNodeValue(detailNode, "examine_way_name"),
  286. examine_no = GetNodeValue(detailNode, "examine_no"),
  287. examine_code = GetNodeValue(detailNode, "examine_code"),
  288. examine_name = GetNodeValue(detailNode, "examine_name"),
  289. examine_en_name = GetNodeValue(detailNode, "examine_en_name"),
  290. examine_result_type = GetNodeValue(detailNode, "examine_result_type"),
  291. examine_result = GetNodeValue(detailNode, "examine_result"),
  292. computing_unit = GetNodeValue(detailNode, "computing_unit"),
  293. abnormal_tip = GetNodeValue(detailNode, "abnormal_tip"),
  294. reference_range = GetNodeValue(detailNode, "reference_range"),
  295. remark = GetNodeValue(detailNode, "remark"),
  296. batch_no = GetNodeValue(detailNode, "batch_no"),
  297. report_url = GetNodeValue(detailNode, "report_url")
  298. };
  299. request.body.data.request_details.detail.Add(detail);
  300. }
  301. }
  302. }
  303. }
  304. }
  305. return request;
  306. }
  307. catch (Exception ex)
  308. {
  309. //_logger.LogError(ex, "解析 XML 失败");
  310. return null;
  311. }
  312. }
  313. private string GetNodeValue(XmlNode parent, string nodeName)
  314. {
  315. var node = parent.SelectSingleNode(nodeName);
  316. return node?.InnerText ?? "";
  317. }
  318. #endregion
  319. private async Task<TOut> CallAppServiceAsync<TInput, TOut>(string url, TInput data, string method = "post")
  320. {
  321. if (string.IsNullOrWhiteSpace(_appBaseAddress))
  322. {
  323. throw new Exception("_appBaseAddress不能为空");
  324. }
  325. string baseAddress = _appBaseAddress;
  326. await CheckLoginAsync();
  327. using (var httpClientHandler = new HttpClientHandler())
  328. {
  329. using (var httpClient = new HttpClient(httpClientHandler))
  330. {
  331. httpClient.BaseAddress = new Uri(baseAddress);
  332. httpClient.DefaultRequestHeaders.Accept.Add(
  333. new MediaTypeWithQualityHeaderValue("application/json"));//设置accept标头,告诉JSON是可接受的响应类型
  334. httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _accesToken);
  335. IsoDateTimeConverter timeFormat = new IsoDateTimeConverter();
  336. timeFormat.DateTimeFormat = "yyyy-MM-dd HH:mm:ss";
  337. var sendData = JsonConvert.SerializeObject(data, Newtonsoft.Json.Formatting.Indented, timeFormat);
  338. using (HttpContent httpContent = new StringContent(sendData))
  339. {
  340. httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
  341. HttpResponseMessage response = null;
  342. if (method == "post")
  343. {
  344. response = await httpClient.PostAsync(url, httpContent);
  345. }
  346. else
  347. {
  348. response = await httpClient.GetAsync(url);
  349. }
  350. string result;
  351. if (!response.IsSuccessStatusCode)
  352. {
  353. result = response.Content.ReadAsStringAsync().Result;
  354. throw new Exception("http通信错误:" + response.StatusCode + ",结果:" + result);
  355. }
  356. result = await response.Content.ReadAsStringAsync();
  357. var resultDto = JsonConvert.DeserializeObject<WebApiOutDto<TOut>>(result);
  358. if (resultDto.Code == -1)
  359. {
  360. throw new Exception($"调用WebApi失败,返回-1,消息:" + resultDto.Message);
  361. }
  362. return resultDto.Data;
  363. }
  364. }
  365. }
  366. }
  367. #region 获取token
  368. private async Task<WebApiOutDto<LoginOutDataDto>> LoginAsync(string userId, string password)
  369. {
  370. if (string.IsNullOrWhiteSpace(userId))
  371. {
  372. throw new Exception("用户ID不能为空");
  373. }
  374. if (string.IsNullOrWhiteSpace(password))
  375. {
  376. throw new Exception("密码不能为空");
  377. }
  378. using (var httpClientHandler = new HttpClientHandler())
  379. {
  380. using (var httpClient = new HttpClient(httpClientHandler))
  381. {
  382. httpClient.BaseAddress = new Uri(_appBaseAddress);
  383. httpClient.DefaultRequestHeaders.Accept.Add(
  384. new MediaTypeWithQualityHeaderValue("application/json"));//设置accept标头,告诉JSON是可接受的响应类型
  385. var url = "api/identity/users/login";
  386. var loginUser = new LoginInputDto()
  387. {
  388. UserName = userId,
  389. Password = password
  390. };
  391. var sendData = JsonConvert.SerializeObject(loginUser);
  392. using (HttpContent httpContent = new StringContent(sendData))
  393. {
  394. httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
  395. HttpResponseMessage response = await httpClient.PostAsync(url, httpContent);
  396. string result;
  397. if (!response.IsSuccessStatusCode)
  398. {
  399. result = response.Content.ReadAsStringAsync().Result;
  400. throw new Exception("http通信错误:" + response.StatusCode + ",结果:" + result);
  401. }
  402. result = await response.Content.ReadAsStringAsync();
  403. var restultDto = JsonConvert.DeserializeObject<WebApiOutDto<LoginOutDataDto>>(result);
  404. if (restultDto == null)
  405. {
  406. throw new Exception("返回结果是空");
  407. }
  408. if (restultDto.Code != 1)
  409. {
  410. throw new Exception($"登录失败{restultDto.Message}");
  411. }
  412. _accesToken = restultDto.Data.access_token;
  413. return restultDto;
  414. }
  415. }
  416. }
  417. }
  418. private async Task CheckLoginAsync()
  419. {
  420. if (string.IsNullOrWhiteSpace(_accesToken))
  421. {
  422. await LoginAsync();
  423. }
  424. else
  425. {
  426. var handler = new JwtSecurityTokenHandler();
  427. var payload = handler.ReadJwtToken(_accesToken).Payload;
  428. var claims = payload.Claims;
  429. var exp = claims.First(claim => claim.Type == "exp").Value;
  430. if (exp == null)
  431. {
  432. await LoginAsync();
  433. }
  434. else
  435. {
  436. if (long.TryParse(exp, out var expires))
  437. {
  438. var expireTime = DateTimeOffset.FromUnixTimeSeconds(expires).LocalDateTime;
  439. if (expireTime <= DateTime.Now)
  440. {
  441. await LoginAsync();
  442. }
  443. }
  444. else
  445. {
  446. await LoginAsync();
  447. }
  448. }
  449. }
  450. }
  451. private async Task<WebApiOutDto<LoginOutDataDto>> LoginAsync()
  452. {
  453. if (string.IsNullOrWhiteSpace(AppUser))
  454. {
  455. throw new Exception("SelfUser不能为空");
  456. }
  457. if (string.IsNullOrWhiteSpace(AppPassword))
  458. {
  459. throw new Exception("SelfPassword不能为空");
  460. }
  461. var relult = await LoginAsync(AppUser, AppPassword);
  462. return relult;
  463. }
  464. #endregion
  465. }
  466. }