domian-build

This commit is contained in:
tongfei
2023-10-18 10:37:41 +08:00
parent 9b739e2e37
commit 05ee79a04f
18 changed files with 2894 additions and 5 deletions

View File

@@ -0,0 +1,230 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using WMS.Web.Core.Exceptions;
using WMS.Web.Domain.IService.Public;
namespace WMS.Web.Domain.Services.Public
{
public class HttpClientService : IHttpClientService
{
private readonly IHttpClientFactory _clientFactory;
private readonly ILogger<HttpClientService> _logger;
private Dictionary<string, string> headers;
private Dictionary<string, string> contentHeaders;
public HttpClientService(IHttpClientFactory clientFactory, ILogger<HttpClientService> logger)
{
_clientFactory = clientFactory;
_logger = logger;
headers = new Dictionary<string, string>();
headers.Add("Accept", "application/json");
headers.Add("User-Agent", "HttpClientFactory-Sample");
contentHeaders = new Dictionary<string, string>();
contentHeaders.Add("Content-Type", "application/json; charset=utf-8");
}
/// <summary>
/// Get方法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="url"></param>
/// <param name="dicHeaders"></param>
/// <param name="timeoutSecond"></param>
/// <returns></returns>
public async Task<T> GetAsync<T>(string url, int timeoutSecond = 180)
{
try
{
var client = BuildHttpClient(headers, timeoutSecond);
var response = await client.GetAsync(url);
//var responseContent = await response.Content.ReadAsStreamAsync();//1.相比ReadAsString这个方法返回要快点效率高
var responseContent = await response.Content.ReadAsStringAsync(); //2.当前使用这里是为了迎合错误信息观看
if (response.IsSuccessStatusCode)
{
var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
//var t = await JsonSerializer.DeserializeAsync<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });//3.配合1的ReadAsStream使用
return t;
}
throw new WebHttpException(response.StatusCode.ToString(), "请求出错");
}
catch (Exception ex)
{
_logger.LogError($"HttpGet:{url} Error:{ex.Message}");
throw new Exception($"HttpGet:{url} Error", ex);
}
}
/// <summary>
/// Get方法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="url"></param>
/// <param name="dicHeaders"></param>
/// <param name="timeoutSecond"></param>
/// <returns></returns>
public async Task<T> GetAsync<T>(string url, Dictionary<string, string> dicHeaders, int timeoutSecond = 180)
{
try
{
var client = BuildHttpClient(dicHeaders, timeoutSecond);
var response = await client.GetAsync(url);
//var responseContent = await response.Content.ReadAsStreamAsync();//1.相比ReadAsString这个方法返回要快点效率高
var responseContent = await response.Content.ReadAsStringAsync(); //2.当前使用这里是为了迎合错误信息观看
if (response.IsSuccessStatusCode)
{
var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
//var t = await JsonSerializer.DeserializeAsync<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });//3.配合1的ReadAsStream使用
return t;
}
throw new WebHttpException(response.StatusCode.ToString(), "请求出错");
}
catch (Exception ex)
{
_logger.LogError($"HttpGet:{url} Error:{ex.Message}");
throw new Exception($"HttpGet:{url} Error", ex);
}
}
/// <summary>
/// Post方法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="url"></param>
/// <param name="requestBody"></param>
/// <param name="dicHeaders"></param>
/// <param name="timeoutSecond"></param>
/// <returns></returns>
public async Task<T> PostAsync<T>(string url, string requestBody, Dictionary<string, string> dicHeaders, int timeoutSecond = 180)
{
var client = BuildHttpClient(null, timeoutSecond);
var requestContent = GenerateStringContent(requestBody, dicHeaders);
var response = await client.PostAsync(url, requestContent);
var responseContent = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
return t;
}
_logger.LogError($"HttpGet:{url} Error:{responseContent}");
throw new WebHttpException(response.StatusCode.ToString(), responseContent);
}
/// <summary>
/// Post方法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="url"></param>
/// <param name="requestBody"></param>
/// <param name="timeoutSecond"></param>
/// <returns></returns>
public async Task<T> PostAsync<T>(string url, string requestBody, int timeoutSecond = 180)
{
var client = BuildHttpClient(null, timeoutSecond);
var requestContent = GenerateStringContent(requestBody, contentHeaders);
var response = await client.PostAsync(url, requestContent);
var responseContent = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
if (t == null)
_logger.LogInformation($"获取单点数据为空---{responseContent}");
return t;
}
_logger.LogError($"HttpGet:{url} Error:{responseContent}");
throw new WebHttpException(response.StatusCode.ToString(), responseContent);
}
/// <summary>
/// 公共http请求
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="url"></param>
/// <param name="method"></param>
/// <param name="requestBody"></param>
/// <param name="dicHeaders"></param>
/// <param name="timeoutSecond"></param>
/// <returns></returns>
public async Task<T> ExecuteAsync<T>(string url, HttpMethod method, string requestBody, Dictionary<string, string> dicHeaders, int timeoutSecond = 180)
{
var client = BuildHttpClient(null, timeoutSecond);
var request = GenerateHttpRequestMessage(url, requestBody, method, dicHeaders);
var response = await client.SendAsync(request);
var responseContent = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var t = JsonSerializer.Deserialize<T>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
return t;
}
throw new WebHttpException(response.StatusCode.ToString(), responseContent);
}
/// <summary>
/// 设置HttpRequestMessage
/// </summary>
/// <param name="url"></param>
/// <param name="requestBody"></param>
/// <param name="method"></param>
/// <param name="dicHeaders"></param>
/// <returns></returns>
private HttpRequestMessage GenerateHttpRequestMessage(string url, string requestBody, HttpMethod method, Dictionary<string, string> dicHeaders)
{
var request = new HttpRequestMessage(method, url);
if (!string.IsNullOrEmpty(requestBody)) request.Content = new StringContent(requestBody);
if (dicHeaders != null)
foreach (var headerItme in dicHeaders)
request.Headers.Add(headerItme.Key, headerItme.Value);
return request;
}
/// <summary>
/// 设置请求内容
/// </summary>
/// <param name="requestBody"></param>
/// <param name="dicHeaders"></param>
/// <returns></returns>
private StringContent GenerateStringContent(string requestBody, Dictionary<string, string> dicHeaders)
{
var content = new StringContent(requestBody);
if (dicHeaders != null)
content.Headers.Remove("content-type");
foreach (var headerItme in dicHeaders)
content.Headers.Add(headerItme.Key, headerItme.Value);
return content;
}
/// <summary>
/// 设置请求头和超时时间返回client
/// </summary>
/// <param name="dicDefaultHeaders"></param>
/// <param name="timeoutSecond"></param>
/// <returns></returns>
private HttpClient BuildHttpClient(Dictionary<string, string> dicDefaultHeaders, int? timeoutSecond)
{
var httpClient = _clientFactory.CreateClient("ops_client");
httpClient.DefaultRequestHeaders.Clear(); //为了使客户端不受最后一个请求的影响它需要清除DefaultRequestHeaders
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
if (dicDefaultHeaders != null)
foreach (var headItem in dicDefaultHeaders)
if (!httpClient.DefaultRequestHeaders.Contains(headItem.Key))
httpClient.DefaultRequestHeaders.Add(headItem.Key, headItem.Value);
if (timeoutSecond != null) httpClient.Timeout = TimeSpan.FromSeconds(timeoutSecond.Value);
return httpClient;
}
}
}

