2026-03-10 16:11:22 +08:00

167 lines
5.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)未配置");
}
}