Selaa lähdekoodia

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

tangjiang 10 kuukautta sitten
vanhempi
commit
c0b71ede1f

+ 10 - 4
src/Push.Share/Enums/EPushStatus.cs

@@ -7,21 +7,27 @@ namespace Push.Share.Enums;
 /// </summary>
 public enum EPushStatus
 {
+    /// <summary>
+    /// 
+    /// </summary>
+    [Description("待推送")]
+    Waiting = 0,
+
     /// <summary>
     /// 
     /// </summary>
     [Description("推送中")]
-    Pushing = 0,
+    Pushing = 1,
 
     /// <summary>
     /// 
     /// </summary>
     [Description("推送成功")]
-    Success = 1,
+    Success = 2,
 
     /// <summary>
     /// 
     /// </summary>
     [Description("推送失败")]
-    Failed = 2
-}
+    Failed = 3
+}

+ 14 - 1
src/yibin/Push.YiBin.Host/Controllers/PushMessageController.cs

@@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
 using Push.Share.Dtos;
 using Push.Share.Dtos.FWMessage;
+using Push.YiBin.Dtos;
 using XF.Domain.Filters;
 using XF.Domain.Repository;
 
@@ -31,6 +32,19 @@ namespace Push.YiBin.Host.Controllers
 
         #endregion
 
+        /// <summary>
+        /// 新增代发短信
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("addwaitmsg")]
+        [AllowAnonymous]
+        public async Task<Reponse> AddWaitMessage([FromBody] WaitMessageDto dto)
+        {
+            return await _pushDomainService.AddWaitMessage(_mapper.Map<WaitMessage>(dto), HttpContext.RequestAborted);
+        }
+
+
         #region 新增
 
         /// <summary>
@@ -54,7 +68,6 @@ namespace Push.YiBin.Host.Controllers
         /// </summary>
         /// <returns></returns>
         [HttpGet("query")]
-        [AllowAnonymous]
         public async Task<string> GetAccountNum()
         {
             return await _pushDomainService.GetAccountNum();

+ 1 - 0
src/yibin/Push.YiBin.Host/Push.YiBin.Host.csproj

@@ -8,6 +8,7 @@
 
   <ItemGroup>
     <PackageReference Include="Mapster.DependencyInjection" Version="1.0.1" />
+    <PackageReference Include="Quartz.AspNetCore" Version="3.9.0" />
     <PackageReference Include="Serilog.Sinks.Grafana.Loki" Version="8.1.0" />
     <PackageReference Include="Serilog.Sinks.MongoDB" Version="5.3.1" />
     <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />

+ 4 - 0
src/yibin/Push.YiBin.Host/StartupExtensions.cs

@@ -26,6 +26,8 @@ internal static class StartupExtensions
 
         services.AddHttpClient();
 
+        services.Configure<ChannelConfiguration>(d => configuration.GetSection(nameof(ChannelConfiguration)).Bind(d));
+
         // services.Configure<ChannelConfiguration>(d => configuration.GetSection(nameof(ChannelConfiguration)).Bind(d));
 
         // Add services to the container.
@@ -80,6 +82,8 @@ internal static class StartupExtensions
         //mq
         services.AddMq(configuration);
 
+        services.RegisterJob();
+
         return builder.Build();
     }
 

+ 34 - 0
src/yibin/Push.YiBin.Host/StartupHelper.cs

@@ -3,6 +3,8 @@ using MapsterMapper;
 using Microsoft.OpenApi.Models;
 using XF.Domain.Entities;
 using XF.Domain.Repository;
+using Quartz;
+using Quartz.AspNetCore;
 namespace Push.YiBin.Host
 {
     public static class StartupHelper
@@ -112,6 +114,38 @@ namespace Push.YiBin.Host
             return services;
         }
 
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="services"></param>
+        /// <returns></returns>
+        public static IServiceCollection RegisterJob(this IServiceCollection services)
+        {
+            services.AddQuartz(d =>
+            {
+                d.SchedulerId = "scheduler1";
+                d.InterruptJobsOnShutdown = true;
+                d.InterruptJobsOnShutdownWithWait = true;
+                d.MaxBatchSize = 3;
 
+                //服务工单受理  
+                var taskSendMessageJobKey = new JobKey("task-send-message-job", "task send message job");
+                d.AddJob<TaskSendMessageJob>(taskSendMessageJobKey);
+                d.AddTrigger(t => t
+                    .WithIdentity("task-send-message-trigger")
+                    .ForJob(taskSendMessageJobKey)
+                    .StartNow()
+                    .WithCronSchedule("0/5 * * * * ? ")
+                );
+            });
+
+            services.AddQuartzServer(d =>
+            {
+                d.WaitForJobsToComplete = true;
+                d.StartDelay = TimeSpan.FromSeconds(5);
+            });
+
+            return services;
+        }
     }
 }