View File

@@ -0,0 +1,387 @@
using AutoMapper;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Json;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WMS.Web.Core.Dto.Login;
using WMS.Web.Core.Dto.Login.Temp;
using WMS.Web.Core.Help;
using WMS.Web.Core.Internal.Results;
using WMS.Web.Core.Internal.Security;
using WMS.Web.Domain.IService.Public;
using WMS.Web.Domain.Options;
using WMS.Web.Domain.Values.Single;
namespace WMS.Web.Domain.Services.Public
{
public class LoginService : ILoginService
{
private IMapper _mapper;
private SoaOptions _soaOptions;
private ILogger<LoginService> _logger;
private HttpClientHelp _httpClientHelp;
private readonly ISingleDataService _singleDataService;
private readonly RedisClientService _redisClientService;
public LoginService(
IMapper mapper,
IOptions<SoaOptions> soaOptions,
ILogger<LoginService> logger,
HttpClientHelp httpClientHelp,
ISingleDataService singleDataService,
RedisClientService redisClientService)
{
this._redisClientService = redisClientService;
this._singleDataService = singleDataService;
this._soaOptions = soaOptions?.Value;
this._mapper = mapper;
this._logger = logger;
this._httpClientHelp = httpClientHelp;
}
/// <summary>
/// 创建token
/// </summary>
/// <param name="data"></param>
/// <param name="tempDto"></param>
/// <param name="NewToken"></param>
/// <returns></returns>
private async Task<AccessTokenDto> CreateToken(UserInfoDto data, LoginTempDto tempDto, string NewToken)
{
return await Task.Run(() =>
{
DateTime expires_time = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)).AddSeconds(tempDto.expires_in);
AccessTokenDto accessToken = new AccessTokenDto()
{
Token = NewToken,
PhpToken = tempDto.access_token,
RefreshToken = tempDto.refresh_token,
Expired = expires_time
};
return accessToken;
});
}
/// <summary>
/// 得到单点用户信息
/// </summary>
/// <param name="code"></param>
/// <returns></returns>
public async Task<Result<LoginInDto>> GetUserInfoAsync(string code)
{
JsonObject reqData = new JsonObject();
reqData.Add("app_id", _soaOptions.AppId);
reqData.Add("app_secret", _soaOptions.AppSecret);
reqData.Add("code", code);
//这个是登录的时候给前端验证的token,以及传给php单点那边的一个session值用于单点退出时通知ops退出
string NewToken = Guid.NewGuid().ToString("N");
try
{
string result = _httpClientHelp.PostHttp(_soaOptions.Url + "/uc/authorize/access_token", reqData, true, NewToken);
var jObject = JsonObject.Parse(result);
LoginInDto r = new LoginInDto();
r.UserInfo = new UserInfoDto();
r.TokenInfo = new AccessTokenDto();
var login_result = jObject["errno"] == 0 ? "成功" : "失败";
_logger.LogInformation($"登录信息:单点->{login_result}");
if (jObject["errno"] == 0)
{
string datajson = jObject["data"].ToString();
var _loginDto = JsonConvert.DeserializeObject<LoginTempDto>(datajson);
#region
string enptStr = _loginDto.encryptedData;
List<string> enptlist = enptStr.Trim().Split(',').ToList();
string str = RSA.DecryptSection(_soaOptions.PrivateKey, enptlist);
var entity = JsonConvert.DeserializeObject<LoginJsonTokenTempDto>(str);
#endregion
//映射登录信息
r.UserInfo = _mapper.Map<UserInfoDto>(entity);
_logger.LogInformation($"登录信息用户ID->{entity.uc_id}");
//HTTP请求获取登录信息人员客户供应商公司
var loginRequest = new LoginSingleRequest()
{
UserId = entity.uc_id,
SupplierId = entity.supplier_id ?? 0,
CustomerId = entity.customer_id ?? 0
};
var loginResponse_result = await _singleDataService.GetSingleDataNoCache<Result<LoginSingleResponse>, LoginSingleRequest, SingleLoginAction>
(loginRequest, SingleLoginAction.All, type: SingleControllerType.Login);
//绑定返回对象的登录信息
var staffName = "Null";
var token = await CreateToken(r.UserInfo, _loginDto, NewToken);
r.TokenInfo = token;
if (loginResponse_result.Success && loginResponse_result.Data != null)
{
var loginResponse = loginResponse_result.Data;
if (loginResponse.Supplier != null)
r.UserInfo.SupplierName = loginResponse.Supplier.Name;
if (loginResponse.Customer != null)
r.UserInfo.CustomerName = loginResponse.Customer.Name;
if (loginResponse.Staff != null)
{
r.UserInfo.StaffId = loginResponse.Staff.Id;
staffName = loginResponse.Staff.Name;
}
if (loginResponse.Company != null)
r.UserInfo.CompanyName = loginResponse.Company.Name;
}
r.UserInfo.UcId = entity.uc_id;
r.UserInfo.SeesionId = _loginDto?.uc_sessid;
r.UserInfo.CompanyId = entity.company_id.Value;
r.UserInfo.Identity = entity.identity;
r.UserInfo.OrgId = entity.org_id;
r.UserInfo.CustomerId = entity.customer_id;
r.UserInfo.SupplierId = entity.supplier_id;
r.SignedIn = true;
_logger.LogInformation($"登录信息:用户人员信息->{staffName}{r.UserInfo.StaffId}),公司名称->{r.UserInfo.CompanyName}");
//登录后缓存登录的用户信息和token信息
var loginInfo = new LoginInDto();
loginInfo.UserInfo = r.UserInfo;
loginInfo.TokenInfo = token;
var ops_login_time = token.Expired.AddDays(1) - DateTime.Now;//用于正式
_redisClientService.SetStringKey<LoginInDto>($"ops_login_{token.Token}", loginInfo, ops_login_time);
//登录成功移出对应的用户token黑名单应为新的token产生,移除登录的信息
string blacktoken = _redisClientService.GetStringKey($"ops_black_token_{r.UserInfo.UcId}");
if (!string.IsNullOrEmpty(blacktoken))
{
this.RemoveLoginInfo(blacktoken);
_redisClientService.RemoveStringKey($"ops_black_token_{r.UserInfo.UcId}");
}
if (r == null || r.UserInfo == null || r.TokenInfo == null)
return Result<LoginInDto>.ReFailure("授权失败,请重新登录", 401);
return Result<LoginInDto>.ReSuccess(r);
}
else
{
var errno_text = "登陆失败:" + jObject["errmsg"];
r.SignedIn = false;
string datajson_sessid = jObject["data"]["uc_sessid"];
//调用单点的退出接口
result = _httpClientHelp.GetHttp(_soaOptions.Url + "/uc/authorize/signin_out", true, cookieValue: datajson_sessid);
jObject = JsonObject.Parse(result);
if (jObject["errno"] == 0)
{
_logger.LogInformation("用户信息登录:" + errno_text);
return Result<LoginInDto>.ReFailure("拒绝用户证书试图访问此web站点请与站点管理员联系以建立用户证书权限", 403);
}
else
{
return Result<LoginInDto>.ReFailure(jObject["errmsg"], jObject["errno"]);
}
}
}
catch (Exception ex)
{
return Result<LoginInDto>.ReFailure("授权失败,请重新登录", 401);
}
}
/// <summary>
/// 登录退出
/// </summary>
/// <returns></returns>
public async Task<Result> LoginOutAsync(LoginOutDto dto)
{
_logger.LogInformation("dto_SessionId:" + dto.SessionId);
//2.请求PHP单点登出接口
JsonObject reqData = new JsonObject();
reqData.Add("app_id", _soaOptions.AppId);
reqData.Add("app_secret", _soaOptions.AppSecret);
reqData.Add("access_token", dto.AccessToken);
string result = _httpClientHelp.PostHttp(_soaOptions.Url + "/uc/authorize/signin_out", reqData, true, dto.SessionId);
_logger.LogInformation("退出登录返回:" + result);
var jObject = JsonObject.Parse(result);
if (jObject["errno"] == 0)
{
//设置本地token的缓存为黑名单的token做存储
await CacheOutToken(dto);
return Result.ReSuccess();
}
else
{
return Result.ReFailure(jObject["errmsg"], jObject["errno"]);
}
}
/// <summary>
/// 刷新token
/// </summary>
/// <returns></returns>
public async Task<Result<LoginInDto>> RefreshToken(string Token, string RefreshToken)
{
_logger.LogInformation("RefreshToken:" + RefreshToken);
//1.根据旧token 找到登录对象
var loginInfo = _redisClientService.GetStringKey<LoginInDto>($"ops_login_{Token}");
//2.请求PHP单点登出接口
JsonObject reqData = new JsonObject();
reqData.Add("app_id", _soaOptions.AppId);
reqData.Add("app_secret", _soaOptions.AppSecret);
reqData.Add("refresh_token", RefreshToken);
string result = _httpClientHelp.PostHttp(_soaOptions.Url + "/uc/authorize/refresh_token", reqData, true, Token);
var jObject = JsonObject.Parse(result);
LoginInDto r = new LoginInDto();
r.UserInfo = new UserInfoDto();
r.TokenInfo = new AccessTokenDto();
if (jObject["errno"] == 0)
{
string datajson = jObject["data"].ToString();
var _loginDto = JsonConvert.DeserializeObject<LoginTempDto>(datajson);
r.UserInfo = loginInfo.UserInfo;
r.SignedIn = true;
var token = await CreateToken(loginInfo.UserInfo, _loginDto, Token);
r.TokenInfo = token;
loginInfo.TokenInfo = token;
var ops_login_time = token.Expired.AddDays(1) - DateTime.Now;//用于正式
_redisClientService.SetStringKey<LoginInDto>($"ops_login_{token.Token}", loginInfo, ops_login_time);
return Result<LoginInDto>.ReSuccess(r);
}
else
{
//失败了1就把登录的token清除 2 ucid添加到黑名单
var time = new TimeSpan(r.TokenInfo.Expired.Day, r.TokenInfo.Expired.Hour, r.TokenInfo.Expired.Minute, r.TokenInfo.Expired.Second, r.TokenInfo.Expired.Millisecond);
_redisClientService.SetStringKey($"ops_black_token_{r.UserInfo.UcId}", r.TokenInfo.Token, time);
this.RemoveLoginInfo(r.TokenInfo.Token);
r.SignedIn = false;
return Result<LoginInDto>.ReFailure(jObject["errmsg"], jObject["errno"]);
}
}
/// <summary>
/// 单点退出通知token失效
/// </summary>
/// <param name="ucid"></param>
/// <param name="token"></param>
/// <param name="expires_in"></param>
/// <returns></returns>
public async Task LoginOutSingleAsync(int ucid, string token, int expires_in)
{
await Task.Run(() =>
{
var cache_token = _redisClientService.GetStringKey($"ops_black_token_{ucid}");
if (string.IsNullOrEmpty(cache_token))
{
DateTime expires_time = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)).AddSeconds(expires_in);
var time = new TimeSpan(expires_time.Day, expires_time.Hour, expires_time.Minute, expires_time.Second, expires_time.Millisecond);
_redisClientService.SetStringKey($"ops_black_token_{ucid}", token, time);
this.RemoveLoginInfo(token);
}
});
}
/// <summary>
/// 单点退出通知token失效
/// </summary>
/// <param name="SeesionId">这个是单点传过来的SeesionId</param>
/// <returns></returns>
public async Task LoginOutSingleAsync(string SeesionId)
{
var logininfo = _redisClientService.GetStringKey<LoginInDto>($"ops_login_{SeesionId}");
await Task.Run(() =>
{
if (logininfo != null)
{
var cache_token = _redisClientService.GetStringKey($"ops_black_token_{logininfo.UserInfo.UcId}");
if (string.IsNullOrEmpty(cache_token))
{
DateTime expires_time = logininfo.TokenInfo.Expired;
var time = new TimeSpan(expires_time.Day, expires_time.Hour, expires_time.Minute, expires_time.Second, expires_time.Millisecond);
_redisClientService.SetStringKey($"ops_black_token_{logininfo.UserInfo.UcId}", logininfo.TokenInfo.Token, time);
this.RemoveLoginInfo(logininfo.TokenInfo.Token);
}
}
});
}
/// <summary>
/// 缓存退出的token
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
private async Task CacheOutToken(LoginOutDto dto)
{
await Task.Run(() =>
{
if (!string.IsNullOrEmpty(dto.AccessToken))
{
var time = new TimeSpan(dto.ExpiresIn.Day, dto.ExpiresIn.Hour, dto.ExpiresIn.Minute, dto.ExpiresIn.Second, dto.ExpiresIn.Millisecond);
_redisClientService.SetStringKey($"ops_black_token_{dto.UcId}", dto.AccessToken, time);
this.RemoveLoginInfo(dto.Token);
}
});
}
/// <summary>
/// 获取登录后的信息
/// </summary>
/// <param name="authorization"></param>
/// <returns></returns>
public LoginInDto GetLoginInfo(string authorization)
{
string token = string.Empty;
if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
{
token = authorization.Substring("Bearer ".Length).Trim();
}
var logininfo = _redisClientService.GetStringKey<LoginInDto>($"ops_login_{token}");
return logininfo;
}
/// <summary>
/// 移除登录后的用户信息
/// </summary>
/// <param name="token"></param>
private void RemoveLoginInfo(string token)
{
if (!string.IsNullOrEmpty(token))
{
var info = _redisClientService.GetStringKey<LoginInDto>($"ops_login_{token}");
if (info != null)
{
_redisClientService.RemoveStringKey($"ops_login_{token}");
}
}
}
/// <summary>
/// 单点-在线接口
/// </summary>
/// <param name="sessionId"></param>
/// <returns></returns>
public async Task<Result> Online(string sessionId)
{
var request = new { PHPSESSID = sessionId };
string result = _httpClientHelp.PostHttpNoData(_soaOptions.Url + "/uc/user/online.html?app_id=" + _soaOptions.AppId, sessionId);
return Result.ReSuccess();
}
/// <summary>
/// 单点-下线接口
/// </summary>
/// <param name="sessionId"></param>
/// <returns></returns>
public async Task<Result> Offline(string sessionId)
{
var request = new { PHPSESSID = sessionId };
string result = _httpClientHelp.PostHttpNoData(_soaOptions.Url + "/uc/user/offline.html?app_id=" + _soaOptions.AppId, sessionId);
return Result.ReSuccess();
}
}
}

