增加配置

This commit is contained in:
18942506660
2024-10-16 17:47:34 +08:00
parent 04c758d6d7
commit f85e04fe97
19 changed files with 608 additions and 3 deletions

View File

@@ -13,6 +13,7 @@ namespace WMS.Web.Domain.IService.Public
Task<T> GetAsync<T>(string url, Dictionary<string, string> dicHeaders, int timeoutSecond = 180);
Task<T> PostAsync<T>(string url, string requestBody, int timeoutSecond = 180);
Task<T> PostAsync<T>(string url, string requestBody, Dictionary<string, string> dicHeaders, int timeoutSecond = 180);
Task<T> PostAsync<T>(string url, HttpContent content, Dictionary<string, string> dicHeaders, int timeoutSecond = 180);
Task<T> ExecuteAsync<T>(string url, HttpMethod method, string requestBody, Dictionary<string, string> dicHeaders, int timeoutSecond = 180);
}
}

View File

@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using WMS.Web.Core.Dto.LingXing;
using WMS.Web.Core.Internal.Results;
namespace WMS.Web.Domain.IService.Public
{
/// <summary>
/// 领星服务接口
/// </summary>
public interface ILingXingService
{
/// <summary>
/// 获取领星所有仓库
/// </summary>
/// <returns></returns>
public Task<Result<List<LingXingStockResponse>>> GetStock();
/// <summary>
/// 获取即时库存
/// </summary>
/// <returns></returns>
public Task<Result<List<LingXingInventoryResponse>>> GetInventory(LingXingInventoryRequest dto);
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace WMS.Web.Domain.Options
{
/// <summary>
/// 领星配置
/// </summary>
public class lingXingOptions
{
public string Url { get; set; }
public string AppId { get; set; }
public string AppSecret { get; set; }
}
}

View File

@@ -226,5 +226,20 @@ namespace WMS.Web.Domain.Services.Public
if (timeoutSecond != null) httpClient.Timeout = TimeSpan.FromSeconds(timeoutSecond.Value);
return httpClient;
}
public async Task<T> PostAsync<T>(string url, HttpContent content, Dictionary<string, string> dicHeaders, int timeoutSecond = 180)
{
var client = BuildHttpClient(dicHeaders, timeoutSecond);
var response = await client.PostAsync(url, content);
var responseContent = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var t = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(responseContent);
return t;
}
_logger.LogError($"HttpGet:{url} Error:{responseContent}");
throw new WebHttpException(response.StatusCode.ToString(), responseContent);
}
}
}

View File

