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
}