// OaApiService.cs using System; using System.Collections.Generic; using System.Dynamic; using System.IO; using System.Net.Http; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; public class OaApiService : IDisposable { private readonly HttpClient _httpClient; private const string AppId = "303233EF-AC39-40C1-8364-AC989C6258A5"; private const string BaseUrl = "http://192.168.1.149:8099/api/ec/dev/auth/"; private const string WorkflowUrl = "http://192.168.1.149:8099/api/workflow/paService/doCreateRequest"; public OaApiService() { _httpClient = new HttpClient(); _httpClient.Timeout = TimeSpan.FromSeconds(30); } public async Task SubmitIQCToOA(dynamic queryObj) { //if (unity.userName.IsNullOrEmpty()) throw new Exception("用户名不允许为空"); //if (unity.sectionCode.IsNullOrEmpty()) throw new Exception("库位编号不允许为空"); //if (unity.barcode.IsNullOrEmpty()) throw new Exception("条码不允许为空"); //if (unity.billNo.IsNullOrEmpty()) throw new Exception("申请单号不允许为空"); try { // 解析请求参数 var query = queryObj; //var query = JObject.FromObject(queryObj); // 1. 注册获取凭证 var registResult = await GetRegistAsync(); var secret = registResult["secrit"].ToString(); var spk = registResult["spk"].ToString(); // 2. 获取访问令牌 var tokenResult = await ApplyTokenAsync(secret, spk); var token = tokenResult["token"].ToString(); // 3. 准备请求头(移除Content-Type设置) _httpClient.DefaultRequestHeaders.Clear(); _httpClient.DefaultRequestHeaders.Add("token", token); _httpClient.DefaultRequestHeaders.Add("appid", AppId); _httpClient.DefaultRequestHeaders.Add("userid", RSAEncrypt("1268", spk)); // 4. 构建请求体 var requestData = BuildRequestData(); // 5. 发送请求 var response = await PostFormAsync(WorkflowUrl, requestData); return JObject.Parse(response); } catch (Exception ex) { dynamic error = new ExpandoObject(); error.Error = true; error.Message = ex.Message; return error; } } private Dictionary BuildRequestData() { // 从query参数中获取实际业务数据 return new Dictionary { {"mainData", BuildMainData()}, {"requestName", $"IQC流程-{DateTime.Now:yyyyMMddHHmmss}"}, {"workflowId", "379"}, //{"otherParams", BuildOtherParams()}, //{"detailData", BuildDetailData(query)} }; } private JArray BuildMainData() { // 示例字段,根据实际业务需求调整 return new JArray { new JObject { ["fieldName"] = "wlbm", ["fieldValue"] = "1.01.01.001" }, new JObject { ["fieldName"] = "khgys", ["fieldValue"] = "陈雪年" }, new JObject { ["fieldName"] = "bhgpqxms", ["fieldValue"] = "外观不合格,尺寸不合格,颜色不符合" }, new JObject { ["fieldName"] = "dhdhmes", ["fieldValue"] = "MES001" } }; } private JArray BuildAttachments(JToken attachments) { var array = new JArray(); if (attachments != null) { foreach (var att in attachments) { array.Add(new JObject { ["filePath"] = att["url"]?.ToString(), ["fileName"] = att["fileName"]?.ToString() }); } } return array; } private JArray BuildDetailData(JObject query) { // 示例明细数据,根据实际业务调整 return new JArray { new JObject { ["tableDBName"] = "formtable_main_24_dt1", ["workflowRequestTableRecords"] = new JArray { new JObject { ["recordOrder"] = "0", ["workflowRequestTableFields"] = new JArray { new JObject { ["fieldName"] = "xm", ["fieldValue"] = query["inspector"] ?? "默认检验员" }, new JObject { ["fieldName"] = "bh", ["fieldValue"] = query["batchNo"] ?? "默认批次号" }, new JObject { ["fieldName"] = "dz", ["fieldValue"] = query["location"] ?? "默认地点" } } } } } }; } private JObject BuildOtherParams() { return new JObject { ["isnextflow"] = "1", ["delReqFlowFaild"] = "1" }; } private async Task GetRegistAsync() { using var rsa = new RSACryptoServiceProvider(2048); var cpk = Convert.ToBase64String(rsa.ExportRSAPublicKey()); _httpClient.DefaultRequestHeaders.Clear(); _httpClient.DefaultRequestHeaders.Add("appid", AppId); _httpClient.DefaultRequestHeaders.Add("cpk", cpk); var response = await _httpClient.PostAsync(BaseUrl + "regist", null); return JObject.Parse(await response.Content.ReadAsStringAsync()); } private async Task ApplyTokenAsync(string secret, string spk) { _httpClient.DefaultRequestHeaders.Clear(); _httpClient.DefaultRequestHeaders.Add("appid", AppId); _httpClient.DefaultRequestHeaders.Add("secret", RSAEncrypt(secret, spk)); var response = await _httpClient.PostAsync(BaseUrl + "applytoken", null); return JObject.Parse(await response.Content.ReadAsStringAsync()); } private string RSAEncrypt(string data, string publicKey) { //using var rsa = new RSACryptoServiceProvider(); //rsa.ImportRSAPublicKey(Convert.FromBase64String(publicKey), out _); //var dataBytes = Encoding.UTF8.GetBytes(data); //var encrypted = rsa.Encrypt(dataBytes, RSAEncryptionPadding.Pkcs1); //return Convert.ToBase64String(encrypted); RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey)); string XML = string.Format("{0}{1}", Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()), Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned())); string encryptedContent = string.Empty; using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) { rsa.FromXmlString(XML); byte[] encryptedData = rsa.Encrypt(Encoding.Default.GetBytes(data), false); encryptedContent = Convert.ToBase64String(encryptedData); } return encryptedContent; } private async Task PostFormAsync(string url, Dictionary data) { // 改用FormUrlEncodedContent并正确设置Content-Type var formData = new List>(); foreach (var item in data) { formData.Add(new KeyValuePair(item.Key, item.Value.ToString())); } var content = new FormUrlEncodedContent(formData); content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded"); var response = await _httpClient.PostAsync(url, content); var responseString = await response.Content.ReadAsStringAsync(); // 添加响应元数据 var responseInfo = new JObject { ["StatusCode"] = (int)response.StatusCode, ["ReasonPhrase"] = response.ReasonPhrase, ["Headers"] = JToken.FromObject(response.Headers), ["Content"] = responseString }; // 调试输出完整响应信息 Console.WriteLine($"完整响应:\n{responseInfo.ToString(Formatting.Indented)}"); return responseInfo.ToString(); } public void Dispose() { _httpClient?.Dispose(); } }