View File

@@ -0,0 +1,93 @@
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Text;
using WMS.Web.Domain.Options;
namespace WMS.Web.Domain.Services.Public
{
public class RedisClientService
{
private static readonly object Locker = new object();
private ConnectionMultiplexer redisMultiplexer;
IDatabase db = null;
private readonly AppOptions _options;
public RedisClientService(IOptions<AppOptions> options)
{
_options = options?.Value;
redisMultiplexer = ConnectionMultiplexer.Connect(_options.RedisConnectionString);
db = redisMultiplexer.GetDatabase();
}
#region String
/// <summary>
/// 保存单个key value
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public bool SetStringKey(string key, string value, TimeSpan? expiry = default(TimeSpan?))
{
var lastKey = _options.RedisDirectory + ":" + key;
return db.StringSet(lastKey, value, expiry);
}
/// <summary>
/// 获取单个key的值
/// </summary>
public RedisValue GetStringKey(string key)
{
var lastKey = _options.RedisDirectory + ":" + key;
return db.StringGet(lastKey);
}
/// <summary>
/// 移除redis
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool RemoveStringKey(string key)
{
var lastKey = _options.RedisDirectory + ":" + key;
return db.KeyDelete(lastKey);
}
/// <summary>
/// 获取一个key的对象
/// </summary>
public T GetStringKey<T>(string key)
{
if (db == null)
{
return default;
}
var lastKey = _options.RedisDirectory + ":" + key;
var value = db.StringGet(lastKey);
if (value.IsNullOrEmpty)
{
return default;
}
return JsonConvert.DeserializeObject<T>(value);
}
/// <summary>
/// 保存一个对象
/// </summary>
/// <param name="obj"></param>
public bool SetStringKey<T>(string key, T obj, TimeSpan? expiry = default(TimeSpan?))
{
if (db == null)
{
return false;
}
var lastKey = _options.RedisDirectory + ":" + key;
string json = JsonConvert.SerializeObject(obj);
return db.StringSet(lastKey, json, expiry);
}
#endregion
}
}

