Pārlūkot izejas kodu

Merge branch 'master' of http://git.12345lm.cn/Fengwo/hotline

Dun.Jason 1 gadu atpakaļ
vecāks
revīzija
c643c55862

+ 9 - 4
src/Hotline.Api/Controllers/OrderController.cs

@@ -41,6 +41,7 @@ using Hotline.Share.Dtos.Push;
 using Hotline.Share.Enums.Push;
 using XF.Domain.Cache;
 using Hotline.Api.Filter;
+using Hotline.Push.Notifies;
 
 namespace Hotline.Api.Controllers;
 
@@ -1513,7 +1514,7 @@ public class OrderController : BaseController
             .FirstAsync(x => x.Id == id);
         var rspModel = _mapper.Map<OrderScreenListDto>(model);
         rspModel.IsCanHandle = model.Workflow.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
-        rspModel.Handle = rspModel.IsCanHandle && "start".Equals(model.Workflow.CurrentStepCode) && model.Workflow.FlowType == EFlowType.Review;
+        rspModel.Handle = await _workflowDomainService.CheckCurrentIsStartStepAsync(rspModel.WorkflowId, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, HttpContext.RequestAborted);
 		if (rspModel.FileJson != null && rspModel.FileJson.Any())
         {
             var ids = rspModel.FileJson.Select(x => x.Id).ToList();
@@ -2070,7 +2071,8 @@ public class OrderController : BaseController
             if (order.AcceptSms)
             {
                 _logger.LogInformation($"推送短信: orderNo: {order.No}");
-                await _pushDomainService.PushAsync(new MessageDto
+
+                var messageDto = new MessageDto
                 {
                     PushBusiness = EPushBusiness.OrderAccept,
                     ExternalId = order.Id,
@@ -2081,7 +2083,10 @@ public class OrderController : BaseController
                     Remark = order.Title,
                     Name = order.FromName,
                     TelNumber = order.Contact
-                }, HttpContext.RequestAborted);
+                };
+                await _mediator.Publish(new PushMessageNotify(messageDto), HttpContext.RequestAborted);
+                //await _pushDomainService.PushAsync(MessageDto, HttpContext.RequestAborted);
+
                 order.SmsSended = true;
                 await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted);
             }
@@ -2407,7 +2412,7 @@ public class OrderController : BaseController
             var currentStep = _workflowDomainService.GetUnHandleStep(workflow.Steps, _sessionContext.RequiredOrgId,
                 _sessionContext.RequiredUserId);
 
-            if (currentStep.StepType is EStepType.Start)
+            if (workflow.FlowType is EFlowType.Review && currentStep.StepType is EStepType.Start && currentStep.IsOrigin)
                 throw UserFriendlyException.SameMessage("当前流程已退回到开始节点");
 
             var prevStep = workflow.Steps.FirstOrDefault(d => d.Id == currentStep.PrevStepId);

+ 3 - 82
src/Hotline.Api/Controllers/PushMessageController.cs

@@ -47,92 +47,13 @@ namespace Hotline.Api.Controllers
         /// <param name="dto"></param>
         /// <returns></returns>
         [HttpPut("add")]
-        public async Task AddMessage([FromBody] MessageDto dto)
-        {
-            await _pushDomainService.PushAsync(dto, HttpContext.RequestAborted);
-        }
-
-        /// <summary>
-        /// 再次发送
-        /// </summary>
-        /// <param name="id"></param>
-        /// <returns></returns>
-        [HttpGet("{id}")]
-        public async Task ResendMessage(string id)
-        {
-            var data = await _messageRepository.GetAsync(p => p.Id == id, HttpContext.RequestAborted);
-            if (data is null)
-                throw UserFriendlyException.SameMessage("重新发送失败");
-
-            //修改重发次数
-            data.ResendCount++;
-            await _messageRepository.UpdateAsync(data, HttpContext.RequestAborted);
-            //组装数据
-            MessageDto dto = new()
-            {
-                PushBusiness = data.PushBusiness,
-                ExternalId = data.ExternalId,
-                PushPlatform = data.PushPlatform,
-                //  Status = EPushStatus.Pushing,
-                Template = data.Template,
-                Content = data.Content,
-                Remark = data.Remark,
-                Name = data.Name,
-                TelNumber = data.TelNumber,
-                OrderId = data.OrderId
-            };
-            await _pushDomainService.PushAsync(dto, HttpContext.RequestAborted);
-        }
-
-        #endregion
-
-        #region 查询短信剩余数量
-
-        /// <summary>
-        /// 查询短信剩余数量
-        /// </summary>
-        /// <returns></returns>
-        [HttpGet("query")]
-        public async Task<string> GetAccountNum()
-        {
-            return await _pushDomainService.GetAccountNum();
-        }
-
-        #endregion
-
-        #region 短信发送状态回调接口
-
-        /// <summary>
-        /// 短信发送状态回调接口
-        /// </summary>
-        /// <param name="receiveMessageDto"></param>
-        /// <returns></returns>
-        [HttpPost("receiveobtain")]
         [AllowAnonymous]
