单位认证完善

This commit is contained in:
马梓彭 2026-03-10 16:11:22 +08:00
parent 3268e24f1d
commit 8a94c46eed
14 changed files with 775 additions and 4 deletions

View File

@ -1,4 +1,4 @@
using YD_Event.Application.Logging.Dtos;
using YD_Event.Application.Logging.Dtos;
namespace YD_Event.Application.Logging;
/// <summary>

View File

@ -1,4 +1,4 @@
using YD_Event.Application.Logging.Dtos;
using YD_Event.Application.Logging.Dtos;
namespace YD_Event.Application.Logging;
/// <summary>

View File

@ -0,0 +1,43 @@
using System.ComponentModel.DataAnnotations;
namespace YD_Event.Application.Merchant.Dtos;
public class SubmitCertificationInput
{
/// <summary>
/// 单位名称
/// </summary>
[Required(ErrorMessage = "单位名称不能为空")]
public string MerchantName { get; set; }
/// <summary>
/// 统一社会信用代码
/// </summary>
[Required(ErrorMessage = "统一社会信用代码不能为空")]
public string CreditCode { get; set; }
/// <summary>
/// 营业执照图片URL
/// </summary>
[Required(ErrorMessage = "请上传营业执照")]
public string BusinessLicenseUrl { get; set; }
/// <summary>
/// 地址
/// </summary>
[Required(ErrorMessage = "地址不能为空")]
public string Address { get; set; }
/// <summary>
/// 联系方式
/// </summary>
[Required(ErrorMessage = "联系方式不能为空")]
[RegularExpression(@"^1[3456789]\d{9}$", ErrorMessage = "手机号格式不正确")]
public string ContactPhone { get; set; }
/// <summary>
/// 验证码
/// </summary>
[Required(ErrorMessage = "验证码不能为空")]
public string VerificationCode { get; set; }
}

View File

@ -1,5 +1,7 @@
using Microsoft.Extensions.Caching.Memory;
using YD_Event.Application.Auth;
using YD_Event.Application.Merchant.Dtos;
using YD_Event.Application.Sms;
using YD_Event.Core.Entities;
using YD_Event.Core.Enum;
@ -14,16 +16,111 @@ public class MerchantService : BaseService<YD_Event.Core.Entities.Merchant>, ITr
private readonly ISqlSugarRepository<UserCoupon> _userCouponRepository;
private readonly AuthManager _authManager;
private readonly IIdGenerator _idGenerator;
private readonly IMemoryCache _memoryCache;
private readonly AliyunSmsService _smsService;
public MerchantService(ISqlSugarRepository<YD_Event.Core.Entities.Merchant> repository,
ISqlSugarRepository<UserCoupon> userCouponRepository,
AuthManager authManager,
IIdGenerator idGenerator) : base(repository)
IIdGenerator idGenerator,
IMemoryCache memoryCache,
AliyunSmsService smsService) : base(repository)
{
_repository = repository;
_userCouponRepository = userCouponRepository;
_authManager = authManager;
_idGenerator = idGenerator;
_memoryCache = memoryCache;
_smsService = smsService;
}
/// <summary>
/// 发送验证码
/// </summary>
[DisplayName("发送验证码")]
[HttpPost("sendVerificationCode")]
[AllowAnonymous]
public async Task SendVerificationCode([FromQuery] string phone)
{
if (string.IsNullOrWhiteSpace(phone) || !System.Text.RegularExpressions.Regex.IsMatch(phone, @"^1[3456789]\d{9}$"))
throw Oops.Bah("手机号格式不正确");
// 生成6位验证码
var code = new Random().Next(100000, 999999).ToString();
// 存入缓存,有效期5分钟
_memoryCache.Set($"verification_code_{phone}", code, TimeSpan.FromMinutes(5));
// 发送短信
await _smsService.SendVerificationCodeAsync(phone, code);
}
/// <summary>
/// 提交单位认证
/// </summary>
[DisplayName("提交单位认证")]
[HttpPost("submitCertification")]
public async Task SubmitCertification(SubmitCertificationInput input)
{
// 验证验证码
if (!_memoryCache.TryGetValue($"verification_code_{input.ContactPhone}", out string? cachedCode) || cachedCode != input.VerificationCode)
{
throw Oops.Bah("验证码错误或已过期");
}
// 获取当前用户关联的商户信息
var userId = _authManager.UserId;
var merchant = await _repository.GetFirstAsync(m => m.CreatedUserId == userId);
if (merchant == null)
{
// 新增商户
merchant = new YD_Event.Core.Entities.Merchant
{
Id = _idGenerator.NextId(),
MerchantName = input.MerchantName,
CreditCode = input.CreditCode,
BusinessLicenseUrl = input.BusinessLicenseUrl,
Address = input.Address,
ContactPhone = input.ContactPhone,
BankName = "", // 默认为空,后续完善
AccountNumber = "", // 默认为空,后续完善
AuditStatus = AuditStatus.PendingAudit, // 待审核
Status = AvailabilityStatus.Enable,
CreatedUserId = userId,
CreatedTime = DateTime.Now
};
await _repository.InsertAsync(merchant);
}
else
{
// 更新商户信息
merchant.MerchantName = input.MerchantName;
merchant.CreditCode = input.CreditCode;
merchant.BusinessLicenseUrl = input.BusinessLicenseUrl;
merchant.Address = input.Address;
merchant.ContactPhone = input.ContactPhone;
merchant.AuditStatus = AuditStatus.PendingAudit; // 重新提交后变为待审核
merchant.UpdatedUserId = userId;
merchant.UpdatedTime = DateTime.Now;
await _repository.UpdateAsync(merchant);
}
// 清除验证码
_memoryCache.Remove($"verification_code_{input.ContactPhone}");
}
/// <summary>
/// 获取我的认证信息
/// </summary>
[DisplayName("获取我的认证信息")]
[HttpGet("myCertification")]
public async Task<YD_Event.Core.Entities.Merchant> GetMyCertification()
{
var userId = _authManager.UserId;
var merchant = await _repository.GetFirstAsync(m => m.CreatedUserId == userId);
return merchant;
}
/// <summary>