+ 5 - 0
src/yibin/Push.YiBin.Host/config/appsettings.Development.json

@@ -41,5 +41,10 @@
       "HostName": "110.188.24.182",
       "VirtualHost": "fwt-master"
     }
+  },
+  //系统配置
+  "ChannelConfiguration": {
+    "ProcessingServices": "Services1", //服务名称
+    "HotlineAddressUrl": "http://localhost:50100/" //推送地址
   }
 }

+ 6 - 0
src/yibin/Push.YiBin.Host/config/appsettings.json

@@ -41,5 +41,11 @@
       "HostName": "110.188.24.182",
       "VirtualHost": "fwt-master"
     }
+  },
+
+  //系统配置
+  "ChannelConfiguration": {
+    "ProcessingServices": "Services1", //服务名称
+    "HotlineAddressUrl": "http://110.188.24.28:50100/" //推送地址
   }
 }

+ 47 - 0
src/yibin/Push.YiBin/BaseHttpInvoker.cs

@@ -0,0 +1,47 @@
+using Microsoft.AspNetCore.Http;
+using System.Net.Http.Headers;
+using System.Text;
+using XF.Domain.Dependency;
+using XF.Domain.Exceptions;
+
+namespace Push.YiBin
+{
+    public class BaseHttpInvoker : IHttpInvoker, IScopeDependency
+    {
+        private readonly IHttpClientFactory _httpClientFactory;
+
+        public BaseHttpInvoker(IHttpClientFactory httpClientFactory)
+        {
+            _httpClientFactory = httpClientFactory;
+        }
+
+        public async Task<TResponse?> RequestStringContentAsync<TResponse>(string url, string httpMethod, string? stringContent = null,
+     Action<HttpClient>? setHttpClient = null, CancellationToken cancellationToken = default)
+        {
+            var httpClient = _httpClientFactory.CreateClient();
+
+            if (setHttpClient != null)
+                setHttpClient.Invoke(httpClient);
+
+            var rsp = string.Empty;
+            if (HttpMethods.IsGet(httpMethod))
+            {
+                rsp = await httpClient.GetStringAsync(url, cancellationToken);
+            }
+            else if (HttpMethods.IsPost(httpMethod))
+            {
+                using var responseMessage = await httpClient.PostAsync(url, new StringContent(stringContent, Encoding.UTF8, new MediaTypeWithQualityHeaderValue("application/json")),
+                    cancellationToken);
+                responseMessage.EnsureSuccessStatusCode();
+                using var responseContent = responseMessage.Content;
+                rsp = await responseContent.ReadAsStringAsync(cancellationToken);
+            }
+            else
+            {
+                throw new UserFriendlyException("暂不支持该请求方式");
+            }
+
+            return System.Text.Json.JsonSerializer.Deserialize<TResponse>(rsp);
+        }
+    }
+}

+ 15 - 0
src/yibin/Push.YiBin/ChannelConfiguration.cs

@@ -0,0 +1,15 @@
+namespace Push.YiBin
+{
+    public class ChannelConfiguration
+    {
+        /// <summary>
+        /// 服务名称
+        /// </summary>
+        public string ProcessingServices { get; set; }
+
+        /// <summary>
+        /// 短信推送地址
+        /// </summary>
+        public string HotlineAddressUrl { get; set; }
+    }
+}

+ 37 - 0
src/yibin/Push.YiBin/ChannelConfigurationManager.cs

