This commit is contained in:
18942506660
2024-11-07 09:46:58 +08:00
56 changed files with 3239 additions and 74 deletions

View File

@@ -7,6 +7,7 @@ using WMS.Web.Core.Dto.Erp;
using WMS.Web.Core.Dto.Erp.Customer;
using WMS.Web.Core.Dto.Erp.Org;
using WMS.Web.Core.Dto.Erp.Supplier;
using WMS.Web.Core.Dto.SingleData;
using WMS.Web.Domain.Infrastructure;
using WMS.Web.Domain.IService.Public;
@@ -407,6 +408,18 @@ namespace WMS.Web.Domain.Services.Public
var stock = erpStocks.Where(x => x.Code == code).FirstOrDefault();
return stock == null ? "" : stock.Name;
}
/// <summary>
/// 成品即时库存仓库
/// </summary>
/// <param name="list"></param>
/// <param name="code"></param>
/// <returns></returns>
public string GetProductInventoryStockName(List<UcStockHeadOfficeResponse> list, string code)
{
if (list == null || list.Count == 0)
return "";
var stock = list.Where(x => x.Code == code).FirstOrDefault();
return stock == null ? "" : stock.Name;
}
}
}

View File

@@ -0,0 +1,320 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MySqlX.XDevAPI.Common;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using WMS.Web.Core.Dto.Erp;
using WMS.Web.Core.Dto.JuShuiTan;
using WMS.Web.Core.Internal.Results;
using WMS.Web.Domain.IService.Public;
using WMS.Web.Domain.Options;
using WMS.Web.Domain.Values;
namespace WMS.Web.Domain.Services.Public
{
public class ErpInventoryService : IErpInventoryService
{
private ErpOptions _erpOptions;
private readonly ILogger<ErpInventoryService> _logger;
public ErpInventoryService(IOptions<ErpOptions> erpOptions, ILogger<ErpInventoryService> logger)
{
_erpOptions = erpOptions?.Value;
_logger = logger;
}
private bool Login(HttpClientEx httpClient)
{
string baseUrl = _erpOptions.EndpointAddress.Replace("/ERPGW.asmx", ""); //"http://192.168.1.1/k3cloud";//服务器地址
httpClient.Url = string.Format("{0}/Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc", baseUrl);
List<object> Parameters = new List<object>();
Parameters.Add(_erpOptions.ZhangTaoId);//帐套Id
Parameters.Add(_erpOptions.UserName);//用户名
Parameters.Add(_erpOptions.Password);//密码
Parameters.Add(2052);//多语言:中文
httpClient.Content = JsonConvert.SerializeObject(Parameters);
string response = httpClient.AsyncRequest();
var iResult = JObject.Parse(response)["LoginResultType"].Value<int>();
return iResult == 1 ? true : false;
}
public async Task<Result<List<ErpInventoryDto>>> GetInventory(List<string> stockCodes)
{
List<ErpInventoryDto> list = new List<ErpInventoryDto>();
HttpClientEx httpClient = new HttpClientEx();
var isSuccess = Login(httpClient);
string baseUrl = _erpOptions.EndpointAddress.Replace("/ERPGW.asmx", "");
httpClient.Url = string.Format("{0}/Kingdee.K3.SCM.WebApi.ServicesStub.InventoryQueryService.GetInventoryData.common.kdsvc", baseUrl);
int count = stockCodes.Count() / 10;
count = count + 1;
for (int ic = 1; ic <= count; ic++)
{
var codes = stockCodes.Skip((ic-1) * 10).Take(10).ToList();
if (codes.Count() <= 0)
{
return Result<List<ErpInventoryDto>>.ReSuccess(list.Where(w => w.Qty > 0 || w.BeforeQty > 0).ToList());
}
string code = string.Join(",", codes);
//foreach (var code in stockCodes)
//{
List<object> Parameters = new List<object>();
var model = new InventoryParamModel();
model.fstocknumbers = code;
//model.fmaterialnumbers = "G01-11-572474";
model.isshowauxprop = true;
model.isshowstockloc = true;
model.pageindex = 1;
model.pagerows = 5000;
Parameters.Add(model);
httpClient.Content = JsonConvert.SerializeObject(Parameters);
//_logger.LogInformation($"1.开始进行连接 {code}");
string content = httpClient.AsyncRequest();
//_logger.LogInformation($"金蝶返回数据{content}");
JObject resData = JObject.Parse(content);
if (resData["success"].ToString().ToLower() != "true")
return Result<List<ErpInventoryDto>>.ReFailure(ResultCodes.Erp_Inventory_Error);
string json = resData["data"].ToString();
var datas = JsonConvert.DeserializeObject<List<ErpInventoryDto>>(json);
if (datas != null && datas.Count() > 0)
list.AddRange(datas);
int num = Convert.ToInt32(resData["rowcount"]) / 5000;
for (int i = 1; i <= num; i++)
{
model.pageindex++;
httpClient.Content = JsonConvert.SerializeObject(Parameters);
content = httpClient.AsyncRequest();
//_logger.LogInformation($"金蝶返回数据{content}");
resData = JObject.Parse(content);
if (resData["success"].ToString().ToLower() != "true")
return Result<List<ErpInventoryDto>>.ReFailure(ResultCodes.Erp_Inventory_Error);
json = resData["data"].ToString();
datas = JsonConvert.DeserializeObject<List<ErpInventoryDto>>(json);
if (datas != null && datas.Count() > 0)
list.AddRange(datas);
}
}
var blist = list.Where(w => w.Qty > 0 || w.BeforeQty > 0).ToList();
return Result<List<ErpInventoryDto>>.ReSuccess(blist);
}
}
class HttpClientEx
{
/// <summary>
/// Seivice URL
/// </summary>
public string Url { get; set; }
/// <summary>
/// 内容
/// </summary>
public string Content { get; set; }
/// <summary>
/// Cookie保证登录后所有访问持有一个Cookie
/// </summary>
static CookieContainer Cookie = new CookieContainer();
/// <summary>
/// HTTP访问
/// </summary>
public string AsyncRequest()
{
HttpWebRequest httpRequest = HttpWebRequest.Create(Url) as HttpWebRequest;
httpRequest.Method = "POST";
httpRequest.ContentType = "application/json";
httpRequest.CookieContainer = Cookie;
httpRequest.Timeout = 1000 * 60 * 10;//10min
using (Stream reqStream = httpRequest.GetRequestStream())
{
JObject jObj = new JObject();
jObj.Add("format", 1);
jObj.Add("useragent", "ApiClient");
jObj.Add("rid", Guid.NewGuid().ToString().GetHashCode().ToString());
jObj.Add("parameters", Content);
jObj.Add("timestamp", DateTime.Now);
jObj.Add("v", "1.0");
string sContent = jObj.ToString();
var bytes = UnicodeEncoding.UTF8.GetBytes(sContent);
reqStream.Write(bytes, 0, bytes.Length);
reqStream.Flush();
}
using (var repStream = httpRequest.GetResponse().GetResponseStream())
{
using (var reader = new StreamReader(repStream))
{
return ValidateResult(reader.ReadToEnd());
}
}
}
private static string ValidateResult(string responseText)
{
if (responseText.StartsWith("response_error:"))
{
return responseText.TrimStart("response_error:".ToCharArray());
}
return responseText;
}
}
class InventoryParamModel
{
/// <summary>
/// 库存组织编码,多个使用英文逗号【,】分隔
/// </summary>
public string fstockorgnumbers { get; set; }
/// <summary>
/// 物料编码,多个使用英文逗号【,】分隔
/// </summary>
public string fmaterialnumbers { get; set; }
/// <summary>
/// 仓库编码,多个使用英文逗号【,】分隔
/// </summary>
public string fstocknumbers { get; set; }
/// <summary>
/// 批号编码,多个使用英文逗号【,】分隔
/// </summary>
public string flotnumbers { get; set; }
/// <summary>
/// 是否查询仓位
/// </summary>
public bool isshowstockloc { get; set; }
/// <summary>
/// 是否查询辅助属性
/// </summary>
public bool isshowauxprop { get; set; }
/// <summary>
/// 当前页码
/// </summary>
public int pageindex { get; set; }
/// <summary>
/// 每页显示行数
/// </summary>
public int pagerows { get; set; }
}
}

