兼容win7版应用
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

221 lines
10 KiB

using System.Threading.Tasks;
using System.Threading;
using AIK.Common.Interface;
using AIK.Common.SysCommon;
using AIK.Models.ApiModels;
using AIK.Models.ApiModels.Membership;
using AIK.Service.IService;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
namespace AIK.Service.Service
{
public class MembershipService : IMembershipService
{
private static readonly JsonSerializerSettings JsonSettings = new()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore
};
private readonly IHttpClientService _httpClientService;
private readonly IConfigurationService _configurationService;
private readonly ISettingsService _settingsService;
private readonly IRetryPolicyService _retryPolicyService;
private readonly ILogger<MembershipService> _logger;
public MembershipService(
IHttpClientService httpClientService,
IConfigurationService configurationService,
ISettingsService settingsService,
IRetryPolicyService retryPolicyService,
ILogger<MembershipService> logger)
{
_httpClientService = httpClientService;
_configurationService = configurationService;
_settingsService = settingsService;
_retryPolicyService = retryPolicyService;
_logger = logger;
}
public Task<List<MembershipModule>> GetModuleListAsync(string model = "key", CancellationToken cancellationToken = default)
{
return _retryPolicyService.ExecuteWithRetryAsync(async () =>
{
var url = BuildUrl(WebApiAddress.MembershipModuleList, new()
{
["model"] = string.IsNullOrWhiteSpace(model) ? "key" : model,
["language"] = GetLanguage()
});
var response = await _httpClientService.GetStringWithTimeoutAsync(url, TimeSpan.FromSeconds(15), cancellationToken);
var apiResponse = DeserializeResponse<List<MembershipModule>>(response, nameof(GetModuleListAsync));
return IsSuccess(apiResponse) ? apiResponse.Data ?? new List<MembershipModule>() : new List<MembershipModule>();
}, nameof(GetModuleListAsync), cancellationToken);
}
public Task<ApiPageResult<MembershipRecord>> FindOpenedFunctionsAsync(string token, MembershipFindRequest request, CancellationToken cancellationToken = default)
{
return _retryPolicyService.ExecuteWithRetryAsync(async () =>
{
request.Language ??= GetLanguage();
var url = BuildUrl(WebApiAddress.MembershipFind);
var json = JsonConvert.SerializeObject(request, JsonSettings);
var response = await _httpClientService.PostJsonWithTimeoutAndTokenAsync(url, json, token, TimeSpan.FromSeconds(15), cancellationToken);
return DeserializePageResponse<MembershipRecord>(response, nameof(FindOpenedFunctionsAsync));
}, nameof(FindOpenedFunctionsAsync), cancellationToken);
}
public Task<ApiResponse<int>> OpenFunctionAsync(string token, OpenMembershipRequest request, CancellationToken cancellationToken = default)
{
return _retryPolicyService.ExecuteWithRetryAsync(async () =>
{
request.Language ??= GetLanguage();
return await PostWithTokenAsync<int>(WebApiAddress.MembershipOpen, token, request, nameof(OpenFunctionAsync), cancellationToken);
}, nameof(OpenFunctionAsync), cancellationToken);
}
public Task<ApiResponse> BindDeviceAsync(string token, BindMembershipDeviceRequest request, CancellationToken cancellationToken = default)
{
return _retryPolicyService.ExecuteWithRetryAsync(async () =>
{
request.Language ??= GetLanguage();
var response = await PostWithTokenAsync<object>(WebApiAddress.MembershipBind, token, request, nameof(BindDeviceAsync), cancellationToken);
return ToUntypedResponse(response);
}, nameof(BindDeviceAsync), cancellationToken);
}
public Task<bool> CheckPermissionAsync(string token, CheckMembershipPermissionRequest request, CancellationToken cancellationToken = default)
{
return _retryPolicyService.ExecuteWithRetryAsync(async () =>
{
request.Language ??= GetLanguage();
var response = await PostWithTokenAsync<bool>(WebApiAddress.MembershipCheck, token, request, nameof(CheckPermissionAsync), cancellationToken);
return IsSuccess(response) && response.Data;
}, nameof(CheckPermissionAsync), cancellationToken);
}
public Task<ApiResponse> ActivateDeviceAsync(string token, ActivateDeviceRequest request, CancellationToken cancellationToken = default)
{
return _retryPolicyService.ExecuteWithRetryAsync(async () =>
{
request.Language ??= GetLanguage();
var response = await PostWithTokenAsync<object>(WebApiAddress.MembershipActivate, token, request, nameof(ActivateDeviceAsync), cancellationToken);
return ToUntypedResponse(response);
}, nameof(ActivateDeviceAsync), cancellationToken);
}
public Task<BurnCountInfo?> GetBurnCountInfoAsync(string token, CancellationToken cancellationToken = default)
{
return _retryPolicyService.ExecuteWithRetryAsync(async () =>
{
var url = BuildUrl(WebApiAddress.MembershipFindCount);
var response = await _httpClientService.GetStringWithTimeoutAndTokenAsync(url, token, TimeSpan.FromSeconds(15), cancellationToken);
var apiResponse = DeserializeResponse<BurnCountInfo>(response, nameof(GetBurnCountInfoAsync));
return IsSuccess(apiResponse) ? apiResponse.Data : null;
}, nameof(GetBurnCountInfoAsync), cancellationToken);
}
public Task<ApiResponse> AddBurnCountAsync(string token, string type = "ysjs", CancellationToken cancellationToken = default)
{
return _retryPolicyService.ExecuteWithRetryAsync(async () =>
{
var url = BuildUrl(WebApiAddress.MembershipAddCount, new()
{
["type"] = string.IsNullOrWhiteSpace(type) ? "ysjs" : type
});
var response = await _httpClientService.GetStringWithTimeoutAndTokenAsync(url, token, TimeSpan.FromSeconds(15), cancellationToken);
return ToUntypedResponse(DeserializeResponse<object>(response, nameof(AddBurnCountAsync)));
}, nameof(AddBurnCountAsync), cancellationToken);
}
private async Task<ApiResponse<T>> PostWithTokenAsync<T>(string path, string token, object request, string operationName, CancellationToken cancellationToken)
{
var url = BuildUrl(path);
var json = JsonConvert.SerializeObject(request, JsonSettings);
var response = await _httpClientService.PostJsonWithTimeoutAndTokenAsync(url, json, token, TimeSpan.FromSeconds(15), cancellationToken);
return DeserializeResponse<T>(response, operationName);
}
private string BuildUrl(string path, Dictionary<string, string?>? query = null)
{
var url = $"{_configurationService.ApiSettings.BaseUrl}{path}";
if (query == null || query.Count == 0)
{
return url;
}
var queryString = string.Join("&", query
.Where(item => !string.IsNullOrWhiteSpace(item.Value))
.Select(item => $"{WebUtility.UrlEncode(item.Key)}={WebUtility.UrlEncode(item.Value)}"));
return string.IsNullOrEmpty(queryString) ? url : $"{url}?{queryString}";
}
private string GetLanguage()
{
return string.IsNullOrWhiteSpace(_settingsService.Load().Language) ? "zh" : _settingsService.Load().Language;
}
private ApiResponse<T> DeserializeResponse<T>(string response, string operationName)
{
var apiResponse = JsonConvert.DeserializeObject<ApiResponse<T>>(response) ?? new ApiResponse<T>();
if (!IsSuccess(apiResponse))
{
_logger.LogWarning("{OperationName} failed. Code: {Code}, Message: {Message}, Response: {Response}", operationName, apiResponse.Code, apiResponse.Msg, response);
}
return apiResponse;
}
private ApiPageResult<T> DeserializePageResponse<T>(string response, string operationName)
{
var pageResponse = JsonConvert.DeserializeObject<ApiPageResponse<T>>(response) ?? new ApiPageResponse<T>();
if (pageResponse.Code != 1)
{
_logger.LogWarning("{OperationName} failed. Code: {Code}, Message: {Message}, Response: {Response}", operationName, pageResponse.Code, pageResponse.Msg, response);
return new ApiPageResult<T>();
}
return new ApiPageResult<T>
{
Records = pageResponse.Records ?? new List<T>(),
Total = pageResponse.Total,
Current = pageResponse.Current,
Size = pageResponse.Size,
Pages = pageResponse.Pages
};
}
private static bool IsSuccess<T>(ApiResponse<T> response)
{
return response.Code == 1;
}
private static ApiResponse ToUntypedResponse<T>(ApiResponse<T> response)
{
return new ApiResponse
{
Code = response.Code,
Msg = response.Msg,
I18nMsg = response.I18nMsg,
Data = response.Data,
Dict = response.Dict
};
}
private sealed class ApiPageResponse<T> : ApiPageResult<T>
{
public int Code { get; set; }
public string? Msg { get; set; }
public string? I18nMsg { get; set; }
public Dictionary<string, object>? Dict { get; set; }
}
}
}