using System.Text; using System.Text.RegularExpressions; using System.ComponentModel.DataAnnotations; using System.Collections.Concurrent; using System.Security.Cryptography; using System.Text.Json; using System.Net.Http.Json; using ReZero.DependencyInjection; using Newtonsoft.Json.Linq; using Microsoft.Extensions.Logging; using System.Threading.Tasks; using medical.transfomer.business; namespace medical.insu.transfomer { /// /// 定义InsuranceRequest类,用于替代缺失的引用 /// public class InsuranceRequest { public string MsgId { get; set; } = string.Empty; public string MdtrtareaAdmvs { get; set; } = string.Empty; public string RecerSysCode { get; set; } = string.Empty; public string Infver { get; set; } = string.Empty; public int OpterType { get; set; } public string Opter { get; set; } = string.Empty; public string OpterName { get; set; } = string.Empty; public DateTime InfTime { get; set; } public string FixmedinsCode { get; set; } = string.Empty; public string FixmedinsName { get; set; } = string.Empty; public string Input { get; set; } = string.Empty; public string InsuplcAdmdvs { get; set; } = string.Empty; public string Signtype { get; set; } = string.Empty; public string Infno { get; set; } = string.Empty; } /// /// 定义ResponseHeader类,用于替代缺失的引用 /// public class ResponseHeader { public string Version { get; set; } = string.Empty; public string SenderCode { get; set; } = string.Empty; public string ReceiverCode { get; set; } = string.Empty; public string MsgId { get; set; } = string.Empty; public string InfTime { get; set; } = string.Empty; public string ResultCode { get; set; } = string.Empty; public string ResultMsg { get; set; } = string.Empty; public string SignatureAlgorithm { get; set; } = string.Empty; public string EncryptionAlgorithm { get; set; } = string.Empty; } /// /// 定义Response类,用于替代缺失的引用 /// public class Response { public ResponseHeader Header { get; set; } = new ResponseHeader(); public string Body { get; set; } = string.Empty; public string Signature { get; set; } = string.Empty; } /// /// 业务服务接口 /// public interface IInsuranceBusinessService { object Execute(InsuranceRequest request); } public class MedicalInsuranceService: IScopeContract { private readonly ConcurrentDictionary _serviceCache = new(); private readonly TransformerFactory _transformerFactory; private readonly ILogger _logger; public MedicalInsuranceService( TransformerFactory transformerFactory, ILogger logger) { _transformerFactory = transformerFactory; _logger = logger; } /// /// 处理医保交易请求 /// /// 操作类型 /// 交易数据 /// 处理结果 public async Task ProcessMedicalInsurance(string action, JObject data) { try { _logger.LogInformation($"开始处理医保交易请求: {action}"); // 使用转换工厂执行医保交易 var result = await _transformerFactory.ExecuteMethod(action, data); _logger.LogInformation($"医保交易请求处理完成: {action}"); return result; } catch (Exception ex) { _logger.LogError(ex, $"处理医保交易请求异常: {action}"); return new { code = -1, msg = $"处理请求异常: {ex.Message}" }; } } public void ValidateRequest(InsuranceRequest request) { if (string.IsNullOrEmpty(request.MsgId)) throw new ValidationException("报文ID不能为空"); if (string.IsNullOrEmpty(request.MdtrtareaAdmvs)) throw new ValidationException("就医地医保区划不能为空"); if (string.IsNullOrEmpty(request.RecerSysCode)) throw new ValidationException("接收方系统代码不能为空"); if (string.IsNullOrEmpty(request.Infver)) throw new ValidationException("接口版本号不能为空"); if (string.IsNullOrEmpty(request.OpterType.ToString())) throw new ValidationException("经办人类别不能为空"); if (string.IsNullOrEmpty(request.Opter)) throw new ValidationException("经办人不能为空"); if (string.IsNullOrEmpty(request.OpterName)) throw new ValidationException("经办人姓名不能为空"); // 假设 request.InfTime 现在是 DateTime 类型,将其转换为字符串进行判断 if (string.IsNullOrEmpty(request.InfTime.ToString("yyyyMMddHHmmss"))) throw new ValidationException("交易时间不能为空"); if (string.IsNullOrEmpty(request.FixmedinsCode)) throw new ValidationException("定点医药机构编号不能为空"); if (string.IsNullOrEmpty(request.FixmedinsName)) throw new ValidationException("定点医药机构名称不能为空"); } public IInsuranceBusinessService GetServiceByInfoNo(string infoNo) { return _serviceCache.GetOrAdd(infoNo, key => key switch { // "1101" => new PersonInfoService(), // "2101" => new RegistrationService(), // "2201" => new PreSettlementService(), // _ => throw new BusinessException($"未知的交易编号: {key}") _ => null }); } /// /// 入口方法 /// /// /// public Response ProcessRequest(InsuranceRequest request) { ValidateRequest(request); ValidateParameterFormat(request); VerifySignature(request); var service = GetServiceByInfoNo(request.Infno); if (service == null) { throw new InvalidOperationException($"未找到处理服务: {request.Infno}"); } var result = service.Execute(request); return new Response { Header = GenerateResponseHeader(request), Body = EncryptData(result), Signature = GenerateSignature(result) }; } /// /// 新增参数格式验证 /// /// /// public static void ValidateParameterFormat(InsuranceRequest request) { // 增强msgid格式校验 if (!Regex.IsMatch(request.MsgId, @"^\d{12}\d{14}\d{4}$")) throw new ValidationException("报文ID格式必须为12位机构编号+14位时间+4位流水号"); // 条件必填验证 if (!string.IsNullOrEmpty(request.Input) && string.IsNullOrEmpty(request.InsuplcAdmdvs)) throw new ValidationException("当交易输入包含人员编号时,参保地医保区划为必填项"); // 版本号格式校验 if (!Regex.IsMatch(request.Infver, @"^V\d+\.\d+$")) throw new ValidationException("接口版本号格式应为VX.X"); // 签名类型校验 if (!string.IsNullOrEmpty(request.Signtype) && !new[] { "SM2", "SM3" }.Contains(request.Signtype)) throw new ValidationException("签名类型只支持SM2/SM3"); // 由于 request.InfTime 是 DateTime 类型,先将其转换为指定格式的字符串再进行正则匹配 if (!Regex.IsMatch(request.InfTime.ToString("yyyyMMddHHmmss"), @"^\d{14}$")) throw new ValidationException("交易时间格式必须为yyyyMMddHHmmss"); if (request.OpterName?.Length > 50) throw new ValidationException("经办人姓名不能超过50个字符"); } /// /// 增强版响应头生成 /// /// /// public static ResponseHeader GenerateResponseHeader(InsuranceRequest request) { return new ResponseHeader { Version = "1.0", // 由于 _config 不存在,这里假设添加一个默认值,实际使用时需要根据业务逻辑修改 SenderCode = "DefaultInstitutionCode", ReceiverCode = request.FixmedinsCode, MsgId = Guid.NewGuid().ToString("N").ToUpper(), InfTime = DateTime.Now.ToString("yyyyMMddHHmmss"), ResultCode = "1000", ResultMsg = "处理成功", SignatureAlgorithm = "HMAC-SHA256", EncryptionAlgorithm = "AES-256-GCM" }; } /// /// 完整签名验证流程 /// /// /// public static void VerifySignature(InsuranceRequest request) { var rawData = $"{request.MsgId}{request.InfTime}{request.FixmedinsCode}"; var hmac = new HMACSHA256(Encoding.UTF8.GetBytes("DefaultSignKey")); var computedSignature = hmac.ComputeHash(Encoding.UTF8.GetBytes(rawData)); // 由于 InsuranceRequest 未包含 Signature 的定义,这里假设添加一个默认空字符串处理 if (!computedSignature.SequenceEqual(Convert.FromBase64String(""))) // 由于 SecurityException 可能未找到,使用更通用的 InvalidOperationException 替代 throw new InvalidOperationException("数字签名验证失败"); } /// /// 医保系统通信模块 /// /// /// /// public async Task CallInsuranceSystem(string endpoint, object payload) { // 由于 _httpClientFactory 不存在,使用新创建的 HttpClient 实例替代 using var client = new HttpClient(); // 由于 _config 不存在,暂时使用一个默认的 API Key,实际使用时需根据业务逻辑修改 client.DefaultRequestHeaders.Add("X-Medicare-API-Key", "DefaultApiKey"); var content = new StringContent( // 引入 System.Text.Json 命名空间以使用 JsonSerializer System.Text.Json.JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json"); var response = await client.PostAsync(endpoint, content); response.EnsureSuccessStatusCode(); return await response.Content.ReadFromJsonAsync(); } public static string EncryptData(object data) { var json = JsonSerializer.Serialize(data); // 由于 AesUtility 不存在,使用 .NET 内置的 AES 加密实现 // 定义一个临时的 AES 加密方法 static string EncryptWithAes(string plainText, string key) { byte[] encrypted; using var aesAlg = Aes.Create(); { aesAlg.Key = Encoding.UTF8.GetBytes(key); aesAlg.GenerateIV(); ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV); using (MemoryStream msEncrypt = new MemoryStream()) { using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) { using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) { swEncrypt.Write(plainText); } encrypted = msEncrypt.ToArray(); } } // 将 IV 和加密后的数据拼接,以方便后续解密 byte[] combinedIvCt = new byte[aesAlg.IV.Length + encrypted.Length]; Array.Copy(aesAlg.IV, 0, combinedIvCt, 0, aesAlg.IV.Length); Array.Copy(encrypted, 0, combinedIvCt, aesAlg.IV.Length, encrypted.Length); return Convert.ToBase64String(combinedIvCt); } } // 由于 _config 不存在,使用一个默认的加密密钥替代,实际使用时需根据业务逻辑修改 return EncryptWithAes(json, "DefaultEncryptionKey"); } public static string GenerateSignature(object data) { var json = JsonSerializer.Serialize(data); // 由于 HMACSHA256.HashData 没有单参数重载,需要创建 HMACSHA256 实例来计算哈希值 using var hmac = new HMACSHA256(); { byte[] hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(json)); return Convert.ToBase64String(hashBytes); } } } }