From 28209ad3ed7b73c680ca53a4a2af305b143070f1 Mon Sep 17 00:00:00 2001 From: cKey <35512826+colinin@users.noreply.github.com> Date: Wed, 10 Jun 2020 15:39:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=BE=AE=E4=BF=A1=E5=B0=8F?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E9=80=9A=E7=9F=A5=E5=8A=9F=E8=83=BD,?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=80=E4=B8=AA=E6=B6=88=E6=81=AF=E6=A0=87?= =?UTF-8?q?=E8=AF=86=E7=AC=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AbpWeChatWeAppNotificationOptions.cs | 4 ++ .../WeChatWeAppNotificationPublishProvider.cs | 14 +++-- .../WeApp/WeChatWeAppNotificationSender.cs | 3 +- .../WeApp/WeChatWeAppSendNotificationData.cs | 42 +++++++++++++++ .../LINGYUN.Abp.Notifications.csproj | 1 + .../Notifications/AbpNotificationModule.cs | 5 ++ .../Internal/DefaultNotificationDispatcher.cs | 51 ++++++++++++++----- .../Notifications/NotificationPublishJob.cs | 34 +++++++++++++ .../NotificationPublishJobArgs.cs | 20 ++++++++ .../Controllers/NotificationController.cs | 15 +++++- 10 files changed, 171 insertions(+), 18 deletions(-) create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationPublishJob.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationPublishJobArgs.cs diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/AbpWeChatWeAppNotificationOptions.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/AbpWeChatWeAppNotificationOptions.cs index 17f20e7be..cacc4e47b 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/AbpWeChatWeAppNotificationOptions.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/AbpWeChatWeAppNotificationOptions.cs @@ -2,6 +2,10 @@ { public class AbpWeChatWeAppNotificationOptions { + /// + /// 默认消息头部标记 + /// + public string DefaultMsgPrefix { get; set; } = "[wx]"; /// /// 默认小程序模板 /// diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/WeChatWeAppNotificationPublishProvider.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/WeChatWeAppNotificationPublishProvider.cs index 837e8c7b2..f30a14580 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/WeChatWeAppNotificationPublishProvider.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/WeChatWeAppNotificationPublishProvider.cs @@ -31,6 +31,7 @@ namespace LINGYUN.Abp.Notifications.WeChat.WeApp // 如果不是,需要自行处理openid获取逻辑 // step2 调用微信消息推送接口 + foreach (var identifier in identifiers) { await SendWeChatTemplateMessagAsync(notification, identifier); @@ -42,18 +43,21 @@ namespace LINGYUN.Abp.Notifications.WeChat.WeApp var templateId = GetOrDefaultTemplateId(notification.Data); Logger.LogDebug($"Get wechat weapp template id: {templateId}"); - var redirect = GetOrDefault(notification.Data, "RedirectPage", ""); - Logger.LogDebug($"Get wechat weapp redirect page: {redirect}"); + var redirect = GetOrDefault(notification.Data, "RedirectPage", null); + Logger.LogDebug($"Get wechat weapp redirect page: {redirect ?? "null"}"); var weAppState = GetOrDefault(notification.Data, "WeAppState", Options.DefaultWeAppState); - Logger.LogDebug($"Get wechat weapp state: {weAppState}"); + Logger.LogDebug($"Get wechat weapp state: {weAppState ?? null}"); var weAppLang = GetOrDefault(notification.Data, "WeAppLanguage", Options.DefaultWeAppLanguage); - Logger.LogDebug($"Get wechat weapp language: {weAppLang}"); + Logger.LogDebug($"Get wechat weapp language: {weAppLang ?? null}"); var weChatWeAppNotificationData = new WeChatWeAppSendNotificationData(identifier.UserName, templateId, redirect, weAppState, weAppLang); + // 写入模板数据 + weChatWeAppNotificationData.WriteData(Options.DefaultMsgPrefix, notification.Data.Properties); + Logger.LogDebug($"Sending wechat weapp notification: {notification.Name}"); // 发送小程序订阅消息 await NotificationSender.SendAsync(weChatWeAppNotificationData); @@ -68,6 +72,8 @@ namespace LINGYUN.Abp.Notifications.WeChat.WeApp { if (data.Properties.TryGetValue(key, out object value)) { + // 取得了数据就删除对应键值 + data.Properties.Remove(key); return value.ToString(); } return defaultValue; diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/WeChatWeAppNotificationSender.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/WeChatWeAppNotificationSender.cs index ba912aaa4..701c11573 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/WeChatWeAppNotificationSender.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/WeChatWeAppNotificationSender.cs @@ -43,7 +43,8 @@ namespace LINGYUN.Abp.Notifications.WeChat.WeApp protected virtual async Task MakeRequestAndGetResultAsync(string url, WeChatWeAppSendNotificationData notificationData) { var client = HttpClientFactory.CreateClient(SendNotificationClientName); - var requestContent = new StringContent(JsonSerializer.Serialize(notificationData)); + var sendDataContent = JsonSerializer.Serialize(notificationData); + var requestContent = new StringContent(sendDataContent); var requestMessage = new HttpRequestMessage(HttpMethod.Post, url) { Content = requestContent diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/WeChatWeAppSendNotificationData.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/WeChatWeAppSendNotificationData.cs index 27852d822..bf71c952a 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/WeChatWeAppSendNotificationData.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.WeChat/LINGYUN/Abp/Notifications/WeChat/WeApp/WeChatWeAppSendNotificationData.cs @@ -1,4 +1,6 @@ #pragma warning disable IDE1006 // 禁止编译器提示 +using System.Collections.Generic; + namespace LINGYUN.Abp.Notifications.WeChat.WeApp { public class WeChatWeAppSendNotificationData @@ -29,6 +31,11 @@ namespace LINGYUN.Abp.Notifications.WeChat.WeApp /// 默认为zh_CN /// public string lang { get; set; } + /// + /// 模板内容, + /// 格式形如 { "key1": { "value": any }, "key2": { "value": any } } + /// + public Dictionary data { get; set; } public WeChatWeAppSendNotificationData() { } public WeChatWeAppSendNotificationData(string openId, string templateId, string redirectPage = "", @@ -39,6 +46,41 @@ namespace LINGYUN.Abp.Notifications.WeChat.WeApp page = redirectPage; miniprogram_state = state; lang = miniLang; + + data = new Dictionary(); + } + + public WeChatWeAppSendNotificationData WriteData(string prefix, string key, object value) + { + // 只截取符合标记的数据 + if (key.StartsWith(prefix)) + { + key = key.Replace(prefix, ""); + if (!data.ContainsKey(key)) + { + data.Add(key, new WeChatNotificationData(value)); + } + } + return this; + } + + public WeChatWeAppSendNotificationData WriteData(string prefix, IDictionary setData) + { + foreach(var kv in setData) + { + WriteData(prefix, kv.Key, kv.Value); + } + return this; + } + } + + public class WeChatNotificationData + { + public object Value { get; } + + public WeChatNotificationData(object value) + { + Value = value; } } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN.Abp.Notifications.csproj b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN.Abp.Notifications.csproj index a6f38bfc2..8611e478a 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN.Abp.Notifications.csproj +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN.Abp.Notifications.csproj @@ -14,6 +14,7 @@ + diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationModule.cs index bc983485c..92b5fce3b 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationModule.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/AbpNotificationModule.cs @@ -2,10 +2,15 @@ using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.Json; using Volo.Abp.Modularity; namespace LINGYUN.Abp.Notifications { + [DependsOn( + typeof(AbpBackgroundJobsModule), + typeof(AbpJsonModule))] public class AbpNotificationModule : AbpModule { diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Internal/DefaultNotificationDispatcher.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Internal/DefaultNotificationDispatcher.cs index 36fea5853..b53ae524e 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Internal/DefaultNotificationDispatcher.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Internal/DefaultNotificationDispatcher.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Volo.Abp.BackgroundJobs; namespace LINGYUN.Abp.Notifications.Internal { @@ -11,14 +12,20 @@ namespace LINGYUN.Abp.Notifications.Internal { public ILogger Logger { get; set; } + private readonly IBackgroundJobManager _backgroundJobManager; + private readonly INotificationStore _notificationStore; private readonly INotificationDefinitionManager _notificationDefinitionManager; private readonly INotificationPublishProviderManager _notificationPublishProviderManager; public DefaultNotificationDispatcher( + IBackgroundJobManager backgroundJobManager, + INotificationStore notificationStore, INotificationDefinitionManager notificationDefinitionManager, INotificationPublishProviderManager notificationPublishProviderManager) { + _backgroundJobManager = backgroundJobManager; + _notificationStore = notificationStore; _notificationDefinitionManager = notificationDefinitionManager; _notificationPublishProviderManager = notificationPublishProviderManager; @@ -100,21 +107,41 @@ namespace LINGYUN.Abp.Notifications.Internal // 发布通知 foreach (var provider in providers) { - try - { - Logger.LogDebug($"Sending notification with provider {provider.Name}"); + await PublishAsync(provider, notificationInfo, subscriptionUserIdentifiers); + } + + // TODO: 需要计算队列大小,根据情况是否需要并行发布消息 + //Parallel.ForEach(providers, async (provider) => + //{ + // await PublishAsync(provider, notificationInfo, subscriptionUserIdentifiers); + //}); + } - await provider.PublishAsync(notificationInfo, subscriptionUserIdentifiers); + protected async Task PublishAsync(INotificationPublishProvider provider, NotificationInfo notificationInfo, + IEnumerable subscriptionUserIdentifiers) + { + try + { + Logger.LogDebug($"Sending notification with provider {provider.Name}"); - Logger.LogDebug($"Send notification {notificationInfo.Name} with provider {provider.Name} was successful"); - } - catch(Exception ex) - { - Logger.LogWarning($"Send notification error with provider {provider.Name}"); - Logger.LogWarning($"Error message:{ex.Message}"); + await provider.PublishAsync(notificationInfo, subscriptionUserIdentifiers); - Logger.LogTrace(ex, $"Send notification error with provider { provider.Name}"); - } + Logger.LogDebug($"Send notification {notificationInfo.Name} with provider {provider.Name} was successful"); + } + catch (Exception ex) + { + Logger.LogWarning($"Send notification error with provider {provider.Name}"); + Logger.LogWarning($"Error message:{ex.Message}"); + + Logger.LogTrace(ex, $"Send notification error with provider { provider.Name}"); + + Logger.LogDebug($"Send notification error, notification {notificationInfo.Name} entry queue"); + // 发送失败的消息进入后台队列 + await _backgroundJobManager.EnqueueAsync( + new NotificationPublishJobArgs(notificationInfo.GetId(), + provider.GetType().AssemblyQualifiedName, + subscriptionUserIdentifiers.ToList(), + notificationInfo.TenantId)); } } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationPublishJob.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationPublishJob.cs new file mode 100644 index 000000000..2ae41faff --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationPublishJob.cs @@ -0,0 +1,34 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Threading.Tasks; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.Notifications +{ + public class NotificationPublishJob : AsyncBackgroundJob, ITransientDependency + { + protected INotificationStore Store { get; } + protected IServiceProvider ServiceProvider { get; } + + public NotificationPublishJob( + INotificationStore store, + IServiceProvider serviceProvider) + { + Store = store; + ServiceProvider = serviceProvider; + } + + public override async Task ExecuteAsync(NotificationPublishJobArgs args) + { + var providerType = Type.GetType(args.ProviderType); + + if (ServiceProvider.GetRequiredService(providerType) is INotificationPublishProvider publishProvider) + { + var notification = await Store.GetNotificationOrNullAsync(args.TenantId, args.NotificationId); + + await publishProvider.PublishAsync(notification, args.UserIdentifiers); + } + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationPublishJobArgs.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationPublishJobArgs.cs new file mode 100644 index 000000000..128019301 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationPublishJobArgs.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; + +namespace LINGYUN.Abp.Notifications +{ + public class NotificationPublishJobArgs + { + public Guid? TenantId { get; set; } + public long NotificationId { get; set; } + public string ProviderType { get; set; } + public List UserIdentifiers { get; set; } + public NotificationPublishJobArgs(long id, string providerType, List userIdentifiers, Guid? tenantId = null ) + { + NotificationId = id; + ProviderType = providerType; + UserIdentifiers = userIdentifiers; + TenantId = tenantId; + } + } +} diff --git a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Controllers/NotificationController.cs b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Controllers/NotificationController.cs index 476873529..6ff6f3732 100644 --- a/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Controllers/NotificationController.cs +++ b/aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/Controllers/NotificationController.cs @@ -17,9 +17,22 @@ namespace LINGYUN.Abp.MessageService.Controllers _notificationDispatcher = notificationDispatcher; } + [HttpGet] + [Route("Test")] + public async Task> Test() + { + await Task.CompletedTask; + + return new Dictionary() + { + {"thing2", "测试标题" }, + {"name3", "测试人员" }, + }; + } + [HttpPost] [Route("Send")] - public async Task SendNofitication([FromForm] SendNotification notification) + public async Task SendNofitication([FromBody] SendNotification notification) { var notificationData = new NotificationData(); notificationData.Properties["title"] = notification.Title;