View File

@@ -0,0 +1,473 @@
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using WMS.Web.Core.Dto.SingleData;
using WMS.Web.Core.Internal.Results;
using WMS.Web.Domain.IService.Public;
using WMS.Web.Domain.Options;
using WMS.Web.Domain.Values.Single;
namespace WMS.Web.Domain.Services.Public
{
/// <summary>
/// 单点数据返回服务
/// </summary>
public class SingleDataService : ISingleDataService
{
private readonly AppOptions _options;
private readonly IHttpClientService _httpClientService;
private readonly ILogger<SingleDataService> _logger;
private readonly IMemoryCache _memoryCache;
private int hours = 10;//过期时间 默认10小时
public SingleDataService(IOptions<AppOptions> options, IHttpClientService httpClientService, ILogger<SingleDataService> logger, IMemoryCache memoryCache)
{
this._memoryCache = memoryCache;
this._options = options?.Value;
this._httpClientService = httpClientService;
this._logger = logger;
}
/// <summary>
/// 获取单点数据根据接口方法名和公司ID
/// 后端列表查询统一使用
/// </summary>
/// <param name="action"></param>
/// <param name="companyId"></param>
/// <returns></returns>
public string GetSingleData(SingleAction action, int companyId, int id)
{
try
{
if (id == 0)
return "";
var cache_key = action + "_" + companyId + "_IdGetName";
var dic = _memoryCache.Get<Dictionary<int, string>>(cache_key);
if (dic == null || dic.Count <= 0 || !dic.ContainsKey(id))
{
if (dic != null)
{
string no_data_key = cache_key + "_NoData";
var cache_id = _memoryCache.Get<bool>(no_data_key);
if (cache_id == true) return "";
//未找到数据请求
if (!dic.ContainsKey(id))
{
_memoryCache.Set(no_data_key, true, new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromMinutes(30)));
}
}
var list = SingleDataPost<SingleDataResponse>(action, companyId, cache_key);
if (list.Count() <= 0) return "";
dic = list.ToDictionary(s => s.Id, s => s.Name);
_memoryCache.Set(cache_key, dic, new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromHours(hours)));
}
if (!dic.ContainsKey(id)) return "";
return dic[id];
}
catch (Exception ex)
{
_logger.LogError($"请求单点数据错误Action->{action.ToString()}CompanyeId->{companyId},Id->{id}(错误原因)=>{ex.Message}");
return "";
}
}
/// <summary>
/// 获取单点数据根据接口方法名和公司ID
/// 后端列表查询统一使用
/// </summary>
/// <param name="action"></param>
/// <param name="companyId"></param>
/// <returns></returns>
public decimal GetSingleDataNumber(SingleAction action, int companyId, int id)
{
try
{
if (id == 0)
return 0;
var cache_key = action + "_" + companyId + "_IdGetNumber";
var dic = _memoryCache.Get<Dictionary<int, decimal>>(cache_key);
if (dic == null || dic.Count <= 0 || !dic.ContainsKey(id))
{
if (dic != null)
{
string no_data_key = cache_key + "_NoData";
var cache_id = _memoryCache.Get<bool>(no_data_key);
if (cache_id == true) return 0;
//未找到数据请求
if (!dic.ContainsKey(id))
{
_memoryCache.Set(no_data_key, true, new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromMinutes(30)));
}
}
var list = SingleDataPost<SingleDataResponse>(action, companyId, cache_key);
if (list.Count() <= 0) return 0;
dic = list.ToDictionary(s => s.Id, s => s.Number);
_memoryCache.Set(cache_key, dic, new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromHours(hours)));
}
if (!dic.ContainsKey(id)) return 0;
return dic[id];
}
catch (Exception ex)
{
_logger.LogError($"请求单点数据错误:{action.ToString()}=>{ex.Message}");
return 0;
}
}
/// <summary>
/// 获取单点数据根据接口方法名和公司ID
/// 后端列表查询统一使用
/// </summary>
/// <param name="action"></param>
/// <param name="companyId"></param>
/// <returns></returns>
public string GetSingleDataCode(SingleAction action, int companyId, int id)
{
try
{
if (id == 0)
return "";
var cache_key = action + "_" + companyId + "_IdGetCode";
var dic = _memoryCache.Get<Dictionary<int, string>>(cache_key);
if (dic == null || dic.Count <= 0 || !dic.ContainsKey(id))
{
if (dic != null)
{
string no_data_key = cache_key + "_NoData";
var cache_id = _memoryCache.Get<bool>(no_data_key);
if (cache_id == true) return "";
//未找到数据请求
if (!dic.ContainsKey(id))
{
_memoryCache.Set(no_data_key, true, new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromMinutes(30)));
}
}
var list = SingleDataPost<SingleDataResponse>(action, companyId, cache_key);
if (list.Count() <= 0) return "";
dic = list.ToDictionary(s => s.Id, s => s.Code);
_memoryCache.Set(cache_key, dic, new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromHours(hours)));
}
if (!dic.ContainsKey(id)) return "";
return dic[id];
}
catch (Exception ex)
{
_logger.LogError($"请求单点数据错误:{action.ToString()}=>{ex.Message}");
return "";
}
}
/// <summary>
/// 根据名字模糊匹配
/// </summary>
/// <param name="action"></param>
/// <param name="companyId"></param>
/// <param name="name"></param>
/// <returns></returns>
public List<int> GetIdsBySingleName(SingleAction action, int companyId, string name)
{
try
{
var cache_key = action + "_" + companyId + "_NameGetIds";
var dic = _memoryCache.Get<Dictionary<int, string>>(cache_key);
if (dic == null || dic.Count <= 0)
{
var list = SingleDataPost<SingleDataResponse>(action, companyId, cache_key);
if (list.Count() <= 0) return new List<int>();
dic = list.ToDictionary(s => s.Id, s => s.Name);
_memoryCache.Set(cache_key, dic, new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromHours(hours)));
}
var res = from d in dic where d.Value.Contains(name) select d;
return res.Select(s => s.Key).ToList();
}
catch (Exception ex)
{
_logger.LogError($"请求单点数据错误:{action.ToString()}=>{ex.Message}");
return new List<int>();
}
}
/// <summary>
/// 获取单点数据根据接口方法名和公司ID
/// 后端列表查询统一使用
/// </summary>
/// <param name="action"></param>
/// <param name="companyId"></param>
/// <returns></returns>
public string GetSingleData(SingleAction action, int companyId, string code)
{
try
{
if (string.IsNullOrEmpty(code))
return "";
var cache_key = action + "_" + companyId + "_CodeGetName";
var dic = _memoryCache.Get<Dictionary<string, string>>(cache_key);
//仓库和客户仓库 不能为空了就重新请求 应为 这里是从仓库和客户仓库取值 有一个必然取不到
if (dic == null || dic.Count <= 0)
{
if (dic != null)
{
string no_data_key = cache_key + "_NoData";
var cache_id = _memoryCache.Get<bool>(no_data_key);
if (cache_id == true) return "";
//未找到数据请求
if (!dic.ContainsKey(code))
{
_memoryCache.Set(no_data_key, true, new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromMinutes(30)));
}
}
var list = SingleDataPost<SingleDataResponse>(action, companyId, cache_key);
if (list.Count() <= 0) return "";
dic = list.ToDictionary(s => s.Code, s => s.Name);
_memoryCache.Set(cache_key, dic, new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromHours(hours)));
}
if (!dic.ContainsKey(code)) return "";
return dic[code];
}
catch (Exception ex)
{
_logger.LogError($"请求单点数据错误:{action.ToString()}=>{ex.Message}");
return "";
}
}
/// <summary>
/// 获取单点数据集合:泛型-同步
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="action"></param>
/// <param name="companyId"></param>
/// <returns></returns>
public List<T> GetSingleData<T>(SingleAction action, int companyId) where T : class
{
try
{
var cache_key = action + "_list_" + companyId;
var list = _memoryCache.Get<List<T>>(cache_key);
if (list == null || list.Count <= 0)
list = SingleDataPost<T>(action, companyId, cache_key);
return list;
}
catch (Exception ex)
{
_logger.LogError($"请求单点数据错误:{action.ToString()}=>{ex.Message}");
return null;
}
}
/// <summary>
/// 获取单点数据集合:泛型-异步
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="action"></param>
/// <param name="companyId"></param>
/// <returns></returns>
public async Task<List<T>> GetSingleDataAsync<T>(SingleAction action, int companyId) where T : class
{
try
{
var cache_key = action + "_list_" + companyId;
var list = _memoryCache.Get<List<T>>(cache_key);
if (list == null || list.Count <= 0)
list = await SingleDataPostAsync<T>(action, companyId, cache_key);
return list;
}
catch (Exception ex)
{
_logger.LogError($"请求单点数据错误:{action.ToString()}=>{ex.Message}");
return null;
}
}
/// <summary>
/// 获取单点数据集合:泛型-异步-无缓存
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="action"></param>
/// <param name="companyId"></param>
/// <returns></returns>
public async Task<List<T>> GetSingleDataNoCacheAsync<T>(SingleAction action, int companyId) where T : class
{
try
{
var list = await SingleDataPostAsync<T>(action, companyId, "");
return list;
}
catch (Exception ex)
{
_logger.LogError($"请求单点数据错误:{action.ToString()}=>{ex.Message}");
return null;
}
}
/// <summary>
/// 单点数据:可对接全部接口
/// </summary>
/// <typeparam name="T">返回对象</typeparam>
/// <typeparam name="X">请求对象</typeparam>
/// <typeparam name="Y">方法名称</typeparam>
/// <param name="dto">请求对象</param>
/// <param name="action">方法名称</param>
/// <param name="type">控制器名称</param>
/// <returns></returns>
public async Task<T> GetSingleData<T, X, Y>(X dto, Y action, SingleControllerType type = SingleControllerType.Single) where T : class
{
try
{
var para = JsonExtensions.SerializeToJson(dto);
var cache_key = action + "_list_" + type + "_" + para;
var list = _memoryCache.Get<T>(cache_key);
if (list == null)
{
var url = _options.SingleBaseUrl + "/" + type.ToString() + "/" + action.ToString();
var result = await _httpClientService.PostAsync<T>(url, para);
_memoryCache.Set(cache_key, result, new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromHours(hours)));
}
return _memoryCache.Get<T>(cache_key);
}
catch (Exception ex)
{
_logger.LogError($"请求单点数据错误:{action.ToString()}=>{ex.Message}");
return default(T);
}
}
/// <summary>
/// 单点数据:可对接全部接口
/// </summary>
/// <typeparam name="T">返回对象</typeparam>
/// <typeparam name="X">请求对象</typeparam>
/// <typeparam name="Y">方法名称</typeparam>
/// <param name="dto">请求对象</param>
/// <param name="action">方法名称</param>
/// <param name="type">控制器名称</param>
/// <returns></returns>
public async Task<T> GetSingleDataNoCache<T, X, Y>(X dto, Y action, SingleControllerType type = SingleControllerType.Single) where T : class
{
try
{
var para = JsonExtensions.SerializeToJson(dto);
var url = _options.SingleBaseUrl + "/" + type.ToString() + "/" + action.ToString();
var result = await _httpClientService.PostAsync<T>(url, para);
return result;
}
catch (Exception ex)
{
_logger.LogError($"请求单点数据错误:{action.ToString()}=>{ex.Message}");
return default(T);
}
}
/// <summary>
/// 获取单点数据:配置项接口
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="X"></typeparam>
/// <param name="dto"></param>
/// <param name="action"></param>
/// <returns></returns>
public async Task<T> GetSysConfigData<T, X>(X dto, SysConfigAction action)
{
try
{
var para = JsonExtensions.SerializeToJson(dto);
var url = _options.SingleBaseUrl + "/" + SingleControllerType.SysConfig.ToString() + "/" + action.ToString();
var result = await _httpClientService.PostAsync<T>(url, para);
return result;
}
catch (Exception ex)
{
_logger.LogError($"请求单点数据错误:{action.ToString()}=>{ex.Message}");
return default(T);
}
}
#region
/// <summary>
/// 请求单点服务接口:同步
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="action"></param>
/// <param name="companyId"></param>
/// <returns></returns>
private List<T> SingleDataPost<T>(SingleAction action, int companyId, string cache_key)
{
var dto = new SingleDataRequest(companyId);
//var para = JsonExtensions.SerializeToJson(dto);
var para = JsonSerializer.Serialize(dto);
var url = _options.SingleBaseUrl + "/" + SingleControllerType.Single.ToString() + "/" + action.ToString();
var result = _httpClientService.PostAsync<ResultList<T>>(url, para).GetAwaiter().GetResult();
if (!result.Success)
return new List<T>();
return result.Data.ToList();
}
/// <summary>
/// 请求单点服务接口:异步
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="action"></param>
/// <param name="companyId"></param>
/// <returns></returns>
private async Task<List<T>> SingleDataPostAsync<T>(SingleAction action, int companyId, string cache_key)
{
var dto = new SingleDataRequest(companyId);
var para = JsonSerializer.Serialize(dto);
var url = _options.SingleBaseUrl + "/" + SingleControllerType.Single.ToString() + "/" + action.ToString();
var result = await _httpClientService.PostAsync<ResultList<T>>(url, para);
if (result.Success)
{
if (!string.IsNullOrEmpty(cache_key))
{
_memoryCache.Set(cache_key, result.Data.ToList(), new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromHours(hours)));
return _memoryCache.Get<List<T>>(cache_key);
}
return result.Data.ToList();
}
return null;
}
#endregion
/// <summary>
/// 获取客户仓库
/// </summary>
/// <param name="companyId"></param>
/// <param name="customerStockCode"></param>
/// <returns></returns>
public string GetCustomerStock(int companyId, string customerStockCode)
{
return string.IsNullOrEmpty(this.GetSingleData(SingleAction.CustomerStocks, companyId, customerStockCode)) ?
this.GetSingleData(SingleAction.Stocks, companyId, customerStockCode) :
this.GetSingleData(SingleAction.CustomerStocks, companyId, customerStockCode);
}
}
}