From 1287699bb0f221712e5c0aaf7ef1d074abdc158c Mon Sep 17 00:00:00 2001 From: colin Date: Mon, 10 Nov 2025 15:20:38 +0800 Subject: [PATCH] refactor(wechat): Refactor the wechat message resolver --- ...AbpWeChatWorkClaimsPrincipalContributor.cs | 36 +++++++++++ .../AbpWeChatMessageResolveOptions.cs | 12 ---- .../Messages/IMessageResolveContributor.cs | 1 + .../Common/Messages/IMessageResolver.cs | 7 --- .../Messages/MessageResolveContributorBase.cs | 1 + ...sageResolver.cs => MessageResolverBase.cs} | 34 ++++------- .../Message/WeChatMessageAppService.cs | 7 ++- .../Official/AbpWeChatOfficialModule.cs | 3 - .../AbpWeChatOfficialMessageResolveOptions.cs | 2 + .../IWeChatOfficialMessageResolver.cs | 16 +++++ .../WeChatOfficialEventResolveContributor.cs | 5 +- ...WeChatOfficialMessageResolveContributor.cs | 5 +- ...atOfficialMessageResolveContributorBase.cs | 11 ++-- .../Messages/WeChatOfficialMessageResolver.cs | 39 ++++++++++++ .../Message/WeChatWorkMessageAppService.cs | 7 ++- .../LINGYUN.Abp.WeChat.Work.Common.csproj | 1 + .../Work/Common/AbpWeChatWorkCommonModule.cs | 5 +- .../AbpWeChatWorkMessageResolveOptions.cs | 2 + .../Messages/IWeChatWorkMessageResolver.cs | 16 +++++ .../Messages/Models/BookMeetingRoomEvent.cs | 30 +++++++++ .../Messages/Models/CancelMeetingRoomEvent.cs | 30 +++++++++ .../WeChatWorkEventResolveContributor.cs | 5 +- .../WeChatWorkMessageResolveContributor.cs | 5 +- ...WeChatWorkMessageResolveContributorBase.cs | 12 ++-- .../Messages/WeChatWorkMessageResolver.cs | 39 ++++++++++++ .../LINGYUN.Abp.WeChat.Work.csproj | 1 + .../Abp/WeChat/Work/AbpWeChatWorkModule.cs | 18 +----- .../Abp/WeChat/Work/WeChatWorkRequest.cs | 7 +++ .../IHttpClientFactoryWeChatWorkExtensions.cs | 61 +++++++++++++++++++ 29 files changed, 320 insertions(+), 98 deletions(-) create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.Identity.WeChat.Work/LINGYUN/Abp/Identity/WeChat/Work/AbpWeChatWorkClaimsPrincipalContributor.cs delete mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/AbpWeChatMessageResolveOptions.cs delete mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/IMessageResolver.cs rename aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/{MessageResolver.cs => MessageResolverBase.cs} (69%) create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/IWeChatOfficialMessageResolver.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/WeChatOfficialMessageResolver.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/IWeChatWorkMessageResolver.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/Models/BookMeetingRoomEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/Models/CancelMeetingRoomEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/WeChatWorkMessageResolver.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/Microsoft/Extensions/DependencyInjection/IHttpClientFactoryWeChatWorkExtensions.cs diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.Identity.WeChat.Work/LINGYUN/Abp/Identity/WeChat/Work/AbpWeChatWorkClaimsPrincipalContributor.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.Identity.WeChat.Work/LINGYUN/Abp/Identity/WeChat/Work/AbpWeChatWorkClaimsPrincipalContributor.cs new file mode 100644 index 000000000..7087e0c6d --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.Identity.WeChat.Work/LINGYUN/Abp/Identity/WeChat/Work/AbpWeChatWorkClaimsPrincipalContributor.cs @@ -0,0 +1,36 @@ +using LINGYUN.Abp.WeChat.Work.Authorize; +using LINGYUN.Abp.WeChat.Work.Security.Claims; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Linq; +using System.Security.Claims; +using System.Security.Principal; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Security.Claims; + +namespace LINGYUN.Abp.Identity.WeChat.Work; +public class AbpWeChatWorkClaimsPrincipalContributor : IAbpClaimsPrincipalContributor, ITransientDependency +{ + public async virtual Task ContributeAsync(AbpClaimsPrincipalContributorContext context) + { + var claimsIdentity = context.ClaimsPrincipal.Identities.First(); + if (claimsIdentity.HasClaim(x => x.Type == AbpWeChatWorkClaimTypes.UserId)) + { + return; + } + var userId = claimsIdentity.FindUserId(); + if (userId.HasValue) + { + var userClaimProvider = context.ServiceProvider.GetService(); + + var weChatWorkUserId = await userClaimProvider?.FindUserIdentifierAsync(userId.Value); + if (!weChatWorkUserId.IsNullOrWhiteSpace()) + { + claimsIdentity.AddOrReplace(new Claim(AbpWeChatWorkClaimTypes.UserId, weChatWorkUserId)); + + context.ClaimsPrincipal.AddIdentityIfNotContains(claimsIdentity); + } + } + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/AbpWeChatMessageResolveOptions.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/AbpWeChatMessageResolveOptions.cs deleted file mode 100644 index 91af5f200..000000000 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/AbpWeChatMessageResolveOptions.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; - -namespace LINGYUN.Abp.WeChat.Common.Messages; -public class AbpWeChatMessageResolveOptions -{ - public List MessageResolvers { get; } - - public AbpWeChatMessageResolveOptions() - { - MessageResolvers = new List(); - } -} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/IMessageResolveContributor.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/IMessageResolveContributor.cs index 78bb587b6..dd1b0a93f 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/IMessageResolveContributor.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/IMessageResolveContributor.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; namespace LINGYUN.Abp.WeChat.Common.Messages; + public interface IMessageResolveContributor { string Name { get; } diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/IMessageResolver.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/IMessageResolver.cs deleted file mode 100644 index c708a2aa1..000000000 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/IMessageResolver.cs +++ /dev/null @@ -1,7 +0,0 @@ -using System.Threading.Tasks; - -namespace LINGYUN.Abp.WeChat.Common.Messages; -public interface IMessageResolver -{ - Task ResolveMessageAsync(MessageResolveData messageData); -} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/MessageResolveContributorBase.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/MessageResolveContributorBase.cs index 088b67e21..56f9089fc 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/MessageResolveContributorBase.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/MessageResolveContributorBase.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; namespace LINGYUN.Abp.WeChat.Common.Messages; + public abstract class MessageResolveContributorBase : IMessageResolveContributor { public abstract string Name { get; } diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/MessageResolver.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/MessageResolverBase.cs similarity index 69% rename from aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/MessageResolver.cs rename to aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/MessageResolverBase.cs index 145b4efca..42952f73e 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/MessageResolver.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/MessageResolverBase.cs @@ -1,7 +1,6 @@ using LINGYUN.Abp.WeChat.Common.Crypto; using LINGYUN.Abp.WeChat.Common.Crypto.Models; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; using System; using System.Linq; using System.Threading.Tasks; @@ -9,29 +8,25 @@ using System.Xml.Linq; using Volo.Abp.DependencyInjection; namespace LINGYUN.Abp.WeChat.Common.Messages; -public class MessageResolver : IMessageResolver, ITransientDependency +public abstract class MessageResolverBase : ITransientDependency { private readonly IWeChatCryptoService _cryptoService; private readonly IServiceProvider _serviceProvider; - private readonly AbpWeChatMessageResolveOptions _options; - public MessageResolver( - IOptions options, + protected MessageResolverBase( IWeChatCryptoService cryptoService, IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; _cryptoService = cryptoService; - _options = options.Value; } /// /// 解析微信服务器推送消息/事件 /// /// /// - public async virtual Task ResolveMessageAsync(MessageResolveData messageData) + public async virtual Task ResolveAsync(MessageResolveData messageData) { - var result = new MessageResolveResult(messageData.Data); using (var serviceScope = _serviceProvider.CreateScope()) { /* 明文数据格式 @@ -65,24 +60,17 @@ public class MessageResolver : IMessageResolver, ITransientDependency // 经过解密函数得到如上真实数据 var decryptMessage = _cryptoService.Decrypt(cryptoDecryptData); xmlDocument = XDocument.Parse(decryptMessage); - result.Input = decryptMessage; } - var context = new MessageResolveContext(result.Input, xmlDocument, serviceScope.ServiceProvider); + var context = new MessageResolveContext(messageData.Data, xmlDocument, serviceScope.ServiceProvider); - foreach (var messageResolver in _options.MessageResolvers) - { - await messageResolver.ResolveAsync(context); - - result.AppliedResolvers.Add(messageResolver.Name); - - if (context.HasResolvedMessage()) - { - result.Message = context.Message; - break; - } - } + return await ResolveMessageAsync(context); } - return result; } + /// + /// 实现具体的解析微信服务器推送消息/事件方法 + /// + /// + /// + protected abstract Task ResolveMessageAsync(MessageResolveContext context); } diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official.Application/LINGYUN/Abp/WeChat/Official/Message/WeChatMessageAppService.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official.Application/LINGYUN/Abp/WeChat/Official/Message/WeChatMessageAppService.cs index bc4096c6b..6ee32744d 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official.Application/LINGYUN/Abp/WeChat/Official/Message/WeChatMessageAppService.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official.Application/LINGYUN/Abp/WeChat/Official/Message/WeChatMessageAppService.cs @@ -1,6 +1,7 @@ using LINGYUN.Abp.WeChat.Common.Crypto; using LINGYUN.Abp.WeChat.Common.Crypto.Models; using LINGYUN.Abp.WeChat.Common.Messages; +using LINGYUN.Abp.WeChat.Official.Messages; using Microsoft.Extensions.Logging; using System.Threading.Tasks; using Volo.Abp; @@ -13,9 +14,9 @@ public class WeChatMessageAppService : ApplicationService, IWeChatMessageAppServ private readonly IWeChatCryptoService _cryptoService; private readonly AbpWeChatOfficialOptionsFactory _optionsFactory; private readonly IDistributedEventBus _distributedEventBus; - private readonly IMessageResolver _messageResolver; + private readonly IWeChatOfficialMessageResolver _messageResolver; public WeChatMessageAppService( - IMessageResolver messageResolver, + IWeChatOfficialMessageResolver messageResolver, IWeChatCryptoService cryptoService, IDistributedEventBus distributedEventBus, AbpWeChatOfficialOptionsFactory optionsFactory) @@ -67,7 +68,7 @@ public class WeChatMessageAppService : ApplicationService, IWeChatMessageAppServ input.Nonce, input.Data); - var result = await _messageResolver.ResolveMessageAsync(messageData); + var result = await _messageResolver.ResolveAsync(messageData); if (result.Message == null) { Logger.LogWarning(input.Data); diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/AbpWeChatOfficialModule.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/AbpWeChatOfficialModule.cs index f695ba86d..b265a0739 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/AbpWeChatOfficialModule.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/AbpWeChatOfficialModule.cs @@ -40,10 +40,7 @@ public class AbpWeChatOfficialModule : AbpModule options.MapMessage("shortvideo", context => context.GetWeChatMessage()); options.MapMessage("location", context => context.GetWeChatMessage()); options.MapMessage("link", context => context.GetWeChatMessage()); - }); - Configure(options => - { // 事件处理器 options.MessageResolvers.AddIfNotContains(new WeChatOfficialEventResolveContributor()); // 消息处理器 diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/AbpWeChatOfficialMessageResolveOptions.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/AbpWeChatOfficialMessageResolveOptions.cs index d145468e7..506e08e03 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/AbpWeChatOfficialMessageResolveOptions.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/AbpWeChatOfficialMessageResolveOptions.cs @@ -5,10 +5,12 @@ using System.Collections.Generic; namespace LINGYUN.Abp.WeChat.Official.Messages; public class AbpWeChatOfficialMessageResolveOptions { + public List MessageResolvers { get; } public IDictionary> EventMaps { get; } public IDictionary> MessageMaps { get; } public AbpWeChatOfficialMessageResolveOptions() { + MessageResolvers = new List(); EventMaps = new Dictionary>(); MessageMaps = new Dictionary>(); } diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/IWeChatOfficialMessageResolver.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/IWeChatOfficialMessageResolver.cs new file mode 100644 index 000000000..570eb0662 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/IWeChatOfficialMessageResolver.cs @@ -0,0 +1,16 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WeChat.Official.Messages; +/// +/// 微信公众号消息解析器 +/// +public interface IWeChatOfficialMessageResolver +{ + /// + /// 解析微信公众号消息 + /// + /// 公众号消息 + /// + Task ResolveAsync(MessageResolveData messageData); +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/WeChatOfficialEventResolveContributor.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/WeChatOfficialEventResolveContributor.cs index 9db7070ca..4f62e84c8 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/WeChatOfficialEventResolveContributor.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/WeChatOfficialEventResolveContributor.cs @@ -1,6 +1,4 @@ using LINGYUN.Abp.WeChat.Common.Messages; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; using System; using System.Threading.Tasks; @@ -12,9 +10,8 @@ public class WeChatOfficialEventResolveContributor : WeChatOfficialMessageResolv { public override string Name => "WeChat.Official.Event"; - protected override Task ResolveWeChatMessageAsync(IMessageResolveContext context) + protected override Task ResolveMessageAsync(IMessageResolveContext context, AbpWeChatOfficialMessageResolveOptions options) { - var options = context.ServiceProvider.GetRequiredService>().Value; var messageType = context.GetMessageData("MsgType"); var eventName = context.GetMessageData("Event"); if ("event".Equals(messageType, StringComparison.InvariantCultureIgnoreCase) && diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/WeChatOfficialMessageResolveContributor.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/WeChatOfficialMessageResolveContributor.cs index 5a0b4aa3c..da22ec390 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/WeChatOfficialMessageResolveContributor.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/WeChatOfficialMessageResolveContributor.cs @@ -1,6 +1,4 @@ using LINGYUN.Abp.WeChat.Common.Messages; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; using System.Threading.Tasks; namespace LINGYUN.Abp.WeChat.Official.Messages; @@ -11,9 +9,8 @@ public class WeChatOfficialMessageResolveContributor : WeChatOfficialMessageReso { public override string Name => "WeChat.Official.Message"; - protected override Task ResolveWeChatMessageAsync(IMessageResolveContext context) + protected override Task ResolveMessageAsync(IMessageResolveContext context, AbpWeChatOfficialMessageResolveOptions options) { - var options = context.ServiceProvider.GetRequiredService>().Value; var messageType = context.GetMessageData("MsgType"); if (options.MessageMaps.TryGetValue(messageType, out var messageFactory)) { diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/WeChatOfficialMessageResolveContributorBase.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/WeChatOfficialMessageResolveContributorBase.cs index cf82e7a8e..998b8ed8d 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/WeChatOfficialMessageResolveContributorBase.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/WeChatOfficialMessageResolveContributorBase.cs @@ -1,4 +1,6 @@ using LINGYUN.Abp.WeChat.Common.Messages; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using System.Threading.Tasks; namespace LINGYUN.Abp.WeChat.Official.Messages; @@ -6,13 +8,10 @@ public abstract class WeChatOfficialMessageResolveContributorBase : MessageResol { public override Task ResolveAsync(IMessageResolveContext context) { - if (!context.HasMessageKey("AgentID")) - { - return ResolveWeChatMessageAsync(context); - } + var options = context.ServiceProvider.GetRequiredService>().Value; - return Task.CompletedTask; + return ResolveMessageAsync(context, options); } - protected abstract Task ResolveWeChatMessageAsync(IMessageResolveContext context); + protected abstract Task ResolveMessageAsync(IMessageResolveContext context, AbpWeChatOfficialMessageResolveOptions options); } diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/WeChatOfficialMessageResolver.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/WeChatOfficialMessageResolver.cs new file mode 100644 index 000000000..6ce0d69e5 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/WeChatOfficialMessageResolver.cs @@ -0,0 +1,39 @@ +using LINGYUN.Abp.WeChat.Common.Crypto; +using LINGYUN.Abp.WeChat.Common.Messages; +using Microsoft.Extensions.Options; +using System; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WeChat.Official.Messages; +public class WeChatOfficialMessageResolver : MessageResolverBase, IWeChatOfficialMessageResolver +{ + private readonly AbpWeChatOfficialMessageResolveOptions _options; + public WeChatOfficialMessageResolver( + IWeChatCryptoService cryptoService, + IServiceProvider serviceProvider, + IOptions options) + : base(cryptoService, serviceProvider) + { + _options = options.Value; + } + + protected async override Task ResolveMessageAsync(MessageResolveContext context) + { + var result = new MessageResolveResult(context.Origin); + + foreach (var messageResolver in _options.MessageResolvers) + { + await messageResolver.ResolveAsync(context); + + result.AppliedResolvers.Add(messageResolver.Name); + + if (context.HasResolvedMessage()) + { + result.Message = context.Message; + break; + } + } + + return result; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Application/LINGYUN/Abp/WeChat/Work/Message/WeChatWorkMessageAppService.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Application/LINGYUN/Abp/WeChat/Work/Message/WeChatWorkMessageAppService.cs index 52506017b..4c880252d 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Application/LINGYUN/Abp/WeChat/Work/Message/WeChatWorkMessageAppService.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Application/LINGYUN/Abp/WeChat/Work/Message/WeChatWorkMessageAppService.cs @@ -1,6 +1,7 @@ using LINGYUN.Abp.WeChat.Common.Crypto; using LINGYUN.Abp.WeChat.Common.Crypto.Models; using LINGYUN.Abp.WeChat.Common.Messages; +using LINGYUN.Abp.WeChat.Work.Common.Messages; using LINGYUN.Abp.WeChat.Work.Settings; using Microsoft.Extensions.Logging; using System.Linq; @@ -14,9 +15,9 @@ public class WeChatWorkMessageAppService : ApplicationService, IWeChatWorkMessag { private readonly IWeChatCryptoService _cryptoService; private readonly IDistributedEventBus _distributedEventBus; - private readonly IMessageResolver _messageResolver; + private readonly IWeChatWorkMessageResolver _messageResolver; public WeChatWorkMessageAppService( - IMessageResolver messageResolver, + IWeChatWorkMessageResolver messageResolver, IWeChatCryptoService cryptoService, IDistributedEventBus distributedEventBus) { @@ -82,7 +83,7 @@ public class WeChatWorkMessageAppService : ApplicationService, IWeChatWorkMessag input.Nonce, input.Data); - var result = await _messageResolver.ResolveMessageAsync(messageData); + var result = await _messageResolver.ResolveAsync(messageData); if (result.Message == null) { Logger.LogWarning(input.Data); diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN.Abp.WeChat.Work.Common.csproj b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN.Abp.WeChat.Work.Common.csproj index 71d137f5f..44a9562dc 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN.Abp.WeChat.Work.Common.csproj +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN.Abp.WeChat.Work.Common.csproj @@ -10,6 +10,7 @@ false false false + True diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/AbpWeChatWorkCommonModule.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/AbpWeChatWorkCommonModule.cs index c011747a5..5fa41c334 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/AbpWeChatWorkCommonModule.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/AbpWeChatWorkCommonModule.cs @@ -57,6 +57,8 @@ public class AbpWeChatWorkCommonModule : AbpModule _ => throw new AbpWeChatException($"Contact change event {changeType} is not mounted!"), }; }); + options.MapEvent("book_meeting_room", context => context.GetWeChatMessage()); + options.MapEvent("cancel_meeting_room", context => context.GetWeChatMessage()); options.MapMessage("text", context => context.GetWeChatMessage()); options.MapMessage("image", context => context.GetWeChatMessage()); @@ -65,10 +67,7 @@ public class AbpWeChatWorkCommonModule : AbpModule options.MapMessage("shortvideo", context => context.GetWeChatMessage()); options.MapMessage("location", context => context.GetWeChatMessage()); options.MapMessage("link", context => context.GetWeChatMessage()); - }); - Configure(options => - { // 事件处理器 options.MessageResolvers.AddIfNotContains(new WeChatWorkEventResolveContributor()); // 消息处理器 diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/AbpWeChatWorkMessageResolveOptions.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/AbpWeChatWorkMessageResolveOptions.cs index e994957b3..99be696f9 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/AbpWeChatWorkMessageResolveOptions.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/AbpWeChatWorkMessageResolveOptions.cs @@ -5,10 +5,12 @@ using System.Collections.Generic; namespace LINGYUN.Abp.WeChat.Work.Common.Messages; public class AbpWeChatWorkMessageResolveOptions { + public List MessageResolvers { get; } public IDictionary> EventMaps { get; } public IDictionary> MessageMaps { get; } public AbpWeChatWorkMessageResolveOptions() { + MessageResolvers = new List(); EventMaps = new Dictionary>(); MessageMaps = new Dictionary>(); } diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/IWeChatWorkMessageResolver.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/IWeChatWorkMessageResolver.cs new file mode 100644 index 000000000..04e57b30b --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/IWeChatWorkMessageResolver.cs @@ -0,0 +1,16 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WeChat.Work.Common.Messages; +/// +/// 企业微信消息解析器 +/// +public interface IWeChatWorkMessageResolver +{ + /// + /// 解析企业微信消息 + /// + /// 企业微信消息 + /// + Task ResolveAsync(MessageResolveData messageData); +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/Models/BookMeetingRoomEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/Models/BookMeetingRoomEvent.cs new file mode 100644 index 000000000..4efc03105 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/Models/BookMeetingRoomEvent.cs @@ -0,0 +1,30 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using System.Xml.Serialization; +using Volo.Abp.EventBus; + +namespace LINGYUN.Abp.WeChat.Work.Common.Messages.Models; +/// +/// 会议室预定事件 +/// +/// +/// 当用户在企业微信预定会议室时,会触发该事件回调给会议室系统应用。 +/// +[EventName("book_meeting_room")] +public class BookMeetingRoomEvent : WeChatWorkEventMessage +{ + /// + /// 会议室id + /// + [XmlElement("MeetingRoomId")] + public int MeetingRoomId { get; set; } + /// + /// 预定id,可根据该ID查询具体的会议预定情况 + /// + [XmlElement("BookingId")] + public string BookingId { get; set; } + + public override WeChatMessageEto ToEto() + { + return new WeChatWorkEventMessageEto(this); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/Models/CancelMeetingRoomEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/Models/CancelMeetingRoomEvent.cs new file mode 100644 index 000000000..9fa50cadc --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/Models/CancelMeetingRoomEvent.cs @@ -0,0 +1,30 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using System.Xml.Serialization; +using Volo.Abp.EventBus; + +namespace LINGYUN.Abp.WeChat.Work.Common.Messages.Models; +/// +/// 会议室取消事件 +/// +/// +/// 当用户在企业微信取消预定会议室时,会触发该事件回调给会议室系统应用;如果该会议室由自建应用预定,除了会议室系统应用外,也会回调给对应的自建应用。 +/// +[EventName("cancel_meeting_room")] +public class CancelMeetingRoomEvent : WeChatWorkEventMessage +{ + /// + /// 会议室id + /// + [XmlElement("MeetingRoomId")] + public int MeetingRoomId { get; set; } + /// + /// 预定id,可根据该ID查询具体的会议预定情况 + /// + [XmlElement("BookingId")] + public string BookingId { get; set; } + + public override WeChatMessageEto ToEto() + { + return new WeChatWorkEventMessageEto(this); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/WeChatWorkEventResolveContributor.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/WeChatWorkEventResolveContributor.cs index b2974c092..4caaba554 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/WeChatWorkEventResolveContributor.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/WeChatWorkEventResolveContributor.cs @@ -1,6 +1,4 @@ using LINGYUN.Abp.WeChat.Common.Messages; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; using System; using System.Threading.Tasks; @@ -12,9 +10,8 @@ public class WeChatWorkEventResolveContributor : WeChatWorkMessageResolveContrib { public override string Name => "WeChat.Work.Event"; - protected override Task ResolveWeComMessageAsync(IMessageResolveContext context) + protected override Task ResolveMessageAsync(IMessageResolveContext context, AbpWeChatWorkMessageResolveOptions options) { - var options = context.ServiceProvider.GetRequiredService>().Value; var messageType = context.GetMessageData("MsgType"); var eventName = context.GetMessageData("Event"); if ("event".Equals(messageType, StringComparison.InvariantCultureIgnoreCase) && diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/WeChatWorkMessageResolveContributor.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/WeChatWorkMessageResolveContributor.cs index acf5ec6df..bd358de45 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/WeChatWorkMessageResolveContributor.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/WeChatWorkMessageResolveContributor.cs @@ -1,6 +1,4 @@ using LINGYUN.Abp.WeChat.Common.Messages; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; using System.Threading.Tasks; namespace LINGYUN.Abp.WeChat.Work.Common.Messages; @@ -11,9 +9,8 @@ public class WeChatWorkMessageResolveContributor : WeChatWorkMessageResolveContr { public override string Name => "WeChat.Work.Message"; - protected override Task ResolveWeComMessageAsync(IMessageResolveContext context) + protected override Task ResolveMessageAsync(IMessageResolveContext context, AbpWeChatWorkMessageResolveOptions options) { - var options = context.ServiceProvider.GetRequiredService>().Value; var messageType = context.GetMessageData("MsgType"); if (options.MessageMaps.TryGetValue(messageType, out var messageFactory)) { diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/WeChatWorkMessageResolveContributorBase.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/WeChatWorkMessageResolveContributorBase.cs index 7d503ba01..8b45d819e 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/WeChatWorkMessageResolveContributorBase.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/WeChatWorkMessageResolveContributorBase.cs @@ -1,4 +1,6 @@ using LINGYUN.Abp.WeChat.Common.Messages; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using System.Threading.Tasks; namespace LINGYUN.Abp.WeChat.Work.Common.Messages; @@ -6,14 +8,10 @@ public abstract class WeChatWorkMessageResolveContributorBase : MessageResolveCo { public override Task ResolveAsync(IMessageResolveContext context) { - // 企业微信消息需要企业标识字段 - if (context.HasMessageKey("AgentID")) - { - return ResolveWeComMessageAsync(context); - } + var options = context.ServiceProvider.GetRequiredService>().Value; - return Task.CompletedTask; + return ResolveMessageAsync(context, options); } - protected abstract Task ResolveWeComMessageAsync(IMessageResolveContext context); + protected abstract Task ResolveMessageAsync(IMessageResolveContext context, AbpWeChatWorkMessageResolveOptions options); } diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/WeChatWorkMessageResolver.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/WeChatWorkMessageResolver.cs new file mode 100644 index 000000000..f361e7f04 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/WeChatWorkMessageResolver.cs @@ -0,0 +1,39 @@ +using LINGYUN.Abp.WeChat.Common.Crypto; +using LINGYUN.Abp.WeChat.Common.Messages; +using Microsoft.Extensions.Options; +using System; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WeChat.Work.Common.Messages; +public class WeChatWorkMessageResolver : MessageResolverBase, IWeChatWorkMessageResolver +{ + private readonly AbpWeChatWorkMessageResolveOptions _options; + public WeChatWorkMessageResolver( + IWeChatCryptoService cryptoService, + IServiceProvider serviceProvider, + IOptions options) + : base(cryptoService, serviceProvider) + { + _options = options.Value; + } + + protected async override Task ResolveMessageAsync(MessageResolveContext context) + { + var result = new MessageResolveResult(context.Origin); + + foreach (var messageResolver in _options.MessageResolvers) + { + await messageResolver.ResolveAsync(context); + + result.AppliedResolvers.Add(messageResolver.Name); + + if (context.HasResolvedMessage()) + { + result.Message = context.Message; + break; + } + } + + return result; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN.Abp.WeChat.Work.csproj b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN.Abp.WeChat.Work.csproj index 64de80866..7ad47e365 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN.Abp.WeChat.Work.csproj +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN.Abp.WeChat.Work.csproj @@ -10,6 +10,7 @@ false false false + True diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/AbpWeChatWorkModule.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/AbpWeChatWorkModule.cs index fa7c3c2c3..c7855d4d9 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/AbpWeChatWorkModule.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/AbpWeChatWorkModule.cs @@ -42,20 +42,8 @@ public class AbpWeChatWorkModule : AbpModule options.MapCodeNamespace(WeChatWorkErrorCodes.Namespace, typeof(WeChatWorkResource)); }); - context.Services.AddHttpClient(AbpWeChatWorkGlobalConsts.ApiClient, - options => - { - options.BaseAddress = new Uri("https://qyapi.weixin.qq.com"); - }); - context.Services.AddHttpClient(AbpWeChatWorkGlobalConsts.OAuthClient, - options => - { - options.BaseAddress = new Uri("https://open.weixin.qq.com"); - }); - context.Services.AddHttpClient(AbpWeChatWorkGlobalConsts.LoginClient, - options => - { - options.BaseAddress = new Uri("https://login.work.weixin.qq.com"); - }); + context.Services.AddApiClient(); + context.Services.AddOAuthClient(); + context.Services.AddLoginClient(); } } diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/WeChatWorkRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/WeChatWorkRequest.cs index d63e96a2d..698440684 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/WeChatWorkRequest.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/WeChatWorkRequest.cs @@ -7,6 +7,13 @@ public abstract class WeChatWorkRequest { public virtual string SerializeToJson() { + Validate(); + return WeChatObjectSerializeExtensions.SerializeToJson(this); } + + protected virtual void Validate() + { + + } } diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/Microsoft/Extensions/DependencyInjection/IHttpClientFactoryWeChatWorkExtensions.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/Microsoft/Extensions/DependencyInjection/IHttpClientFactoryWeChatWorkExtensions.cs new file mode 100644 index 000000000..db1ef7009 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/Microsoft/Extensions/DependencyInjection/IHttpClientFactoryWeChatWorkExtensions.cs @@ -0,0 +1,61 @@ +using LINGYUN.Abp.WeChat.Work; +using System; +using System.Net.Http; + +namespace Microsoft.Extensions.DependencyInjection; +public static class IHttpClientFactoryWeChatWorkExtensions +{ + internal static IServiceCollection AddApiClient(this IServiceCollection services, Action configureClient = null) + { + services.AddHttpClient(AbpWeChatWorkGlobalConsts.ApiClient, + options => + { + options.BaseAddress = new Uri("https://qyapi.weixin.qq.com"); + + configureClient?.Invoke(options); + }); + + return services; + } + + public static HttpClient CreateWeChatWorkApiClient(this IHttpClientFactory httpClientFactory) + { + return httpClientFactory.CreateClient(AbpWeChatWorkGlobalConsts.ApiClient); + } + + internal static IServiceCollection AddOAuthClient(this IServiceCollection services, Action configureClient = null) + { + services.AddHttpClient(AbpWeChatWorkGlobalConsts.OAuthClient, + options => + { + options.BaseAddress = new Uri("https://open.weixin.qq.com"); + + configureClient?.Invoke(options); + }); + + return services; + } + + public static HttpClient CreateWeChatWorkOAuthClient(this IHttpClientFactory httpClientFactory) + { + return httpClientFactory.CreateClient(AbpWeChatWorkGlobalConsts.OAuthClient); + } + + internal static IServiceCollection AddLoginClient(this IServiceCollection services, Action configureClient = null) + { + services.AddHttpClient(AbpWeChatWorkGlobalConsts.LoginClient, + options => + { + options.BaseAddress = new Uri("https://login.work.weixin.qq.com"); + + configureClient?.Invoke(options); + }); + + return services; + } + + public static HttpClient CreateWeChatWorkLoginClient(this IHttpClientFactory httpClientFactory) + { + return httpClientFactory.CreateClient(AbpWeChatWorkGlobalConsts.LoginClient); + } +}