@@ -0,0 +1,37 @@
+using Microsoft.Extensions.Options;
+using XF.Domain.Dependency;
+
+namespace Push.YiBin
+{
+    public class ChannelConfigurationManager : IChannelConfigurationManager, IScopeDependency
+    {
+        private readonly IOptionsSnapshot<ChannelConfiguration> _channelOption;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="channelOption"></param>
+        public ChannelConfigurationManager(IOptionsSnapshot<ChannelConfiguration> channelOption)
+        {
+            _channelOption = channelOption;
+        }
+
+        /// <summary>
+        /// 获取服务名称
+        /// </summary>
+        /// <returns></returns>
+        public string GetConfigurationProcessingServices()
+        {
+            return _channelOption.Value.ProcessingServices;
+        }
+
+        /// <summary>
+        /// 获取短信推送地址
+        /// </summary>
+        /// <returns></returns>
+        public string GetConfigurationHotlineAddressUrl()
+        {
+            return _channelOption.Value.HotlineAddressUrl;
+        }
+    }
+}

+ 11 - 0
src/yibin/Push.YiBin/Dtos/Reponse.cs

@@ -0,0 +1,11 @@
+namespace Push.YiBin.Dtos
+{
+    public class Reponse
+    {
+        public int Code { get; set; }
+
+        public string Message { get; set; }
+
+        public string Error { get; set; }
+    }
+}

+ 36 - 0
src/yibin/Push.YiBin/Dtos/WaitMessageDto.cs

@@ -0,0 +1,36 @@
+namespace Push.YiBin.Dtos
+{
+    public class WaitMessageDto
+    {
+        /// <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; }
+
+    }
+}

+ 58 - 0
src/yibin/Push.YiBin/FwClient.cs

@@ -0,0 +1,58 @@
+using Microsoft.Extensions.DependencyInjection;
+using XF.Domain.Dependency;
+using XF.Domain.Exceptions;
+
+namespace Push.YiBin
+{
+    public class FwClient : ISingletonDependency, ISelfDependency
+    {
+        private readonly IServiceScopeFactory _scopeFactory;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="scopeFactory"></param>
+        public FwClient(IServiceScopeFactory scopeFactory)
+        {
+            _scopeFactory = scopeFactory;
+        }
+
+        /// <summary>
+        /// 请求,不带token
+        /// </summary>
+        /// <typeparam name="TResponse"></typeparam>
+        /// <param name="url"></param>
+        /// <param name="httpMethod"></param>
+        /// <param name="stringContent"></param>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
+        public async Task<TResponse?> RequestNoTokenAsync<TResponse>(string url, string httpMethod, string? stringContent = null, CancellationToken cancellationToken = default)
+        {
+            using var scope = _scopeFactory.CreateScope();
+            var provider = scope.ServiceProvider;
+            var channelconfigManager = provider.GetRequiredService<IChannelConfigurationManager>();
+            var httpInvoker = provider.GetRequiredService<IHttpInvoker>();
+
+            var configHotlineClient = channelconfigManager.GetConfigurationHotlineAddressUrl();
+            if (!configHotlineClient.EndsWith('/'))
+                configHotlineClient += "/";
+            var postUrl = configHotlineClient + url;
+            return await httpInvoker.RequestStringContentAsync<TResponse>(postUrl, httpMethod, stringContent,
+                d => d.SetHttpClient(configHotlineClient), cancellationToken);
+        }
+    }
+
+    public static class HttpClientExtensions
+    {
+        public static HttpClient SetHttpClient(this HttpClient httpClient, string baseAddress) =>
+          httpClient.SetBaseAddress(baseAddress);
+
+        public static HttpClient SetBaseAddress(this HttpClient httpClient, string baseAddress)
+        {
+            if (string.IsNullOrEmpty(baseAddress))
+                throw new UserFriendlyException("无效 base address");
+            httpClient.BaseAddress = new Uri(baseAddress);
+            return httpClient;
+        }
+    }
+}

+ 17 - 0
src/yibin/Push.YiBin/IChannelConfigurationManager.cs

@@ -0,0 +1,17 @@
+namespace Push.YiBin
+{
+    public interface IChannelConfigurationManager
+    {
+        /// <summary>
+        /// 获取服务名称
+        /// </summary>
+        /// <returns></returns>
+        string GetConfigurationProcessingServices();
+
+        /// <summary>
+        /// 获取短信推送地址
+        /// </summary>
+        /// <returns></returns>
+        string GetConfigurationHotlineAddressUrl();
+    }
+}

+ 9 - 0
src/yibin/Push.YiBin/IHttpInvoker.cs

