增加配置

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

@@ -28,6 +28,8 @@ using System.Reflection;
using WMS.Web.Domain.Services;
using SkiaSharp;
using Google.Protobuf.Collections;
using NPOI.SS.Formula.Functions;
using System.Text.Json;
namespace WMS.Web.Api.Controllers
{
@@ -57,11 +59,12 @@ namespace WMS.Web.Api.Controllers
private readonly IMemoryCache _memoryCache;
private readonly IRedisConcurrentProcessService _redisConcurrentProcessService;
private IInStockService _inStockService;
private readonly ILingXingService _lingXingService;
public TestController(IErpService erpService, IInStockTaskService inStockTaskService, IBoxInventoryRepositories boxInventoryRepositories, IRedisConcurrentProcessService redisConcurrentProcessService,
IBasicsRepositories transactionRepositories, IOpsService opsService, IBoxService boxService, IBasicsRepositories basicsRepositories, IMemoryCache memoryCache,
IOutStockTaskRepositories outStockTaskRepositories, IOutStockTaskService outStockTaskService, IOptions<AppOptions> options, ILoginService loginService, ISendMessageService sendMessageService,
ITakeStockService takeStockService, ITakeStockRepositories takeStockRepositories, IOutStockService outStockService, IInStockTaskRepositories inStockTaskRepositories,
IWebHostEnvironment env, IMaterialService materialService, IOutStockRepositories outStockRepositories, IInStockService inStockService)
IWebHostEnvironment env, IMaterialService materialService, IOutStockRepositories outStockRepositories, IInStockService inStockService, ILingXingService lingXingService)
{
_inStockService = inStockService;
_redisConcurrentProcessService = redisConcurrentProcessService;
@@ -85,12 +88,23 @@ namespace WMS.Web.Api.Controllers
_outStockService = outStockService;
_outStockRepositories = outStockRepositories;
_env = env;
_lingXingService = lingXingService;
}
[HttpGet]
[Route("hj")]
public async Task<string> TestHJ()
{
////var myJson = "{\"name\":\"小明\",\"address\":\"威海\"}";//json字符串
//var myJson= "{\"code\":\"200\",\"msg\":\"OK\",\"data\":{\"access_token\":\"05895ad6-e318-41da-9b2c-579dedd18fd1\",\"refresh_token\":\"ad9145cf-8af9-4617-9dbe-187b0ff3edf9\",\"expires_in\":7162}}";
//var myObj = JsonConvert.DeserializeObject<dynamic>(myJson);//反序列化为 dynamic 对象
//var my2 = System.Text.Json.JsonSerializer.Deserialize<dynamic>(myJson);
//string m = myObj.code;
//var m2 = my2.Object;
//var md = m2.code;
await _lingXingService.GetStock();
//List<string> list = new List<string>();
//list.Add("GD-02-15");
//list.Add("GD-01-15");

View File

@@ -46,6 +46,11 @@
"UserName": "admin",
"PassWord": "888888"
},
"LingXingOptions": {
"Url": "https://openapi.lingxing.com",
"AppId": "ak_QGK2J8TssERmu",
"AppSecret": "n/HUKD2wVdTbvhnFZbVBPw=="
},
"Qiniu": {
"AccessKey": "dOsTum4a5qvhPTBbZRPX0pIOU7PZWRX7htKjztms",
"SecretKey": "KFxsGbnErkALFfeGdMa8QWTdodJbamMX0iznLe-q",

View File

@@ -579,7 +579,7 @@
<param name="dto"></param>
<returns></returns>
</member>
<member name="M:WMS.Web.Api.Controllers.ProductInventoryController.Export(WMS.Web.Core.Dto.OutStock.OutStockQueryRequest)">
<member name="M:WMS.Web.Api.Controllers.ProductInventoryController.Export(WMS.Web.Core.Dto.ProductInventory.ProductInventoryQueryRequest)">
<summary>
导出
</summary>

View File

@@ -3969,6 +3969,36 @@
wms箱ID
</summary>
</member>
<member name="T:WMS.Web.Core.Dto.LingXing.LingXingLoginRequest">
<summary>
领星登录
</summary>
</member>
<member name="P:WMS.Web.Core.Dto.LingXing.LingXingLoginRequest.AppId">
<summary>
id
</summary>
</member>
<member name="P:WMS.Web.Core.Dto.LingXing.LingXingLoginRequest.AppSecret">
<summary>
Secret
</summary>
</member>
<member name="T:WMS.Web.Core.Dto.LingXing.LingXingRequest">
<summary>
领星请求
</summary>
</member>
<member name="P:WMS.Web.Core.Dto.LingXing.LingXingRequest.offset">
<summary>
页码
</summary>
</member>
<member name="P:WMS.Web.Core.Dto.LingXing.LingXingRequest.ength">
<summary>
页条数
</summary>
</member>
<member name="P:WMS.Web.Core.Dto.Login.AccessTokenDto.ClientName">
<summary>
客户端名称

View File

@@ -4310,6 +4310,11 @@
</summary>
<returns></returns>
</member>
<member name="T:WMS.Web.Domain.IService.Public.ILingXingService">
<summary>
领星服务接口
</summary>
</member>
<member name="T:WMS.Web.Domain.IService.Public.ILoginService">
<summary>
登录服务接口
@@ -6271,6 +6276,43 @@
<param name="timeoutSecond"></param>
<returns></returns>
</member>
<member name="T:WMS.Web.Domain.Services.Public.LingXingService">
<summary>
领星服务接口
</summary>
</member>
<member name="M:WMS.Web.Domain.Services.Public.LingXingService.GetStock">
<summary>
获取所有仓库
</summary>
<returns></returns>
</member>
<member name="M:WMS.Web.Domain.Services.Public.LingXingService.MD5Encrypt(System.String,System.Boolean)">
<summary>
32位MD5加密
</summary>
<param name="strText">要加密字符串</param>
<param name="IsLower">是否以小写方式返回</param>
<returns></returns>
</member>
<member name="M:WMS.Web.Domain.Services.Public.LingXingService.Encrypt(System.String,System.String)">
<summary>
AES加密
</summary>
<param name="str">需要加密的字符串</param>
<param name="key">32位密钥</param>
<param name="lv">向量(默认偏移量)</param>
<returns>加密后的字符串</returns>
</member>
<member name="M:WMS.Web.Domain.Services.Public.LingXingService.GetEntityPropertyToDic``1(System.Collections.Generic.Dictionary{System.String,System.Object},System.Reflection.PropertyInfo[],``0)">
<summary>
类实体的属性与值转化成键值对形式
</summary>
<typeparam name="T"></typeparam>
<param name="inParam"></param>
<param name="infos"></param>
<param name="Entity"></param>
</member>
<member name="M:WMS.Web.Domain.Services.Public.LoginService.CreateToken(WMS.Web.Core.Dto.Login.UserInfoDto,WMS.Web.Core.Dto.Login.Temp.LoginTempDto,System.String)">
<summary>
创建token

View File

@@ -0,0 +1,20 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
namespace WMS.Web.Core.Dto.LingXing
{
/// <summary>
/// 领星即时库存
/// </summary>
[Serializable]
public class LingXingInventoryRequest:LingXingRequest
{
/// <summary>
/// 仓库Id 1,3,234,33
/// </summary>
[JsonProperty("offset")]
public string wid { get; set; }
}
}

View File

@@ -0,0 +1,41 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
namespace WMS.Web.Core.Dto.LingXing
{
/// <summary>
/// 领星即时库存
/// </summary>
[Serializable]
public class LingXingInventoryResponse
{
/// <summary>
/// 仓库Id
/// </summary>
[JsonProperty("wid")]
public int StockId { get; set; }
/// <summary>
/// SKU
/// </summary>
[JsonProperty("sku")]
public string SKU { get; set; }
/// <summary>
/// 店铺id
/// </summary>
[JsonProperty("seller_id")]
public string SellerId { get; set; }
/// <summary>
/// 库存总量
/// </summary>
[JsonProperty("product_total")]
public decimal Product_Total { get; set; }
/// <summary>
/// 可用量
/// </summary>
[JsonProperty("product_valid_num")]
public decimal Product_Valid_Num { get; set; }
}
}

View File

@@ -0,0 +1,24 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
namespace WMS.Web.Core.Dto.LingXing
{
/// <summary>
/// 领星登录
/// </summary>
public class LingXingLoginRequest
{
/// <summary>
/// id
/// </summary>
[JsonProperty("appId")]
public string AppId { get; set; }
/// <summary>
/// Secret
/// </summary>
[JsonProperty("appSecret")]
public string AppSecret { get; set; }
}
}

View File

@@ -0,0 +1,24 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
namespace WMS.Web.Core.Dto.LingXing
{
/// <summary>
/// 领星请求
/// </summary>
public class LingXingRequest
{
/// <summary>
/// 页码
/// </summary>
[JsonProperty("offset")]
public int offset { get; set; } = 1;
/// <summary>
/// 页条数
/// </summary>
[JsonProperty("ength")]
public int ength { get; set; } = 1000;
}
}

View File

@@ -0,0 +1,23 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
namespace WMS.Web.Core.Dto.LingXing
{
[Serializable]
public class LingXingResponse<T>
{
public LingXingResponse() { }
[JsonProperty("code")]
public int Code { get; set; }
[JsonProperty("message")]
public string Message { get; set; }
[JsonProperty("error_details")]
public List<object> Error_details { get; set; }
[JsonProperty("total")]
public int Total { get; set; }
[JsonProperty("data")]
public List<T> Data { get; set; }
}
}

View File

@@ -0,0 +1,17 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
namespace WMS.Web.Core.Dto.LingXing
{
[Serializable]
public class LingXingStockResponse
{
public LingXingStockResponse() { }
[JsonProperty("wid")]
public int Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
}
}

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, "请求领星数据失败");
}
}

View File

@@ -182,6 +182,8 @@ namespace WMS.Web.Repositories.DependencyInjection
Services.Configure<EmailOptions>(Configuration.GetSection("EmailOptions"));
Services.AddOptions<SmsOptions>();
Services.Configure<SmsOptions>(Configuration.GetSection("SmsOptions"));
Services.AddOptions<lingXingOptions>();
Services.Configure<lingXingOptions>(Configuration.GetSection("LingXingOptions"));
@@ -345,6 +347,7 @@ namespace WMS.Web.Repositories.DependencyInjection
Services.AddTransient<ISendMessageService, SendMessageService>();
Services.AddTransient<IMaterialService, MaterialService>();
Services.AddTransient<IRedisConcurrentProcessService, RedisConcurrentProcessService>();
Services.AddTransient<ILingXingService, LingXingService>();
}