View File

@ -0,0 +1,166 @@
using AlibabaCloud.OpenApiClient.Models;
using AlibabaCloud.SDK.Dysmsapi20170525;
using AlibabaCloud.SDK.Dysmsapi20170525.Models;
using Furion.DependencyInjection;
using Furion.FriendlyException;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using SqlSugar;
using Tea;
using YD_Event.Core.Entities;
using YD_Event.Core.Options;
namespace YD_Event.Application.Sms;
/// <summary>
/// 阿里云短信服务实现
/// </summary>
public class AliyunSmsService : ITransient
{
private readonly SmsOptions _options;
private readonly ILogger<AliyunSmsService> _logger;
private readonly ISqlSugarRepository<SysSmsLog> _smsLogRepository;
private AlibabaCloud.SDK.Dysmsapi20170525.Client _client;
public AliyunSmsService(IOptions<SmsOptions> options,
ILogger<AliyunSmsService> logger,
ISqlSugarRepository<SysSmsLog> smsLogRepository)
{
_options = options.Value;
_logger = logger;
_smsLogRepository = smsLogRepository;
InitClient();
}
/// <summary>
/// 初始化阿里云短信客户端
/// </summary>
private void InitClient()
{
if (string.IsNullOrWhiteSpace(_options.AccessKeyId) || string.IsNullOrWhiteSpace(_options.AccessKeySecret))
{
_logger.LogWarning("阿里云短信配置缺失:AccessKeyId或AccessKeySecret为空");
return;
}
var config = new Config
{
AccessKeyId = _options.AccessKeyId,
AccessKeySecret = _options.AccessKeySecret,
Endpoint = _options.Endpoint
};
try
{
_client = new AlibabaCloud.SDK.Dysmsapi20170525.Client(config);
}
catch (Exception ex)
{
_logger.LogError(ex, "阿里云短信客户端初始化失败");
}
}
/// <summary>
/// 发送验证码短信
/// </summary>
public async Task SendVerificationCodeAsync(string phone, string code)
{
// 校验配置
ValidateConfig();
if (string.IsNullOrWhiteSpace(_options.VerificationCodeTemplateCode))
throw Oops.Bah("短信验证码模板未配置");
var param = JsonConvert.SerializeObject(new { code = code });
await SendSmsAsync(phone, _options.VerificationCodeTemplateCode, param);
}
/// <summary>
/// 发送短信核心方法
/// </summary>
public async Task SendSmsAsync(string phone, string templateCode, string templateParam)
{
// 1. 参数校验
if (string.IsNullOrWhiteSpace(phone)) throw Oops.Bah("手机号不能为空");
if (string.IsNullOrWhiteSpace(templateCode)) throw Oops.Bah("短信模板不能为空");
ValidateConfig();
// 2. 构造请求
var request = new SendSmsRequest
{
PhoneNumbers = phone,
SignName = _options.SignName,
TemplateCode = templateCode,
TemplateParam = templateParam
};
// 3. 准备日志实体
var log = new SysSmsLog
{
Phone = phone,
TemplateCode = templateCode,
TemplateParam = templateParam,
CreatedTime = DateTime.Now
};
try
{
// 4. 发送请求
var response = await _client.SendSmsAsync(request);
// 5. 处理响应
log.ResponseCode = response.Body.Code;
log.ResponseMessage = response.Body.Message;
log.RequestId = response.Body.RequestId;
log.Success = response.Body.Code == "OK";
if (!log.Success)
{
_logger.LogWarning($"短信发送失败:{phone}, Code: {response.Body.Code}, Message: {response.Body.Message}");
throw Oops.Bah($"短信发送失败:{response.Body.Message}");
}
}
catch (TeaException error)
{
// 阿里云SDK异常
log.Success = false;
log.Exception = $"Code: {error.Code}, Message: {error.Message}, Data: {JsonConvert.SerializeObject(error.Data)}";
_logger.LogError(error, "阿里云短信发送异常");
throw Oops.Bah("短信服务异常,请稍后重试");
}
catch (Exception ex)
{
// 其他异常(网络等)
log.Success = false;
log.Exception = ex.Message;
_logger.LogError(ex, "短信发送未知异常");
throw Oops.Bah("短信发送失败,请检查网络或联系管理员");
}
finally
{
// 6. 日志持久化
await _smsLogRepository.InsertAsync(log);
}
}
/// <summary>
/// 校验配置是否有效
/// </summary>
public void ValidateConfig()
{
if (_client == null)
{
InitClient();
if (_client == null)
throw Oops.Bah("短信服务未初始化,请检查AccessKeyId和AccessKeySecret配置");
}
if (string.IsNullOrWhiteSpace(_options.SignName))
throw Oops.Bah("短信签名(SignName)未配置");
if (string.IsNullOrWhiteSpace(_options.VerificationCodeTemplateCode))
throw Oops.Bah("验证码模板(VerificationCodeTemplateCode)未配置");
}
}