@@ -0,0 +1,9 @@
+namespace Push.YiBin
+{
+    public partial interface IHttpInvoker
+    {
+        Task<TResponse?> RequestStringContentAsync<TResponse>(
+            string url, string httpMethod, string? stringContent = null,
+            Action<HttpClient>? setHttpClient = null, CancellationToken cancellationToken = default);
+    }
+}

+ 16 - 0
src/yibin/Push.YiBin/IPushDomainService.cs

@@ -1,11 +1,27 @@
 using DotNetCore.CAP;
 using Push.Share.Dtos;
 using Push.Share.Dtos.FWMessage;
+using Push.YiBin.Dtos;
 
 namespace Push.YiBin
 {
     public interface IPushDomainService
     {
+        /// <summary>
+        /// 短信写入待发表
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <param name="cancellation"></param>
+        /// <returns></returns>
+        Task<Reponse> AddWaitMessage(WaitMessage dto, CancellationToken cancellation);
+
+        /// <summary>
+        /// 短信发送
+        /// </summary>
+        /// <param name="messageDto"></param>
+        /// <returns></returns>
+        Task<Message> PushNewAsync(Share.Dtos.MessageDto messageDto);
+
         /// <summary>
         /// 短信发送
         /// </summary>

+ 5 - 0
src/yibin/Push.YiBin/Message.cs

@@ -109,5 +109,10 @@ namespace Push.YiBin
         [SugarColumn(ColumnDescription = "发送失败原因等", ColumnDataType = "varchar(200)", IsNullable = true)]
         public string? Reason { get; set; }
 
+        /// <summary>
+        /// 读取服务名称
+        /// </summary>
+        [SugarColumn(ColumnDescription = "读取服务名称")]
+        public string? ProcessingServices { get; set; }
     }
 }

+ 1 - 0
src/yibin/Push.YiBin/Push.YiBin.csproj

@@ -9,6 +9,7 @@
     <ItemGroup>
         <PackageReference Include="Mapster" Version="7.3.0" />
         <PackageReference Include="MediatR" Version="12.0.1" />
+        <PackageReference Include="Quartz.Jobs" Version="3.9.0" />
         <PackageReference Include="System.Linq.Dynamic.Core" Version="1.3.7" />
       <PackageReference Include="XF.Domain.Repository" Version="1.0.6" />
       <PackageReference Include="XF.EasyCaching" Version="1.0.6" />

+ 133 - 20
src/yibin/Push.YiBin/PushDomainService.cs

@@ -2,12 +2,13 @@
 using MapsterMapper;
 using MediatR;
 using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
 using Push.Share.Dtos;
 using Push.Share.Dtos.FWMessage;
 using Push.Share.Enums;
+using Push.YiBin.Dtos;
 using System.Net;
 using System.Xml;
-using Microsoft.Extensions.Logging;
 using XF.Domain.Cache;
 using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
@@ -30,6 +31,8 @@ public class PushDomainService : IPushDomainService, IScopeDependency
     private readonly ITypedCache<CacheWaitSendId> _cacheWaitSendId;
     private readonly ICapPublisher _capPublisher;
     private readonly ILogger<PushDomainService> _logger;
+    private readonly IRepository<WaitMessage> _waitMessageRepository;
+    private readonly FwClient _fwClient;
 
     /// <summary>
     /// 
@@ -45,7 +48,9 @@ public class PushDomainService : IPushDomainService, IScopeDependency
         , IMapper mapper, IConfiguration config, IMediator mediator,
         ITypedCache<CacheWaitSendId> cacheWaitSendId,
         ICapPublisher capPublisher,
-        ILogger<PushDomainService> logger)
+        ILogger<PushDomainService> logger,
+        IRepository<WaitMessage> waitMessageRepository,
+       FwClient fwClient)
     {
         _messageRepository = messageRepository;
         _httpClientFactory = httpClientFactory;
@@ -56,10 +61,104 @@ public class PushDomainService : IPushDomainService, IScopeDependency
         _cacheWaitSendId = cacheWaitSendId;
         _capPublisher = capPublisher;
         _logger = logger;
+        _waitMessageRepository = waitMessageRepository;
+        _fwClient = fwClient;
     }
 
     #endregion
 