-        public OpenResponse ReceiveObtain([FromForm] ReceiveMessageDto receiveMessageDto)
+        public async Task AddMessage([FromBody] MessageDto dto)
         {
-            var result = _pushDomainService.ReceiveObtain(receiveMessageDto).GetAwaiter().GetResult();
-
-            return OpenResponse.Ok(result);
+            //  await _pushDomainService.PushAsync(dto, HttpContext.RequestAborted);
+            await _pushDomainService.PushMsgAsync(dto, HttpContext.RequestAborted);
         }
 
-        #endregion
-
-        #region 短信接收
-
-        /// <summary>
-        /// 短信接收
-        /// </summary>
-        /// <param name="receiveMessageDto"></param>
-        /// <returns></returns>
-        [HttpPost("receivesms")]
-        [AllowAnonymous]
-        public OpenResponse ReceiveSms([FromForm] ReceiveMessageDto receiveMessageDto)
-        {
-            var result = _pushDomainService.ReceiveSms(receiveMessageDto).GetAwaiter().GetResult();
-
-            return OpenResponse.Ok(result);
-        }
 
         #endregion
 

+ 2 - 1
src/Hotline.Api/StartupExtensions.cs

@@ -49,7 +49,8 @@ internal static class StartupExtensions
             .RegisterRepository()
             .AddApplication()
             //.AddClientCore(configuration)
-            .AddScoped<IPasswordHasher<Account>, PasswordHasher<Account>>()
+            //.AddScoped<IPasswordHasher<Account>, PasswordHasher<Account>>()
+            .AddScoped(typeof(IPasswordHasher<>), typeof(PasswordHasher<>))
             ;
 
         //Authentication

+ 15 - 15
src/Hotline.Application/FlowEngine/WorkflowApplication.cs

@@ -55,7 +55,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     private readonly IMapper _mapper;
     private readonly IFileRepository _fileRepository;
 
-	public WorkflowApplication(
+    public WorkflowApplication(
         IDefinitionDomainService definitionDomainService,
         IWorkflowDomainService workflowDomainService,
         IOrderDomainService orderDomainService,
@@ -72,7 +72,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         ITimeLimitDomainService timeLimitDomainService,
         ISessionContext sessionContext,
         IMapper mapper,
-		IFileRepository fileRepository
+        IFileRepository fileRepository
     )
     {
         _definitionDomainService = definitionDomainService;
@@ -140,7 +140,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
 
         var workflow = await _workflowDomainService.CreateWorkflowAsync(wfModule, dto.Title,
             _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, externalId, expiredTimeConfig?.TimeText,
-            expiredTimeConfig?.Count, expiredTimeConfig?.TimeType, expiredTimeConfig?.ExpiredTime,expiredTimeConfig?.NearlyExpiredTime, cancellationToken);
+            expiredTimeConfig?.Count, expiredTimeConfig?.TimeType, expiredTimeConfig?.ExpiredTime, expiredTimeConfig?.NearlyExpiredTime, cancellationToken);
 
         var startStep = _workflowDomainService.CreateStartStep(workflow, startStepDefine, dto,
             new List<Kv> { new(_sessionContext.RequiredUserId, _sessionContext.UserName) });
@@ -183,7 +183,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         //    (dto.StepExpiredTime <= DateTime.Now || dto.StepExpiredTime > workflow.ExpiredTime))
         //    throw UserFriendlyException.SameMessage("节点期满时间无效");
 
-        var currentStep = _workflowDomainService.FindCurrentStepWaitForHandle(workflow);
+        var currentStep = _workflowDomainService.FindCurrentStepWaitForHandle(workflow, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
         if (currentStep.Status is EWorkflowStepStatus.Handled)
             throw new UserFriendlyException("该状态不支持继续办理");
 
@@ -236,8 +236,8 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     {
         var workflow =
             await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true, cancellationToken: cancellationToken);
-        User user = await _userRepository.Queryable().Includes(x => x.Organization).Where(x=> x.Id == _sessionContext.RequiredUserId).FirstAsync();
-		await _workflowDomainService.PreviousAsync(workflow, dto, user, cancellationToken);
+        User user = await _userRepository.Queryable().Includes(x => x.Organization).Where(x => x.Id == _sessionContext.RequiredUserId).FirstAsync();
+        await _workflowDomainService.PreviousAsync(workflow, dto, user, cancellationToken);
     }
 
     /// <summary>
@@ -245,16 +245,16 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     /// </summary>
     public async Task OrderPreviousAsync(PreviousWorkflowDto dto, string UserId, CancellationToken cancellationToken)
     {
-	    var workflow =
-		    await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true, cancellationToken: cancellationToken);
-        User user = await _userRepository.Queryable().Includes(x=>x.Organization).Where(x => x.Id == UserId).FirstAsync();
-		await _workflowDomainService.PreviousAsync(workflow, dto, user, cancellationToken);
+        var workflow =
+            await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true, cancellationToken: cancellationToken);
+        User user = await _userRepository.Queryable().Includes(x => x.Organization).Where(x => x.Id == UserId).FirstAsync();
+        await _workflowDomainService.PreviousAsync(workflow, dto, user, cancellationToken);
     }
 
