From 61bf9556cf570e75bffcce42e6e12e2316331ff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=94=A6=E9=BA=9F=20=E7=8E=8B?= Date: Tue, 21 Apr 2026 10:05:40 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96OA=E7=94=A8=E5=8D=B0?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=8B=E8=BD=BD=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E6=94=B9=E8=BF=9B=E6=96=87=E4=BB=B6=E6=8F=90=E5=8F=96=E5=92=8C?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Modules/TradeModule/TradeOAService.cs | 128 +++++++++++------- 1 file changed, 82 insertions(+), 46 deletions(-) diff --git a/YLErpDAL/Modules/TradeModule/TradeOAService.cs b/YLErpDAL/Modules/TradeModule/TradeOAService.cs index 08ca0ee4..29c670ea 100644 --- a/YLErpDAL/Modules/TradeModule/TradeOAService.cs +++ b/YLErpDAL/Modules/TradeModule/TradeOAService.cs @@ -405,11 +405,10 @@ namespace YLErp.Modules.TradeModule continue; } - // 3. 判断用印是否完成:fj 字段为空表示未盖完章,有值表示已用印 - var fj = flowData.flowInfos?["fj"]; - if (fj == null || fj.Type == Newtonsoft.Json.Linq.JTokenType.Null) + // 3. 判断用印是否完成:检查 detailMap 中是否有用印文件 + if (!HasStampFiles(flowData.flowInfos)) { - logger.Info($"OA用印未完成,fj为空,requestid:{oa.oa_fileid}"); + logger.Info($"OA用印未完成,detailMap 中无文件信息,requestid:{oa.oa_fileid}"); continue; } @@ -471,31 +470,55 @@ namespace YLErp.Modules.TradeModule } /// - /// 下载 OA 用印文件 + /// 通过 OA 接口下载用印文件 /// - /// 文件下载地址 + /// 文件 ID /// 文件字节数组 - private byte[] DownloadOAFile(string fileUrl) + private byte[] DownloadOAFile(string fileId) { try { - if (string.IsNullOrEmpty(fileUrl)) + if (string.IsNullOrEmpty(fileId)) { return null; } - logger.Info($"下载OA用印文件: {fileUrl}"); + var oaConfigSection = AppManager.GetConfiguration().GetSection("oa_confg"); + var baseUrl = oaConfigSection["BaseUrl"]; + var downloadFileUrl = oaConfigSection["DownloadFileUrl"]; + var systemToken = oaConfigSection["SystemToken"]; + var systemName = oaConfigSection["SystemName"]; - var response = _httpClient.GetAsync(fileUrl).Result; - response.EnsureSuccessStatusCode(); - var fileBytes = response.Content.ReadAsByteArrayAsync().Result; + if (string.IsNullOrEmpty(baseUrl) || string.IsNullOrEmpty(downloadFileUrl)) + { + logger.Info("OA下载接口配置不完整"); + return null; + } - logger.Info($"下载OA用印文件成功,大小: {fileBytes.Length} 字节"); - return fileBytes; + var requestUrl = $"{baseUrl.TrimEnd('/')}/{downloadFileUrl.TrimStart('/')}?fileid={Uri.EscapeDataString(fileId)}&systemToken={Uri.EscapeDataString(systemToken)}&systemName={Uri.EscapeDataString(systemName ?? string.Empty)}"; + logger.Info($"通过OA接口下载用印文件: fileid={fileId}"); + + using (var httpClient = new System.Net.Http.HttpClient { Timeout = TimeSpan.FromMinutes(2) }) + { + var response = httpClient.GetAsync(requestUrl).Result; + var fileBytes = response.Content.ReadAsByteArrayAsync().Result; + + // 检查返回的是否为错误 JSON + if (response.Content.Headers.ContentType?.MediaType == "application/json" || + (fileBytes.Length > 0 && fileBytes[0] == (byte)'{')) + { + var responseStr = System.Text.Encoding.UTF8.GetString(fileBytes); + logger.Error($"下载用印文件接口返回错误: {responseStr}"); + return null; + } + + logger.Info($"通过OA接口下载用印文件成功,大小: {fileBytes.Length} 字节"); + return fileBytes; + } } catch (Exception ex) { - logger.Error($"下载OA用印文件失败: {fileUrl}, 错误:{ex.Message}", ex); + logger.Error($"通过OA接口下载用印文件失败: fileid={fileId}, 错误:{ex.Message}", ex); return null; } } @@ -518,16 +541,15 @@ namespace YLErp.Modules.TradeModule return new TradeOAResult { TradeId = oa.trade_id, Success = false, Message = "未找到确认书文档" }; } - // 从 fj 字段提取用印文件信息 - var fj = queryData.flowInfos?["fj"]; - if (!TryExtractFileFromFj(fj, out var fileUrl, out var fileName)) + // 从 detailMap 中提取用印文件信息 + if (!TryExtractFileFromDetailMap(queryData.flowInfos, out var fileId, out var fileName)) { - logger.Info($"无法从 fj 中提取用印文件信息,contract_code:{oa.contract_code}"); + logger.Info($"无法从 detailMap 中提取用印文件信息,contract_code:{oa.contract_code}"); return new TradeOAResult { TradeId = oa.trade_id, Success = false, Message = "无法提取用印文件信息" }; } - // 下载用印文件 - var fileBytes = DownloadOAFile(fileUrl); + // 通过 OA 接口下载用印文件 + var fileBytes = DownloadOAFile(fileId); if (fileBytes == null || fileBytes.Length == 0) { logger.Info($"未获取到用印文件,contract_code:{oa.contract_code}"); @@ -597,47 +619,61 @@ namespace YLErp.Modules.TradeModule } /// - /// 从 fj 字段尝试提取文件下载地址和文件名 - /// fj 格式:{"annexId":"url1,url2","annexName":"name1,name2"} + /// 判断 flowInfos 中是否存在用印文件 /// - private bool TryExtractFileFromFj(Newtonsoft.Json.Linq.JToken fj, out string fileUrl, out string fileName) + private bool HasStampFiles(Newtonsoft.Json.Linq.JObject flowInfos) { - fileUrl = null; - fileName = null; - - if (fj == null || fj.Type == Newtonsoft.Json.Linq.JTokenType.Null) + var detailMap = flowInfos?["detailMap"]; + if (detailMap == null || !detailMap.Any()) { return false; } - // 如果是字符串,直接当作 URL - if (fj.Type == Newtonsoft.Json.Linq.JTokenType.String) + foreach (var detail in detailMap) { - fileUrl = fj.ToString(); - fileName = Path.GetFileName(fileUrl); - return !string.IsNullOrEmpty(fileUrl); + var fileInfos = detail["gatewayFileRequestFileInfo"]; + if (fileInfos != null && fileInfos.Any()) + { + return true; + } } - // 解析 annexId(逗号分隔的 URL 数组)和 annexName(逗号分隔的文件名数组) - var annexIdStr = fj["annexId"]?.ToString(); - var annexNameStr = fj["annexName"]?.ToString(); + return false; + } - if (!string.IsNullOrEmpty(annexIdStr)) + /// + /// 从 detailMap 中提取用印文件 ID 和文件名 + /// + private bool TryExtractFileFromDetailMap(Newtonsoft.Json.Linq.JObject flowInfos, out string fileId, out string fileName) + { + fileId = null; + fileName = null; + + var detailMap = flowInfos?["detailMap"]; + if (detailMap == null || !detailMap.Any()) { - fileUrl = annexIdStr.Split(',').Select(s => s.Trim()).FirstOrDefault(s => !string.IsNullOrEmpty(s)); + return false; } - if (!string.IsNullOrEmpty(annexNameStr)) + foreach (var detail in detailMap) { - fileName = annexNameStr.Split(',').Select(s => s.Trim()).FirstOrDefault(s => !string.IsNullOrEmpty(s)); + var fileInfos = detail["gatewayFileRequestFileInfo"]; + if (fileInfos != null && fileInfos.Any()) + { + var firstFile = fileInfos.FirstOrDefault(); + if (firstFile != null) + { + fileId = firstFile["id"]?.ToString(); + fileName = firstFile["fileName"]?.ToString(); + if (!string.IsNullOrEmpty(fileId)) + { + return true; + } + } + } } - if (string.IsNullOrEmpty(fileName) && !string.IsNullOrEmpty(fileUrl)) - { - fileName = Path.GetFileName(fileUrl); - } - - return !string.IsNullOrEmpty(fileUrl); + return false; } ///