@@ -0,0 +1,300 @@
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using WMS.Web.Core.Dto;
using WMS.Web.Domain.IService.Public;
using WMS.Web.Domain.Options;
using WMS.Web.Core.Internal.Results;
using WMS.Web.Core.Dto.LingXing;
using System.Json;
using System.Net.Http;
using NPOI.POIFS.Crypt.Dsig;
using NPOI.SS.Formula.Functions;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.Reflection;
using WMS.Web.Core.Help;
using static System.Net.WebRequestMethods;
using WMS.Web.Domain.Values;
namespace WMS.Web.Domain.Services.Public
{
/// <summary>
/// 领星服务接口
/// </summary>
public class LingXingService : ILingXingService
{
private readonly IHttpClientService _httpClientService;
private readonly ILogger<LingXingService> _logger;
private readonly IMemoryCache _memoryCache;
private int hours = 10;//过期时间 默认10小时
private readonly lingXingOptions _option;
public LingXingService(IHttpClientService httpClientService, ILogger<LingXingService> logger,
IMemoryCache memoryCache, IOptions<lingXingOptions> option)
{
this._memoryCache = memoryCache;
this._httpClientService = httpClientService;
this._logger = logger;
_option = option?.Value;
}
public async Task<Result<string>> Login()
{
string endStr = "/api/auth-server/oauth/access-token";
var formData = new MultipartFormDataContent();
formData.Add(new StringContent(_option.AppId), "appId");
formData.Add(new StringContent(_option.AppSecret), "appSecret");
var res = await _httpClientService.PostAsync<dynamic>(_option.Url + endStr, formData, null);
if (res.code != "200")
{
_logger.LogInformation($"领星获取授权失败:{res.msg}");
return Result<string>.ReFailure(ResultCodes.LingXingTokenError);
}
string token = res.data.access_token;
return Result<string>.ReSuccess(token);
}
/// <summary>
/// 获取所有仓库
/// </summary>
/// <returns></returns>
public async Task<Result<List<LingXingStockResponse>>> GetStock()
{
var request = new LingXingRequest();
var resUrl =await GetStr<LingXingRequest>("/erp/sc/data/local_inventory/warehouse", request);
if (!resUrl.IsSuccess) return Result<List<LingXingStockResponse>>.ReFailure(ResultCodes.LingXingUrlError);
var res = await _httpClientService.PostAsync<LingXingResponse<LingXingStockResponse>>(resUrl.Data, JsonConvert.SerializeObject(request), null);
if (res.Code!=0) return Result<List<LingXingStockResponse>>.ReFailure(ResultCodes.LingXingDataError);
return Result<List<LingXingStockResponse>>.ReSuccess(res.Data);
}
/// <summary>
/// 获取即使库存
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<Result<List<LingXingInventoryResponse>>> GetInventory(LingXingInventoryRequest dto)
{
var resUrl = await GetStr<LingXingRequest>("/erp/sc/routing/data/local_inventory/inventoryDetails", dto);
if (!resUrl.IsSuccess) return Result<List<LingXingInventoryResponse>>.ReFailure(ResultCodes.LingXingUrlError);
var res = await _httpClientService.PostAsync<LingXingResponse<LingXingInventoryResponse>>(resUrl.Data, JsonConvert.SerializeObject(dto), null);
if (res.Code != 0) return Result<List<LingXingInventoryResponse>>.ReFailure(ResultCodes.LingXingDataError);
return Result<List<LingXingInventoryResponse>>.ReSuccess(res.Data);
}
#region
public async Task<Result<string>> GetStr<T>(string urlStr,T data)
{
var res = await Login();
if (!res.IsSuccess)return res;
LxSignInfo lxSign = new LxSignInfo();
lxSign.access_token = res.Data;
lxSign.app_key = _option.AppId;
lxSign.timestamp = DateTime.Now.DateTimeToTimeStamp().ToString();
#region ASCII排序
Dictionary<string, object> testParamDics = new Dictionary<string, object>();
var ssi = GetEntityPropertyToDic(testParamDics, lxSign.GetType().GetProperties(), lxSign);//把签名参数实体转化为键值对
var ssdata = GetEntityPropertyToDic(testParamDics, data.GetType().GetProperties(), data);//把参数实体转化为键值对
// List<KeyValueInfo<string, string>> list = new List<KeyValueInfo<string, string>>();
Dictionary<string, string> list = new Dictionary<string, string>();
//string[] arrays = new string[data];
foreach (var item in typeof(LxSignInfo).GetProperties())
{
//KeyValueInfo<string, string> keys = new KeyValueInfo<string, string>();
//keys.Key = item.Name;
//keys.Value = ssi[$"{item.Name}"].ToString();
//list.Add(keys);
list.Add(item.Name, ssi[$"{item.Name}"].ToString());
}
foreach (var item in typeof(T).GetProperties())
{
//KeyValueInfo<string, string> keys = new KeyValueInfo<string, string>();
//keys.Key = item.Name;
//keys.Value = JsonConvert.SerializeObject(ssdata[$"{item.Name}"]);
//if (ssdata[$"{item.Name}"] == null) { list.Add(keys); continue; }
//if (string.IsNullOrEmpty(ssdata[$"{item.Name}"].ToString()))
//{
// continue;//跳过值为NULL的
//}
if (ssdata[$"{item.Name}"] == null) { list.Add(item.Name, JsonConvert.SerializeObject(ssdata[$"{item.Name}"])); continue; }
if (string.IsNullOrEmpty(ssdata[$"{item.Name}"].ToString()))
{
continue;//跳过值为NULL的
}
list.Add(item.Name, JsonConvert.SerializeObject(ssdata[$"{item.Name}"]));
}
string[] arrays = new string[list.Count];
int i = 0;
foreach (var item in list)
{
arrays[i] = item.Key;
i++;
}
Array.Sort(arrays, string.CompareOrdinal); //ASCII排序
string sig = null;
int j = 0;
foreach (var item in arrays)
{
string key = list.Where(a => a.Key == item).ToList()[0].Key.ToString();
string value = list.Where(a => a.Key == item).ToList()[0].Value.ToString();
#region
if (value.IndexOf("{", StringComparison.OrdinalIgnoreCase) > -1) { }
else
{
value = Regex.Replace(value, @"[\""]+", "");//去掉双引号
}
#endregion
if (j == i - 1)
{
sig += $"{key}={value}";
}
else
{
sig += $"{key}={value}&";
}
j++;
}
#endregion
#region MD5加密转大写+AES/ECB/PKCS5PADDING加密
//sig = Regex.Replace(sig, @"[\""]+", "");//去掉双引号
var md5 = MD5Encrypt(sig, false);
var signs = Encrypt(md5, lxSign.app_key);
#endregion
#region
signs = WebUtility.UrlEncode(signs);
#endregion
#region
var url = _option.Url + urlStr;
var ret = $"{url}?app_key={lxSign.app_key}&access_token={lxSign.access_token}&timestamp={lxSign.timestamp}&sign={signs}";
return Result<string>.ReSuccess(ret);
#endregion
}
/// <summary>
/// 32位MD5加密
/// </summary>
/// <param name="strText">要加密字符串</param>
/// <param name="IsLower">是否以小写方式返回</param>
/// <returns></returns>
public static string MD5Encrypt(string strText, bool IsLower = true)
{
MD5 md5 = new MD5CryptoServiceProvider();
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(strText);
bytes = md5.ComputeHash(bytes);
md5.Clear();
string ret = "";
for (int i = 0; i < bytes.Length; i++)
{
ret += Convert.ToString(bytes[i], 16).PadLeft(2, '0');
}
if (IsLower == false) { return ret.PadLeft(32, '0').ToUpper(); }
return ret.PadLeft(32, '0');
}
/// <summary>
/// AES加密
/// </summary>
/// <param name="str">需要加密的字符串</param>
/// <param name="key">32位密钥</param>
///<param name="lv">向量(默认偏移量)</param>
/// <returns>加密后的字符串</returns>
public static string Encrypt(string str, string key)
{
try
{
Byte[] keyArray = System.Text.Encoding.UTF8.GetBytes(key);
Byte[] toEncryptArray = System.Text.Encoding.UTF8.GetBytes(str);
var rijndael = new System.Security.Cryptography.RijndaelManaged();
rijndael.Key = keyArray;
rijndael.Mode = System.Security.Cryptography.CipherMode.ECB;
rijndael.Padding = System.Security.Cryptography.PaddingMode.PKCS7;
rijndael.IV = System.Text.Encoding.UTF8.GetBytes(key);
System.Security.Cryptography.ICryptoTransform cTransform = rijndael.CreateEncryptor();
Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
catch (Exception ex)
{
//YellowJLog("调用AES加密方法异常异常原因" + ex.Message, "加密异常");
return "";
}
}
/// <summary>
/// 类实体的属性与值转化成键值对形式
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="inParam"></param>
/// <param name="infos"></param>
/// <param name="Entity"></param>
public static Dictionary<string, object> GetEntityPropertyToDic<T>(Dictionary<string, object> inParam, PropertyInfo[] infos, T Entity)
{
foreach (var info in infos)
{
var itemTpe = info.PropertyType;
//实体中有嵌套类的处理
if (itemTpe.IsClass && !itemTpe.Name.Equals("String", StringComparison.OrdinalIgnoreCase))
{
//if (info.GetValue(Entity) == null) continue;
//GetEntityPropertyToDic(inParam, itemTpe.GetProperties(), info.GetValue(Entity));
//inParam.Add(info.Name, info.GetValue(JsonConvert.SerializeObject(Entity), null));
inParam.Add(info.Name, info.GetValue(Entity, null));
}
else
{
inParam.Add(info.Name, info.GetValue(Entity, null));
//sig = Regex.Replace(sig, @"[\""]+", "");//去掉双引号
}
}
return inParam;
}
#endregion
}
public class LxSignInfo
{
public string access_token { get; set; }
public string app_key { get; set; }
public string timestamp { get; set; }
}
}

View File

@@ -97,5 +97,9 @@ namespace WMS.Web.Domain.Values
public static ValueTuple<int, string> SubscribeNotificationNoData = (700001, "订阅通知信息不存在");
public static ValueTuple<int, string> GetBarCodeSerialNumberError = (800001, "获取序列码异常");
public static ValueTuple<int, string> LingXingTokenError = (810001, "获取领星授权失败");
public static ValueTuple<int, string> LingXingUrlError = (810002, "拼接领星请求参数失败");
public static ValueTuple<int, string> LingXingDataError = (810003, "请求领星数据失败");
}
}