fix 多钱包调整
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
using Dlhis.Canteen.Dishes.Request;
|
||||
using Dlhis.Canteen.Order.Request;
|
||||
using Dlhis.Canteen.Order.Request;
|
||||
using Dlhis.Canteen.Order.Response;
|
||||
using Dlhis.Canteen.Order.Services;
|
||||
using Kurisu.AspNetCore.DataAccess.Dto;
|
||||
@@ -35,8 +34,7 @@ public class OrdersController : ControllerBase
|
||||
[IgnoreTenant]
|
||||
public async Task<DefaultApiResult<OrderResultResponse>> AddAsync(OrderAddRequest request)
|
||||
{
|
||||
var result = await _orderService.AddAsync(request);
|
||||
return result.Response;
|
||||
return await _orderService.AddAsync(request);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -49,8 +47,7 @@ public class OrdersController : ControllerBase
|
||||
[IgnoreTenant]
|
||||
public async Task<DefaultApiResult<OrderResultResponse>> DeviceConsume(OrderAddRequest request)
|
||||
{
|
||||
var result = await _orderService.AddAsync(request);
|
||||
return result.Response;
|
||||
return await _orderService.AddAsync(request);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -16,15 +16,18 @@ public class BalanceRepository : IBalanceRepository
|
||||
|
||||
public async Task<decimal> GetBalanceAsync(string userCode, string factory)
|
||||
{
|
||||
var factories = await GetWalletFactoriesAsync(factory);
|
||||
|
||||
return await _dbContext.Queryable<BalanceRecordEntity>()
|
||||
var queryable = _dbContext.Queryable<BalanceRecordEntity>()
|
||||
.Where(x => x.UserCode == userCode && x.Status == BalanceRecordStatusEnumType.Valid)
|
||||
.Where(x => factories.Contains(x.TenantId))
|
||||
.Where(x => x.Source != BalanceRecordSourceEnumType.EMealVoucher)
|
||||
.SumAsync(x => x.Amount);
|
||||
}
|
||||
.Where(x => x.Source != BalanceRecordSourceEnumType.EMealVoucher);
|
||||
|
||||
if (!factory.IsPresent())
|
||||
{
|
||||
return await queryable.SumAsync(x => x.Amount);
|
||||
}
|
||||
|
||||
var factories = await GetWalletFactoriesAsync(factory);
|
||||
return await queryable.Where(x => factories.Contains(x.TenantId)).SumAsync(x => x.Amount);
|
||||
}
|
||||
|
||||
public async Task<List<BalanceRecordEntity>> GetBalanceRecordsAsync(string userCode, string factory, DateTime startTime, DateTime endTime)
|
||||
{
|
||||
|
||||
@@ -32,4 +32,13 @@ public class OrderResultResponse
|
||||
/// 余额
|
||||
/// </summary>
|
||||
public string Balance => CurrentBalance.ToString("f2");
|
||||
}
|
||||
|
||||
|
||||
[JsonIgnore]
|
||||
public decimal CurrentTotalBalance { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总余额
|
||||
/// </summary>
|
||||
public string TotalBalance => CurrentTotalBalance.ToString("f2");
|
||||
}
|
||||
@@ -1,19 +1,20 @@
|
||||
using Dlhis.Canteen.Order.Request;
|
||||
using Dlhis.Canteen.Order.Response;
|
||||
using Kurisu.AspNetCore.DataAccess.Dto;
|
||||
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
||||
|
||||
namespace Dlhis.Canteen.Order.Services;
|
||||
|
||||
public interface IOrderService : IScopeDependency
|
||||
{
|
||||
Task<OrderResultResponseWithLogs> AddAsync(OrderAddRequest request);
|
||||
Task<DefaultApiResult<OrderResultResponse>> AddAsync(OrderAddRequest request);
|
||||
|
||||
/// <summary>
|
||||
/// 设备消费
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
Task<OrderResultResponseWithLogs> DeviceConsume(OrderAddRequest request);
|
||||
Task<DefaultApiResult<OrderResultResponse>> DeviceConsume(OrderAddRequest request);
|
||||
|
||||
Task<Pagination<OrderAggregationResponse>> GetOrdersAggregationAsync(PageDto page);
|
||||
}
|
||||
@@ -57,7 +57,7 @@ public class OrderService : IOrderService
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<OrderResultResponseWithLogs> DeviceConsume(OrderAddRequest request)
|
||||
public async Task<DefaultApiResult<OrderResultResponse>> DeviceConsume(OrderAddRequest request)
|
||||
{
|
||||
return await AddAsync(request);
|
||||
}
|
||||
@@ -67,7 +67,7 @@ public class OrderService : IOrderService
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<OrderResultResponseWithLogs> AddAsync(OrderAddRequest request)
|
||||
public async Task<DefaultApiResult<OrderResultResponse>> AddAsync(OrderAddRequest request)
|
||||
{
|
||||
await SetDeviceIpInfoAsync(request.DeviceUniqueNo);
|
||||
|
||||
@@ -75,10 +75,7 @@ public class OrderService : IOrderService
|
||||
handler.Acquired.ThrowIfFalse("请勿频繁消费");
|
||||
|
||||
var gainfo = await GetUserAsync(request);
|
||||
return new OrderResultResponseWithLogs
|
||||
{
|
||||
Response = await ToDoAsync(request, gainfo)
|
||||
};
|
||||
return await ToDoAsync(request, gainfo);
|
||||
}
|
||||
|
||||
|
||||
@@ -256,7 +253,7 @@ public class OrderService : IOrderService
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="gainfo"></param>
|
||||
private async Task HandleOfflineAsync(ConsumeRequest request, GainfoEntity gainfo)
|
||||
private async Task OfflineHandleAsync(ConsumeRequest request, GainfoEntity gainfo)
|
||||
{
|
||||
var bindingInfo = await _dbContext.Queryable<DeviceRegistryEntity>()
|
||||
.LeftJoin<BusinessPlaceEntity>((x, b) => x.BusinessPlaceCode == b.Code)
|
||||
@@ -273,11 +270,13 @@ public class OrderService : IOrderService
|
||||
var shifts = await _dbContext.Queryable<BusinessShiftMealRelationshipEntity>()
|
||||
.Where(x => x.ShiftCode == bindingInfo.ShiftCode).ToListAsync();
|
||||
|
||||
var shift = shifts.FirstOrDefault(x => new TimePeriod
|
||||
{
|
||||
Start = x.Start,
|
||||
End = x.End
|
||||
}.IsPresent(request.CostDateTime));
|
||||
var shift = shifts.FirstOrDefault(x =>
|
||||
new TimePeriod
|
||||
{
|
||||
Start = x.Start,
|
||||
End = x.End
|
||||
}.IsPresent(request.CostDateTime)
|
||||
);
|
||||
|
||||
var costDate = await _canteenSettingService.GetCostDateAsync(bindingInfo.Factory, request.CostDateTime);
|
||||
|
||||
@@ -317,7 +316,7 @@ public class OrderService : IOrderService
|
||||
TenantId = bindingInfo.Factory,
|
||||
};
|
||||
|
||||
await _dbContext.InsertReturnIdentityAsync(order);
|
||||
await _dbContext.InsertAsync(order);
|
||||
var balanceRecord = order.Adapt<BalanceRecordEntity>();
|
||||
await _dbContext.InsertAsync(balanceRecord);
|
||||
}
|
||||
@@ -391,16 +390,36 @@ public class OrderService : IOrderService
|
||||
//获取餐券余额
|
||||
var data = await _dbContext.Queryable<EMealVoucherEntity>()
|
||||
.LeftJoin<EMealVoucherDetailEntity>((x, d) => x.No == d.No)
|
||||
.LeftJoin<GainfoEntity>((x, d, u) => u.IdNo == d.IdNo)
|
||||
.Where((x, d) => x.No == no && d.IdNo == idNo)
|
||||
.Select((x, d, u) => new OrderResultResponse
|
||||
.Select((x, d) => new OrderResultResponse
|
||||
{
|
||||
UserCode = u.Code,
|
||||
UserName = u.Name,
|
||||
UserCode = d.IdNo,
|
||||
UserName = d.Name,
|
||||
CurrentBalance = d.Balance
|
||||
})
|
||||
.SingleAsync();
|
||||
|
||||
try
|
||||
{
|
||||
var v = data.UserCode ?? string.Empty;
|
||||
var vc = v.ToCharArray().Reverse().ToList();
|
||||
|
||||
for (int i = 0; i < vc.Count; i++)
|
||||
{
|
||||
if (i + 1 > 4)
|
||||
{
|
||||
vc[i] = '*';
|
||||
}
|
||||
}
|
||||
|
||||
vc.Reverse();
|
||||
data.UserCode = string.Join("", vc);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//ignore
|
||||
}
|
||||
|
||||
return new DefaultApiResult<OrderResultResponse>
|
||||
{
|
||||
Code = msg.IsPresent() ? ApiStateCode.Error : ApiStateCode.Success,
|
||||
@@ -409,6 +428,30 @@ public class OrderService : IOrderService
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private async Task OfflineConsumeAsync(OrderAddRequest request, GainfoEntity gainfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (request.ThirdNo.IsPresent() && await ToCheckAbleOfflineConsumeAsync(request.ThirdNo))
|
||||
{
|
||||
await using var handler = await _redisCache.LockAsync($"consume:device-offline:{request.ThirdNo}");
|
||||
if (handler.Acquired)
|
||||
{
|
||||
await OfflineHandleAsync(request.Adapt<ConsumeRequest>(), gainfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await OfflineHandleAsync(request.Adapt<ConsumeRequest>(), gainfo);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "离线入库错误: 订单号:{no} .{message}", request.ThirdNo, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分支处理在线/离线消费
|
||||
/// </summary>
|
||||
@@ -423,27 +466,7 @@ public class OrderService : IOrderService
|
||||
return await EMealVoucherConsumeAsync(request, gainfo);
|
||||
|
||||
if (request.IsOffline)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (request.ThirdNo.IsPresent() && await ToCheckAbleOfflineConsumeAsync(request.ThirdNo))
|
||||
{
|
||||
await using var handler = await _redisCache.LockAsync($"consume:device-offline:{request.ThirdNo}");
|
||||
if (handler.Acquired)
|
||||
{
|
||||
await HandleOfflineAsync(request.Adapt<ConsumeRequest>(), gainfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await HandleOfflineAsync(request.Adapt<ConsumeRequest>(), gainfo);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "离线入库错误: 订单号:{no} .{message}", request.ThirdNo, ex.Message);
|
||||
}
|
||||
}
|
||||
await OfflineConsumeAsync(request, gainfo);
|
||||
else
|
||||
{
|
||||
try
|
||||
@@ -454,52 +477,17 @@ public class OrderService : IOrderService
|
||||
{
|
||||
message = ex.Message;
|
||||
}
|
||||
|
||||
//获取餐券余额
|
||||
var data = await DbContext.Queryable<EMealVoucherEntity>()
|
||||
.LeftJoin<EMealVoucherDetailEntity>((x, d) => x.No == d.No)
|
||||
.Where((x, d) => x.No == no && d.IdNo == idNo)
|
||||
.Select((x, d) => new OrderResultResponse
|
||||
{
|
||||
UserCode = d.IdNo,
|
||||
UserName = d.Name,
|
||||
CurrentBalance = d.Balance
|
||||
})
|
||||
.SingleAsync();
|
||||
|
||||
try
|
||||
{
|
||||
var v = data.UserCode ?? string.Empty;
|
||||
var vc = v.ToCharArray().Reverse().ToList();
|
||||
|
||||
for (int i = 0; i < vc.Count; i++)
|
||||
{
|
||||
if (i + 1 > 4)
|
||||
{
|
||||
vc[i] = '*';
|
||||
}
|
||||
}
|
||||
|
||||
vc.Reverse();
|
||||
data.UserCode = string.Join("", vc);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return new DefaultApiResult<OrderResultResponse>
|
||||
{
|
||||
Code = message.IsPresent() ? ApiStateCode.Error : ApiStateCode.Success,
|
||||
Data = data,
|
||||
Msg = message
|
||||
};
|
||||
}
|
||||
|
||||
var currentFactory = await _dbContext.Queryable<DeviceEntity>().Where(x => x.UniqueNo == request.DeviceUniqueNo).Select(x => x.TenantId).SingleAsync();
|
||||
var balance = await _balanceRepository.GetBalanceAsync(gainfo.Code, currentFactory);
|
||||
//获取人员信息
|
||||
var currentFactory = await _dbContext.Queryable<DeviceEntity>()
|
||||
.Where(x => x.UniqueNo == request.DeviceUniqueNo)
|
||||
.Select(x => x.TenantId)
|
||||
.SingleAsync();
|
||||
|
||||
var balance = await _balanceRepository.GetBalanceAsync(gainfo.Code, currentFactory);
|
||||
var totalBalance = await _balanceRepository.GetBalanceAsync(gainfo.Code, string.Empty);
|
||||
|
||||
//获取人员余额
|
||||
var data = await _dbContext.Queryable<GainfoEntity>()
|
||||
.LeftJoin<DepartmentEntity>((x, department) => x.DepartmentNo == department.No)
|
||||
.Where(x => x.Code == gainfo.Code)
|
||||
@@ -509,7 +497,9 @@ public class OrderService : IOrderService
|
||||
UserName = x.Name,
|
||||
DepartmentNo = x.DepartmentNo,
|
||||
DepartmentName = department.Name,
|
||||
CurrentBalance = balance
|
||||
|
||||
CurrentBalance = balance,
|
||||
CurrentTotalBalance = totalBalance
|
||||
})
|
||||
.SingleAsync();
|
||||
|
||||
@@ -555,6 +545,7 @@ public class OrderService : IOrderService
|
||||
|
||||
(nowDate >= current.Start && nowDate <= current.End).ThrowIfFalse("餐券已过期");
|
||||
|
||||
|
||||
var eMealVoucher = await _dbContext.Queryable<EMealVoucherEntity>().Where(x => x.No == no).SingleAsync();
|
||||
|
||||
var checkData = await PreCheckAsync(request.DeviceUniqueNo, request.CostDateTime);
|
||||
|
||||
@@ -44,7 +44,13 @@ public interface ICanteenSettingService : IScopeDependency
|
||||
Task<TimeOnly?> GetBusinessSwitchTimeAsync(string tenantId);
|
||||
|
||||
|
||||
Task<T> GetSettingAsync<T>(CanteenSettingItemEnumType item, string factory, string userNo , T defaultValue = default);
|
||||
Task<T> GetSettingAsync<T>(CanteenSettingItemEnumType item, string factory, string userNo, T defaultValue = default);
|
||||
|
||||
/// <summary>
|
||||
/// 获取消费日期
|
||||
/// </summary>
|
||||
/// <param name="factory"></param>
|
||||
/// <param name="costDateTime"></param>
|
||||
/// <returns></returns>
|
||||
Task<DateTime> GetCostDateAsync(string factory, DateTime costDateTime);
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using System.Text;
|
||||
using Dlhis.Middle.Response;
|
||||
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
||||
using Kurisu.RemoteCall.Abstractions;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Dlhis.Middle.Api
|
||||
{
|
||||
public class FaceBearerTokenHandler : IAuthTokenHandler
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public string GetToken(IServiceProvider serviceProvider)
|
||||
{
|
||||
var cache = serviceProvider.GetService<IMemoryCache>();
|
||||
if (cache.TryGetValue("token", out string token)) return "Bearer " + token;
|
||||
|
||||
var httpClient = serviceProvider.GetService<IHttpClientFactory>().CreateClient("face");
|
||||
var hostName = serviceProvider.GetService<IConfiguration>().GetSection("HostName").Value;
|
||||
|
||||
var tokenResponse = httpClient.PostAsync($"https://{hostName}/api/user/oauth2/clientgrant", new StringContent(JsonConvert.SerializeObject(new
|
||||
{
|
||||
ClientId = "e509c2aaa98e300c",
|
||||
ClientSecret = "6184d8979fc48105"
|
||||
}), Encoding.UTF8, "application/json")).GetAwaiter().GetResult();
|
||||
|
||||
var tokenJson = tokenResponse.Content.ReadAsStringAsync().GetAwaiter().GetResult();
|
||||
var tokenInfo = JsonConvert.DeserializeObject<DefaultApiResult<TokenResponse>>(tokenJson);
|
||||
|
||||
token = tokenInfo.Data.AccessToken;
|
||||
|
||||
cache.Set("token", token, TimeSpan.FromSeconds(tokenInfo.Data.Expires));
|
||||
|
||||
return token;
|
||||
}
|
||||
}
|
||||
}
|
||||
23
Src/Dlhis.Middle/Apis/Handlers/ClientHandler.cs
Normal file
23
Src/Dlhis.Middle/Apis/Handlers/ClientHandler.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using Kurisu.RemoteCall.Abstractions;
|
||||
|
||||
namespace Dlhis.Middle.Apis.Handlers;
|
||||
|
||||
public class ClientHandler : IHttpRemoteCallPolicyHandler
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public IHttpClientBuilder ConfigureHttpClient(IHttpClientBuilder builder)
|
||||
{
|
||||
builder.ConfigureHttpClient(client => { client.Timeout = TimeSpan.FromSeconds(10); }).ConfigurePrimaryHttpMessageHandler(() =>
|
||||
{
|
||||
var handler = new HttpClientHandler
|
||||
{
|
||||
ClientCertificateOptions = ClientCertificateOption.Manual,
|
||||
ServerCertificateCustomValidationCallback = (_, _, _, _) => true
|
||||
};
|
||||
|
||||
return handler;
|
||||
});
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
14
Src/Dlhis.Middle/Apis/Handlers/FaceBearerTokenHandler.cs
Normal file
14
Src/Dlhis.Middle/Apis/Handlers/FaceBearerTokenHandler.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using Dlhis.Middle.Services;
|
||||
using Kurisu.RemoteCall.Abstractions;
|
||||
|
||||
namespace Dlhis.Middle.Apis.Handlers;
|
||||
|
||||
public class FaceBearerTokenHandler : IAsyncAuthTokenHandler
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<string> GetTokenAsync(IServiceProvider serviceProvider)
|
||||
{
|
||||
var tokenService = serviceProvider.GetService<ITokenService>();
|
||||
return await tokenService.AuthAsync();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
using Dlhis.Middle.Apis.Handlers;
|
||||
using Dlhis.Middle.Request;
|
||||
using Dlhis.Middle.Response;
|
||||
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
||||
using Kurisu.RemoteCall.Attributes;
|
||||
|
||||
namespace Dlhis.Middle.Api;
|
||||
namespace Dlhis.Middle.Apis;
|
||||
|
||||
[EnableRemoteClient(Name = "face-service", BaseUrl = "${Authority}")]
|
||||
[RequestLog]
|
||||
[EnableRemoteClient(Name = "face-service", BaseUrl = "${BaseUrl}", PolicyHandler = typeof(ClientHandler))]
|
||||
public interface IAssignmentDeviceTaskApi
|
||||
{
|
||||
[Auth(TokenHandler = typeof(FaceBearerTokenHandler))]
|
||||
@@ -1,26 +1,29 @@
|
||||
using Dlhis.Middle.Apis.Handlers;
|
||||
using Dlhis.Middle.Entities;
|
||||
using Dlhis.Middle.Request;
|
||||
using Dlhis.Middle.Response;
|
||||
using Kurisu.AspNetCore.DataAccess.Dto;
|
||||
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
||||
using Kurisu.RemoteCall.Attributes;
|
||||
|
||||
namespace Dlhis.Middle.Api;
|
||||
namespace Dlhis.Middle.Apis;
|
||||
|
||||
[EnableRemoteClient(Name = "face-service", BaseUrl = "${Authority}")]
|
||||
[RequestLog]
|
||||
[EnableRemoteClient(Name = "face-service", BaseUrl = "${BaseUrl}", PolicyHandler = typeof(ClientHandler))]
|
||||
public interface ICanteenApi
|
||||
{
|
||||
|
||||
[Auth(TokenHandler = typeof(FaceBearerTokenHandler))]
|
||||
[Post("/api/canteen/orders")]
|
||||
Task<DefaultApiResult<OrderResultResponse>> AddAsync(OrderAddRequest request);
|
||||
|
||||
|
||||
|
||||
|
||||
[Auth(TokenHandler = typeof(FaceBearerTokenHandler))]
|
||||
[Post("/api/canteen/middle/upload")]
|
||||
Task<DefaultApiResult<OrderResultResponse>> UploadAsync(LocalBalanceRecordEntity entity);
|
||||
|
||||
[Auth(TokenHandler = typeof(FaceBearerTokenHandler))]
|
||||
[Post("/api/canteen/balances/device/page")]
|
||||
Task<DefaultApiResult<Pagination<BalanceRecordDeviceResponse>>> GetPageByDeviceUniqueNoAsync(BalanceRecordPageByDeviceUniqueNoRequest request);
|
||||
|
||||
|
||||
|
||||
[Auth(TokenHandler = typeof(FaceBearerTokenHandler))]
|
||||
[Post("/api/canteen/balances/refund")]
|
||||
Task<DefaultApiResult<OrderResultResponse>> RefundAsync(BalanceRecordRefundRequest request);
|
||||
22
Src/Dlhis.Middle/Apis/ICommonApi.cs
Normal file
22
Src/Dlhis.Middle/Apis/ICommonApi.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using Dlhis.Middle.Apis.Handlers;
|
||||
using Dlhis.Middle.Request;
|
||||
using Dlhis.Middle.Response;
|
||||
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
||||
using Kurisu.RemoteCall.Attributes;
|
||||
|
||||
namespace Dlhis.Middle.Apis;
|
||||
|
||||
[EnableRemoteClient(Name = "face-service", BaseUrl = "${BaseUrl}", PolicyHandler = typeof(ClientHandler))]
|
||||
public interface ICommonApi
|
||||
{
|
||||
[Post("/api/user/oauth2/clientgrant")]
|
||||
public Task<DefaultApiResult<TokenResponse>> AuthAsync(object request);
|
||||
|
||||
[Auth(TokenHandler = typeof(FaceBearerTokenHandler))]
|
||||
[Post("/api/common/middles/healthz")]
|
||||
public Task<DefaultApiResult> CheckHealthAsync(HealthCheckRequest request);
|
||||
|
||||
[Auth(TokenHandler = typeof(FaceBearerTokenHandler))]
|
||||
[Get("/api/common/SysData/download")]
|
||||
public Task<DefaultApiResult<List<T>>> DownloadAsync<T>(string factory, string tableName);
|
||||
}
|
||||
@@ -1,46 +1,43 @@
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using Dlhis.Middle.Apis;
|
||||
using Dlhis.Middle.Entities;
|
||||
using Dlhis.Middle.Response;
|
||||
using Dlhis.Middle.Services;
|
||||
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
|
||||
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
||||
using Kurisu.AspNetCore.Utils.Extensions;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Dlhis.Middle.Services.Implements;
|
||||
namespace Dlhis.Middle.BackgroundServices;
|
||||
|
||||
public class BalanceRecordCheckBackgroundService : BackgroundService
|
||||
public class BalanceRecordUploadBackgroundService : BackgroundService
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly ILogger<BalanceRecordCheckBackgroundService> _logger;
|
||||
private readonly IMemoryCache _memoryCache;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly ILogger<BalanceRecordUploadBackgroundService> _logger;
|
||||
private readonly IWebHostEnvironment _environment;
|
||||
private readonly ISettingService _settingService;
|
||||
private readonly ICanteenApi _canteenApi;
|
||||
|
||||
private readonly IHealthCheckService _healthCheckService;
|
||||
|
||||
private readonly string _factory;
|
||||
private readonly string _hostName;
|
||||
|
||||
public BalanceRecordCheckBackgroundService(IServiceProvider serviceProvider,
|
||||
ILogger<BalanceRecordCheckBackgroundService> logger,
|
||||
IMemoryCache memoryCache,
|
||||
IHttpClientFactory httpClientFactory,
|
||||
IHealthCheckService healthCheckService,
|
||||
IConfiguration configuration)
|
||||
public BalanceRecordUploadBackgroundService(IServiceProvider serviceProvider,
|
||||
ILogger<BalanceRecordUploadBackgroundService> logger,
|
||||
IWebHostEnvironment environment,
|
||||
ISettingService settingService,
|
||||
ICanteenApi canteenApi,
|
||||
IHealthCheckService healthCheckService)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_logger = logger;
|
||||
_memoryCache = memoryCache;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_environment = environment;
|
||||
_settingService = settingService;
|
||||
_canteenApi = canteenApi;
|
||||
_healthCheckService = healthCheckService;
|
||||
_factory = configuration.GetSection("Factory").Value;
|
||||
_hostName = configuration.GetSection("HostName").Value;
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
while (!stoppingToken.IsCancellationRequested && _environment.IsProduction())
|
||||
{
|
||||
if (!_healthCheckService.GetIsOffline())
|
||||
{
|
||||
@@ -50,7 +47,8 @@ public class BalanceRecordCheckBackgroundService : BackgroundService
|
||||
var db = scope.ServiceProvider.GetService<IDbContext>();
|
||||
var ds = scope.ServiceProvider.GetService<IDataDownloadService>();
|
||||
|
||||
foreach (var factory in _factory.Split(','))
|
||||
var factories = _settingService.GetFactories();
|
||||
foreach (var factory in factories)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -64,7 +62,7 @@ public class BalanceRecordCheckBackgroundService : BackgroundService
|
||||
await db.Client.Ado.BeginTranAsync();
|
||||
try
|
||||
{
|
||||
var r = await UploadAsync(balanceRecord);
|
||||
var r = await _canteenApi.UploadAsync(balanceRecord);
|
||||
if (r.Code != ApiStateCode.Success)
|
||||
{
|
||||
throw new Exception(r.Msg);
|
||||
@@ -108,62 +106,23 @@ public class BalanceRecordCheckBackgroundService : BackgroundService
|
||||
&& !_healthCheckService.GetIsOffline()
|
||||
&& !await db.Queryable<LocalBalanceRecordEntity>().Where(x => !x.IsSync).AnyAsync())
|
||||
{
|
||||
await ds.InitAsync(_factory);
|
||||
await ds.InitAsync(factories);
|
||||
}
|
||||
else if (now is { Hour: 15, Minute: 1 }
|
||||
&& !_healthCheckService.GetIsOffline()
|
||||
&& !await db.Queryable<LocalBalanceRecordEntity>().Where(x => !x.IsSync).AnyAsync())
|
||||
{
|
||||
await ds.InitAsync(_factory);
|
||||
await ds.InitAsync(factories);
|
||||
}
|
||||
else if (now is { Hour: 20, Minute: 1 }
|
||||
&& !_healthCheckService.GetIsOffline()
|
||||
&& !await db.Queryable<LocalBalanceRecordEntity>().Where(x => !x.IsSync).AnyAsync())
|
||||
{
|
||||
await ds.InitAsync(_factory);
|
||||
await ds.InitAsync(factories);
|
||||
}
|
||||
}
|
||||
|
||||
await Task.Delay(60 * 1000, stoppingToken);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<DefaultApiResult<OrderResultResponse>> UploadAsync(LocalBalanceRecordEntity entity)
|
||||
{
|
||||
var token = await AuthAsync();
|
||||
|
||||
var httpClient = _httpClientFactory.CreateClient("face");
|
||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
||||
|
||||
var url = $"https://{_hostName}/api/canteen/middle/upload";
|
||||
|
||||
var json = entity.ToJson();
|
||||
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
||||
|
||||
var response = await httpClient.PostAsync(url, content);
|
||||
var responseJson = await response.Content.ReadAsStringAsync();
|
||||
return responseJson.ToObject<DefaultApiResult<OrderResultResponse>>();
|
||||
}
|
||||
|
||||
private async Task<string> AuthAsync()
|
||||
{
|
||||
var httpClient = _httpClientFactory.CreateClient("face");
|
||||
|
||||
if (_memoryCache.TryGetValue("token", out string token)) return token;
|
||||
|
||||
var tokenResponse = await httpClient.PostAsync($"https://{_hostName}/api/User/OAuth2/clientgrant", new StringContent(JsonConvert.SerializeObject(new
|
||||
{
|
||||
ClientId = "e509c2aaa98e300c",
|
||||
ClientSecret = "6184d8979fc48105"
|
||||
}), Encoding.UTF8, "application/json"));
|
||||
|
||||
var tokenJson = await tokenResponse.Content.ReadAsStringAsync();
|
||||
var tokenInfo = JsonConvert.DeserializeObject<DefaultApiResult<TokenResponse>>(tokenJson);
|
||||
|
||||
token = tokenInfo.Data.AccessToken;
|
||||
|
||||
_memoryCache.Set("token", token, TimeSpan.FromSeconds(tokenInfo.Data.Expires));
|
||||
|
||||
return token;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace Dlhis.Middle.Services.Implements;
|
||||
using Dlhis.Middle.Services;
|
||||
|
||||
namespace Dlhis.Middle.BackgroundServices;
|
||||
|
||||
public class HealthCheckBackgroundService : BackgroundService
|
||||
{
|
||||
@@ -1,5 +1,5 @@
|
||||
using Dlhis.Entity.Device.Enums;
|
||||
using Dlhis.Middle.Api;
|
||||
using Dlhis.Middle.Apis;
|
||||
using Dlhis.Middle.Request;
|
||||
using Dlhis.Middle.Response;
|
||||
using Dlhis.Middle.Services;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Dlhis.Middle.Api;
|
||||
using Dlhis.Middle.Apis;
|
||||
using Dlhis.Middle.Request;
|
||||
using Dlhis.Middle.Response;
|
||||
using Dlhis.Middle.Services;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Dlhis.Middle.Filters;
|
||||
using Dlhis.Middle.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
@@ -12,14 +13,13 @@ namespace Dlhis.Middle.Controllers;
|
||||
public class GainfosController : ControllerBase
|
||||
{
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ILogger<GainfosController> _logger;
|
||||
private readonly ISettingService _settingService;
|
||||
|
||||
public GainfosController(IHttpClientFactory httpClientFactory, IConfiguration configuration, ILogger<GainfosController> logger)
|
||||
public GainfosController(IHttpClientFactory httpClientFactory,
|
||||
ISettingService settingService)
|
||||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_configuration = configuration;
|
||||
_logger = logger;
|
||||
_settingService = settingService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -32,14 +32,11 @@ public class GainfosController : ControllerBase
|
||||
[HttpGet("face")]
|
||||
public async Task<IActionResult> GetFaceAsync(string token)
|
||||
{
|
||||
var hostName = _configuration.GetSection("HostName").Value;
|
||||
var httpClient = _httpClientFactory.CreateClient("face");
|
||||
|
||||
_logger.LogInformation("token:{token}", token);
|
||||
var httpClient = _httpClientFactory.CreateClient();
|
||||
|
||||
try
|
||||
{
|
||||
var faceBytes = await httpClient.GetByteArrayAsync($"https://{hostName}/api/basic/gainfos/face?token={token}");
|
||||
var faceBytes = await httpClient.GetByteArrayAsync($"{_settingService.GetBaseUrl()}/api/basic/gainfos/face?token={token}");
|
||||
|
||||
if (faceBytes.Length == 0)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Text;
|
||||
using Dlhis.Middle.Apis;
|
||||
using Dlhis.Middle.Request;
|
||||
using Dlhis.Middle.Services;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@@ -13,23 +14,20 @@ namespace Dlhis.Middle.Controllers;
|
||||
[ApiController]
|
||||
public class OAuth2Controller : ControllerBase
|
||||
{
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ICommonApi _commonApi;
|
||||
private readonly IHealthCheckService _healthCheckService;
|
||||
|
||||
public OAuth2Controller(IHttpClientFactory httpClientFactory, IConfiguration configuration, IHealthCheckService healthCheckService)
|
||||
public OAuth2Controller(
|
||||
ICommonApi commonApi,
|
||||
IHealthCheckService healthCheckService)
|
||||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_configuration = configuration;
|
||||
_commonApi = commonApi;
|
||||
_healthCheckService = healthCheckService;
|
||||
}
|
||||
|
||||
[HttpPost("clientgrant")]
|
||||
public async Task<object> ClientGrant(ClientGrantRequest request)
|
||||
{
|
||||
var authority = _configuration.GetSection("Authority").Value;
|
||||
var httpClient = _httpClientFactory.CreateClient("face");
|
||||
|
||||
if (_healthCheckService.GetIsOffline())
|
||||
{
|
||||
return new
|
||||
@@ -41,9 +39,12 @@ public class OAuth2Controller : ControllerBase
|
||||
};
|
||||
}
|
||||
|
||||
var content = new StringContent($"grant_type=client_credentials&client_id={request.ClientId}&client_secret={request.ClientSecret}&scope={request.Scope}", Encoding.UTF8, "application/x-www-form-urlencoded");
|
||||
var response = await httpClient.PostAsync($"{authority}/oauth2/connect/token", content);
|
||||
var result = await response.Content.ReadAsStringAsync();
|
||||
return JObject.Parse(result);
|
||||
var r = await _commonApi.AuthAsync(new
|
||||
{
|
||||
request.ClientId,
|
||||
request.ClientSecret
|
||||
});
|
||||
|
||||
return r.Data;
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,23 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Kurisu.RemoteCall" Version="0.4.2" />
|
||||
<PackageReference Include="Kurisu.RemoteCall" Version="0.4.4" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="8.0.6" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.5" />
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlcipher" Version="2.1.8" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="appsettings.Development.json">
|
||||
<DependentUpon>appsettings.json</DependentUpon>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Api\FaceBearerTokenHandler.cs" />
|
||||
<Compile Remove="Api\IAssignmentDeviceTaskApi.cs" />
|
||||
<Compile Remove="Services\Implements\BalanceRecordCheckBackgroundService.cs" />
|
||||
<Compile Remove="Services\Implements\HealthCheckBackgroundService.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using Dlhis.Entity.Basic.Entity;
|
||||
using Kurisu.AspNetCore.DataAccess.Entity;
|
||||
using Kurisu.AspNetCore.DataAccess.SqlSugar;
|
||||
using SqlSugar;
|
||||
@@ -12,7 +11,7 @@ namespace Dlhis.Middle.Entities
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 就餐人员
|
||||
/// 就餐人员
|
||||
/// </summary>
|
||||
[SugarTable(TableName = "GainfoMeal", TableDescription = "就餐人员")]
|
||||
public class GainfoMealEntity : SugarBaseEntity, IVersion
|
||||
@@ -24,25 +23,13 @@ namespace Dlhis.Middle.Entities
|
||||
public string UserCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 余额
|
||||
/// 余额
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "余额")]
|
||||
public decimal Balance { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 余额(充值)
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "余额(充值)")]
|
||||
public decimal BalanceOfRecharge { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 余额(餐补)
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "余额(餐补)")]
|
||||
public decimal BalanceOfSubsidies { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 版本号
|
||||
/// 版本号
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "版本号")]
|
||||
public int Version { get; set; }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Dlhis.Middle.BackgroundServices;
|
||||
using Dlhis.Middle.Services;
|
||||
using Dlhis.Middle.Services.Implements;
|
||||
using Kurisu.AspNetCore;
|
||||
using Kurisu.AspNetCore.Startup;
|
||||
using Microsoft.IdentityModel.Logging;
|
||||
@@ -24,20 +24,11 @@ public class Startup : DefaultStartup
|
||||
public override void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
base.ConfigureServices(services);
|
||||
|
||||
services.AddHostedService<BalanceRecordUploadBackgroundService>();
|
||||
services.AddHostedService<HealthCheckBackgroundService>();
|
||||
|
||||
services.AddRemoteCall(App.ActiveTypes);
|
||||
services.AddHttpClient("face", client => { client.Timeout = TimeSpan.FromSeconds(30); }).ConfigurePrimaryHttpMessageHandler(() =>
|
||||
{
|
||||
var handler = new HttpClientHandler
|
||||
{
|
||||
ClientCertificateOptions = ClientCertificateOption.Manual,
|
||||
ServerCertificateCustomValidationCallback = (_, _, _, _) => true
|
||||
};
|
||||
|
||||
return handler;
|
||||
});
|
||||
services.AddHostedService<BalanceRecordCheckBackgroundService>();
|
||||
services.AddHostedService<HealthCheckBackgroundService>();
|
||||
services.AddMemoryCache();
|
||||
}
|
||||
|
||||
@@ -49,10 +40,9 @@ public class Startup : DefaultStartup
|
||||
if (Configuration.GetSection("Download").Value == "1")
|
||||
{
|
||||
using var scope = app.ApplicationServices.CreateScope();
|
||||
var factory = Configuration.GetSection("Factory").Value;
|
||||
|
||||
var factories = scope.ServiceProvider.GetService<ISettingService>().GetFactories();
|
||||
var ds = scope.ServiceProvider.GetService<IDataDownloadService>();
|
||||
ds.InitAsync(factory).Wait();
|
||||
ds.InitAsync(factories).Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
6
Src/Dlhis.Middle/Request/HealthCheckRequest.cs
Normal file
6
Src/Dlhis.Middle/Request/HealthCheckRequest.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Dlhis.Middle.Request;
|
||||
|
||||
public class HealthCheckRequest
|
||||
{
|
||||
public List<string> Factories { get; set; }
|
||||
}
|
||||
@@ -28,4 +28,7 @@ public class OrderResultResponse
|
||||
/// 余额
|
||||
/// </summary>
|
||||
public decimal Balance { get; set; }
|
||||
|
||||
|
||||
public decimal TotalBalance { get; set; }
|
||||
}
|
||||
@@ -2,9 +2,7 @@ namespace Dlhis.Middle.Services;
|
||||
|
||||
public interface IDataDownloadService : IScopeDependency
|
||||
{
|
||||
Task InitAsync(string factory);
|
||||
Task InitAsync(string[] factories);
|
||||
|
||||
Task DownloadAsync<T>(string factory) where T : class, new();
|
||||
|
||||
Task TruncateAsync();
|
||||
}
|
||||
@@ -1,12 +1,8 @@
|
||||
using Dlhis.Middle.Request;
|
||||
using Dlhis.Middle.Response;
|
||||
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
||||
|
||||
namespace Dlhis.Middle.Services;
|
||||
|
||||
public interface IRemoteOrderService : IScopeDependency
|
||||
{
|
||||
Task<DefaultApiResult<OrderResultResponse>> AddAsync(OrderAddRequest request);
|
||||
//Task<DefaultApiResult<OrderResultResponse>> AddAsync(OrderAddRequest request);
|
||||
|
||||
Task<bool> AbleRemoteCallAsync();
|
||||
}
|
||||
8
Src/Dlhis.Middle/Services/ISettingService.cs
Normal file
8
Src/Dlhis.Middle/Services/ISettingService.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Dlhis.Middle.Services;
|
||||
|
||||
public interface ISettingService : ISingletonDependency
|
||||
{
|
||||
string[] GetFactories();
|
||||
|
||||
string GetBaseUrl();
|
||||
}
|
||||
6
Src/Dlhis.Middle/Services/ITokenService.cs
Normal file
6
Src/Dlhis.Middle/Services/ITokenService.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Dlhis.Middle.Services;
|
||||
|
||||
public interface ITokenService : ISingletonDependency
|
||||
{
|
||||
Task<string> AuthAsync();
|
||||
}
|
||||
@@ -1,43 +1,32 @@
|
||||
using System.Net.Http.Headers;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Dlhis.Middle.Apis;
|
||||
using Dlhis.Middle.Entities;
|
||||
using Dlhis.Middle.Response;
|
||||
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
|
||||
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
||||
using Kurisu.AspNetCore.Utils.Extensions;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Newtonsoft.Json;
|
||||
using SqlSugar;
|
||||
|
||||
namespace Dlhis.Middle.Services.Implements;
|
||||
|
||||
public class DataDownloadService : IDataDownloadService
|
||||
{
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly IMemoryCache _memoryCache;
|
||||
private readonly IDbContext _dbContext;
|
||||
private readonly ICommonApi _commonApi;
|
||||
private readonly ILogger<DataDownloadService> _logger;
|
||||
private readonly string _hostName;
|
||||
|
||||
public DataDownloadService(IHttpClientFactory httpClientFactory, IMemoryCache memoryCache, IConfiguration configuration, IDbContext dbContext, ILogger<DataDownloadService> logger)
|
||||
public DataDownloadService(
|
||||
IDbContext dbContext,
|
||||
ICommonApi commonApi,
|
||||
ILogger<DataDownloadService> logger)
|
||||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_memoryCache = memoryCache;
|
||||
_dbContext = dbContext;
|
||||
_commonApi = commonApi;
|
||||
_logger = logger;
|
||||
_hostName = configuration.GetSection("HostName").Value;
|
||||
}
|
||||
|
||||
public async Task InitAsync(string factory)
|
||||
public async Task InitAsync(string[] factories)
|
||||
{
|
||||
//需要上传完记录才可下载
|
||||
if (await _dbContext.Queryable<LocalBalanceRecordEntity>().Where(x => x.IsSync == false).AnyAsync())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var factories = factory.Split(',');
|
||||
|
||||
await _dbContext.Client.Ado.BeginTranAsync();
|
||||
try
|
||||
@@ -84,9 +73,10 @@ public class DataDownloadService : IDataDownloadService
|
||||
_logger.LogInformation("档案{count}", await _dbContext.Queryable<LocalGainfoEntity>().CountAsync());
|
||||
_logger.LogInformation("余额{count}", await _dbContext.Queryable<LocalGainfoMealEntity>().CountAsync());
|
||||
_logger.LogInformation("下载完成");
|
||||
|
||||
await _dbContext.Client.Ado.CommitTranAsync();
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Exception)
|
||||
{
|
||||
await _dbContext.Client.Ado.RollbackTranAsync();
|
||||
throw;
|
||||
@@ -95,27 +85,11 @@ public class DataDownloadService : IDataDownloadService
|
||||
|
||||
public async Task DownloadAsync<T>(string factory) where T : class, new()
|
||||
{
|
||||
var token = await AuthAsync();
|
||||
|
||||
var httpClient = _httpClientFactory.CreateClient("face");
|
||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
||||
|
||||
var url = $"https://{_hostName}/api/common/SysData/download";
|
||||
|
||||
var requestUrl = QueryHelpers.AddQueryString(url, new Dictionary<string, string>
|
||||
{
|
||||
["factory"] = factory,
|
||||
["tableName"] = typeof(T).GetCustomAttribute<SugarTable>()!.TableName
|
||||
});
|
||||
|
||||
var response = await httpClient.GetStringAsync(requestUrl);
|
||||
var pack = response.ToObject<DefaultApiResult<List<T>>>();
|
||||
|
||||
var pack = await _commonApi.DownloadAsync<T>(factory, typeof(T).GetCustomAttribute<SugarTable>()!.TableName);
|
||||
await _dbContext.InsertAsync(pack.Data);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task TruncateAsync()
|
||||
private async Task TruncateAsync()
|
||||
{
|
||||
await _dbContext.Client.Deleteable<LocalDepartmentEntity>().ExecuteCommandAsync();
|
||||
await _dbContext.Client.Deleteable<LocalDeviceEntity>().ExecuteCommandAsync();
|
||||
@@ -128,26 +102,4 @@ public class DataDownloadService : IDataDownloadService
|
||||
await _dbContext.Client.Deleteable<LocalGainfoEntity>().ExecuteCommandAsync();
|
||||
await _dbContext.Client.Deleteable<LocalGainfoMealEntity>().ExecuteCommandAsync();
|
||||
}
|
||||
|
||||
private async Task<string> AuthAsync()
|
||||
{
|
||||
var httpClient = _httpClientFactory.CreateClient("face");
|
||||
|
||||
if (_memoryCache.TryGetValue("token", out string token)) return token;
|
||||
|
||||
var tokenResponse = await httpClient.PostAsync($"https://{_hostName}/api/User/OAuth2/clientgrant", new StringContent(JsonConvert.SerializeObject(new
|
||||
{
|
||||
ClientId = "e509c2aaa98e300c",
|
||||
ClientSecret = "6184d8979fc48105"
|
||||
}), Encoding.UTF8, "application/json"));
|
||||
|
||||
var tokenJson = await tokenResponse.Content.ReadAsStringAsync();
|
||||
var tokenInfo = JsonConvert.DeserializeObject<DefaultApiResult<TokenResponse>>(tokenJson);
|
||||
|
||||
token = tokenInfo.Data.AccessToken;
|
||||
|
||||
_memoryCache.Set("token", token, TimeSpan.FromSeconds(tokenInfo.Data.Expires));
|
||||
|
||||
return token;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,26 @@
|
||||
using System.Net.Sockets;
|
||||
using Dlhis.Middle.Apis;
|
||||
using Dlhis.Middle.Request;
|
||||
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
||||
|
||||
namespace Dlhis.Middle.Services.Implements;
|
||||
|
||||
public class HealthCheckService : IHealthCheckService
|
||||
{
|
||||
private bool _isOffline;
|
||||
private readonly string _hostName;
|
||||
private readonly ILogger<HealthCheckService> _logger;
|
||||
private int _successRetry;
|
||||
private int _retry;
|
||||
private readonly ISettingService _settingService;
|
||||
private readonly ICommonApi _healthCheckApi;
|
||||
private int _attempted;
|
||||
|
||||
public HealthCheckService(ILogger<HealthCheckService> logger, IConfiguration configuration)
|
||||
private bool _isBegin;
|
||||
|
||||
public HealthCheckService(ILogger<HealthCheckService> logger,
|
||||
ISettingService settingService,
|
||||
ICommonApi healthCheckApi)
|
||||
{
|
||||
_logger = logger;
|
||||
_hostName = configuration.GetSection("HostName").Value;
|
||||
_settingService = settingService;
|
||||
_healthCheckApi = healthCheckApi;
|
||||
}
|
||||
|
||||
public bool GetIsOffline()
|
||||
@@ -23,44 +30,44 @@ public class HealthCheckService : IHealthCheckService
|
||||
|
||||
public async Task DoHealthCheckAsync()
|
||||
{
|
||||
var cancellationTokenSource = new CancellationTokenSource(5000);
|
||||
var tcpClient = new TcpClient();
|
||||
|
||||
try
|
||||
{
|
||||
_logger.LogDebug("tcp connecting {host} {port}", _hostName, 443);
|
||||
await tcpClient.ConnectAsync(_hostName, 443, cancellationTokenSource.Token);
|
||||
_retry++;
|
||||
_logger.LogDebug("retry {retry}", _retry);
|
||||
if (tcpClient.Connected)
|
||||
var factories = _settingService.GetFactories();
|
||||
|
||||
var response = await _healthCheckApi.CheckHealthAsync(new HealthCheckRequest { Factories = factories.ToList() });
|
||||
if (response.Code == ApiStateCode.Success)
|
||||
{
|
||||
_successRetry++;
|
||||
_logger.LogDebug("success connected {count}", _successRetry);
|
||||
if (_successRetry == 4)
|
||||
_attempted++;
|
||||
if (_attempted == 5)
|
||||
{
|
||||
_isOffline = false;
|
||||
_successRetry = 0;
|
||||
_retry = 0;
|
||||
_logger.LogInformation("current is {status}", "healthy");
|
||||
_attempted = 0;
|
||||
}
|
||||
else
|
||||
|
||||
if (!_isBegin)
|
||||
{
|
||||
_logger.LogDebug("wait next check in {waitTime}", _successRetry * 1000);
|
||||
await Task.Delay(_successRetry * 1000, cancellationTokenSource.Token);
|
||||
_isOffline = false;
|
||||
_isBegin = true;
|
||||
}
|
||||
|
||||
if (_isOffline == false)
|
||||
{
|
||||
_logger.LogInformation("Health");
|
||||
}
|
||||
|
||||
await Task.Delay(_attempted * 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
_successRetry = 0;
|
||||
_isOffline = true;
|
||||
_logger.LogDebug("current is {status}", "unavailable");
|
||||
await Task.Delay(500);
|
||||
_logger.LogInformation("Error {message}", response.Msg);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("fail cause :{reason}", ex.Message);
|
||||
_logger.LogError("Failed cause :{reason}", ex.Message);
|
||||
_isOffline = true;
|
||||
await Task.Delay(5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Diagnostics;
|
||||
using Dlhis.Entity.Canteen.Enums;
|
||||
using Dlhis.Middle.Apis;
|
||||
using Dlhis.Middle.Entities;
|
||||
using Kurisu.AspNetCore.Utils;
|
||||
using Kurisu.AspNetCore.Utils.Extensions;
|
||||
@@ -17,6 +18,7 @@ public class OrderService : IOrderService
|
||||
{
|
||||
private readonly ICanteenSettingService _canteenSettingService;
|
||||
private readonly IRemoteOrderService _remoteOrderService;
|
||||
private readonly ICanteenApi _canteenApi;
|
||||
private readonly ILogger<OrderService> _logger;
|
||||
private readonly string _factory;
|
||||
private readonly IDbContext _dbContext;
|
||||
@@ -24,14 +26,16 @@ public class OrderService : IOrderService
|
||||
|
||||
public OrderService(ICanteenSettingService canteenSettingService,
|
||||
IRemoteOrderService remoteOrderService,
|
||||
IConfiguration configuration,
|
||||
ISettingService settingService,
|
||||
ICanteenApi canteenApi,
|
||||
ILogger<OrderService> logger,
|
||||
IDbContext dbContext)
|
||||
{
|
||||
_canteenSettingService = canteenSettingService;
|
||||
_remoteOrderService = remoteOrderService;
|
||||
_canteenApi = canteenApi;
|
||||
_logger = logger;
|
||||
_factory = configuration.GetSection("Factory").Value;
|
||||
_factory = settingService.GetFactories().Join(",");
|
||||
_dbContext = dbContext;
|
||||
}
|
||||
|
||||
@@ -43,12 +47,12 @@ public class OrderService : IOrderService
|
||||
{
|
||||
if (await _remoteOrderService.AbleRemoteCallAsync())
|
||||
{
|
||||
var remoteResult = await _remoteOrderService.AddAsync(request);
|
||||
var remoteResult = await _canteenApi.AddAsync(request);
|
||||
if (remoteResult.Code == ApiStateCode.Success)
|
||||
{
|
||||
var d = remoteResult.Data;
|
||||
await _dbContext.Updateable<LocalGainfoMealEntity>()
|
||||
.SetColumns(x => x.Balance == d.Balance)
|
||||
.SetColumns(x => x.Balance == d.TotalBalance)
|
||||
.Where(x => x.UserCode == d.UserCode)
|
||||
.ExecuteCommandAsync();
|
||||
}
|
||||
|
||||
@@ -1,54 +1,37 @@
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using Dlhis.Middle.Entities;
|
||||
using Dlhis.Middle.Request;
|
||||
using Dlhis.Middle.Response;
|
||||
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
|
||||
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
||||
using Kurisu.AspNetCore.Utils.Extensions;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Dlhis.Middle.Services.Implements;
|
||||
|
||||
public class RemoteOrderService : IRemoteOrderService
|
||||
{
|
||||
private readonly string _hostName;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly IMemoryCache _memoryCache;
|
||||
private readonly IHealthCheckService _healthCheckService;
|
||||
private readonly IDbContext _dbContext;
|
||||
|
||||
public RemoteOrderService(IHttpClientFactory httpClientFactory,
|
||||
IMemoryCache memoryCache,
|
||||
IConfiguration configuration,
|
||||
public RemoteOrderService(
|
||||
IHealthCheckService healthCheckService,
|
||||
IDbContext dbContext)
|
||||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_memoryCache = memoryCache;
|
||||
_hostName = configuration.GetSection("hostName").Value;
|
||||
_healthCheckService = healthCheckService;
|
||||
_dbContext = dbContext;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<DefaultApiResult<OrderResultResponse>> AddAsync(OrderAddRequest request)
|
||||
{
|
||||
var token = await AuthAsync();
|
||||
|
||||
var httpClient = _httpClientFactory.CreateClient("face");
|
||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
||||
|
||||
var content = new StringContent(request.ToJson(), Encoding.UTF8, "application/json");
|
||||
|
||||
var response = await httpClient.PostAsync($"https://{_hostName}/api/canteen/orders", content);
|
||||
|
||||
var responseJson = await response.Content.ReadAsStringAsync();
|
||||
return responseJson.ToObject<DefaultApiResult<OrderResultResponse>>();
|
||||
}
|
||||
///// <inheritdoc />
|
||||
// public async Task<DefaultApiResult<OrderResultResponse>> AddAsync(OrderAddRequest request)
|
||||
// {
|
||||
// var token = await _tokenService.AuthAsync();
|
||||
//
|
||||
// var httpClient = _httpClientFactory.CreateClient("face");
|
||||
// httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
||||
//
|
||||
// var content = new StringContent(request.ToJson(), Encoding.UTF8, "application/json");
|
||||
//
|
||||
// var response = await httpClient.PostAsync($"{_settingService.GetBaseUrl()}/api/canteen/orders", content);
|
||||
//
|
||||
// var responseJson = await response.Content.ReadAsStringAsync();
|
||||
// return responseJson.ToObject<DefaultApiResult<OrderResultResponse>>();
|
||||
// }
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> AbleRemoteCallAsync()
|
||||
@@ -60,28 +43,4 @@ public class RemoteOrderService : IRemoteOrderService
|
||||
|
||||
return !_healthCheckService.GetIsOffline();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private async Task<string> AuthAsync()
|
||||
{
|
||||
var httpClient = _httpClientFactory.CreateClient("face");
|
||||
|
||||
if (_memoryCache.TryGetValue("token", out string token)) return token;
|
||||
|
||||
var tokenResponse = await httpClient.PostAsync($"https://{_hostName}/api/User/OAuth2/clientgrant", new StringContent(JsonConvert.SerializeObject(new
|
||||
{
|
||||
ClientId = "e509c2aaa98e300c",
|
||||
ClientSecret = "6184d8979fc48105"
|
||||
}), Encoding.UTF8, "application/json"));
|
||||
|
||||
var tokenJson = await tokenResponse.Content.ReadAsStringAsync();
|
||||
var tokenInfo = JsonConvert.DeserializeObject<DefaultApiResult<TokenResponse>>(tokenJson);
|
||||
|
||||
token = tokenInfo.Data.AccessToken;
|
||||
|
||||
_memoryCache.Set("token", token, TimeSpan.FromSeconds(tokenInfo.Data.Expires));
|
||||
|
||||
return token;
|
||||
}
|
||||
}
|
||||
23
Src/Dlhis.Middle/Services/Implements/SettingService.cs
Normal file
23
Src/Dlhis.Middle/Services/Implements/SettingService.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
namespace Dlhis.Middle.Services.Implements;
|
||||
|
||||
public class SettingService : ISettingService
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public SettingService(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string[] GetFactories()
|
||||
{
|
||||
return _configuration.GetSection("Factory").Value.Split(",");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetBaseUrl()
|
||||
{
|
||||
return _configuration.GetSection("BaseUrl").Value;
|
||||
}
|
||||
}
|
||||
43
Src/Dlhis.Middle/Services/Implements/TokenService.cs
Normal file
43
Src/Dlhis.Middle/Services/Implements/TokenService.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using Dlhis.Middle.Apis;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace Dlhis.Middle.Services.Implements;
|
||||
|
||||
public class TokenService : ITokenService
|
||||
{
|
||||
private readonly IMemoryCache _memoryCache;
|
||||
private readonly ICommonApi _commonApi;
|
||||
|
||||
public TokenService(IMemoryCache memoryCache, ICommonApi commonApi)
|
||||
{
|
||||
_memoryCache = memoryCache;
|
||||
_commonApi = commonApi;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<string> AuthAsync()
|
||||
{
|
||||
var exists = _memoryCache.TryGetValue("token", out string token);
|
||||
try
|
||||
{
|
||||
if (!exists)
|
||||
{
|
||||
var tokenInfo = await _commonApi.AuthAsync(new
|
||||
{
|
||||
ClientId = "e509c2aaa98e300c",
|
||||
ClientSecret = "6184d8979fc48105"
|
||||
});
|
||||
|
||||
token = tokenInfo.Data.AccessToken;
|
||||
|
||||
_memoryCache.Set("token", token, TimeSpan.FromSeconds(tokenInfo.Data.Expires));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
token = "Bearer " + token;
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,7 @@
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"Authority": "https://face.jinkosolar.com",
|
||||
"Factory": "1201",
|
||||
"HostName": "face.jinkosolar.com",
|
||||
"BaseUrl": "https://yikatong.isawesome.cn",
|
||||
"Factory": "1234",
|
||||
"Download":1
|
||||
}
|
||||
|
||||
@@ -12,9 +12,6 @@
|
||||
"SlowSqlTime": 1,
|
||||
"EnableSqlLog": false
|
||||
},
|
||||
"Authority": "https://face.jinkosolar.com",
|
||||
"Factory": "",
|
||||
"HostName": "face.jinkosolar.com",
|
||||
"AllowedHosts": "*",
|
||||
"SwaggerOptions": {
|
||||
"Enable": true,
|
||||
|
||||
BIN
Src/Dlhis.Middle/local.db-journal
Normal file
BIN
Src/Dlhis.Middle/local.db-journal
Normal file
Binary file not shown.
Reference in New Issue
Block a user