View File

@ -2508,6 +2508,36 @@
商户审核输入
</summary>
</member>
<member name="P:YD_Event.Application.Merchant.Dtos.SubmitCertificationInput.MerchantName">
<summary>
单位名称
</summary>
</member>
<member name="P:YD_Event.Application.Merchant.Dtos.SubmitCertificationInput.CreditCode">
<summary>
统一社会信用代码
</summary>
</member>
<member name="P:YD_Event.Application.Merchant.Dtos.SubmitCertificationInput.BusinessLicenseUrl">
<summary>
营业执照图片URL
</summary>
</member>
<member name="P:YD_Event.Application.Merchant.Dtos.SubmitCertificationInput.Address">
<summary>
地址
</summary>
</member>
<member name="P:YD_Event.Application.Merchant.Dtos.SubmitCertificationInput.ContactPhone">
<summary>
联系方式
</summary>
</member>
<member name="P:YD_Event.Application.Merchant.Dtos.SubmitCertificationInput.VerificationCode">
<summary>
验证码
</summary>
</member>
<member name="P:YD_Event.Application.Merchant.Dtos.UpdateMerchantInput.Id">
<summary>
主键Id
@ -2518,6 +2548,21 @@
商户管理
</summary>
</member>
<member name="M:YD_Event.Application.Merchant.MerchantService.SendVerificationCode(System.String)">
<summary>
发送验证码
</summary>
</member>
<member name="M:YD_Event.Application.Merchant.MerchantService.SubmitCertification(YD_Event.Application.Merchant.Dtos.SubmitCertificationInput)">
<summary>
提交单位认证
</summary>
</member>
<member name="M:YD_Event.Application.Merchant.MerchantService.GetMyCertification">
<summary>
获取我的认证信息
</summary>
</member>
<member name="M:YD_Event.Application.Merchant.MerchantService.Page(YD_Event.Application.Merchant.Dtos.MerchantQueryInput)">
<summary>
商户分页查询
@ -3581,6 +3626,31 @@
</summary>
<returns></returns>
</member>
<member name="T:YD_Event.Application.Sms.AliyunSmsService">
<summary>
阿里云短信服务实现
</summary>
</member>
<member name="M:YD_Event.Application.Sms.AliyunSmsService.InitClient">
<summary>
初始化阿里云短信客户端
</summary>
</member>
<member name="M:YD_Event.Application.Sms.AliyunSmsService.SendVerificationCodeAsync(System.String,System.String)">
<summary>
发送验证码短信
</summary>
</member>
<member name="M:YD_Event.Application.Sms.AliyunSmsService.SendSmsAsync(System.String,System.String,System.String)">
<summary>
发送短信核心方法
</summary>
</member>
<member name="M:YD_Event.Application.Sms.AliyunSmsService.ValidateConfig">
<summary>
校验配置是否有效
</summary>
</member>
<member name="P:YD_Event.Application.User.Dtos.AddSysUserInput.Name">
<summary>
姓名