+    #region 短信发送---新版
+    /// <summary>
+    /// 短信写入待发表
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <param name="cancellation"></param>
+    /// <returns></returns>
+    public async Task<Reponse> AddWaitMessage(WaitMessage dto, CancellationToken cancellation)
+    {
+        Reponse reponse = new Reponse() { Code = 1 };
+        if (dto == null)
+        {
+            reponse.Message = "消息不能为空!";
+            return reponse;
+        }
+
+
+        if (string.IsNullOrEmpty(dto.ClientId))
+        {
+            reponse.Message = "发送平台不能为空!";
+            return reponse;
+        }
+
+        if (string.IsNullOrEmpty(dto.TelNumber))
+        {
+            reponse.Message = "短信接收号码不能为空!";
+            return reponse;
+        }
+
+        if (string.IsNullOrEmpty(dto.Name))
+        {
+            reponse.Message = "接收姓名不能为空!";
+            return reponse;
+        }
+
+        if (string.IsNullOrEmpty(dto.Content))
+        {
+            reponse.Message = "短信内容不能为空!";
+            return reponse;
+        }
+
+        var id = await _waitMessageRepository.AddAsync(dto, cancellation);
+        if (string.IsNullOrEmpty(id))
+        {
+            reponse.Message = "新增失败!";
+            return reponse;
+        }
+        else
+        {
+            reponse.Code = 0;
+            reponse.Message = "新增成功!";
+            return reponse;
+
+        }
+    }
+
+    /// <summary>
+    /// 短信发送
+    /// </summary>
+    /// <param name="messageDto"></param>
+    /// <returns></returns>
+    public async Task<Message> PushNewAsync(Share.Dtos.MessageDto messageDto)
+    {
+        var message = _mapper.Map<Message>(messageDto);
+        int WaitSendId = GenerateWaitSendId();
+        message.WaitSendId = WaitSendId;
+
+        _logger.LogInformation($"取到WaitSendId值:{WaitSendId}"+DateTime.Now);
+
+        //调用短信发送业务
+        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;
+        }
+        return message;
+    }
+    #endregion
 
     #region 短信发送
 
@@ -69,7 +168,7 @@ public class PushDomainService : IPushDomainService, IScopeDependency
     /// <param name="messageDto"></param>
     /// <param name="cancellation"></param>
     /// <returns></returns>
-    public async Task PushAsync(MessageDto messageDto, CancellationToken cancellation)
+    public async Task PushAsync(Share.Dtos.MessageDto messageDto, CancellationToken cancellation)
     {
         if (messageDto == null)
             throw UserFriendlyException.SameMessage("消息不能为空!");
@@ -115,12 +214,12 @@ public class PushDomainService : IPushDomainService, IScopeDependency
 
         await _messageRepository.AddAsync(message, cancellation); //写入本地数据库
 
-        if (message.ClientId == "Hotline")
-        {
-            var data = _mapper.Map<PushMessageDto>(message);
-            data.Type = "0";
-            await _capPublisher.PublishAsync(Push.Share.EventNames.UpdateSendSmsState, data, cancellationToken: cancellation);
-        }
+        //if (message.ClientId == "Hotline")
+        //{
+        //    var data = _mapper.Map<PushMessageDto>(message);
+        //    data.Type = "0";
+        //    await _capPublisher.PublishAsync(Push.Share.EventNames.UpdateSendSmsState, data, cancellationToken: cancellation);
+        //}
     }
 
     #endregion
@@ -196,11 +295,18 @@ public class PushDomainService : IPushDomainService, IScopeDependency
             data.Reason = receiveMessageDto.errormsg;
             await _messageRepository.UpdateAsync(data);
 
-            if (data.ClientId == "Hotline")
+            try
             {
-                var dataPush = _mapper.Map<PushMessageDto>(data);
-                dataPush.Type = "1";
-                await _capPublisher.PublishAsync(Push.Share.EventNames.UpdateSendSmsState, dataPush, cancellationToken: default);
+                if (data.ClientId == "Hotline")
+                {
+                    var dataPush = _mapper.Map<PushMessageDto>(data);
+                    dataPush.Type = "1";
+                    await _fwClient.RequestNoTokenAsync<Reponse>("api/v1/PushMessage/update-send-sms-state", "Post", System.Text.Json.JsonSerializer.Serialize(dataPush), cancellationToken: default);
+                }
+            }
+            catch (Exception)
+            {
+
             }
         }
         // 成功返回值必须是ok