View File

@@ -160,7 +160,7 @@ namespace WMS.Web.Domain.Services.Public
/// <param name="billNo">模糊搜索</param>
/// <param name="sourceBillNos">单据编号集合精确查找</param>
/// <returns></returns>
public async Task<ResultList<ErpInStockResultDto>> BillQueryForPurchaseInStock(List<string> sourceBillNos = null, DateTime? beginTime = null,bool isCheck=true)
public async Task<ResultList<ErpInStockResultDto>> BillQueryForPurchaseInStock(List<string> sourceBillNos = null, DateTime? beginTime = null, bool isCheck = true)
{
string result_json = "";
try
@@ -194,7 +194,7 @@ namespace WMS.Web.Domain.Services.Public
//5.仓库wms系统的仓库值---现在这个没有加,因为还单点没有和金蝶同步
//param.FilterString = " FDocumentStatus='C' and (FBillTypeID='83d822ca3e374b4ab01e5dd46a0062bd' or FBillTypeID='6d01d059713d42a28bb976c90a121142') and FMRPCloseStatus='A'";
param.FilterString = " FMRPCloseStatus='A'";
if(isCheck) param.FilterString += " and FDocumentStatus='C'";
if (isCheck) param.FilterString += " and FDocumentStatus='C'";
for (int i = 0; i < stocks.Count(); i++)
{
if (i == 0)
@@ -2637,7 +2637,7 @@ namespace WMS.Web.Domain.Services.Public
}
}
public async Task<ResultList<ErpInventoryDto>> BillQueryForInventory(List<(string materialNumber, string orgCode, string stockCode, int subStockId)> request)
public async Task<ResultList<ErpInventoryDto>> BillQueryForInventory(List<(string orgCode, string stockCode)> request)
{
try
{
@@ -2650,51 +2650,76 @@ namespace WMS.Web.Domain.Services.Public
//3.获取金蝶采购订单:拼接参数和条件
var query = new ErpBillQueryDto(token_result.Data);
var param = new ErpBillQueryParamDto(FormIdParam.STK_Inventory.ToString());
param.FieldKeys = "FBASEQTY,FMATERIALID.FNumber,FSTOCKORGID.FNumber,FSTOCKID.FNumber,FSTOCKLOCID";
param.Limit = 100;
//param.FilterString = $"FSTOCKORGID.FNumber='{request[0].orgCode}' and FSTOCKID.FNumber='{request[0].stockCode}'";
//param.FilterString = $"";
// ORICO_AD,FF100004 ORICO_GD,FF100005 ORICO_HD,FF100007 ORICO_JD,FF100008
param.FieldKeys = "FMATERIALID.FNumber,FSTOCKORGID.FNumber,FSTOCKID.FNumber,FLot.FNumber,FBASEQTY,FSTOREURNOM,FSTOREURNUM,FSTOCKLOCID.FF100004.FName,FSTOCKLOCID.FF100005.FName,FSTOCKLOCID.FF100007.FName,FSTOCKLOCID.FF100008.FName";
param.Limit = 10000;
//param.FilterString = $" FMATERIALID.FNumber='G01-11-572474' and FSTOCKID.FNumber='AD' and FBASEQTY>0";
//param.FilterString = $" FBASEQTY>0";
for (int i = 0; i < request.Count(); i++)
{
if (i == 0)
{
param.FilterString = $"(FMATERIALID.FNumber='{request[0].materialNumber}' and FSTOCKORGID.FNumber='{request[0].orgCode}' and FSTOCKID.FNumber='{request[0].stockCode}' and FSTOCKLOCID={request[0].subStockId})";
param.FilterString += $" and ((FSTOCKORGID.FNumber='{request[0].orgCode}' and FSTOCKID.FNumber='{request[0].stockCode}' )";
if (request.Count() == 1) param.FilterString += ")";
}
else
{
param.FilterString += $" or (FMATERIALID.FNumber='{request[i].materialNumber}' and FSTOCKORGID.FNumber='{request[i].orgCode}' and FSTOCKID.FNumber='{request[i].stockCode}' and FSTOCKLOCID={request[i].subStockId})";
param.FilterString += $" or (FSTOCKORGID.FNumber='{request[i].orgCode}' and FSTOCKID.FNumber='{request[i].stockCode}' ))";
}
}
query.Data = JsonConvert.SerializeObject(param);
var json = JsonConvert.SerializeObject(query);
//4.请求查询接口
var result_json = await _client.ExecuteBillQueryAsync(json);
var result = JsonConvert.DeserializeObject<List<List<string>>>(result_json);
bool isHave = true;
var erp_list = new List<ErpInventoryDto>();
foreach (var item in result)
int skip = 0;
while (isHave)
{
//4.1.页码页码按照金蝶的要求从0开始
param.StartRow = (Convert.ToInt32(skip) * param.Limit);
var lis = erp_list.FirstOrDefault(f => f.MaterialNumber.Equals(item[1])
&& f.OrgCode.Equals(item[2])
&& f.StockCode.Equals(item[3]));
query.Data = JsonConvert.SerializeObject(param);
var json = JsonConvert.SerializeObject(query);
if (lis == null)
//4.请求查询接口
var result_json = await _client.ExecuteBillQueryAsync(json);
var result = JsonConvert.DeserializeObject<List<List<string>>>(result_json);
//4.4.判断数据是否全部拉取完成:并停止循环的条件
if (result == null || result.Count == 0)
isHave = false;
foreach (var item in result)
{
lis = new ErpInventoryDto();
lis.Qty = Convert.ToDecimal(item[0]);
lis.MaterialNumber = item[1];
lis.OrgCode = item[2];
lis.StockCode = item[3];
lis.Erp_SubStockId = Convert.ToInt32(item[4]);
erp_list.Add(lis);
}
else
lis.Qty = lis.Qty + Convert.ToDecimal(item[0]);
}
string name = GetName(item[7], item[8], item[9], item[10]);
var lis = erp_list.FirstOrDefault(f => f.MaterialNumber.Equals(item[0])
&& f.OrgCode.Equals(item[1])
&& f.StockCode.Equals(item[2]) && f.Erp_SubStockName.Equals(name));
return ResultList<ErpInventoryDto>.ReSuccess(erp_list);
if (lis == null)
{
lis = new ErpInventoryDto();
lis.MaterialNumber = item[0];
lis.OrgCode = item[1];
lis.StockCode = item[2];
lis.Batch = item[3];
//查询库存单位数量FQTYFMaterialid.FSTOREURNOM,FMaterialid.FSTOREURNUM
//查出结果后用(FBASEQTY*FSTOREURNOM/FSTOREURNUM)计算得到库存单位数量。
lis.BeforeQty = Convert.ToDecimal(item[4]) * Convert.ToDecimal(item[5]) / Convert.ToDecimal(item[6]);
//lis.Qty= Convert.ToDecimal(item[10]) * Convert.ToDecimal(item[5]) / Convert.ToDecimal(item[6]);
lis.Erp_SubStockName = name;
erp_list.Add(lis);
}
else
{
lis.BeforeQty = lis.BeforeQty + (Convert.ToDecimal(item[4]) * Convert.ToDecimal(item[5]) / Convert.ToDecimal(item[6]));
//lis.Qty = lis.Qty + Convert.ToDecimal(item[5]);
}
}
//4.6页面的叠加
skip++;
}
var list = erp_list.Where(w => w.BeforeQty > 0 || w.Qty > 0).ToList();
return ResultList<ErpInventoryDto>.ReSuccess(list);
}
catch (Exception ex)
{
@@ -2702,9 +2727,16 @@ namespace WMS.Web.Domain.Services.Public
return ResultList<ErpInventoryDto>.ReFailure(ResultCodes.Erp_Inventory_Error);
}
}
public string GetName(string name1,string name2,string name3,string name4)
{
if (!string.IsNullOrEmpty(name1)) return name1;
if (!string.IsNullOrEmpty(name2)) return name2;
if (!string.IsNullOrEmpty(name3)) return name3;
if (!string.IsNullOrEmpty(name4)) return name4;
return "";
}
#endregion
}

