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;
///
/// 阿里云短信服务实现
///
public class AliyunSmsService : ITransient
{
private readonly SmsOptions _options;
private readonly ILogger _logger;
private readonly ISqlSugarRepository _smsLogRepository;
private AlibabaCloud.SDK.Dysmsapi20170525.Client _client;
public AliyunSmsService(IOptions options,
ILogger logger,
ISqlSugarRepository smsLogRepository)
{
_options = options.Value;
_logger = logger;
_smsLogRepository = smsLogRepository;
InitClient();
}
///
/// 初始化阿里云短信客户端
///
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, "阿里云短信客户端初始化失败");
}
}
///
/// 发送验证码短信
///
public async Task SendVerificationCode(string phone, string code)
{
// 校验配置
ValidateConfig();
if (string.IsNullOrWhiteSpace(_options.VerificationCodeTemplateCode))
throw Oops.Bah("短信验证码模板未配置");
var param = JsonConvert.SerializeObject(new { code = code });
await SendSms(phone, _options.VerificationCodeTemplateCode, param);
}
///
/// 发送短信核心方法
///
public async Task SendSms(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);
}
}
///
/// 校验配置是否有效
///
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)未配置");
}
}