wip: upms 开发中

main
NoahLan 8 months ago
parent becd8df532
commit 7c36b64ac4

@ -3,6 +3,8 @@
<ItemGroup>
<PackageReference Include="Mapster" Version="7.4.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageReference Include="NUnit" Version="4.1.0" />
<PackageReference Include="Volo.Abp.ObjectMapping" Version="8.0.0" />
</ItemGroup>

@ -0,0 +1,13 @@
namespace NPin.Framework.Upms.Domain.Shared.Consts;
public class ConfigConst
{
/// <summary>
/// 系统配置前缀
/// </summary>
public const string SysConfigPrefix = "Sys";
public const string AliyunConfigKey = "Aliyun";
public const string TencentConfigKey = "Tencent";
public const string SmsConfigKey = "Sms";
}

@ -0,0 +1,22 @@
using System.ComponentModel;
namespace NPin.Framework.Upms.Domain.Shared.Enums;
/// <summary>
/// 短信提供商枚举
/// </summary>
public enum SmsProviderEnum
{
Aliyun,
Tencent
}
/// <summary>
/// 短信类型枚举
/// </summary>
public enum SmsTypeEnum
{
[Description("登录")] Login,
[Description("注册")] Register,
[Description("找回密码(重置密码)")] ResetPassword,
}

@ -0,0 +1,24 @@
namespace NPin.Framework.Upms.Domain.Shared.Model;
public class AliyunConfigModel
{
/// <summary>
/// 访问密钥Key
/// </summary>
public string AccessKeyId { get; set; }
/// <summary>
/// 访问密钥
/// </summary>
public string AccessKeySecret { get; set; }
/// <summary>
/// 默认 区域ID
/// </summary>
public string RegionId { get; set; }
/// <summary>
/// 默认 短信访问 端点
/// </summary>
public string SmsEndpoint { get; set; } = "dysmsapi.aliyuncs.com";
}

@ -0,0 +1,54 @@
using NPin.Framework.Upms.Domain.Shared.Enums;
namespace NPin.Framework.Upms.Domain.Shared.Model;
public class SmsConfigModel
{
/// <summary>
/// 是否启用(总控)
/// </summary>
public bool Enabled { get; set; } = false;
/// <summary>
/// 设定集
/// </summary>
public Dictionary<SmsTypeEnum, SmsSettings> Settings { get; set; }
}
public class SmsSettings
{
/// <summary>
/// 是否启用
/// </summary>
public bool Enabled { get; set; } = false;
/// <summary>
/// 服务提供商
/// </summary>
public SmsProviderEnum Provider { get; set; }
/// <summary>
/// 区域
/// </summary>
public string Region { get; set; }
/// <summary>
/// 短信访问 端点
/// </summary>
public string Endpoint { get; set; }
/// <summary>
/// 短信签名名称
/// </summary>
public string SignName { get; set; }
/// <summary>
/// 短信模板Code
/// </summary>
public string TemplateCode { get; set; }
/// <summary>
/// 过期时间,单位:秒
/// </summary>
public int Expires { get; set; }
}

@ -0,0 +1,31 @@
using Newtonsoft.Json;
namespace NPin.Framework.Upms.Domain.Shared.Model;
public class TencentConfigModel
{
/// <summary>
/// 访问密钥Key
/// </summary>
public string SecretId { get; set; }
/// <summary>
/// 访问密钥
/// </summary>
public string SecretKey { get; set; }
/// <summary>
/// 默认区域
/// </summary>
public string Region { get; set; }
/// <summary>
/// 默认短信访问 端点
/// </summary>
public string SmsEndpoint { get; set; } = "sms.tencentcloudapi.com";
/// <summary>
/// 短信SdkAppId
/// </summary>
public string SmsSdkAppId { get; set; }
}

@ -7,8 +7,5 @@
<ItemGroup>
<PackageReference Include="Volo.Abp.Users.Domain.Shared" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<Folder Include="Model\" />
</ItemGroup>
</Project>

@ -1,17 +0,0 @@
namespace NPin.Framework.Upms.Domain.Shared.Options;
/// <summary>
/// 阿里云SDK相关配置
/// </summary>
public class AliyunOptions
{
public string AccessKeyId { get; set; }
public string AccessKeySecret { get; set; }
public AliyunSms Sms { get; set; }
}
public class AliyunSms
{
public string SignName { get; set; }
public string TemplateCode { get; set; }
}

