using Newtonsoft.Json.Linq; using PTMedicalInsurance.Helper; using PTMedicalInsurance.Variables; using System; using System.IO; using System.IO.Compression; using System.Net.Http; using System.Text; using System.Threading.Tasks; using System.Xml.Linq; namespace PTMedicalInsurance.Business { public class ElectronicSettlementCertificate { public string ecSettlCertNo; public string upldBchno; private string xmlPath; private string folderPath; private string xmlName; private string pdfName; private string savePath; //保存路径 private InvokeHelper invoker = new InvokeHelper(); private MIIrisServices mIs = new MIIrisServices(); public ElectronicSettlementCertificate() { } // 路径属性 public string SavePath { get { return savePath; } // 获取 set { if (string.IsNullOrEmpty(value)) { throw new ArgumentException("路径不能为空", nameof(value)); } savePath = value; // 设置 if (!Directory.Exists(savePath)) { Directory.CreateDirectory(savePath); } } } #region 获取入参 public JObject Get4901Input(JObject joIn) { //JoIn包含 患者数电号 JObject joRtn = invoker.invokeHISService(JsonHelper.setIrisInpar("05110041", joIn).ToString(), "获取该数电号对应的数电入参"); //测试服05110039 return joRtn; } #endregion #region 解构入参 /// /// 异步下载,会造成压缩时文件还没生成,导致压缩包内容与实际文件夹内容不符 /// /// /// /// private async Task DownloadPdfFileAsync(string url, string filePath) { try { using (var httpClient = new HttpClient()) { // 发送GET请求获取内容 HttpResponseMessage response = await httpClient.GetAsync(url); if (response.IsSuccessStatusCode) { // 读取内容到字节数组 byte[] fileBytes = await response.Content.ReadAsByteArrayAsync(); // 将字节数组写入文件 File.WriteAllBytes(filePath, fileBytes); return true; } else { Console.WriteLine($"无法下载文件,状态码:{response.StatusCode}"); return false; } } } catch (Exception ex) { Console.WriteLine($"下载过程中发生错误:{ex.Message}"); return false; } } /// /// 同步下载 /// /// /// /// private bool DownloadPdfFile(string url, string filePath) { try { using (var httpClient = new HttpClient()) { // 发送GET请求获取内容 HttpResponseMessage response = httpClient.GetAsync(url).Result; if (response.IsSuccessStatusCode) { // 读取内容到字节数组 byte[] fileBytes = response.Content.ReadAsByteArrayAsync().Result; // 将字节数组写入文件 File.WriteAllBytes(filePath, fileBytes); return true; } else { Console.WriteLine($"无法下载文件,状态码:{response.StatusCode}"); return false; } } } catch (Exception ex) { Console.WriteLine($"下载过程中发生错误:{ex.Message}"); return false; } } /// /// 保存XML文件 /// /// private void SaveXML(JArray jaXML) { foreach (JObject jo in jaXML) { //税务数电票结构化数据文件(xml),命名规则为:电子结算凭证号码-extinfo ,因可能存在多条结算信息, 命名规则为:电子结算凭证号码-结算ID-extinfo ecSettlCertNo = JsonHelper.getDestValue(jo, "tktextinfo.billInfo.elecSetlCertNo"); string setlId = JsonHelper.getDestValue(jo, "tktextinfo.mdtrtInfo.setlId"); //xmlName = $"{ecSettlCertNo}-{setlId}-extinfo.xml"; xmlName = $"{ecSettlCertNo}-extinfo.xml"; pdfName = $"{ecSettlCertNo}.pdf"; // 创建临时XML文件 folderPath = $@"{savePath}\ElecXml\{ecSettlCertNo}"; xmlPath = $@"{savePath}\ElecXml\{ecSettlCertNo}\{xmlName}"; if (!Directory.Exists(folderPath)) { Directory.CreateDirectory(folderPath); } XmlHelper xmler = new XmlHelper(); string xmlContent = xmler.ToXML(jo.ToString()); XElement xe = XElement.Parse(xmlContent); string xml = xmler.setInput(xe); File.WriteAllText(xmlPath, xml, Encoding.UTF8); } } /// /// 压缩指定的文件夹及其内容到ZIP文件中。 /// /// 源文件夹路径。 /// 输出的ZIP文件路径。 private void CompressFolderToZIP(string sourceFolderPath, string zipFilePath) { if (!Directory.Exists(sourceFolderPath)) { throw new DirectoryNotFoundException($"源文件夹不存在: {sourceFolderPath}"); } try { using (FileStream fileStream = new FileStream(zipFilePath, FileMode.Create)) { using (ZipArchive archive = new ZipArchive(fileStream, ZipArchiveMode.Create, true)) { //AddFolderToZip(archive, sourceFolderPath, Path.GetFileName(sourceFolderPath)); AddFolderToZip(archive, sourceFolderPath, ""); //相对路径,为空则表示ZIP无第一层 } } } catch (Exception ex) { throw new Exception($"压缩文件夹时发生错误: {ex.Message}"); } } /// /// 递归地将文件夹添加到ZIP存档中。 /// /// ZIP存档对象。 /// 当前处理的文件夹路径。 /// 基础路径,用于构建ZIP内的相对路径。 private static void AddFolderToZip(ZipArchive archive, string folderPath, string basePath) { DirectoryInfo directoryInfo = new DirectoryInfo(folderPath); // 添加当前文件夹中的所有文件到ZIP存档 foreach (FileInfo fileInfo in directoryInfo.GetFiles()) { string entryPath = Path.Combine(basePath, fileInfo.Name); ZipArchiveEntry entry = archive.CreateEntry(entryPath); using (FileStream stream = fileInfo.OpenRead()) { using (Stream entryStream = entry.Open()) { stream.CopyTo(entryStream); } } } // 递归地处理所有子文件夹 foreach (DirectoryInfo subDirInfo in directoryInfo.GetDirectories()) { string subFolderPath = Path.Combine(folderPath, subDirInfo.Name); string subBasePath = Path.Combine(basePath, subDirInfo.Name); AddFolderToZip(archive, subFolderPath, subBasePath); } } /// /// 转换位Base64 /// /// /// private string ZipTobase64(string path) { byte[] zipBytes = File.ReadAllBytes(path); return Convert.ToBase64String(zipBytes); } private string FormatToFiveDigits(int seconds) { // 确保秒数不会超过五位数的最大值 if (seconds > 86400) throw new ArgumentOutOfRangeException("秒", "一天的秒数不能超过86400"); // 使用格式化字符串将秒数转换为五位数的字符串 return seconds.ToString("D5"); } /// /// 根据当天0点计算当前时刻的5位时间戳,然后加上当前日期,组成序号。要求每个上传时间需要超过1秒,否则会有重复问题 /// /// private string GetSeqNoBySecondStamp() { // 获取当天零点的时间 DateTime todayMidnight = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day); // 计算从当天零点到现在的时间差(秒) TimeSpan timeSinceMidnight = DateTime.Now - todayMidnight; int secondsSinceMidnight = (int)timeSinceMidnight.TotalSeconds; // 将秒数转换为5位时间戳 return DateTime.Now.ToString("yyyyMMdd") + FormatToFiveDigits(secondsSinceMidnight); //2024102168281 //return DateTime.Now.ToString("yyyyMMdd") + "68282"; // 68281 } /// /// 正式解构HIS返回的入参,包括医保编码转换,PDF下载,XML文件保存,ZIP压缩,zip转Base64,业务编号命名等 /// /// /// public JObject Convert4901Input(JObject joSource) { //调用医保服务开始转换为医保对应的编码 09010127 JObject joConvertRtn = mIs.convertEcSettlUploadInpar(joSource); JObject joData = JObject.Parse(JsonHelper.getDestValue(joConvertRtn,"data")); //指定PDF,xml文件,xml文件夹路径 //保存xml ,保存过程中给路径等私有变量赋值 SaveXML(JArray.Parse(JsonHelper.getDestValue(joData, "xml"))); //保存PDF string pdfUrl = JsonHelper.getDestValue(joData, "pdfUrl"); //DownloadPdfFileAsync(pdfUrl,$@"{folderPath}\{pdfName}"); DownloadPdfFile(pdfUrl, $@"{folderPath}\{pdfName}"); //压缩文件为ZIP,并保存到文件夹同级 CompressFolderToZIP(folderPath, $@"{savePath}\ElecXml\{ecSettlCertNo}.zip"); //转换ZIP为Base64 string base64 = ZipTobase64($@"{savePath}\ElecXml\{ecSettlCertNo}.zip"); joData["ftfileCompac"] = base64; joData["filename"] = $@"{ecSettlCertNo}.zip"; joData["elecSetlCertCnt"] = int.Parse(joData["elecSetlCertCnt"].ToString()) + 1; upldBchno = GetSeqNoBySecondStamp(); joData["upldBchno"] = upldBchno;//上传日期年月日加5位顺序号 //移除PDF和xml节点 joData.Remove("xml"); joData.Remove("pdfUrl"); return joData; } #endregion #region 查询,反写数据库 /// /// 查询患者电子发票 /// /// /// public JObject QueryEcSettlCertList(JObject joIn) { //JoIn包含 起止时间,医院ID,接口ID,患者姓名,患者数电号 JObject joHisRtn = invoker.invokeHISService(JsonHelper.setIrisInpar("05110040", joIn).ToString(), "查询某时间段内或某患者电子结算凭证清单"); //测试服为05110038 string errMsg; if (JsonHelper.parseIrisRtnValue(joHisRtn, out errMsg) != 0) { return joHisRtn; } JArray jaData = JArray.Parse(JsonHelper.getDestValue(joHisRtn,"data")); JObject joInsuRtn = invoker.invokeInsuService(JsonHelper.setIrisInpar("09010128", jaData).ToString(), "根据传入的电子凭证记录匹配上传记录表"); return joInsuRtn; } /// /// 查询患者电子发票 /// /// /// public JObject MatchUploadRecord(JObject joIn) { //JoIn包含 起止时间,医院ID,接口ID,患者姓名,患者数电号 JObject joRtn = invoker.invokeHISService(JsonHelper.setIrisInpar("05110040", joIn).ToString(), "查询某时间段内或某患者电子结算凭证清单"); return joRtn; } /// /// 成功后更新记录表 /// /// /// public JObject Update(JObject joIn) { //JoIn包含 起止时间,医院ID,接口ID,患者姓名,患者数电号 JObject joInTmp = JsonHelper.setIrisInpar("02020007", joIn); joInTmp["session"][0]["userID"] = "166"; joInTmp["session"][0]["hospID"] = Global.inf.hospitalDr; JObject joRtn = invoker.invokeInsuService(joInTmp.ToString(),"更新通用记录表"); return joRtn; } #endregion #region 具体功能点封装 /// /// 上传 /// /// /// public JObject Upload(JObject joIn) { JObject joRtn = invoker.invokeCenterService("4901", JsonHelper.setCenterInpar("4901",joIn)); return joRtn; } /// /// 重新上传 /// /// /// public JObject ReUpload(JObject joIn) { JObject joRtn = invoker.invokeCenterService("4905", JsonHelper.setCenterInpar("4905", joIn)); return joRtn; } /// /// 查询上传结果 /// /// /// public JObject QueryUploadResult(JObject joIn) { JObject joRtn = invoker.invokeCenterService("4902", JsonHelper.setCenterInpar("4902", joIn)); return joRtn; } /// /// 查询电子凭证上传状态 /// /// /// public JObject QueryUploadStatus(JObject joIn) { JObject joRtn = invoker.invokeCenterService("5501", JsonHelper.setCenterInpar("5501", joIn)); return joRtn; } #endregion #region 具体流程封装 #endregion } }