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