@ -0,0 +1,32 @@
using NPin.Framework.SqlSugarCore.Abstractions.Data;
using SqlSugar;
using Volo.Abp.Auditing;
using Volo.Abp.Domain.Entities;
namespace NPin.Framework.Upms.Domain.Entities;
[SugarTable("announcement", "系统公告表")]
public class AnnouncementEntity : Entity<Guid>, ISoftDelete, IAuditedObject, IOrderNum, IEnabled
{
[SugarColumn(IsPrimaryKey = true)] public override Guid Id { get; protected set; }
[SugarColumn(ColumnDescription = "公告标题")]
public string Title { get; set; }
[SugarColumn(ColumnDescription = "公告分类")]
public string Category { get; set; }
[SugarColumn(ColumnDescription = "公告行为")]
public string Action { get; set; }
[SugarColumn(ColumnDescription = "公告内容", ColumnDataType = StaticConfig.CodeFirst_BigString)]
public string Content { get; set; }
public bool IsDeleted { get; }
public DateTime CreationTime { get; }
public Guid? CreatorId { get; }
public DateTime? LastModificationTime { get; }
public Guid? LastModifierId { get; }
public int OrderNum { get; set; }
public bool IsEnabled { get; set; }
}

@ -0,0 +1,34 @@
using Mapster;
using NPin.Framework.SqlSugarCore.Abstractions.Data;
using SqlSugar;
using Volo.Abp.Auditing;
using Volo.Abp.Domain.Entities;
namespace NPin.Framework.Upms.Domain.Entities;
[SugarTable("Config", "系统配置表")]
[SugarIndex($"index_{nameof(Key)}", nameof(Key), OrderByType.Asc, true)]
public class ConfigEntity : Entity<Guid>, IEnabled, IOrderNum, ISoftDelete, IAuditedObject
{
[SugarColumn(IsPrimaryKey = true)] public override Guid Id { get; protected set; }
[SugarColumn(ColumnDescription = "配置名称")]
public string Name { get; set; } = string.Empty;
[SugarColumn(ColumnDescription = "配置键")]
public string Key { get; set; } = string.Empty;
[SugarColumn(ColumnDescription = "配置值")]
public string Value { get; set; } = string.Empty;
[SugarColumn(ColumnDescription = "配置描述")]
public string? Remark { get; set; } = string.Empty;
public bool IsEnabled { get; set; }
public int OrderNum { get; set; }
public bool IsDeleted { get; }
public DateTime CreationTime { get; }
public Guid? CreatorId { get; }
public DateTime? LastModificationTime { get; }
public Guid? LastModifierId { get; }
}

@ -0,0 +1,15 @@
using NPin.Framework.SqlSugarCore.Abstractions;
using NPin.Framework.Upms.Domain.Entities;
using Volo.Abp.Domain.Services;
namespace NPin.Framework.Upms.Domain.Managers;
public class RoleManager: DomainService
{
private ISqlSugarRepository<RoleEntity> _repository;
public RoleManager(ISqlSugarRepository<RoleEntity> repository)
{
_repository = repository;
}
}