View File

@@ -1,4 +1,5 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
@@ -48,8 +49,9 @@ namespace WMS.Web.Domain.Services.Public
var responseContent = await response.Content.ReadAsStringAsync(); //2.当前使用这里是为了迎合错误信息观看
if (response.IsSuccessStatusCode)
{
var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
//var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
//var t = await JsonSerializer.DeserializeAsync<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });//3.配合1的ReadAsStream使用
var t = JsonConvert.DeserializeObject<T>(responseContent);
return t;
}
@@ -80,8 +82,9 @@ namespace WMS.Web.Domain.Services.Public
var responseContent = await response.Content.ReadAsStringAsync(); //2.当前使用这里是为了迎合错误信息观看
if (response.IsSuccessStatusCode)
{
var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
//var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
//var t = await JsonSerializer.DeserializeAsync<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });//3.配合1的ReadAsStream使用
var t = JsonConvert.DeserializeObject<T>(responseContent);
return t;
}
@@ -111,7 +114,8 @@ namespace WMS.Web.Domain.Services.Public
var responseContent = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
//var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
var t = JsonConvert.DeserializeObject<T>(responseContent);
return t;
}
@@ -135,7 +139,8 @@ namespace WMS.Web.Domain.Services.Public
var responseContent = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
//var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
var t = JsonConvert.DeserializeObject<T>(responseContent);
if (t == null)
_logger.LogInformation($"获取单点数据为空---{responseContent}");
return t;
@@ -163,8 +168,8 @@ namespace WMS.Web.Domain.Services.Public
var responseContent = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
//var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
var t = JsonConvert.DeserializeObject<T>(responseContent);
return t;
}
@@ -226,5 +231,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,245 @@
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WMS.Web.Core.Dto.Erp;
using WMS.Web.Core.Dto.JuShuiTan;
using WMS.Web.Core.Help;
using WMS.Web.Core.Internal.Results;
using WMS.Web.Domain.IService.Public;
using WMS.Web.Domain.Options;
using WMS.Web.Domain.Values;
namespace WMS.Web.Domain.Services.Public
{
public class JuShuiTanService : IJuShuiTanService
{
private readonly IHttpClientService _httpClientService;
private readonly ILogger<JuShuiTanService> _logger;
private readonly IMemoryCache _memoryCache;
private int hours = 10;//过期时间 默认10小时
private readonly JuShuiTanOptions _option;
public JuShuiTanService(IHttpClientService httpClientService, ILogger<JuShuiTanService> logger,
IMemoryCache memoryCache, IOptions<JuShuiTanOptions> option)
{
this._memoryCache = memoryCache;
this._httpClientService = httpClientService;
this._logger = logger;
_option = option?.Value;
}
public async Task GetTest()
{
//await GetStock();
var list = new List<int>();
list.Add(10923342);
await GetInventory(list);
}
public async Task<Result<List<JuShuiTanStockResponse>>> GetStock()
{
var stock_list = _memoryCache.Get<List<JuShuiTanStockResponse>>("jushuitan_stock");
if (stock_list != null && stock_list.Count > 0)
return Result<List<JuShuiTanStockResponse>>.ReSuccess(stock_list);
List<JuShuiTanStockResponse> list = new List<JuShuiTanStockResponse>();
JuShuiTanStockRequst request = new JuShuiTanStockRequst();
var resContent = PostUrl("/open/wms/partner/query", JsonConvert.SerializeObject(request));
JObject resData = JObject.Parse(resContent);
if (Convert.ToInt32(resData["code"]) != 0)
{
_logger.LogInformation($"聚水潭获取仓库失败:{resData["msg"].ToString()}");
return Result<List<JuShuiTanStockResponse>>.ReFailure(ResultCodes.JuShuiTanDataError);
}
string json = resData["data"]["datas"].ToString();
var datas = JsonConvert.DeserializeObject<List<JuShuiTanStockResponse>>(json);
list.AddRange(datas);
int count = Convert.ToInt32(resData["data"]["page_count"]);
for (int i = 1; i < count; i++)
{
request.page_index++;
resContent = PostUrl("/open/wms/partner/query", JsonConvert.SerializeObject(request));
resData = JObject.Parse(resContent);
if (Convert.ToInt32(resData["code"]) != 0)
{
_logger.LogInformation($"聚水潭获取仓库失败:{resData["msg"].ToString()}");
return Result<List<JuShuiTanStockResponse>>.ReFailure(ResultCodes.JuShuiTanDataError);
}
json = resData["data"]["datas"].ToString();
datas = JsonConvert.DeserializeObject<List<JuShuiTanStockResponse>>(json);
list.AddRange(datas);
}
//设置缓存
_memoryCache.Set("jushuitan_stock", list, new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromMinutes(DateTimeUtil.GetTotalMinutesTimeSpan())));
return Result<List<JuShuiTanStockResponse>>.ReSuccess(list);
}
public async Task<Result<List<JuShuiTanInventoryResponse>>> GetInventory(List<int> StockId)
{
List<JuShuiTanInventoryResponse> list = new List<JuShuiTanInventoryResponse>();
foreach (var id in StockId)
{
Thread.Sleep(1000);//不能太频繁请求
JuShuiTanInventoryRequst request = new JuShuiTanInventoryRequst();
request.wms_co_id = id;//10923342;
request.page_size = 100;
request.modified_begin = DateTime.Now.AddDays(-6).AddHours(-23).ToString("yyyy-MM-dd HH:mm:ss");
request.modified_end = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
var resContent = PostUrl("/open/inventory/query", JsonConvert.SerializeObject(request));
JObject resData = JObject.Parse(resContent);
if (Convert.ToInt32(resData["code"]) != 0)
{
_logger.LogInformation($"聚水潭获取即时库存失败:{resData["msg"].ToString()}");
return Result<List<JuShuiTanInventoryResponse>>.ReFailure(ResultCodes.JuShuiTanDataError);
}
string json = resData["data"]["inventorys"].ToString();
var datas = JsonConvert.DeserializeObject<List<JuShuiTanInventoryResponse>>(json);
datas.ForEach(f => f.wms_co_id = id);
list.AddRange(datas);
int count = Convert.ToInt32(resData["data"]["page_count"]);
for (int i = 1; i < count; i++)
{
Thread.Sleep(1000);//不能太频繁请求
request.page_index++;
resContent = PostUrl("/open/inventory/query", JsonConvert.SerializeObject(request));
resData = JObject.Parse(resContent);
if (Convert.ToInt32(resData["code"]) != 0)
{
_logger.LogInformation($"聚水潭获取即时库存失败:{resData["msg"].ToString()}");
return Result<List<JuShuiTanInventoryResponse>>.ReFailure(ResultCodes.JuShuiTanDataError);
}
json = resData["data"]["inventorys"].ToString();
datas = JsonConvert.DeserializeObject<List<JuShuiTanInventoryResponse>>(json);
datas.ForEach(f => f.wms_co_id = id);
list.AddRange(datas);
}
}
//主仓实际库存-订单占有数+虚拟库存+采购在途(业务设置)+进货仓(业务设置)+销退仓库存(业务设置)
foreach (var item in list)
{
item.qty = item.qty == null ? 0 : item.qty;
item.ky_qty = (item.qty ?? 0) - (item.order_lock ?? 0) + (item.virtual_qty ?? 0)
+ (item.purchase_qty ?? 0) + (item.in_qty ?? 0) + (item.return_qty ?? 0);
}
//这里不能过滤掉都是0的 因为要修改
//var resList = list.Where(w => w.qty > 0 || w.ky_qty > 0).ToList();
return Result<List<JuShuiTanInventoryResponse>>.ReSuccess(list);
}
/// <summary>
/// 调用接口
/// </summary>
private string PostUrl(string urlStr, string biz)
{
Hashtable ht = new Hashtable();
System.DateTime starttime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
string time = Math.Floor((System.DateTime.Now - starttime).TotalSeconds).ToString();
string app_key = _option.AppKey;// "17231841286c45f99eb9acf445404349";
string app_secret = _option.AppSecret;// "5ce9641ae6db4abb8b96eea7df6a81e9";
string access_token = _option.AccessToken;// "4605358c37374780a8a4395e6cdb1c3f";
//string biz = "{\"modified_begin\":\"2022-06-10 00:00:00\",\"modified_end\":\"2022-06-12 00:00:00\",\"page_index\":1,\"page_size\":30}";
ht.Add("access_token", access_token);
ht.Add("app_key", app_key);
ht.Add("biz", biz);
ht.Add("charset", "utf-8");
ht.Add("timestamp", time);
ht.Add("version", "2");
string sign = getSign(app_secret, ht);
ht.Add("sign", sign);
string posturl = _option.Url + urlStr;
Encoding datacode = Encoding.UTF8;
string paramData = GetParamData(ht);
return PostWebRequest(posturl, paramData, datacode);
}
string getSign(string signKey, Hashtable param)
{
ArrayList keys = new ArrayList(param.Keys);
keys.Sort(); //按字母顺序进行排序
string resultStr = "";
foreach (string key in keys)
{
if (key != null && key != "" && key != "sign")
{
resultStr = resultStr + key + param[key];
}
}
resultStr = signKey + resultStr;
MD5 md5 = MD5.Create();
byte[] rstRes = md5.ComputeHash(Encoding.UTF8.GetBytes(resultStr));
string hex = BitConverter.ToString(rstRes, 0).Replace("-", string.Empty).ToLower();
return hex;
}
private string PostWebRequest(string postUrl, string paramData, Encoding dataEncode)
{
string ret = string.Empty;
try
{
byte[] byteArray = dataEncode.GetBytes(paramData);
//转化
HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(new Uri(postUrl));
webReq.Method = "POST";
webReq.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
webReq.ContentLength = byteArray.Length;
Stream newStream = webReq.GetRequestStream();
newStream.Write(byteArray, 0, byteArray.Length);
//写入参数
newStream.Close();
HttpWebResponse response = (HttpWebResponse)webReq.GetResponse();
StreamReader sr = new StreamReader(response.GetResponseStream(), dataEncode);
ret = sr.ReadToEnd();
sr.Close();
response.Close();
newStream.Close();
}
catch (Exception ex)
{
}
return ret;
}
private string GetParamData(Hashtable ht)
{
string str = "";
foreach (DictionaryEntry items in ht)
{
str += items.Key.ToString() + "=" + System.Web.HttpUtility.UrlEncode(items.Value.ToString(), System.Text.Encoding.UTF8) + "&";
}
return str.Substring(0, str.Length - 1);
}
}
}

