using DotNetCore.CAP; using Hotline.Share.Dtos.Push; using Hotline.Share.Dtos.SendSms; using Hotline.Share.Enums.Push; using MapsterMapper; using MediatR; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System.Net; using System.Net.Http.Json; using System.Text.RegularExpressions; using System.Xml; using XF.Domain.Dependency; using XF.Domain.Exceptions; using XF.Domain.Repository; namespace Hotline.Push.FWMessage; /// /// /// public class PushDomainService : IPushDomainService, IScopeDependency { #region 注入 private readonly IRepository _messageRepository; private readonly IMapper _mapper; private readonly IMediator _mediator; private readonly IRepository _messageTemplateRepository; private readonly ICapPublisher _capPublisher; private readonly IHttpClientFactory _httpClientFactory; private readonly ILogger _logger; private readonly IOptionsSnapshot _sendSmsConfiguration; /// /// /// /// /// /// /// /// /// /// /// public PushDomainService(IRepository messageRepository, IMapper mapper, IMediator mediator, IRepository messageTemplateRepository, ICapPublisher capPublisher, IHttpClientFactory httpClientFactory, ILogger logger, IOptionsSnapshot sendSmsConfiguration ) { _messageRepository = messageRepository; _mapper = mapper; _mediator = mediator; _messageTemplateRepository = messageTemplateRepository; _capPublisher = capPublisher; _httpClientFactory = httpClientFactory; _logger = logger; _sendSmsConfiguration = sendSmsConfiguration; } #endregion /// /// 短信发送 /// /// /// /// public async Task PushMsgAsync(MessageDto messageDto, CancellationToken cancellation) { if (messageDto == null) throw UserFriendlyException.SameMessage("消息不能为空!"); if (string.IsNullOrEmpty(messageDto.TemplateCode) && string.IsNullOrEmpty(messageDto.Content)) throw UserFriendlyException.SameMessage("模板和内容不能同时为空!"); #region 替换模板内容 //如果模板为空,参数为空则直接用短信内容 if (!string.IsNullOrEmpty(messageDto.TemplateCode)) { //查询模板信息 var messageTemplate = await _messageTemplateRepository.GetAsync(p => p.Code == messageDto.TemplateCode, cancellation); if (messageTemplate == null || string.IsNullOrEmpty(messageTemplate.Content)) throw UserFriendlyException.SameMessage("未找到模板短信!"); string Template = messageTemplate.Content; if (messageDto.Params != null && messageDto.Params.Count > 0) { //正则查询模板中需要替换的内容 Regex regex = new(@"\{[a-zA-Z0-9]{1,}\}"); var matches = regex.Matches(Template); if (matches != null && matches.Count != messageDto.Params.Count) //参数与需要替换的字符数不匹配 throw UserFriendlyException.SameMessage("模板需要参数与实际传递参数个数不匹配!"); //reason = "模板需要参数与实际传递参数个数不匹配!"; //根据正则查询出来的匹配项替换内容 for (int i = 0; i < matches.Count; i++) Template = Template.Replace(matches[i].ToString(), messageDto.Params[i]); } messageDto.Content = Template; } #endregion var message = _mapper.Map(messageDto); var id = await _messageRepository.AddAsync(message, cancellation);//写入本地数据库 PushMessageDto pushMessage = new() { ClientId = "Hotline", ExternalId = id, Content = message.Content, Remark = message.Remark, Name = message.Name, TelNumber = message.TelNumber }; //消息队列 await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.SendSms, pushMessage, cancellationToken: cancellation); ////http请求 //var result = await ExecuteAsync(_sendSmsConfiguration.Value.Url, pushMessage, cancellationToken: cancellation); //if (result != null && result.code == 0) //{ // message.Status = EPushStatus.Success; // message.SendState = ESendState.Sending; // await _messageRepository.UpdateAsync(message, cancellation); //} } /// /// 修改短信推送状态 /// /// /// /// public async Task PushMsgUpdateStateAsync(PushReceiveMessageDto dto, CancellationToken cancellation) { var data = await _messageRepository.GetAsync(p => p.Id == dto.ExternalId, cancellation); if (data != null) { if (dto.Type == "0") { if (dto.SendState == ESendState.Sending) { data.SmsWaitSendingId = dto.SmsWaitSendingId; data.SendState = ESendState.Sending; data.Status = EPushStatus.Success; } else data.Status = EPushStatus.Failed; } else if (dto.Type == "1") { data.SendTime = Convert.ToDateTime(dto.SendTime); data.SendState = dto.SendState; data.MsgCount = dto.MsgCount; data.SmsSendingCompletedId = dto.SmsSendingCompletedId; } else if (dto.Type == "2") { data.IsSmsReply = dto.IsSmsReply; data.SmsReplyTime = Convert.ToDateTime(dto.SmsReplyTime); data.SmsReplyContent = dto.SmsReplyContent; } data.Reason = dto.Reason; await _messageRepository.UpdateAsync(data, cancellation); } } /// /// 修改短信推送状态 /// /// /// /// public async Task PushMsgUpdateStateNewAsync(PushReceiveMessageDto dto, CancellationToken cancellation) { var data = await _messageRepository.GetAsync(p => p.Id == dto.ExternalId, cancellation); if (data != null) { data.SmsWaitSendingId = dto.SmsWaitSendingId; data.Status = EPushStatus.Success; data.SendTime = Convert.ToDateTime(dto.SendTime); data.SendState = dto.SendState; data.MsgCount = dto.MsgCount; data.SmsSendingCompletedId = dto.SmsSendingCompletedId; data.IsSmsReply = dto.IsSmsReply; data.SmsReplyTime = Convert.ToDateTime(dto.SmsReplyTime); data.SmsReplyContent = dto.SmsReplyContent; data.Reason = dto.Reason; await _messageRepository.UpdateAsync(data, cancellation); } } /// /// /// /// /// /// /// /// /// /// private async Task ExecuteAsync(string path, TRequest request, Action? clientInitialize = null, CancellationToken cancellationToken = default) { var client = _httpClientFactory.CreateClient("sendwaitsms"); clientInitialize?.Invoke(client); using var responseMessage = await client.PostAsJsonAsync(path, request, cancellationToken); responseMessage.EnsureSuccessStatusCode(); var result = await responseMessage.Content.ReadFromJsonAsync(cancellationToken: cancellationToken); return result; } #region http请求 /// /// 封装使用HttpClient调用WebService /// /// URL地址 /// 参数 /// private async Task PostHelper(string url, HttpContent content) { _logger.LogInformation($"准备推送短信, {nameof(PostHelper)}"); var result = string.Empty; try { using var client = _httpClientFactory.CreateClient(); using (var response = await client.PostAsync(url, content)) { if (response.StatusCode == HttpStatusCode.OK) { result = await response.Content.ReadAsStringAsync(); XmlDocument doc = new XmlDocument(); doc.LoadXml(result); result = doc.InnerText; } } } catch (Exception ex) { _logger.LogError(ex.InnerException?.Message); result = ex.Message; } _logger.LogInformation($"推送响应:{result}"); return result; } #endregion }