-	/// <summary>
-	/// 撤回至任意节点
-	/// </summary>
-	public async Task RecallAsync(RecallDto dto, CancellationToken cancellationToken)
+    /// <summary>
+    /// 撤回至任意节点
+    /// </summary>
+    public async Task RecallAsync(RecallDto dto, CancellationToken cancellationToken)
     {
         var workflow =
             await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, true, true, cancellationToken: cancellationToken);
@@ -517,7 +517,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     {
         var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, true, true,
             cancellationToken: cancellationToken);
-        var currentStep = _workflowDomainService.FindCurrentStepWaitForHandle(workflow);
+        var currentStep = _workflowDomainService.FindCurrentStepWaitForHandle(workflow, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
         if (currentStep.StepType is EStepType.End)
             throw new UserFriendlyException("结束节点无需办理");
 

+ 20 - 2
src/Hotline.Application/Push/PushMessageNotifyHandler.cs

@@ -1,21 +1,39 @@
-using Hotline.Push.Notifies;
+using Hotline.Push.FWMessage;
+using Hotline.Push.Notifies;
 using MediatR;
 
 namespace Hotline.Application.Push
 {
+    /// <summary>
+    /// 内部发送短信
+    /// </summary>
     public class PushMessageNotifyHandler : INotificationHandler<PushMessageNotify>
     {
-
+        /// <summary>
+        /// 
+        /// </summary>
+        private readonly IPushDomainService _pushDomainService;
 
         /// <summary>
         /// 
         /// </summary>
+        /// <param name="pushDomainService"></param>
+        public PushMessageNotifyHandler(IPushDomainService pushDomainService)
+        {
+            _pushDomainService = pushDomainService;
+        }
+
+        /// <summary>
+        /// 内部发送短信
+        /// </summary>
         /// <param name="notification"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
         public async Task Handle(PushMessageNotify notification, CancellationToken cancellationToken)
         {
             var data = notification.NotifyDto;
+            await _pushDomainService.PushMsgAsync(data, cancellationToken);
+
         }
     }
 }

+ 10 - 4
src/Hotline.Application/Push/PushTextMessageHandler.cs

@@ -7,9 +7,15 @@ namespace Hotline.Application.Push
 {
     public class PushTextMessageHandler : ICapSubscribe, IScopeDependency
     {
-
+        /// <summary>
+        /// 
+        /// </summary>
         private readonly IPushDomainService _pushDomainService;
 
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="pushDomainService"></param>
         public PushTextMessageHandler(IPushDomainService pushDomainService)
         {
             _pushDomainService = pushDomainService;
@@ -21,10 +27,10 @@ namespace Hotline.Application.Push
         /// <param name="messageDto"></param>
         /// <param name="cancellation"></param>
         /// <returns></returns>
-        [CapSubscribe(Hotline.Share.Mq.EventNames.HotlinePushTextMessage)]
-        public async Task ReceiveMsg(MessageDto messageDto, CancellationToken cancellation)
+        [CapSubscribe(Hotline.Share.Mq.EventNames.UpdateSendSmsState)]
+        public async Task UpdateSendSmsState(PushReceiveMessageDto messageDto, CancellationToken cancellation)
         {
-            await _pushDomainService.PushAsync(messageDto, cancellation);
+            await _pushDomainService.PushMsgUpdateStateAsync(messageDto, cancellation);
         }
     }
 }

+ 6 - 16
src/Hotline.Share/Dtos/Push/MessageDto.cs

@@ -14,20 +14,20 @@ namespace Hotline.Share.Dtos.Push
         /// </summary>
         public string ExternalId { get; set; }
 
+        /// <summary>
+        /// 关联工单编号
+        /// </summary>
+        public string? OrderId { get; set; }
+
         /// <summary>
         /// 推送平台
         /// </summary>
         public EPushPlatform PushPlatform { get; set; }
 
-        ///// <summary>
-        ///// 推送状态
-        ///// </summary>
-        //public EPushStatus Status { get; set; }
-
         /// <summary>
         /// 模板
         /// </summary>
-        public string? Template { get; set; }
+        public string? TemplateCode { get; set; }
 
         /// <summary>
         /// 内容
@@ -49,16 +49,6 @@ namespace Hotline.Share.Dtos.Push
         /// </summary>
         public string TelNumber { get; set; }
 
-        /// <summary>
-        /// 发送时间
-        /// </summary>
-        public DateTime? SendTime { get; set; }
-
-        /// <summary>
-        /// 关联工单编号
-        /// </summary>
-        public string? OrderId { get; set; }
-
         /// <summary>
         /// 参数
         /// </summary>

+ 35 - 0
src/Hotline.Share/Dtos/Push/PushMessageDto.cs

@@ -0,0 +1,35 @@
+namespace Hotline.Share.Dtos.Push
+{
+    public class PushMessageDto
+    {
+        /// <summary>
+        /// 业务类型(区分从哪个平台来的短信数据)
+        /// </summary>
+        public string ClientId { get; set; }
+
+        /// <summary>
+        /// 外部业务唯一编号
+        /// </summary>
+        public string? ExternalId { get; set; }
+
+        /// <summary>
+        /// 内容
+        /// </summary>
+        public string Content { get; set; }
+
+        /// <summary>
+        /// 备注
+        /// </summary>
+        public string? Remark { get; set; }
+
+        /// <summary>
+        /// 接收姓名
+        /// </summary>
+        public string Name { get; set; }
+
+        /// <summary>
+        /// 接收手机号码
+        /// </summary>
+        public string TelNumber { get; set; }
+    }
+}

+ 67 - 0
src/Hotline.Share/Dtos/Push/PushReceiveMessageDto.cs

@@ -0,0 +1,67 @@
+using Hotline.Share.Enums.Push;
+
+namespace Hotline.Share.Dtos.Push
+{
+    public class PushReceiveMessageDto
+    {
+        /// <summary>
+        /// 消息处理类型  0:推送状态修改,2:发送状态,3:短信回复
+        /// </summary>
+        public string Type { get; set; }
+
+        /// <summary>
+        /// 外部业务唯一编号
+        /// </summary>
+        public string? ExternalId { get; set; }
+
+        /// <summary>
+        /// 推送状态
+        /// </summary>
+        public EPushStatus Status { get; set; }
+
+        /// <summary>
+        /// 短信中心待发送ID
+        /// </summary>
+        public string? SmsWaitSendingId { get; set; }
+
+        /// <summary>
+        /// 短信中心已发送ID
+        /// </summary>
+        public string? SmsSendingCompletedId { get; set; }
+
+        /// <summary>
+        /// 短信发送状态
+        /// </summary>
+        public ESendState SendState { get; set; }
+
+        /// <summary>
+        /// 发送时间
+        /// </summary>
+        public DateTime? SendTime { get; set; }
+
+        /// <summary>
+        /// 短信回复是否回复
+        /// </summary>   
+        public bool IsSmsReply { get; set; }
+
+        /// <summary>
+        /// 短信回复内容
+        /// </summary>   
+        public string? SmsReplyContent { get; set; }
+
+        /// <summary>
+        /// 短信回复时间
+        /// </summary>
+        public DateTime? SmsReplyTime { get; set; }
+
+        /// <summary>
+        /// 业务系统短信ID
+        /// </summary>
+        public int WaitSendId { get; set; } = 0;
+
+        /// <summary>
+        /// 发送短信使用的数量
+        /// </summary>
+        public int? MsgCount { get; set; }
+    }
+}

+ 1 - 1
src/Hotline.Share/Hotline.Share.csproj

@@ -7,7 +7,7 @@
     <GenerateDocumentationFile>True</GenerateDocumentationFile>
     <NoWarn>$(NoWarn);1591;8618;</NoWarn>
     <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
-    <Version>1.0.54</Version>
+    <Version>1.0.55</Version>
   </PropertyGroup>
 
   <ItemGroup>

+ 16 - 0
src/Hotline.Share/Mq/EventNames.PushSms.cs

@@ -0,0 +1,16 @@
+namespace Hotline.Share.Mq
+{
+    public partial class EventNames
+    {
+        /// <summary>
+        /// 发送短信
+        /// </summary>
+        public const string SendSms = "send.sms";
+
+        /// <summary>
+        /// 修改发送状态
+        /// </summary>
+        public const string UpdateSendSmsState = "update.send.sms.state";
+
+    }
+}

+ 1 - 4
src/Hotline.Share/Mq/EventNames.cs

@@ -12,9 +12,6 @@
         /// </summary>
         public const string HotlinePushBulletin = "hotline.push.bulletin";
 
-        /// <summary>
-        /// 推送短信
-        /// </summary>
-        public const string HotlinePushTextMessage = "hotline.push.text.message";
+      
     }
 }