View File

@ -139,5 +139,11 @@
// }
//]
}
},
// 阿里云短信配置
"ALiYunSMS": {
"Endpoint": "dysmsapi.aliyuncs.com",
"Sign": "oVpeH1PpDUnWTcBrUSSYkQNS4Fex8Y",
"Template": "SMS_147140268"
}
}

View File

@ -1,4 +1,4 @@
using SqlSugar;
using SqlSugar;
using YD_Event.Core.Enum;
namespace YD_Event.Core.Entities;

View File

@ -0,0 +1,63 @@
using SqlSugar;
using YD_Event.Core.Enum;
namespace YD_Event.Core.Entities;
/// <summary>
/// 短信发送日志
/// </summary>
[SugarTable("SysSmsLog")]
public class SysSmsLog : Entity<long>, ICreatedTime
{
/// <summary>
/// 接收手机号
/// </summary>
[SugarColumn(Length = 20)]
public string Phone { get; set; }
/// <summary>
/// 短信模板Code
/// </summary>
[SugarColumn(Length = 50)]
public string TemplateCode { get; set; }
/// <summary>
/// 模板参数
/// </summary>
[SugarColumn(Length = 512, IsNullable = true)]
public string TemplateParam { get; set; }
/// <summary>
/// 发送状态(成功/失败)
/// </summary>
public bool Success { get; set; }
/// <summary>
/// 响应代码
/// </summary>
[SugarColumn(Length = 50, IsNullable = true)]
public string ResponseCode { get; set; }
/// <summary>
/// 响应消息
/// </summary>
[SugarColumn(Length = 512, IsNullable = true)]
public string ResponseMessage { get; set; }
/// <summary>
/// 请求ID
/// </summary>
[SugarColumn(Length = 128, IsNullable = true)]
public string RequestId { get; set; }
/// <summary>
/// 异常信息
/// </summary>
[SugarColumn(ColumnDataType = "text", IsNullable = true)]
public string Exception { get; set; }
/// <summary>
/// 发送时间
/// </summary>
public DateTime CreatedTime { get; set; }
}

View File

@ -14,6 +14,7 @@ public static class ServiceCollectionExtension
service.AddConfigurableOptions<DbConnectionOptions>();
service.AddConfigurableOptions<OssConnectionOptions>();
service.AddConfigurableOptions<SnowIdOptions>();
service.AddConfigurableOptions<SmsOptions>();
return service;
}
}

View File

@ -0,0 +1,38 @@
using Furion.ConfigurableOptions;
using Microsoft.Extensions.Configuration;
namespace YD_Event.Core.Options;
/// <summary>
/// 短信配置选项
/// </summary>
[OptionsSettings("ALiYunSMS")]
public class SmsOptions : IConfigurableOptions
{
/// <summary>
/// AccessKeyId
/// </summary>
public string AccessKeyId { get; set; }
/// <summary>
/// AccessKeySecret
/// </summary>
public string AccessKeySecret { get; set; }
/// <summary>
/// 短信签名
/// </summary>
[ConfigurationKeyName("Sign")]
public string SignName { get; set; }
/// <summary>
/// 验证码模板Code
/// </summary>
[ConfigurationKeyName("Template")]
public string VerificationCodeTemplateCode { get; set; }
/// <summary>
/// 短信API Endpoint
/// </summary>
public string Endpoint { get; set; } = "dysmsapi.aliyuncs.com";
}

View File