View File

@@ -0,0 +1,392 @@
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;
using WMS.Web.Core.Dto.JuShuiTan;
using System.Threading;
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 stock_list = _memoryCache.Get<List<LingXingStockResponse>>("lingxing_stock");
if (stock_list != null && stock_list.Count > 0)
return Result<List<LingXingStockResponse>>.ReSuccess(stock_list);
List<LingXingStockResponse> list = new List<LingXingStockResponse>();
//默认获取本地仓库 如果需要海外仓 另外需传参数type
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>(resUrl.Data, JsonConvert.SerializeObject(request), null);
if (res.Code != 0) return Result<List<LingXingStockResponse>>.ReFailure(ResultCodes.LingXingDataError);
list.AddRange(JsonConvert.DeserializeObject<List<LingXingStockResponse>>(res.Data.ToString()));
//海外仓
request = new LingXingRequest();
request.type = 3;
resUrl = await GetStr<LingXingRequest>("/erp/sc/data/local_inventory/warehouse", request);
if (!resUrl.IsSuccess) return Result<List<LingXingStockResponse>>.ReFailure(ResultCodes.LingXingUrlError);
res = await _httpClientService.PostAsync<LingXingResponse>(resUrl.Data, JsonConvert.SerializeObject(request), null);
if (res.Code != 0) return Result<List<LingXingStockResponse>>.ReFailure(ResultCodes.LingXingDataError);
list.AddRange(JsonConvert.DeserializeObject<List<LingXingStockResponse>>(res.Data.ToString()));
//设置缓存
_memoryCache.Set("lingxing_stock", list, new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromMinutes(DateTimeUtil.GetTotalMinutesTimeSpan())));
return Result<List<LingXingStockResponse>>.ReSuccess(list);
}
/// <summary>
/// 获取所有店铺
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<Result<List<LingXingSellerResponse>>> GetSeller()
{
var seller_list = _memoryCache.Get<List<LingXingSellerResponse>>("lingxing_seller");
if (seller_list != null && seller_list.Count > 0)
return Result<List<LingXingSellerResponse>>.ReSuccess(seller_list);
var request = new LingXingKongRequest();
var resUrl = await GetStr<LingXingKongRequest>("/erp/sc/data/seller/lists", request);
if (!resUrl.IsSuccess) return Result<List<LingXingSellerResponse>>.ReFailure(ResultCodes.LingXingUrlError);
var res = await _httpClientService.GetAsync<LingXingResponse>(resUrl.Data);
if (res.Code != 0)
{
_logger.LogInformation($"领星获取数据失败{res.Message}");
return Result<List<LingXingSellerResponse>>.ReFailure(ResultCodes.LingXingDataError);
}
var list = JsonConvert.DeserializeObject<List<LingXingSellerResponse>>(res.Data.ToString());
//设置缓存
_memoryCache.Set("lingxing_seller", list, new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromMinutes(DateTimeUtil.GetTotalMinutesTimeSpan())));
return Result<List<LingXingSellerResponse>>.ReSuccess(list);
}
/// <summary>
/// 获取即使库存
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<Result<List<LingXingInventoryResponse>>> GetInventory(List<int> ids)
{
List<LingXingInventoryResponse> list = new List<LingXingInventoryResponse>();
foreach (var id in ids)
{
LingXingInventoryRequest dto = new LingXingInventoryRequest();
dto.wid = id.ToString();
//dto.length = 50;
//dto.sku = "NTONPOWER-OSP-3A2U-US-BK-4.6M";
var resUrl = await GetStr<LingXingInventoryRequest>("/erp/sc/routing/data/local_inventory/inventoryDetails", dto);
if (!resUrl.IsSuccess) return Result<List<LingXingInventoryResponse>>.ReFailure(ResultCodes.LingXingUrlError);
var res = await _httpClientService.PostAsync<LingXingResponse>(resUrl.Data, JsonConvert.SerializeObject(dto), null);
if (res.Code != 0)
{
_logger.LogInformation($"领星获取数据失败{res.Message}");
return Result<List<LingXingInventoryResponse>>.ReFailure(ResultCodes.LingXingDataError);
}
list.AddRange(JsonConvert.DeserializeObject<List<LingXingInventoryResponse>>(res.Data.ToString()));
//var b = list.Where(w => w.SKU.Equals("NTONPOWER-OSP-3A2U-US-BK-4.6M")).ToList();
int num = res.Total / 800;
for (int i = 1; i <= num; i++)
{
Thread.Sleep(1000);//怕拉取过于频繁接口限制
dto.offset = i * 800;
if (i == num) dto.length = res.Total - (num * 800);
var resUrl_f = await GetStr<LingXingInventoryRequest>("/erp/sc/routing/data/local_inventory/inventoryDetails", dto);
if (!resUrl_f.IsSuccess) return Result<List<LingXingInventoryResponse>>.ReFailure(ResultCodes.LingXingUrlError);
var res_f = await _httpClientService.PostAsync<LingXingResponse>(resUrl_f.Data, JsonConvert.SerializeObject(dto), null);
if (res_f.Code != 0)
{
_logger.LogInformation($"领星获取数据失败{res.Message}");
return Result<List<LingXingInventoryResponse>>.ReFailure(ResultCodes.LingXingDataError);
}
var d = JsonConvert.DeserializeObject<List<LingXingInventoryResponse>>(res_f.Data.ToString());
//var bc = d.Where(w => w.SKU.Equals("NTONPOWER-OSP-3A2U-US-BK-4.6M")).Any();
//_logger.LogInformation($"次数:{i} 是否存在{bc}");
list.AddRange(d);
}
}
//var bcd = list.Where(w => w.SKU.Equals("NTONPOWER-OSP-3A2U-US-BK-4.6M")).ToList();
return Result<List<LingXingInventoryResponse>>.ReSuccess(list.Where(w => w.Product_Total > 0 && w.Product_Valid_Num > 0).ToList());
}
#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; }
}
}