@ -0,0 +1,129 @@
using AlibabaCloud.OpenApiClient.Models;
using AlibabaCloud.SDK.Dysmsapi20170525;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using NPin.Framework.Upms.Domain.Repositories;
using NPin.Framework.Upms.Domain.Shared.Enums;
using NPin.Framework.Upms.Domain.Shared.Model;
using NPin.Framework.Upms.Domain.Shared.Options;
using TencentCloud.Common;
using TencentCloud.Common.Profile;
using TencentCloud.Sms.V20210111;
using TencentCloud.Sms.V20210111.Models;
using Volo.Abp.Caching;
using Volo.Abp.Domain.Services;
namespace NPin.Framework.Upms.Domain.Managers;
public class SmsManager : DomainService, ISms
{
private ILogger<SmsManager> _logger;
private IConfigRepository _configRepository;
private IDistributedCache<SmsConfigModel> _cache;
public SmsManager(ILogger<SmsManager> logger, IConfigRepository configRepository)
{
_logger = logger;
_configRepository = configRepository;
}
public async Task SendSmsAsync(SmsTypeEnum smsType, string phoneNumbers, object templateParam)
{
try
{
var smsSettings = SmsOptions.Config[smsType];
if (!smsSettings.Enabled)
{
return;
}
switch (smsSettings.Provider)
{
case SmsProviderEnum.Aliyun:
await SendAliyunSmsAsync(smsSettings, phoneNumbers, templateParam);
break;
case SmsProviderEnum.Tencent:
await SendTencentSmsAsync(smsSettings, phoneNumbers, templateParam);
break;
default:
throw new Exception("未实现该服务提供商");
}
}
catch (Exception ex)
{
_logger.LogError(ex, $"短信发送失败: {ex.Message}");
throw new UserFriendlyException($"短信发送失败: {ex.Message}");
}
}
private async Task SendTencentSmsAsync(SmsSettings settings, string phoneNumbers,
object templateParam)
{
var client = SmsClientProvider.CreateClient(TencentOptions, settings);
var sendSmsRequest = new SendSmsRequest
{
PhoneNumberSet = phoneNumbers.Split(','),
SignName = settings.SignName,
TemplateId = settings.TemplateCode,
TemplateParamSet = templateParam as string[]
};
var response = await client.SendSms(sendSmsRequest);
}
private async Task SendAliyunSmsAsync(SmsSettings settings, string phoneNumbers,
object templateParam)
{
var client = SmsClientProvider.CreateClient(AliyunOptions, settings);
var sendSmsRequest = new AlibabaCloud.SDK.Dysmsapi20170525.Models.SendSmsRequest
{
PhoneNumbers = phoneNumbers,
SignName = settings.SignName,
TemplateCode = settings.TemplateCode,
TemplateParam = JsonConvert.SerializeObject(templateParam)
};
var response = await client.SendSmsAsync(sendSmsRequest);
}
}
public static class SmsClientProvider
{
public static Client CreateClient(AliyunOptions options, SmsSettings settings)
{
var config = new Config()
{
AccessKeyId = options.AccessKeyId,
AccessKeySecret = options.AccessKeySecret,
Endpoint = settings.Endpoint,
RegionId = settings.RegionId,
};
return new Client(config);
}
public static SmsClient CreateClient(TencentOptions options, SmsSettings settings)
{
var cred = new Credential
{
SecretId = options.SecretId,
SecretKey = options.SecretKey,
};
var httpProfile = new HttpProfile
{
Endpoint = settings.Endpoint,
};
var clientProfile = new ClientProfile()
{
HttpProfile = httpProfile
};
return new SmsClient(cred, settings.RegionId, clientProfile);
}
}

@ -3,7 +3,6 @@ using NPin.Framework.Caching.FreeRedis;
using NPin.Framework.Upms.Domain.Authorization;
using NPin.Framework.Upms.Domain.OperLog;
using NPin.Framework.Upms.Domain.Shared;
using NPin.Framework.Upms.Domain.Shared.Options;
using Volo.Abp.AspNetCore.SignalR;
using Volo.Abp.Caching;
using Volo.Abp.Domain;
@ -29,8 +28,5 @@ public class NPinFrameworkUpmsDomainModule : AbpModule
opts.Filters.Add<PermissionGlobalAttribute>();
opts.Filters.Add<OperLogGlobalAttribute>();
});
// 配置短信
Configure<AliyunOptions>(configuration.GetSection(nameof(AliyunOptions)));
}
}

@ -0,0 +1,9 @@
using NPin.Framework.SqlSugarCore.Abstractions;
using NPin.Framework.Upms.Domain.Entities;
namespace NPin.Framework.Upms.Domain.Repositories;
public interface IConfigRepository : ISqlSugarRepository<ConfigEntity>
{
Task<TDestination> GetSingleByKeyAsync<TDestination>(string key) where TDestination : new();
}

@ -0,0 +1,11 @@
using NPin.Framework.Upms.Domain.Shared.Enums;
namespace NPin.Framework.Upms.Domain.Managers;
/// <summary>
/// 短信接口
/// </summary>
public interface ISms
{
Task SendSmsAsync(SmsTypeEnum smsType, string phoneNumbers, object templateParam);
}

@ -0,0 +1,30 @@
using Newtonsoft.Json;
using NPin.Framework.SqlSugarCore.Abstractions;
using NPin.Framework.SqlSugarCore.Repositories;
using NPin.Framework.Upms.Domain.Entities;
using NPin.Framework.Upms.Domain.Repositories;
using Volo.Abp.DependencyInjection;
namespace NPin.Framework.Upms.SqlSugarCore;
public class ConfigRepository : SqlSugarRepository<ConfigEntity, Guid>, IConfigRepository, ITransientDependency
{
public ConfigRepository(ISugarDbContextProvider<ISqlSugarDbContext> sugarDbContextProvider) : base(
sugarDbContextProvider)
{
}
public async Task<TDestination> GetSingleByKeyAsync<TDestination>(string key) where TDestination : new()
{
var config = await DbQueryable
.Where(e => e.Key.Equals(key))
.FirstAsync();
if (config is null)
{
return new TDestination();
}
var ret = JsonConvert.DeserializeObject<TDestination>(config.Value);
return ret ?? new TDestination();
}
}
Loading…
Cancel
Save