using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Text;
|
using System.Threading.Tasks;
|
using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
|
using WIDESEA_Core.BaseRepository;
|
using WIDESEA_Core.BaseServices;
|
using WIDESEA_DTO.BasicInfo;
|
using WIDESEA_IBasicInfoServices;
|
using WIDESEA_Model.Models;
|
|
namespace WIDESEA_BasicInfoServices
|
{
|
public class ActivationCodeService : ServiceBase<Dt_ActivationCode, IRepository<Dt_ActivationCode>>, IActivationCodeService
|
{
|
private readonly IRepository<Dt_CharMapping> _charMappingRepository;
|
private readonly IRepository<Dt_RuntimeCode> _runtimeCodeRepository;
|
private readonly IRepository<Dt_Products> _productRepository;
|
|
public ActivationCodeService(IRepository<Dt_ActivationCode> BaseDal, IRepository<Dt_CharMapping> charMappingRepository, IRepository<Dt_RuntimeCode> runtimeCodeRepository, IRepository<Dt_Products> productRepository) : base(BaseDal)
|
{
|
_charMappingRepository = charMappingRepository;
|
_runtimeCodeRepository = runtimeCodeRepository;
|
_productRepository = productRepository;
|
}
|
|
/// <summary>
|
/// 生成激活码
|
/// </summary>
|
/// <param name="activationDTO">包含运行码、设备ID和产品名称的数据传输对象</param>
|
/// <returns>生成的激活码</returns>
|
public string GenerateActivationCode(ActivationCodeDTO activationDTO)
|
{
|
// 查询运行码对应的模型
|
Dt_RuntimeCode runtimeCodeModel = _runtimeCodeRepository.QueryFirst(x => x.RuntimeCode == activationDTO.RuntimeCode);
|
// 1. 检查运行码是否已存在
|
if (runtimeCodeModel == null)
|
{
|
throw new InvalidOperationException($"无效的运行码: {activationDTO.RuntimeCode}");
|
}
|
|
// 查询激活码对应的模型
|
Dt_ActivationCode activationCodeModel = BaseDal.QueryFirst(x => x.RuntimeCode == activationDTO.RuntimeCode);
|
// 2. 检查激活码是否已存在
|
if (activationCodeModel != null)
|
{
|
return activationCodeModel.ActivationCode;
|
}
|
|
int productId = -1;
|
// 查询产品对应的模型
|
Dt_Products product = _productRepository.QueryFirst(x => x.ProductName == activationDTO.ProductName);
|
if (product != null)
|
{
|
productId = product.Id;
|
}
|
|
// 3. 检查设备ID和产品ID是否匹配
|
if (runtimeCodeModel.DeviceId != activationDTO.DeviceId || runtimeCodeModel.ProductId != productId)
|
{
|
throw new InvalidOperationException($"设备ID或产品ID不匹配: {activationDTO.DeviceId}, {productId}");
|
}
|
|
// 4. 生成激活码
|
// 去除运行码中的"-"字符
|
string baseRandom = activationDTO.RuntimeCode.Replace("-", string.Empty);
|
|
// 查询字符映射字典
|
Dictionary<char, (char output, int shift)> mappingDict = _charMappingRepository.QueryData().ToDictionary(x => x.InputChar.ToCharArray().FirstOrDefault(), x => (x.OutputChar.ToCharArray().FirstOrDefault(), x.ShiftFactor));
|
|
char[] result = new char[baseRandom.Length];
|
int length = baseRandom.Length;
|
|
// 遍历运行码的每个字符进行转换
|
for (int i = 0; i < length; i++)
|
{
|
char current = baseRandom[i];
|
if (current == '-')
|
continue;
|
if (!mappingDict.TryGetValue(current, out var mapping))
|
throw new InvalidOperationException($"无效字符: {current}");
|
|
// 特殊变换:每5个字符增加复杂度
|
char mappedChar = (i % 5 == 4)
|
? ApplySpecialTransform(mapping.output, mapping.shift)
|
: mapping.output;
|
|
result[i] = mappedChar;
|
}
|
|
// 格式化激活码
|
string activationCode = FormatCode(new string(result));
|
|
// 5. 存储激活码
|
StoredActivationCode(activationDTO.DeviceId, baseRandom, activationCode, activationDTO.RuntimeCode, productId);
|
|
return activationCode;
|
}
|
|
/// <summary>
|
/// 对输入字符进行基于ASCII码的二次变换。
|
/// </summary>
|
/// <param name="c">要变换的字符。</param>
|
/// <param name="position">字符的位置,用于计算变换值。</param>
|
/// <returns>变换后的字符。</returns>
|
private char ApplySpecialTransform(char c, int position)
|
{
|
// 将字符转换为ASCII码
|
int ascii = (int)c;
|
|
// 计算变换后的ASCII码值,基于字符的位置进行偏移,并确保结果在0-35范围内
|
int transformed = (ascii + position) % 36 + 48;
|
|
// 如果变换后的ASCII码值在':'到'@'之间(即字符'9'到字符'@'),则再偏移7个位置
|
if (transformed >= ':' && transformed <= '@')
|
{
|
transformed += 7;
|
}
|
|
// 将变换后的ASCII码值转换回字符并返回
|
return (char)transformed;
|
}
|
|
/// <summary>
|
/// 将原始字符串格式化为XXXXX-XXXXX-XXXXX-XXXXX-XXXXX的形式
|
/// </summary>
|
/// <param name="raw">需要格式化的原始字符串,长度必须为25个字符</param>
|
private string FormatCode(string raw)
|
{
|
// 格式化为XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
|
return string.Join("-",
|
raw.Substring(0, 5),
|
raw.Substring(5, 5),
|
raw.Substring(10, 5),
|
raw.Substring(15, 5),
|
raw.Substring(20, 5));
|
}
|
|
/// <summary>
|
/// 存储激活码信息到数据库
|
/// </summary>
|
/// <param name="deviceId">设备ID,用于标识特定设备</param>
|
/// <param name="baseRandom">基础随机码,用于生成激活码的随机字符串</param>
|
/// <param name="activationCode">激活码,用于产品激活的唯一代码</param>
|
/// <param name="runtimeCode">运行时码,用于验证激活状态的代码</param>
|
/// <param name="productId">产品ID,用于标识不同的产品</param>
|
private void StoredActivationCode(string deviceId, string baseRandom, string activationCode, string runtimeCode, int productId)
|
{
|
Dt_ActivationCode activationRecord = new Dt_ActivationCode
|
{
|
MappedRandom = baseRandom,
|
ActivationCode = activationCode,
|
DeviceId = deviceId,
|
IsUsed = false,
|
ProductId = productId,
|
ExpiresTime = null,
|
RuntimeCode = runtimeCode
|
};
|
|
BaseDal.AddData(activationRecord);
|
}
|
}
|
}
|