+ 11 - 2
src/Hotline/FlowEngine/Workflows/IWorkflowDomainService.cs

@@ -103,7 +103,7 @@ namespace Hotline.FlowEngine.Workflows
         /// <summary>
         /// 查询当前待办理节点
         /// </summary>
-        WorkflowStep FindCurrentStepWaitForHandle(Workflow workflow);
+        WorkflowStep FindCurrentStepWaitForHandle(Workflow workflow, string userId, string orgId);
 
         /// <summary>
         /// 查询待回访部门
@@ -150,5 +150,14 @@ namespace Hotline.FlowEngine.Workflows
 		/// <returns></returns>
 		WorkflowStep GetUnHandleStep(List<WorkflowStep> steps, string orgCode, string userId);
 
-	}
+        /// <summary>
+        /// 检查当前办理节点是否为开始节点
+        /// </summary>
+        /// <param name="workflowId"></param>
+        /// <param name="userId">当前办理人Id</param>
+        /// <param name="orgId">当前办理人orgId</param>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
+        Task<bool> CheckCurrentIsStartStepAsync(string workflowId, string userId, string orgId, CancellationToken cancellationToken);
+    }
 }

+ 20 - 3
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -468,7 +468,7 @@ namespace Hotline.FlowEngine.Workflows
 
             var currentStep = GetUnHandleStep(workflow.Steps, user.OrgId, user.Id);
 