@ -0,0 +1,174 @@
using AlibabaCloud.OpenApiClient.Models;
using AlibabaCloud.SDK.Dysmsapi20170525;
using AlibabaCloud.SDK.Dysmsapi20170525.Models;
using Furion.DependencyInjection;
using Furion.FriendlyException;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using SqlSugar;
using System.Threading.Tasks;
using Tea;
using YD_Event.Core.Entities;
using YD_Event.Core.Options;
namespace YD_Event.Application.Sms;
/// <summary>
/// 阿里云短信服务实现
/// </summary>
public class AliyunSmsService : ITransient
{
private readonly SmsOptions _options;
private readonly ILogger<AliyunSmsService> _logger;
private readonly ISqlSugarRepository<SysSmsLog> _smsLogRepository;
private Client _client;
public AliyunSmsService(IOptions<SmsOptions> options,
ILogger<AliyunSmsService> logger,
ISqlSugarRepository<SysSmsLog> smsLogRepository)
{
_options = options.Value;
_logger = logger;
_smsLogRepository = smsLogRepository;
InitClient();
}
/// <summary>
/// 初始化阿里云短信客户端
/// </summary>
private void InitClient()
{
if (string.IsNullOrWhiteSpace(_options.AccessKeyId) || string.IsNullOrWhiteSpace(_options.AccessKeySecret))
{
_logger.LogWarning("阿里云短信配置缺失:AccessKeyId或AccessKeySecret为空");
return;
}
var config = new Config
{
AccessKeyId = _options.AccessKeyId,
AccessKeySecret = _options.AccessKeySecret,
Endpoint = _options.Endpoint
};
try
{
_client = new Client(config);
}
catch (Exception ex)
{
_logger.LogError(ex, "阿里云短信客户端初始化失败");
}
}
/// <summary>
/// 发送验证码短信
/// </summary>
/// <param name="phone">手机号</param>
/// <param name="code">验证码</param>
/// <returns></returns>
public async Task SendVerificationCodeAsync(string phone, string code)
{
// 校验配置
ValidateConfig();
if (string.IsNullOrWhiteSpace(_options.VerificationCodeTemplateCode))
throw Oops.Bah("短信验证码模板未配置");
var param = JsonConvert.SerializeObject(new { code = code });
await SendSmsAsync(phone, _options.VerificationCodeTemplateCode, param);
}
/// <summary>
/// 发送自定义短信
/// </summary>
/// <param name="phone">手机号</param>
/// <param name="templateCode">模板编码</param>
/// <param name="templateParam">模板参数JSON字符串</param>
/// <returns></returns>
public async Task SendSmsAsync(string phone, string templateCode, string templateParam)
{
// 1. 参数校验
if (string.IsNullOrWhiteSpace(phone)) throw Oops.Bah("手机号不能为空");
if (string.IsNullOrWhiteSpace(templateCode)) throw Oops.Bah("短信模板不能为空");
ValidateConfig();
// 2. 构造请求
var request = new SendSmsRequest
{
PhoneNumbers = phone,
SignName = _options.SignName,
TemplateCode = templateCode,
TemplateParam = templateParam
};
// 3. 准备日志实体
var log = new SysSmsLog
{
Phone = phone,
TemplateCode = templateCode,
TemplateParam = templateParam,
CreatedTime = DateTime.Now
};
try
{
// 4. 发送请求
var response = await _client.SendSmsAsync(request);
// 5. 处理响应
log.ResponseCode = response.Body.Code;
log.ResponseMessage = response.Body.Message;
log.RequestId = response.Body.RequestId;
log.Success = response.Body.Code == "OK";
if (!log.Success)
{
_logger.LogWarning($"短信发送失败:{phone}, Code: {response.Body.Code}, Message: {response.Body.Message}");
throw Oops.Bah($"短信发送失败:{response.Body.Message}");
}
}
catch (TeaException error)
{
// 阿里云SDK异常
log.Success = false;
log.Exception = $"Code: {error.Code}, Message: {error.Message}, Data: {JsonConvert.SerializeObject(error.Data)}";
_logger.LogError(error, "阿里云短信发送异常");
throw Oops.Bah("短信服务异常,请稍后重试");
}
catch (Exception ex)
{
// 其他异常(网络等)
log.Success = false;
log.Exception = ex.Message;
_logger.LogError(ex, "短信发送未知异常");
throw Oops.Bah("短信发送失败,请检查网络或联系管理员");
}
finally
{
// 6. 日志持久化
await _smsLogRepository.InsertAsync(log);
}
}
/// <summary>
/// 校验短信配置
/// </summary>
public void ValidateConfig()
{
if (_client == null)
{
InitClient();
if (_client == null)
throw Oops.Bah("短信服务未初始化,请检查AccessKeyId和AccessKeySecret配置");
}
if (string.IsNullOrWhiteSpace(_options.SignName))
throw Oops.Bah("短信签名(SignName)未配置");
if (string.IsNullOrWhiteSpace(_options.VerificationCodeTemplateCode))
throw Oops.Bah("验证码模板(VerificationCodeTemplateCode)未配置");
}
}