@@ -242,11 +348,18 @@ public class PushDomainService : IPushDomainService, IScopeDependency
             data.SmsReplyTime = Convert.ToDateTime(receiveMessageDto.motime);
             data.SmsReplyContent = receiveMessageDto.msg;
             await _messageRepository.UpdateAsync(data);
-            if (data.ClientId == "Hotline")
+            try
             {
-                var dataPush = _mapper.Map<PushMessageDto>(data);
-                dataPush.Type = "2";
-                await _capPublisher.PublishAsync(Push.Share.EventNames.UpdateSendSmsState, dataPush, cancellationToken: default);
+                if (data.ClientId == "Hotline")
+                {
+                    var dataPush = _mapper.Map<PushMessageDto>(data);
+                    dataPush.Type = "2";
+                    await _fwClient.RequestNoTokenAsync<Reponse>("api/v1/PushMessage/update-send-sms-state", "Post", System.Text.Json.JsonSerializer.Serialize(dataPush), cancellationToken: default);
+                }
+            }
+            catch (Exception)
+            {
+
             }
         }
 
@@ -266,9 +379,9 @@ public class PushDomainService : IPushDomainService, IScopeDependency
     /// 短信发送
     /// </summary>
     /// <returns></returns>
-    private async Task<string> SmsSend(MessageDto messageDto, int WaitSendId)
+    private async Task<string> SmsSend(Share.Dtos.MessageDto messageDto, int WaitSendId)
     {
-        _logger.LogInformation("准备短信推送");
+        _logger.LogInformation("准备短信推送---------------------"+DateTime.Now);
         string strResult;
         try
         {
@@ -371,7 +484,7 @@ public class PushDomainService : IPushDomainService, IScopeDependency
     /// <returns></returns>
     private async Task<string> PostHelper(string url, HttpContent content)
     {
-        _logger.LogInformation($"准备推送短信, {nameof(PostHelper)}");
+        _logger.LogInformation($"准备推送短信, {nameof(PostHelper)}"+DateTime.Now);
         var result = string.Empty;
         try
         {

+ 94 - 0
src/yibin/Push.YiBin/TaskSendMessageJob.cs

@@ -0,0 +1,94 @@
+using MapsterMapper;
+using Microsoft.Extensions.Logging;
+using Push.Share.Enums;
+using Quartz;
+
+namespace Push.YiBin
+{
+    public class TaskSendMessageJob : IJob, IDisposable
+    {
+        private readonly IMapper _mapper;
+        private readonly ILogger<TaskSendMessageJob> _logger;
+        private readonly IRepository<Message> _messageRepository;
+        private readonly IRepository<WaitMessage> _waitMessageRepository;
+        private readonly IPushDomainService _pushDomainService;
+        private readonly IChannelConfigurationManager _channelConfigurationManager;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="mapper"></param>
+        /// <param name="logger"></param>
+        /// <param name="messageRepository"></param>
+        /// <param name="waitMessageRepository"></param>
+        /// <param name="pushDomainService"></param>
+        /// <param name="channelConfigurationManager"></param>
+        public TaskSendMessageJob(IMapper mapper,
+            ILogger<TaskSendMessageJob> logger,
+            IRepository<Message> messageRepository,
+            IRepository<WaitMessage> waitMessageRepository,
+            IPushDomainService pushDomainService,
+           IChannelConfigurationManager channelConfigurationManager)
+        {
+            _mapper = mapper;
+            _logger = logger;
+            _messageRepository = messageRepository;
+            _waitMessageRepository = waitMessageRepository;
+            _pushDomainService = pushDomainService;
+            _channelConfigurationManager = channelConfigurationManager;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="context"></param>
+        /// <returns></returns>
+        public async Task Execute(IJobExecutionContext context)
+        {
+           // _logger.LogWarning("进来了,时间是:" + DateTime.Now);
+            var tasks = await _waitMessageRepository.Queryable()
+                  .Where(d => d.Status == EPushStatus.Waiting && d.SendTimes <= 3)
+                  .OrderBy(d => d.CreationTime)
+                  .Take(50)
+                  .ToListAsync(context.CancellationToken);
+            if (tasks.Count != 0)
+            {
+                foreach (var sendTask in tasks)
+                {
+                    sendTask.Status = EPushStatus.Pushing;
+                    if (await _waitMessageRepository.Updateable(sendTask).ExecuteCommandWithOptLockAsync() > 0)
+                    {
+                        _logger.LogWarning("执行前,时间是:" + DateTime.Now);
+                        var result = await _pushDomainService.PushNewAsync(_mapper.Map<Share.Dtos.MessageDto>(sendTask));
+                        _logger.LogWarning("执行后,时间是:" + DateTime.Now);
+                        if (result.SendState == ESendState.Sending && result.Status == EPushStatus.Success)
+                        {
+                            //删除待推送表
+                            await _waitMessageRepository.RemoveAsync(sendTask, cancellationToken: context.CancellationToken);
+
+                            //修改添加推送数据
+                            result.ProcessingServices = _channelConfigurationManager.GetConfigurationProcessingServices();
+                            await _messageRepository.AddAsync(result, context.CancellationToken); //写入本地数据库
+                        }
+                        else
+                        {
+                            sendTask.SendTimes = sendTask.SendTimes + 1;
+                            sendTask.Reason = result.Reason;
+                            if (sendTask.SendTimes >= 4)
+                                sendTask.Status = EPushStatus.Failed;
+                            else
+                                sendTask.Status = EPushStatus.Waiting;
+                            await _waitMessageRepository.UpdateAsync(sendTask, context.CancellationToken);
+                        }
+                    }
+                }
+            }
+        }
+
+
+        public void Dispose()
+        {
+
+        }
+    }
+}

+ 76 - 0
src/yibin/Push.YiBin/WaitMessage.cs

@@ -0,0 +1,76 @@
+using Push.Share.Enums;
+
+namespace Push.YiBin
+{
+    /// <summary>
+    /// 待发表
+    /// </summary>
+    public class WaitMessage : CreationEntity
+    {
+        /// <summary>
+        /// 业务类型(区分从哪个平台来的短信数据)
+        /// </summary>
+        [SugarColumn(ColumnDescription = "业务类型(区分从哪个平台来的短信数据)")]
+        public string ClientId { get; set; }
+
+        /// <summary>
+        /// 外部业务唯一编号
+        /// </summary>
+        [SugarColumn(ColumnDescription = "外部业务唯一编号")]
+        public string? ExternalId { get; set; }
+
+        /// <summary>
+        /// 业务系统短信ID
+        /// </summary>
+        [SugarColumn(ColumnDescription = "业务系统短信ID")]
+        public int WaitSendId { get; set; } = 0;
+
+        /// <summary>
+        /// 推送状态
+        /// </summary>
+        [SugarColumn(ColumnDescription = "推送状态")]
+        public EPushStatus Status { get; set; } = EPushStatus.Waiting;
+
+        /// <summary>
+        /// 推送次数
+        /// </summary>
+        [SugarColumn(ColumnDescription = "推送次数")]
+        public int SendTimes { get; set; }
+
+        /// <summary>
+        /// 短信内容
+        /// </summary>
+        [SugarColumn(ColumnDescription = "短信内容")]
+        public string Content { get; set; }
+
+        /// <summary>
+        /// 备注
+        /// </summary>
+        [SugarColumn(ColumnDescription = "备注", ColumnDataType = "varchar(500)", IsNullable = true)]
+        public string? Remark { get; set; }
+
+        /// <summary>
+        /// 接收姓名
+        /// </summary>
+        [SugarColumn(ColumnDescription = "接收姓名")]
+        public string Name { get; set; }
+
+        /// <summary>
+        /// 接收手机号码
+        /// </summary>
+        [SugarColumn(ColumnDescription = "接收手机号码")]
+        public string TelNumber { get; set; }
+
+        /// <summary>
+        /// 发送失败原因等
+        /// </summary>
+        [SugarColumn(ColumnDescription = "发送失败原因等", ColumnDataType = "varchar(200)", IsNullable = true)]
+        public string? Reason { get; set; }
+
+        /// <summary>
+        /// 标识版本字段
+        /// </summary>
+        [SqlSugar.SugarColumn(IsEnableUpdateVersionValidation = true)]
+        public Guid Ver { get; set; }
+    }
+}