-            if (currentStep.StepType is EStepType.Start)
+            if (workflow.FlowType is EFlowType.Review && currentStep.StepType is EStepType.Start && currentStep.IsOrigin)
                 throw UserFriendlyException.SameMessage("当前流程已退回到开始节点");
 
             //find prevStep, update handler
@@ -707,8 +707,8 @@ namespace Hotline.FlowEngine.Workflows
         /// <summary>
         /// 查询当前待办理节点
         /// </summary>
-        public WorkflowStep FindCurrentStepWaitForHandle(Workflow workflow) =>
-            GetUnHandleStep(workflow.Steps, _sessionContext.RequiredOrgId, _sessionContext.RequiredUserId);
+        public WorkflowStep FindCurrentStepWaitForHandle(Workflow workflow, string userId, string orgId) =>
+            GetUnHandleStep(workflow.Steps, orgId, userId);
 
         /// <summary>
         /// 查询待回访部门
@@ -1606,6 +1606,23 @@ namespace Hotline.FlowEngine.Workflows
             return step;
         }
 
+        /// <summary>
+        /// 检查当前办理节点是否为开始节点
+        /// </summary>
+        /// <param name="workflowId"></param>
+        /// <param name="userId">当前办理人Id</param>
+        /// <param name="orgId">当前办理人orgId</param>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
+        public async Task<bool> CheckCurrentIsStartStepAsync(string workflowId, string userId, string orgId, CancellationToken cancellationToken)
+        {
+            var workflow = await GetWorkflowAsync(workflowId, withSteps: true, cancellationToken: cancellationToken);
+            //var currentStep = FindCurrentStepWaitForHandle(workflow, userId, orgId);
+            //if (currentStep.StepType is EStepType.End)
+            //    throw new UserFriendlyException("结束节点无需办理");
+            return workflow.Steps.Count == 1;
+        }
+
         private WorkflowStep? GetStep(List<WorkflowStep> steps, string orgCode, string userId,
             Func<EWorkflowStepStatus, bool> predicate) =>
             steps.FirstOrDefault(d =>

+ 6 - 16
src/Hotline/Push/FWMessage/IPushDomainService.cs

@@ -11,26 +11,16 @@ namespace Hotline.Push.FWMessage
         /// <param name="messageDto"></param>
         /// <param name="cancellation"></param>
         /// <returns></returns>
-        Task PushAsync(MessageDto messageDto, CancellationToken cancellation);
+        Task PushMsgAsync(MessageDto messageDto, CancellationToken cancellation);
 
         /// <summary>
-        /// 查询短信剩余数量
+        /// 修改短信推送状态
         /// </summary>
+        /// <param name="dto"></param>
+        /// <param name="cancellation"></param>
         /// <returns></returns>
-        Task<string> GetAccountNum();
-
-        /// <summary>
-        /// 短信发送状态回调接口
-        /// </summary>
-        /// <param name="receiveMessageDto"></param>
-        /// <returns></returns>
-        Task<string> ReceiveObtain(ReceiveMessageDto receiveMessageDto);
+        Task PushMsgUpdateStateAsync(PushReceiveMessageDto dto, CancellationToken cancellation);
 
-        /// <summary>
-        /// 短信接收
-        /// </summary>
-        /// <param name="receiveMessageDto"></param>
-        /// <returns></returns>
-        Task<string> ReceiveSms(ReceiveMessageDto receiveMessageDto);
+       
     }
 }

+ 70 - 337
src/Hotline/Push/FWMessage/PushDomainService.cs

@@ -1,15 +1,11 @@
 using DotNetCore.CAP;
-using Hotline.Push.Notifies;
 using Hotline.Share.Dtos.Push;
 using Hotline.Share.Dtos.Push.FWMessage;
 using Hotline.Share.Enums.Push;
 using MapsterMapper;
 using MediatR;
 using Microsoft.Extensions.Configuration;
-using System.Net;
 using System.Text.RegularExpressions;
-using System.Xml;
-using XF.Domain.Cache;
 using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
@@ -28,8 +24,8 @@ public class PushDomainService : IPushDomainService, IScopeDependency
     private readonly IConfiguration _config;
     private readonly SmsAccountInfo? accountInfo = null;
     private readonly IMediator _mediator;
-    private readonly ITypedCache<CacheWaitSendId> _cacheWaitSendId;
     private readonly IRepository<MessageTemplate> _messageTemplateRepository;
+    private readonly ICapPublisher _capPublisher;
 
     /// <summary>
     /// 
@@ -40,10 +36,11 @@ public class PushDomainService : IPushDomainService, IScopeDependency
     /// <param name="config"></param>
     /// <param name="mediator"></param>
     /// <param name="cacheWaitSendId"></param>