View File

@ -8,6 +8,7 @@
<None Remove="YD_Event.Core.xml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="AlibabaCloud.SDK.Dysmsapi20170525" Version="4.3.0" />
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
<PackageReference Include="EasyCaching.CSRedis" Version="1.9.2" />
<PackageReference Include="EasyCaching.InMemory" Version="1.9.2" />

View File

@ -3366,6 +3366,56 @@
创建时间
</summary>
</member>
<member name="T:YD_Event.Core.Entities.SysSmsLog">
<summary>
短信发送日志
</summary>
</member>
<member name="P:YD_Event.Core.Entities.SysSmsLog.Phone">
<summary>
接收手机号
</summary>
</member>
<member name="P:YD_Event.Core.Entities.SysSmsLog.TemplateCode">
<summary>
短信模板Code
</summary>
</member>
<member name="P:YD_Event.Core.Entities.SysSmsLog.TemplateParam">
<summary>
模板参数
</summary>
</member>
<member name="P:YD_Event.Core.Entities.SysSmsLog.Success">
<summary>
发送状态(成功/失败)
</summary>
</member>
<member name="P:YD_Event.Core.Entities.SysSmsLog.ResponseCode">
<summary>
响应代码
</summary>
</member>
<member name="P:YD_Event.Core.Entities.SysSmsLog.ResponseMessage">
<summary>
响应消息
</summary>
</member>
<member name="P:YD_Event.Core.Entities.SysSmsLog.RequestId">
<summary>
请求ID
</summary>
</member>
<member name="P:YD_Event.Core.Entities.SysSmsLog.Exception">
<summary>
异常信息
</summary>
</member>
<member name="P:YD_Event.Core.Entities.SysSmsLog.CreatedTime">
<summary>
发送时间
</summary>
</member>
<member name="T:YD_Event.Core.Entities.SysUser">
<summary>
系统用户表
@ -4156,6 +4206,36 @@
是否启用对象存储(不启用将存储至站点目录)
</summary>
</member>
<member name="T:YD_Event.Core.Options.SmsOptions">
<summary>
短信配置选项
</summary>
</member>
<member name="P:YD_Event.Core.Options.SmsOptions.AccessKeyId">
<summary>
AccessKeyId
</summary>
</member>
<member name="P:YD_Event.Core.Options.SmsOptions.AccessKeySecret">
<summary>
AccessKeySecret
</summary>
</member>
<member name="P:YD_Event.Core.Options.SmsOptions.SignName">
<summary>
短信签名
</summary>
</member>
<member name="P:YD_Event.Core.Options.SmsOptions.VerificationCodeTemplateCode">
<summary>
验证码模板Code
</summary>
</member>
<member name="P:YD_Event.Core.Options.SmsOptions.Endpoint">
<summary>
短信API Endpoint
</summary>
</member>
<member name="T:YD_Event.Core.Options.SnowIdOptions">
<summary>
雪花id配置
@ -4196,6 +4276,38 @@
子选项
</summary>
</member>
<member name="T:YD_Event.Application.Sms.AliyunSmsService">
<summary>
阿里云短信服务实现
</summary>
</member>
<member name="M:YD_Event.Application.Sms.AliyunSmsService.InitClient">
<summary>
初始化阿里云短信客户端
</summary>
</member>
<member name="M:YD_Event.Application.Sms.AliyunSmsService.SendVerificationCodeAsync(System.String,System.String)">
<summary>
发送验证码短信
</summary>
<param name="phone">手机号</param>
<param name="code">验证码</param>
<returns></returns>
</member>
<member name="M:YD_Event.Application.Sms.AliyunSmsService.SendSmsAsync(System.String,System.String,System.String)">
<summary>
发送自定义短信
</summary>
<param name="phone">手机号</param>
<param name="templateCode">模板编码</param>
<param name="templateParam">模板参数JSON字符串</param>
<returns></returns>
</member>
<member name="M:YD_Event.Application.Sms.AliyunSmsService.ValidateConfig">
<summary>
校验短信配置
</summary>
</member>
<member name="F:Easy.Core.EnumExtension.EnumDic">
<summary>
缓存