Files
jinko.yikatong/Src/Dlhis.Middle/Services/Implements/BalanceRecordCheckBackgroundService.cs
2024-08-21 14:53:30 +08:00

162 lines
6.8 KiB
C#

using System.Net.Http.Headers;
using System.Text;
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.Extensions.Caching.Memory;
using Newtonsoft.Json;
namespace Dlhis.Middle.Services.Implements;
public class BalanceRecordCheckBackgroundService : BackgroundService
{
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<BalanceRecordCheckBackgroundService> _logger;
private readonly IMemoryCache _memoryCache;
private readonly IHttpClientFactory _httpClientFactory;
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)
{
_serviceProvider = serviceProvider;
_logger = logger;
_memoryCache = memoryCache;
_httpClientFactory = httpClientFactory;
_healthCheckService = healthCheckService;
_factory = configuration.GetSection("Factory").Value;
_hostName = configuration.GetSection("HostName").Value;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
if (!_healthCheckService.GetIsOffline())
{
var now = DateTime.Now;
using var scope = _serviceProvider.CreateScope();
var db = scope.ServiceProvider.GetService<IDbContext>();
var ds = scope.ServiceProvider.GetService<IDataDownloadService>();
foreach (var factory in _factory.Split(','))
{
try
{
var balanceRecords = await db.Queryable<LocalBalanceRecordEntity>().Where(x => x.TenantId == factory).Where(x => !x.IsSync).ToListAsync(stoppingToken);
if (balanceRecords.Any())
{
_logger.LogInformation("上传离线订单");
foreach (var balanceRecord in balanceRecords)
{
//事务
await db.Client.Ado.BeginTranAsync();
try
{
//设置为已同步
balanceRecord.IsSync = true;
await db.UpdateAsync(balanceRecord);
var r = await UploadAsync(balanceRecord);
if (r.Code != ApiStateCode.Success)
{
throw new Exception(r.Msg);
}
var d = r.Data;
//更新本地余额表
await db.Updateable<LocalGainfoMealEntity>()
.SetColumns(x => x.Balance == d.Balance)
.Where(x => x.UserCode == d.UserCode)
.ExecuteCommandAsync(stoppingToken);
await db.Client.Ado.CommitTranAsync();
}
catch (Exception e)
{
_logger.LogError(e, "{factory}上传离线消费失败:{message}", factory, e.Message);
await db.Client.Ado.RollbackTranAsync();
}
}
}
}
catch (Exception e)
{
_logger.LogError(e, "{factory}同步离线数据失败:{message}", factory, e.Message);
}
}
if (now is { Hour: 4, Minute: 1 }
&& !_healthCheckService.GetIsOffline()
&& !await db.Queryable<LocalBalanceRecordEntity>().Where(x => !x.IsSync).AnyAsync())
{
await ds.InitAsync(_factory);
}
else if (now is { Hour: 15, Minute: 1 }
&& !_healthCheckService.GetIsOffline()
&& !await db.Queryable<LocalBalanceRecordEntity>().Where(x => !x.IsSync).AnyAsync())
{
await ds.InitAsync(_factory);
}
else if (now is { Hour: 20, Minute: 1 }
&& !_healthCheckService.GetIsOffline()
&& !await db.Queryable<LocalBalanceRecordEntity>().Where(x => !x.IsSync).AnyAsync())
{
await ds.InitAsync(_factory);
}
}
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;
}
}