PusherProviderService.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. using DataSharing.RawData;
  2. using DataSharing.SendTask;
  3. using DataSharing.Share.Dtos.Province;
  4. using DataSharing.Share.Dtos.Province.HuiJu;
  5. using DataSharing.Share.Dtos.Province.XieTong;
  6. using DataSharing.Share.Dtos.Province.XieTong.Receive;
  7. using DataSharing.Share.Enums;
  8. using DotNetCore.CAP;
  9. using MapsterMapper;
  10. using Microsoft.Extensions.Logging;
  11. using Newtonsoft.Json;
  12. using System.Net;
  13. using XF.Domain.Dependency;
  14. using XF.Domain.Repository;
  15. namespace DataSharing.Province
  16. {
  17. public class PusherProviderService : IPusherProviderService, IScopeDependency
  18. {
  19. #region 注入
  20. private readonly IMapper _mapper;
  21. private readonly ILogger<PusherProviderService> _logger;
  22. private readonly IChannelConfigurationManager _channelConfigurationManager;
  23. private readonly IHttpClientFactory _httpClientFactory;
  24. private readonly XieTongClient _xieTongClient;
  25. private readonly HuiJuClient _huiJuClient;
  26. private readonly IRepository<DsSendTask> _dsSendTaskRepository;
  27. private readonly IRepository<DsSendCaseInfo> _sendCaseInfoRepository;
  28. private readonly IRepository<DsGetCaseDistrecordSend> _getCaseDistrecordSendRepository;
  29. private readonly ICapPublisher _capPublisher;
  30. private readonly IRepository<DsSendTaskInfo> _dsSendTaskInfoRepository;
  31. private readonly IRepository<DsOrder> _dataOrderRepository;
  32. private readonly IRepository<DsTelCall> _dsTelCallRepository;
  33. /// <summary>
  34. ///
  35. /// </summary>
  36. /// <param name="mapper"></param>
  37. /// <param name="logger"></param>
  38. /// <param name="channelConfigurationManager"></param>
  39. /// <param name="httpClientFactory"></param>
  40. /// <param name="xieTongClient"></param>
  41. /// <param name="huiJuClient"></param>
  42. /// <param name="dsSendTaskRepository"></param>
  43. /// <param name="sendCaseInfoRepository"></param>
  44. /// <param name="getCaseDistrecordSendRepository"></param>
  45. /// <param name="capPublisher"></param>
  46. /// <param name="dsSendTaskInfoRepository"></param>
  47. /// <param name="dataOrderRepository"></param>
  48. public PusherProviderService(IMapper mapper, ILogger<PusherProviderService> logger,
  49. IChannelConfigurationManager channelConfigurationManager,
  50. IHttpClientFactory httpClientFactory,
  51. XieTongClient xieTongClient,
  52. HuiJuClient huiJuClient,
  53. IRepository<DsSendTask> dsSendTaskRepository,
  54. IRepository<DsSendCaseInfo> sendCaseInfoRepository,
  55. IRepository<DsGetCaseDistrecordSend> getCaseDistrecordSendRepository,
  56. ICapPublisher capPublisher,
  57. IRepository<DsSendTaskInfo> dsSendTaskInfoRepository,
  58. IRepository<DsOrder> dataOrderRepository,
  59. IRepository<DsTelCall> dsTelCallRepository)
  60. {
  61. _mapper = mapper;
  62. _logger = logger;
  63. _channelConfigurationManager = channelConfigurationManager;
  64. _httpClientFactory = httpClientFactory;
  65. _xieTongClient = xieTongClient;
  66. _huiJuClient = huiJuClient;
  67. _dsSendTaskRepository = dsSendTaskRepository;
  68. _sendCaseInfoRepository = sendCaseInfoRepository;
  69. _getCaseDistrecordSendRepository = getCaseDistrecordSendRepository;
  70. _capPublisher = capPublisher;
  71. _dsSendTaskInfoRepository = dsSendTaskInfoRepository;
  72. _dataOrderRepository = dataOrderRepository;
  73. _dsTelCallRepository = dsTelCallRepository;
  74. }
  75. #endregion
  76. /// <summary>
  77. /// 省平台推送数据
  78. /// </summary>
  79. /// <param name="dto"></param>
  80. /// <param name="cancellationToken"></param>
  81. /// <returns></returns>
  82. public async Task SendProvinceDataPusher(DsSendTask dto, CancellationToken cancellationToken)
  83. {
  84. if (dto is null)
  85. return;
  86. var configProvince = _channelConfigurationManager.GetConfigurationProvince();
  87. if (configProvince.SendTaskStartTime != null && configProvince.SendTaskStartTime > dto.GenerationTime)
  88. {
  89. dto.IsSuccess = true;
  90. await _dsSendTaskRepository.UpdateAsync(dto, cancellationToken);
  91. }
  92. var name = GetName(dto.Path);
  93. _logger.LogWarning("省请求参数:" + "--------------" + dto.Request);
  94. ProvinceResponse result = new();
  95. if (dto.PathType == EPathType.HuiJu) //汇聚推送
  96. result = await _huiJuClient.RequestAsync<ProvinceResponse>(configProvince.HuiJu + dto.Path, dto.HttpMethod, dto.Request, cancellationToken);
  97. else if (dto.PathType == EPathType.XieTong)//协同推送
  98. result = await _xieTongClient.RequestAsync<ProvinceResponse>(configProvince.XieTong + dto.Path, dto.HttpMethod, dto.Request, cancellationToken);
  99. else if (dto.PathType == EPathType.File) //附件
  100. {
  101. if (dto != null && dto.FileJson != null && dto.FileJson.Count > 0)
  102. {
  103. var itemFile = dto.FileJson[0];
  104. result = await SendFileData(dto.Request, itemFile.FileId, itemFile.FileId, cancellationToken);
  105. }
  106. }
  107. _logger.LogWarning("省接口返回:" + name + "--------------" + Newtonsoft.Json.JsonConvert.SerializeObject(result));
  108. if (result is not null)
  109. {
  110. #region 处理推送任务表,推送明细表
  111. //写入明细表
  112. DsSendTaskInfo dsSendTaskInfo = new() { TaskId = dto.Id, Result = result };
  113. //看看需不需要处理一些信息
  114. dto.LastTime = DateTime.Now;
  115. dto.SendTimes = dto.SendTimes + 1;
  116. if (dto.FirstTime is null)
  117. dto.FirstTime = DateTime.Now;
  118. if (result.ReturnInfo is not null && result.ReturnInfo.Code == "1")
  119. {
  120. dto.IsSuccess = true;
  121. dsSendTaskInfo.IsSuccess = true;
  122. }
  123. await _dsSendTaskInfoRepository.AddAsync(dsSendTaskInfo, cancellationToken);
  124. await _dsSendTaskRepository.UpdateAsync(dto, cancellationToken);
  125. #endregion
  126. #region 处理工单的推送时间,用于后面计算及时率
  127. if (dto.TaskType == "SubmitCaseInfo")
  128. {
  129. var dataOrder = System.Text.Json.JsonSerializer.Deserialize<ProvinceListRequest<SubmitCaseInfo>>(dto.Request);
  130. if (dataOrder != null && dataOrder.Data != null)
  131. {
  132. var orderItems = dataOrder.Data.Items;
  133. foreach (var item in orderItems)
  134. {
  135. var dsOrder = await _dataOrderRepository.GetAsync(p => p.ProvinceNo == item.CaseSerial, cancellationToken);
  136. if (dsOrder != null)
  137. {
  138. if (dsOrder.FirstSendProvinceTime is null)
  139. dsOrder.FirstSendProvinceTime = DateTime.Now;
  140. dsOrder.LastSendProvinceTime = DateTime.Now;
  141. await _dataOrderRepository.UpdateAsync(dsOrder);
  142. }
  143. }
  144. }
  145. }
  146. #endregion
  147. #region 处理通话记录推送时间
  148. if (dto.TaskType == "SubmitCaseRecord")
  149. {
  150. var telCall = await _dsTelCallRepository.GetAsync(p => p.TaskId == dto.Id, cancellationToken);
  151. if (telCall != null)
  152. {
  153. if (telCall.FirstSendProvinceTime is null)
  154. telCall.FirstSendProvinceTime = DateTime.Now;
  155. telCall.LastSendProvinceTime = DateTime.Now;
  156. await _dsTelCallRepository.UpdateAsync(telCall, cancellationToken);
  157. }
  158. }
  159. #endregion
  160. }
  161. }
  162. /// <summary>
  163. /// 拉取12315工单办理信息
  164. /// </summary>
  165. /// <param name="CaseSerial"></param>
  166. /// <param name="cancellationToken"></param>
  167. /// <returns></returns>
  168. public async Task GetCaseDistrecordSendPusher(CancellationToken cancellationToken)
  169. {
  170. var listSendCaseInfo = await _sendCaseInfoRepository
  171. .Queryable()
  172. .Where(p => p.IsEnd == false)
  173. .OrderBy(p => p.CreationTime)
  174. .ToListAsync();
  175. //处理数据
  176. if (listSendCaseInfo != null && listSendCaseInfo.Count > 0)
  177. {
  178. foreach (var itemData in listSendCaseInfo)
  179. {
  180. GetCaseDistrecordSendInfo distrecordSendInfo = new() { CaseSerial = itemData.CaseSerial };
  181. #region 处理请求参数
  182. var configProvince = _channelConfigurationManager.GetConfigurationProvince();
  183. var request = new ProvinceRequest<GetCaseDistrecordSendInfo>(configProvince.ClientId, configProvince.ClientSecret);
  184. request.SetData(distrecordSendInfo);
  185. var jsonData = request.ToString();
  186. var baseAddress = configProvince.XieTong;
  187. if (!baseAddress.EndsWith('/'))
  188. baseAddress += "/";
  189. var url = baseAddress + "rest/market/get_case_distrecord_send";
  190. #endregion
  191. var response = await _xieTongClient.RequestAsync<ProvinceDistrecordResponse>(url, "Post", jsonData, cancellationToken);
  192. if (response is null || response.status is null || response.custom is null)
  193. continue;
  194. if (response.status.code != "1")
  195. continue;
  196. //这里处理业务
  197. if (response.custom.STEP_List != null && response.custom.STEP_List.Count > 0)
  198. {
  199. //这里调用业务接口,推送办理数据
  200. List<SharingWorkflowTraceDto> Traces = new();
  201. //遍历返回的数据
  202. foreach (var item in response.custom.STEP_List)
  203. {
  204. //检测当前数据是否存在,如果存在不处理,不存在新增到数据库并推送到业务系统
  205. if (!await _getCaseDistrecordSendRepository.AnyAsync(p => p.CaseSerial == response.custom.CASE_SERIAL && p.RowGuid == item.RowGuid, cancellationToken))
  206. {
  207. var tempData = _mapper.Map<DsGetCaseDistrecordSend>(item);
  208. await _getCaseDistrecordSendRepository.AddAsync(tempData);
  209. Traces.Add(new()
  210. {
  211. HandlerName = item.OperatorName,
  212. HandlerOrgName = item.OperatorouName,
  213. HandleTime = item.HandleTime,
  214. Opinion = item.HandleOpinion
  215. });
  216. }
  217. }
  218. SharingAddOrderTracesDto addOrderTracesDto = new()
  219. {
  220. OrderId = itemData.OrderID,
  221. Traces = Traces
  222. };
  223. //往业务系统推送数据
  224. await _capPublisher.PublishAsync(DataSharing.Share.Mq.EventNames.SharingOrderAddTraces, addOrderTracesDto, cancellationToken: cancellationToken);
  225. }
  226. }
  227. }
  228. }
  229. /// <summary>
  230. /// 附件读取以及附件上传
  231. /// </summary>
  232. /// <param name="dto"></param>
  233. /// <param name="fileName"></param>
  234. /// <param name="fileId"></param>
  235. /// <returns></returns>
  236. private async Task<ProvinceResponse> SendFileData(string request, string fileName, string fileId, CancellationToken cancellationToken)
  237. {
  238. //获取配置信息
  239. var configProvince = _channelConfigurationManager.GetConfigurationProvince();
  240. var businessFile = _channelConfigurationManager.GetConfigurationBusinessFile();
  241. byte[] fileContentBytes = null;
  242. try
  243. {
  244. var baseAddress = businessFile.BaseUrl;
  245. if (!baseAddress.EndsWith('/'))
  246. baseAddress += "/";
  247. string url = string.Format("{0}{1}?Source={2}&Id={3}", baseAddress, businessFile.DownloadUrlAddress, "hotline", fileId);
  248. using (var client = _httpClientFactory.CreateClient())
  249. using (var response = await client.GetAsync(url))
  250. {
  251. if (response.StatusCode == HttpStatusCode.OK)
  252. {
  253. fileName = response.Content.Headers.ContentDisposition.FileNameStar;
  254. using var memoryStream = new MemoryStream();
  255. await response.Content.CopyToAsync(memoryStream);
  256. memoryStream.Seek(0, SeekOrigin.Begin);
  257. fileContentBytes = memoryStream.ToArray();
  258. }
  259. }
  260. if (fileContentBytes != null)
  261. {
  262. //获取附件上传Token
  263. string strToken = await _xieTongClient.GetTokenAsync(cancellationToken);
  264. Dictionary<string, object> dicParam = new()
  265. {
  266. { "params", request } // 第一个接口参数,json格式字符串
  267. };
  268. // 构造字典文件数据
  269. // 接口参数名称为files
  270. CFormUpload.FileParameter fileParameter = new CFormUpload.FileParameter("files", fileContentBytes, fileName, null);
  271. dicParam.Add(fileName, fileParameter);
  272. var baseAddressHuiJu = configProvince.HuiJu;
  273. if (!baseAddressHuiJu.EndsWith('/'))
  274. baseAddressHuiJu += "/";
  275. string strUrl = baseAddressHuiJu + "get_case_material_info";
  276. // 上传附件
  277. string strResult = CFormUpload.MultipartFormDataPost(strUrl, null, dicParam, strToken);
  278. _logger.LogWarning("省接口上传附件返回:--------------" + strResult);
  279. if (!string.IsNullOrEmpty(strResult))
  280. return JsonConvert.DeserializeObject<ProvinceResponse>(strResult);
  281. }
  282. return new ProvinceResponse();
  283. }
  284. catch (Exception ex)
  285. {
  286. return new ProvinceResponse();
  287. }
  288. }
  289. /// <summary>
  290. /// 获取接口名称
  291. /// </summary>
  292. /// <param name="path"></param>
  293. /// <returns></returns>
  294. private string GetName(string path)
  295. {
  296. string name = "";
  297. switch (path)
  298. {
  299. case "get_case_back_apply":
  300. name = "业务协同-退回申请接口";
  301. break;
  302. case "send_supervise_process_info":
  303. name = "业务协同-服务工单督办过程接口";
  304. break;
  305. case "send_supervise_result_info":
  306. name = "业务协同-服务工单督办结果接口";
  307. break;
  308. case "screen_case_info_send":
  309. name = "业务协同-工单发起甄别接口";
  310. break;
  311. case "delay_case_info_send":
  312. name = "业务协同-服务工单申请延时接口";
  313. break;
  314. case "submit_case_info":
  315. name = "业务汇聚-服务工单受理接口";
  316. break;
  317. case "submit_case_record":
  318. name = "业务汇聚-电话记录";
  319. break;
  320. case "get_case_process_receive":
  321. name = "业务协同-服务工单交办处理过程接口";
  322. break;
  323. case "submit_case_process":
  324. name = "业务汇聚-服务工单处理过程接口";
  325. break;
  326. case "submit_case_total":
  327. name = "业务汇聚-统计数据接口";
  328. break;
  329. case "supply_case_info_send":
  330. name = "业务协同-上报补充诉求接口";
  331. break;
  332. case "revoke_case_info":
  333. name = "业务协同-服务工单撤单接口";
  334. break;
  335. case "remind_case_info":
  336. name = "业务协同-服务工单催单接口";
  337. break;
  338. case "get_case_result_receive":
  339. name = "业务协同-服务工单交办处理结果接口";
  340. break;
  341. case "zmhd_case_info_public":
  342. name = "业务协同-政民互动提交公开";
  343. break;
  344. case "get_knowledge_info_send":
  345. name = "业务协同-知识库上报接口";
  346. break;
  347. case "get_knowledge_info_update":
  348. name = "业务协同-知识库变更接口";
  349. break;
  350. case "get_knowledge_info_abandon":
  351. name = "业务协同-知识库下架接口";
  352. break;
  353. case "sendrealtimestatus":
  354. name = "实时服务上报接口";
  355. break;
  356. case "get_visit_info_receive":
  357. name = "业务协同-服务工单交办评价接口";
  358. break;
  359. case "submit_visit_info":
  360. name = "业务汇聚-服务工单回访评价接口";
  361. break;
  362. case "submit_case_result":
  363. name = "业务汇聚-服务工单处理结果接口";
  364. break;
  365. case "submit_case_extends":
  366. name = "业务汇聚-服务工单拓展信息接口";
  367. break;
  368. case "send_case_info":
  369. name = "业务协同-服务工单上报";
  370. break;
  371. case "get_case_material_info":
  372. name = "业务汇聚-材料接口";
  373. break;
  374. default:
  375. break;
  376. }
  377. return name;
  378. }
  379. }
  380. }