+    /// <param name="messageTemplateRepository"></param>
+    /// <param name="capPublisher"></param>
     public PushDomainService(IRepository<Message> messageRepository, IHttpClientFactory httpClientFactory
         , IMapper mapper, IConfiguration config, IMediator mediator,
-        ITypedCache<CacheWaitSendId> cacheWaitSendId,
-        IRepository<MessageTemplate> messageTemplateRepository)
+        IRepository<MessageTemplate> messageTemplateRepository, ICapPublisher capPublisher)
     {
         _messageRepository = messageRepository;
         _httpClientFactory = httpClientFactory;
@@ -51,370 +48,106 @@ public class PushDomainService : IPushDomainService, IScopeDependency
         _config = config;
         accountInfo = _config.GetSection("SmsAccountInfo").Get<SmsAccountInfo>();
         _mediator = mediator;
-        _cacheWaitSendId = cacheWaitSendId;
         _messageTemplateRepository = messageTemplateRepository;
+        _capPublisher = capPublisher;
     }
     #endregion
 
-
-
-    #region 短信发送
     /// <summary>
     /// 短信发送
     /// </summary>
     /// <param name="messageDto"></param>
     /// <param name="cancellation"></param>
     /// <returns></returns>
-    public async Task PushAsync(MessageDto messageDto, CancellationToken cancellation)
+    public async Task PushMsgAsync(MessageDto messageDto, CancellationToken cancellation)
     {
         if (messageDto == null)
             throw UserFriendlyException.SameMessage("消息不能为空!");
 
-        if (string.IsNullOrEmpty(messageDto.Template) && string.IsNullOrEmpty(messageDto.Content))
+        if (string.IsNullOrEmpty(messageDto.TemplateCode) && string.IsNullOrEmpty(messageDto.Content))
             throw UserFriendlyException.SameMessage("模板和内容不能同时为空!");
 
-        Message message = new();
-        int WaitSendId = 0;
-        var sendData = await _messageRepository.GetAsync(p => p.ExternalId == messageDto.ExternalId && p.PushBusiness == messageDto.PushBusiness && p.TelNumber == messageDto.TelNumber);
-        if (sendData != null)//处理重复数据
-        {
-            WaitSendId = sendData.WaitSendId;
-            messageDto = _mapper.Map<MessageDto>(sendData);
-            message = sendData;
-        }
-        else
-        {
-
-            #region 替换模板内容
-            string reason = null;
-            //如果模板为空,参数为空则直接用短信内容
-            if (!string.IsNullOrEmpty(messageDto.Template) && messageDto.Params.Count > 0)
-            {
-                //查询模板信息
-                var messageTemplate = await _messageTemplateRepository.GetAsync(p => p.Code == messageDto.Template, cancellation);
-                if (messageTemplate == null || string.IsNullOrEmpty(messageTemplate.Content))
-                    throw UserFriendlyException.SameMessage("未找到模板短信!");
-
-                string Template = messageTemplate.Content;
-                //正则查询模板中需要替换的内容
-                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
-            message = _mapper.Map<Message>(messageDto);
-            WaitSendId = GenerateWaitSendId();
-            message.WaitSendId = WaitSendId;
-            message.Reason = reason;
-        }
-
-        //调用短信发送业务
-        var strResult = await SmsSend(messageDto, WaitSendId);
-
-        //处理返回值
-        if (true == strResult.Contains("ok,"))  // ok,35797257
-        {
-            string[] strArray = strResult.Split(',');
-            if (2 == strArray.Length)
-            {
-                // 短信服务中心返回 IFSFWID,用于短信发送状态接收时匹配
-                message.SmsWaitSendingId = strArray[1];
-                message.SendState = ESendState.Sending;
-                message.Status = EPushStatus.Success;
-            }
-        }
-        else
-        {
-            message.Reason = strResult;
-            message.Status = EPushStatus.Failed;
-        }
-        if (sendData != null)
-            await _messageRepository.UpdateAsync(message);//跟新本地数据库
-        else
-            await _messageRepository.AddAsync(message);//写入本地数据库
-    }
-
-    #endregion
-
-    #region 查询账号短信剩余量
-    /// <summary>
-    /// 查询账号短信剩余量
-    /// </summary>
-    /// <returns></returns>
-    public async Task<string> GetAccountNum()
-    {
-        // 账户,密码
-        string strAcceptContent = $"{accountInfo.AccountUser},{accountInfo.AccountPwd}";
-        // 参数
-        Dictionary<string, string> dicParam = new()
-        {
-            { "AcceptType", "fwAccountNum" },
-            { "AcceptContent", strAcceptContent }
+        #region 替换模板内容
+        //如果模板为空,参数为空则直接用短信内容
+        if (!string.IsNullOrEmpty(messageDto.TemplateCode) && messageDto.Params.Count > 0)
+        {
+            //查询模板信息
+            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;
+            //正则查询模板中需要替换的内容
+            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<Message>(messageDto);
+        var id = await _messageRepository.AddAsync(message);//写入本地数据库
+
+        PushMessageDto pushMessage = new()
+        {
+            ClientId = "Hotline",
+            ExternalId = id,
+            Content = message.Content,
+            Remark = message.Remark,
+            Name = message.Name,
+            TelNumber = message.TelNumber
         };
-        // 将参数转化为HttpContent
-        HttpContent content = new FormUrlEncodedContent(dicParam);
-        // ok,9
-        // error,查询异常
-        string strResult = await PostHelper(accountInfo.MessageServerUrl, content);
-        var strArray = strResult.Split(",");
-        if (2 == strArray.Length)
-        {
-            strResult = strArray[1];
-        }
-        else
-        {
-            strResult = "查询异常";
-        }
-        return strResult;
-    }
-    #endregion
 
-    #region 短信发送状态回调接口
-    /// <summary>
-    /// 短信发送状态回调接口
-    /// </summary>
-    /// <param name="receiveMessageDto"></param>
-    /// <returns></returns>
-    public async Task<string> ReceiveObtain(ReceiveMessageDto receiveMessageDto)
-    {
-        string strResult = "error,缺少参数";
-        if (receiveMessageDto.account != accountInfo.ReturnAccountUser || receiveMessageDto.pswd != accountInfo.ReturnAccountPwd)
-        {
-            strResult = "error,参数错误";
-            return strResult;
-        }
-        if (true == string.IsNullOrEmpty(receiveMessageDto.account) || true == string.IsNullOrEmpty(receiveMessageDto.pswd)
-            || true == string.IsNullOrEmpty(receiveMessageDto.msgid) || true == string.IsNullOrEmpty(receiveMessageDto.sendtime)
-            || receiveMessageDto.msgcount <= 0 || receiveMessageDto.state < 0)
-        {
-            strResult = "error,参数错误";
-            return strResult;
-        }
-        //修改数据
-        var data = await _messageRepository.GetAsync(p => p.SmsWaitSendingId == receiveMessageDto.msgid);
-        if (data != null)
-        {
-            data.SendTime = Convert.ToDateTime(receiveMessageDto.sendtime);
-            data.MsgCount = receiveMessageDto.msgcount;
-            data.SendState = (ESendState)receiveMessageDto.state;
-            data.SmsSendingCompletedId = receiveMessageDto.sfid + "";
-            data.Reason = receiveMessageDto.errormsg;
-            await _messageRepository.UpdateAsync(data);
-            // 成功返回值必须是ok
-            strResult = "ok";
-        }
-        else
-            strResult = "error,调用失败";
-        return strResult;
+        await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.SendSms, pushMessage, cancellationToken: cancellation);
     }
 
-    #endregion
-
-    #region 短信接收
     /// <summary>
-    /// 短信接收
+    /// 修改短信推送状态
     /// </summary>
-    /// <param name="receiveMessageDto"></param>
+    /// <param name="dto"></param>
+    /// <param name="cancellation"></param>
     /// <returns></returns>
-    public async Task<string> ReceiveSms(ReceiveMessageDto receiveMessageDto)
+    public async Task PushMsgUpdateStateAsync(PushReceiveMessageDto dto, CancellationToken cancellation)
     {
-        string strResult = "error,缺少参数";
-        if (receiveMessageDto.account != accountInfo.ReturnAccountUser || receiveMessageDto.pswd != accountInfo.ReturnAccountPwd)
-        {
-            strResult = "error,参数错误";
-            return strResult;
-        }
-        if (true == string.IsNullOrEmpty(receiveMessageDto.account) || true == string.IsNullOrEmpty(receiveMessageDto.pswd)
-            || true == string.IsNullOrEmpty(receiveMessageDto.msg) || true == string.IsNullOrEmpty(receiveMessageDto.mobile)
-            || true == string.IsNullOrEmpty(receiveMessageDto.motime))
-        {
-            strResult = "error,参数错误";
-            return strResult;
-        }
-
-        var data = await _messageRepository.GetAsync(p => p.TelNumber == receiveMessageDto.mobile && p.IsSmsReply == false && p.SmsReplyTime == null);
+        var data = await _messageRepository.GetAsync(p => p.Id == dto.ExternalId, cancellation);
         if (data != null)
         {
-            data.IsSmsReply = true;
-            data.SmsReplyTime = Convert.ToDateTime(receiveMessageDto.motime);
-            data.SmsReplyContent = receiveMessageDto.msg;
-            await _messageRepository.UpdateAsync(data);
-
-            //消息处理
-            await _mediator.Publish(new PushMessageNotify(_mapper.Map<PushMessageNotifyDto>(data)));
-
-        }
-        // 成功返回值必须是ok
-        strResult = "ok";
-
-        return strResult;
-
-    }
-
-    #endregion
-
-    #region 私有方法
-
-    #region 短信发送
-    /// <summary>
-    /// 短信发送
-    /// </summary>
-    /// <returns></returns>
-    private async Task<string> SmsSend(MessageDto messageDto, int WaitSendId)
-    {
-        string strResult;
-        try
-        {
-            SendSmsModelDto tSms = new()
+            if (dto.Type == "0")
             {
-                // 业务系统短信ID
-                nWaitID = WaitSendId,
-                // 短信类型1:默认2:营销
-                strType = "1",
-                // 业务系统工单ID
-                nFlowID = 0,
-                // 姓名
-                strPhoneName = messageDto.Name,
-                // 手机号码
-                strPhoneNumber = messageDto.TelNumber,
-                // 短信内容
-                strPhoneConnent = messageDto.Content,
-                // 添加时间
-                dAddTime = DateTime.Now,
-                strPhoneNumberAll = "",
-                strRemark = "",
-                // 业务系统添加人ID
-                nUserID = 0,
-                // 业务系统添加人姓名
-                strUserName = "",
-                // 业务系统添加部门ID
-                nBMID = 0,
-                // 业务系统添加部门名称
-                strBMName = "",
-                // 短信系统账号
-                strAccountUser = accountInfo.AccountUser,
-                // 短信系统密码
-                strAccountPwd = accountInfo.AccountPwd
-            };
-            // 序列化
-            string strSendJson = Newtonsoft.Json.JsonConvert.SerializeObject(tSms);//System.Text.Json.JsonSerializer.Serialize(tSms);//
-
-            // 参数加密
-            string strKey = await FwEncrypt(strSendJson);
-            // 短信发送参数
-            Dictionary<string, string> dicParam = new Dictionary<string, string>
-            {
-                { "AcceptType", "fwSms" },
-                { "AcceptContent", strKey }
-            };
-            // 将参数转化为HttpContent
-            HttpContent content = new FormUrlEncodedContent(dicParam);
-            strResult = await PostHelper(accountInfo.MessageServerUrl, content);
-        }
-        catch (Exception ex)
-        {
-            strResult = ex.Message;
-        }
-        return strResult;
-    }
-    #endregion
-
-    #region 参数加密
-    /// <summary>
-    /// 参数加密
-    /// </summary>
-    /// <param name="planText"></param>
-    /// <returns></returns>
-    private async Task<string> FwEncrypt(string planText)
-    {
-        // 参数
-        Dictionary<string, string> dicParam = new Dictionary<string, string>();
-        dicParam.Add("AcceptType", "fwEncrypt");
-        dicParam.Add("AcceptContent", planText);
-        // 将参数转化为HttpContent
-        HttpContent content = new FormUrlEncodedContent(dicParam);
-        string strResult = await PostHelper(accountInfo.MessageServerUrl, content);
-        string strValue = "";
-        // ok,XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-        if (true == strResult.Contains("ok,"))
-        {
-            string[] strArray = strResult.Split(',');
-            if (2 == strArray.Length)
+                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")
             {
-                strValue = strArray[1];
+                data.SendTime = Convert.ToDateTime(dto.SendTime);
+                data.SendState = dto.SendState;
+                data.MsgCount = dto.MsgCount;
+                data.SmsSendingCompletedId = dto.SmsSendingCompletedId;
             }
-        }
-        return strValue;
-    }
-    #endregion
-
-    #region http请求
-    /// <summary>
-    /// 封装使用HttpClient调用WebService
-    /// </summary>
-    /// <param name="url">URL地址</param>
-    /// <param name="content">参数</param>
-    /// <returns></returns>
-    private async Task<string> PostHelper(string url, HttpContent content)
-    {
-        var result = string.Empty;
-        try
-        {
-            using (var client = _httpClientFactory.CreateClient())
-            using (var response = await client.PostAsync(url, content))
+            else if (dto.Type == "2")
             {
-                if (response.StatusCode == HttpStatusCode.OK)
-                {
-                    result = await response.Content.ReadAsStringAsync();
-                    XmlDocument doc = new XmlDocument();
-                    doc.LoadXml(result);
-                    result = doc.InnerText;
-                }
+                data.IsSmsReply = dto.IsSmsReply;
+                data.SmsReplyTime = Convert.ToDateTime(dto.SmsReplyTime);
+                data.SmsReplyContent = dto.SmsReplyContent;
             }
+
+            await _messageRepository.UpdateAsync(data, cancellation);
         }
-        catch (Exception ex)
-        {
-            result = ex.Message;
-        }
-        return result;
     }
-    #endregion
 
-    #region 生成待发短信ID缓存
-    /// <summary>
-    /// 生成待发短信ID缓存
-    /// </summary>
-    /// <returns></returns>
-    private int GenerateWaitSendId()
-    {
-        var cacheKey = "PushMessageWaitSendId";
-        var cacheWaitSend = _cacheWaitSendId.GetOrSet(cacheKey, f =>
-        {
-            var waitSendId = _messageRepository.Queryable()
-                .MaxAsync(p => p.WaitSendId)
-                .GetAwaiter()
-                .GetResult();
-            return new CacheWaitSendId { WaitSendId = waitSendId };
-        }, TimeSpan.FromDays(1));
-        cacheWaitSend!.WaitSendId += 1;
 
-        _cacheWaitSendId.Set(cacheKey, cacheWaitSend);
-        return cacheWaitSend.WaitSendId;
-    }
 
-    public class CacheWaitSendId
-    {
-        public int WaitSendId { get; set; }
-    }
-    #endregion
-    #endregion
 }

+ 1 - 1
src/Hotline/Push/Notifies/PushMessageNotify.cs

@@ -3,5 +3,5 @@ using MediatR;
 
 namespace Hotline.Push.Notifies
 {
-    public record PushMessageNotify(PushMessageNotifyDto NotifyDto) : INotification;
+    public record PushMessageNotify(MessageDto NotifyDto) : INotification;
 }