Browse Source

Merge pull request #1373 from colinin/refactor-wechat-message-resolver

refactor(wechat): Refactor the wechat message resolver
pull/1377/head
yx lin 3 months ago
committed by GitHub
parent
commit
b830857a4e
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 36
      aspnet-core/framework/wechat/LINGYUN.Abp.Identity.WeChat.Work/LINGYUN/Abp/Identity/WeChat/Work/AbpWeChatWorkClaimsPrincipalContributor.cs
  2. 12
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/AbpWeChatMessageResolveOptions.cs
  3. 1
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/IMessageResolveContributor.cs
  4. 7
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/IMessageResolver.cs
  5. 1
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/MessageResolveContributorBase.cs
  6. 34
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/MessageResolverBase.cs
  7. 7
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official.Application/LINGYUN/Abp/WeChat/Official/Message/WeChatMessageAppService.cs
  8. 3
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/AbpWeChatOfficialModule.cs
  9. 2
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/AbpWeChatOfficialMessageResolveOptions.cs
  10. 16
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/IWeChatOfficialMessageResolver.cs
  11. 5
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/WeChatOfficialEventResolveContributor.cs
  12. 5
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/WeChatOfficialMessageResolveContributor.cs
  13. 11
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/WeChatOfficialMessageResolveContributorBase.cs
  14. 39
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/Messages/WeChatOfficialMessageResolver.cs
  15. 7
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Application/LINGYUN/Abp/WeChat/Work/Message/WeChatWorkMessageAppService.cs
  16. 1
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN.Abp.WeChat.Work.Common.csproj
  17. 5
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/AbpWeChatWorkCommonModule.cs
  18. 2
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/AbpWeChatWorkMessageResolveOptions.cs
  19. 16
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/IWeChatWorkMessageResolver.cs
  20. 30
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/Models/BookMeetingRoomEvent.cs
  21. 30
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/Models/CancelMeetingRoomEvent.cs
  22. 5
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/WeChatWorkEventResolveContributor.cs
  23. 5
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/WeChatWorkMessageResolveContributor.cs
  24. 12
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/WeChatWorkMessageResolveContributorBase.cs
  25. 39
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN/Abp/WeChat/Work/Common/Messages/WeChatWorkMessageResolver.cs
  26. 1
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN.Abp.WeChat.Work.csproj
  27. 18
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/AbpWeChatWorkModule.cs
  28. 7
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/WeChatWorkRequest.cs
  29. 61
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/Microsoft/Extensions/DependencyInjection/IHttpClientFactoryWeChatWorkExtensions.cs

36
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<IWeChatWorkUserClaimProvider>();
var weChatWorkUserId = await userClaimProvider?.FindUserIdentifierAsync(userId.Value);
if (!weChatWorkUserId.IsNullOrWhiteSpace())
{
claimsIdentity.AddOrReplace(new Claim(AbpWeChatWorkClaimTypes.UserId, weChatWorkUserId));
context.ClaimsPrincipal.AddIdentityIfNotContains(claimsIdentity);
}
}
}
}

12
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/AbpWeChatMessageResolveOptions.cs

@ -1,12 +0,0 @@
using System.Collections.Generic;
namespace LINGYUN.Abp.WeChat.Common.Messages;
public class AbpWeChatMessageResolveOptions
{
public List<IMessageResolveContributor> MessageResolvers { get; }
public AbpWeChatMessageResolveOptions()
{
MessageResolvers = new List<IMessageResolveContributor>();
}
}

1
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/IMessageResolveContributor.cs

@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LINGYUN.Abp.WeChat.Common.Messages; namespace LINGYUN.Abp.WeChat.Common.Messages;
public interface IMessageResolveContributor public interface IMessageResolveContributor
{ {
string Name { get; } string Name { get; }

7
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/IMessageResolver.cs

@ -1,7 +0,0 @@
using System.Threading.Tasks;
namespace LINGYUN.Abp.WeChat.Common.Messages;
public interface IMessageResolver
{
Task<MessageResolveResult> ResolveMessageAsync(MessageResolveData messageData);
}

1
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/MessageResolveContributorBase.cs

@ -1,6 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LINGYUN.Abp.WeChat.Common.Messages; namespace LINGYUN.Abp.WeChat.Common.Messages;
public abstract class MessageResolveContributorBase : IMessageResolveContributor public abstract class MessageResolveContributorBase : IMessageResolveContributor
{ {
public abstract string Name { get; } public abstract string Name { get; }

34
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Messages/MessageResolver.cs → 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;
using LINGYUN.Abp.WeChat.Common.Crypto.Models; using LINGYUN.Abp.WeChat.Common.Crypto.Models;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System; using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -9,29 +8,25 @@ using System.Xml.Linq;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.WeChat.Common.Messages; namespace LINGYUN.Abp.WeChat.Common.Messages;
public class MessageResolver : IMessageResolver, ITransientDependency public abstract class MessageResolverBase : ITransientDependency
{ {
private readonly IWeChatCryptoService _cryptoService; private readonly IWeChatCryptoService _cryptoService;
private readonly IServiceProvider _serviceProvider; private readonly IServiceProvider _serviceProvider;
private readonly AbpWeChatMessageResolveOptions _options;
public MessageResolver( protected MessageResolverBase(
IOptions<AbpWeChatMessageResolveOptions> options,
IWeChatCryptoService cryptoService, IWeChatCryptoService cryptoService,
IServiceProvider serviceProvider) IServiceProvider serviceProvider)
{ {
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
_cryptoService = cryptoService; _cryptoService = cryptoService;
_options = options.Value;
} }
/// <summary> /// <summary>
/// 解析微信服务器推送消息/事件 /// 解析微信服务器推送消息/事件
/// </summary> /// </summary>
/// <param name="messageData"></param> /// <param name="messageData"></param>
/// <returns></returns> /// <returns></returns>
public async virtual Task<MessageResolveResult> ResolveMessageAsync(MessageResolveData messageData) public async virtual Task<MessageResolveResult> ResolveAsync(MessageResolveData messageData)
{ {
var result = new MessageResolveResult(messageData.Data);
using (var serviceScope = _serviceProvider.CreateScope()) using (var serviceScope = _serviceProvider.CreateScope())
{ {
/* /*
@ -65,24 +60,17 @@ public class MessageResolver : IMessageResolver, ITransientDependency
// 经过解密函数得到如上真实数据 // 经过解密函数得到如上真实数据
var decryptMessage = _cryptoService.Decrypt(cryptoDecryptData); var decryptMessage = _cryptoService.Decrypt(cryptoDecryptData);
xmlDocument = XDocument.Parse(decryptMessage); 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) return await ResolveMessageAsync(context);
{
await messageResolver.ResolveAsync(context);
result.AppliedResolvers.Add(messageResolver.Name);
if (context.HasResolvedMessage())
{
result.Message = context.Message;
break;
}
}
} }
return result;
} }
/// <summary>
/// 实现具体的解析微信服务器推送消息/事件方法
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
protected abstract Task<MessageResolveResult> ResolveMessageAsync(MessageResolveContext context);
} }

7
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;
using LINGYUN.Abp.WeChat.Common.Crypto.Models; using LINGYUN.Abp.WeChat.Common.Crypto.Models;
using LINGYUN.Abp.WeChat.Common.Messages; using LINGYUN.Abp.WeChat.Common.Messages;
using LINGYUN.Abp.WeChat.Official.Messages;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp; using Volo.Abp;
@ -13,9 +14,9 @@ public class WeChatMessageAppService : ApplicationService, IWeChatMessageAppServ
private readonly IWeChatCryptoService _cryptoService; private readonly IWeChatCryptoService _cryptoService;
private readonly AbpWeChatOfficialOptionsFactory _optionsFactory; private readonly AbpWeChatOfficialOptionsFactory _optionsFactory;
private readonly IDistributedEventBus _distributedEventBus; private readonly IDistributedEventBus _distributedEventBus;
private readonly IMessageResolver _messageResolver; private readonly IWeChatOfficialMessageResolver _messageResolver;
public WeChatMessageAppService( public WeChatMessageAppService(
IMessageResolver messageResolver, IWeChatOfficialMessageResolver messageResolver,
IWeChatCryptoService cryptoService, IWeChatCryptoService cryptoService,
IDistributedEventBus distributedEventBus, IDistributedEventBus distributedEventBus,
AbpWeChatOfficialOptionsFactory optionsFactory) AbpWeChatOfficialOptionsFactory optionsFactory)
@ -67,7 +68,7 @@ public class WeChatMessageAppService : ApplicationService, IWeChatMessageAppServ
input.Nonce, input.Nonce,
input.Data); input.Data);
var result = await _messageResolver.ResolveMessageAsync(messageData); var result = await _messageResolver.ResolveAsync(messageData);
if (result.Message == null) if (result.Message == null)
{ {
Logger.LogWarning(input.Data); Logger.LogWarning(input.Data);

3
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<VideoMessage>()); options.MapMessage("shortvideo", context => context.GetWeChatMessage<VideoMessage>());
options.MapMessage("location", context => context.GetWeChatMessage<GeoLocationMessage>()); options.MapMessage("location", context => context.GetWeChatMessage<GeoLocationMessage>());
options.MapMessage("link", context => context.GetWeChatMessage<LinkMessage>()); options.MapMessage("link", context => context.GetWeChatMessage<LinkMessage>());
});
Configure<AbpWeChatMessageResolveOptions>(options =>
{
// 事件处理器 // 事件处理器
options.MessageResolvers.AddIfNotContains(new WeChatOfficialEventResolveContributor()); options.MessageResolvers.AddIfNotContains(new WeChatOfficialEventResolveContributor());
// 消息处理器 // 消息处理器

2
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; namespace LINGYUN.Abp.WeChat.Official.Messages;
public class AbpWeChatOfficialMessageResolveOptions public class AbpWeChatOfficialMessageResolveOptions
{ {
public List<IMessageResolveContributor> MessageResolvers { get; }
public IDictionary<string, Func<IMessageResolveContext, WeChatEventMessage>> EventMaps { get; } public IDictionary<string, Func<IMessageResolveContext, WeChatEventMessage>> EventMaps { get; }
public IDictionary<string, Func<IMessageResolveContext, WeChatGeneralMessage>> MessageMaps { get; } public IDictionary<string, Func<IMessageResolveContext, WeChatGeneralMessage>> MessageMaps { get; }
public AbpWeChatOfficialMessageResolveOptions() public AbpWeChatOfficialMessageResolveOptions()
{ {
MessageResolvers = new List<IMessageResolveContributor>();
EventMaps = new Dictionary<string, Func<IMessageResolveContext, WeChatEventMessage>>(); EventMaps = new Dictionary<string, Func<IMessageResolveContext, WeChatEventMessage>>();
MessageMaps = new Dictionary<string, Func<IMessageResolveContext, WeChatGeneralMessage>>(); MessageMaps = new Dictionary<string, Func<IMessageResolveContext, WeChatGeneralMessage>>();
} }

16
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;
/// <summary>
/// 微信公众号消息解析器
/// </summary>
public interface IWeChatOfficialMessageResolver
{
/// <summary>
/// 解析微信公众号消息
/// </summary>
/// <param name="messageData">公众号消息</param>
/// <returns></returns>
Task<MessageResolveResult> ResolveAsync(MessageResolveData messageData);
}

5
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 LINGYUN.Abp.WeChat.Common.Messages;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -12,9 +10,8 @@ public class WeChatOfficialEventResolveContributor : WeChatOfficialMessageResolv
{ {
public override string Name => "WeChat.Official.Event"; 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<IOptions<AbpWeChatOfficialMessageResolveOptions>>().Value;
var messageType = context.GetMessageData("MsgType"); var messageType = context.GetMessageData("MsgType");
var eventName = context.GetMessageData("Event"); var eventName = context.GetMessageData("Event");
if ("event".Equals(messageType, StringComparison.InvariantCultureIgnoreCase) && if ("event".Equals(messageType, StringComparison.InvariantCultureIgnoreCase) &&

5
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 LINGYUN.Abp.WeChat.Common.Messages;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LINGYUN.Abp.WeChat.Official.Messages; namespace LINGYUN.Abp.WeChat.Official.Messages;
@ -11,9 +9,8 @@ public class WeChatOfficialMessageResolveContributor : WeChatOfficialMessageReso
{ {
public override string Name => "WeChat.Official.Message"; 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<IOptions<AbpWeChatOfficialMessageResolveOptions>>().Value;
var messageType = context.GetMessageData("MsgType"); var messageType = context.GetMessageData("MsgType");
if (options.MessageMaps.TryGetValue(messageType, out var messageFactory)) if (options.MessageMaps.TryGetValue(messageType, out var messageFactory))
{ {

11
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 LINGYUN.Abp.WeChat.Common.Messages;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LINGYUN.Abp.WeChat.Official.Messages; namespace LINGYUN.Abp.WeChat.Official.Messages;
@ -6,13 +8,10 @@ public abstract class WeChatOfficialMessageResolveContributorBase : MessageResol
{ {
public override Task ResolveAsync(IMessageResolveContext context) public override Task ResolveAsync(IMessageResolveContext context)
{ {
if (!context.HasMessageKey("AgentID")) var options = context.ServiceProvider.GetRequiredService<IOptions<AbpWeChatOfficialMessageResolveOptions>>().Value;
{
return ResolveWeChatMessageAsync(context);
}
return Task.CompletedTask; return ResolveMessageAsync(context, options);
} }
protected abstract Task ResolveWeChatMessageAsync(IMessageResolveContext context); protected abstract Task ResolveMessageAsync(IMessageResolveContext context, AbpWeChatOfficialMessageResolveOptions options);
} }

39
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<AbpWeChatOfficialMessageResolveOptions> options)
: base(cryptoService, serviceProvider)
{
_options = options.Value;
}
protected async override Task<MessageResolveResult> 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;
}
}

7
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;
using LINGYUN.Abp.WeChat.Common.Crypto.Models; using LINGYUN.Abp.WeChat.Common.Crypto.Models;
using LINGYUN.Abp.WeChat.Common.Messages; using LINGYUN.Abp.WeChat.Common.Messages;
using LINGYUN.Abp.WeChat.Work.Common.Messages;
using LINGYUN.Abp.WeChat.Work.Settings; using LINGYUN.Abp.WeChat.Work.Settings;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Linq; using System.Linq;
@ -14,9 +15,9 @@ public class WeChatWorkMessageAppService : ApplicationService, IWeChatWorkMessag
{ {
private readonly IWeChatCryptoService _cryptoService; private readonly IWeChatCryptoService _cryptoService;
private readonly IDistributedEventBus _distributedEventBus; private readonly IDistributedEventBus _distributedEventBus;
private readonly IMessageResolver _messageResolver; private readonly IWeChatWorkMessageResolver _messageResolver;
public WeChatWorkMessageAppService( public WeChatWorkMessageAppService(
IMessageResolver messageResolver, IWeChatWorkMessageResolver messageResolver,
IWeChatCryptoService cryptoService, IWeChatCryptoService cryptoService,
IDistributedEventBus distributedEventBus) IDistributedEventBus distributedEventBus)
{ {
@ -82,7 +83,7 @@ public class WeChatWorkMessageAppService : ApplicationService, IWeChatWorkMessag
input.Nonce, input.Nonce,
input.Data); input.Data);
var result = await _messageResolver.ResolveMessageAsync(messageData); var result = await _messageResolver.ResolveAsync(messageData);
if (result.Message == null) if (result.Message == null)
{ {
Logger.LogWarning(input.Data); Logger.LogWarning(input.Data);

1
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Common/LINGYUN.Abp.WeChat.Work.Common.csproj

@ -10,6 +10,7 @@
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

5
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!"), _ => throw new AbpWeChatException($"Contact change event {changeType} is not mounted!"),
}; };
}); });
options.MapEvent("book_meeting_room", context => context.GetWeChatMessage<BookMeetingRoomEvent>());
options.MapEvent("cancel_meeting_room", context => context.GetWeChatMessage<CancelMeetingRoomEvent>());
options.MapMessage("text", context => context.GetWeChatMessage<TextMessage>()); options.MapMessage("text", context => context.GetWeChatMessage<TextMessage>());
options.MapMessage("image", context => context.GetWeChatMessage<PictureMessage>()); options.MapMessage("image", context => context.GetWeChatMessage<PictureMessage>());
@ -65,10 +67,7 @@ public class AbpWeChatWorkCommonModule : AbpModule
options.MapMessage("shortvideo", context => context.GetWeChatMessage<VideoMessage>()); options.MapMessage("shortvideo", context => context.GetWeChatMessage<VideoMessage>());
options.MapMessage("location", context => context.GetWeChatMessage<GeoLocationMessage>()); options.MapMessage("location", context => context.GetWeChatMessage<GeoLocationMessage>());
options.MapMessage("link", context => context.GetWeChatMessage<LinkMessage>()); options.MapMessage("link", context => context.GetWeChatMessage<LinkMessage>());
});
Configure<AbpWeChatMessageResolveOptions>(options =>
{
// 事件处理器 // 事件处理器
options.MessageResolvers.AddIfNotContains(new WeChatWorkEventResolveContributor()); options.MessageResolvers.AddIfNotContains(new WeChatWorkEventResolveContributor());
// 消息处理器 // 消息处理器

2
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; namespace LINGYUN.Abp.WeChat.Work.Common.Messages;
public class AbpWeChatWorkMessageResolveOptions public class AbpWeChatWorkMessageResolveOptions
{ {
public List<IMessageResolveContributor> MessageResolvers { get; }
public IDictionary<string, Func<IMessageResolveContext, WeChatWorkEventMessage>> EventMaps { get; } public IDictionary<string, Func<IMessageResolveContext, WeChatWorkEventMessage>> EventMaps { get; }
public IDictionary<string, Func<IMessageResolveContext, WeChatWorkGeneralMessage>> MessageMaps { get; } public IDictionary<string, Func<IMessageResolveContext, WeChatWorkGeneralMessage>> MessageMaps { get; }
public AbpWeChatWorkMessageResolveOptions() public AbpWeChatWorkMessageResolveOptions()
{ {
MessageResolvers = new List<IMessageResolveContributor>();
EventMaps = new Dictionary<string, Func<IMessageResolveContext, WeChatWorkEventMessage>>(); EventMaps = new Dictionary<string, Func<IMessageResolveContext, WeChatWorkEventMessage>>();
MessageMaps = new Dictionary<string, Func<IMessageResolveContext, WeChatWorkGeneralMessage>>(); MessageMaps = new Dictionary<string, Func<IMessageResolveContext, WeChatWorkGeneralMessage>>();
} }

16
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;
/// <summary>
/// 企业微信消息解析器
/// </summary>
public interface IWeChatWorkMessageResolver
{
/// <summary>
/// 解析企业微信消息
/// </summary>
/// <param name="messageData">企业微信消息</param>
/// <returns></returns>
Task<MessageResolveResult> ResolveAsync(MessageResolveData messageData);
}

30
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;
/// <summary>
/// 会议室预定事件
/// </summary>
/// <remarks>
/// 当用户在企业微信预定会议室时,会触发该事件回调给会议室系统应用。
/// </remarks>
[EventName("book_meeting_room")]
public class BookMeetingRoomEvent : WeChatWorkEventMessage
{
/// <summary>
/// 会议室id
/// </summary>
[XmlElement("MeetingRoomId")]
public int MeetingRoomId { get; set; }
/// <summary>
/// 预定id,可根据该ID查询具体的会议预定情况
/// </summary>
[XmlElement("BookingId")]
public string BookingId { get; set; }
public override WeChatMessageEto ToEto()
{
return new WeChatWorkEventMessageEto<BookMeetingRoomEvent>(this);
}
}

30
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;
/// <summary>
/// 会议室取消事件
/// </summary>
/// <remarks>
/// 当用户在企业微信取消预定会议室时,会触发该事件回调给会议室系统应用;如果该会议室由自建应用预定,除了会议室系统应用外,也会回调给对应的自建应用。
/// </remarks>
[EventName("cancel_meeting_room")]
public class CancelMeetingRoomEvent : WeChatWorkEventMessage
{
/// <summary>
/// 会议室id
/// </summary>
[XmlElement("MeetingRoomId")]
public int MeetingRoomId { get; set; }
/// <summary>
/// 预定id,可根据该ID查询具体的会议预定情况
/// </summary>
[XmlElement("BookingId")]
public string BookingId { get; set; }
public override WeChatMessageEto ToEto()
{
return new WeChatWorkEventMessageEto<CancelMeetingRoomEvent>(this);
}
}

5
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 LINGYUN.Abp.WeChat.Common.Messages;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -12,9 +10,8 @@ public class WeChatWorkEventResolveContributor : WeChatWorkMessageResolveContrib
{ {
public override string Name => "WeChat.Work.Event"; 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<IOptions<AbpWeChatWorkMessageResolveOptions>>().Value;
var messageType = context.GetMessageData("MsgType"); var messageType = context.GetMessageData("MsgType");
var eventName = context.GetMessageData("Event"); var eventName = context.GetMessageData("Event");
if ("event".Equals(messageType, StringComparison.InvariantCultureIgnoreCase) && if ("event".Equals(messageType, StringComparison.InvariantCultureIgnoreCase) &&

5
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 LINGYUN.Abp.WeChat.Common.Messages;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LINGYUN.Abp.WeChat.Work.Common.Messages; namespace LINGYUN.Abp.WeChat.Work.Common.Messages;
@ -11,9 +9,8 @@ public class WeChatWorkMessageResolveContributor : WeChatWorkMessageResolveContr
{ {
public override string Name => "WeChat.Work.Message"; 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<IOptions<AbpWeChatWorkMessageResolveOptions>>().Value;
var messageType = context.GetMessageData("MsgType"); var messageType = context.GetMessageData("MsgType");
if (options.MessageMaps.TryGetValue(messageType, out var messageFactory)) if (options.MessageMaps.TryGetValue(messageType, out var messageFactory))
{ {

12
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 LINGYUN.Abp.WeChat.Common.Messages;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LINGYUN.Abp.WeChat.Work.Common.Messages; namespace LINGYUN.Abp.WeChat.Work.Common.Messages;
@ -6,14 +8,10 @@ public abstract class WeChatWorkMessageResolveContributorBase : MessageResolveCo
{ {
public override Task ResolveAsync(IMessageResolveContext context) public override Task ResolveAsync(IMessageResolveContext context)
{ {
// 企业微信消息需要企业标识字段 var options = context.ServiceProvider.GetRequiredService<IOptions<AbpWeChatWorkMessageResolveOptions>>().Value;
if (context.HasMessageKey("AgentID"))
{
return ResolveWeComMessageAsync(context);
}
return Task.CompletedTask; return ResolveMessageAsync(context, options);
} }
protected abstract Task ResolveWeComMessageAsync(IMessageResolveContext context); protected abstract Task ResolveMessageAsync(IMessageResolveContext context, AbpWeChatWorkMessageResolveOptions options);
} }

39
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<AbpWeChatWorkMessageResolveOptions> options)
: base(cryptoService, serviceProvider)
{
_options = options.Value;
}
protected async override Task<MessageResolveResult> 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;
}
}

1
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN.Abp.WeChat.Work.csproj

@ -10,6 +10,7 @@
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>

18
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)); options.MapCodeNamespace(WeChatWorkErrorCodes.Namespace, typeof(WeChatWorkResource));
}); });
context.Services.AddHttpClient(AbpWeChatWorkGlobalConsts.ApiClient, context.Services.AddApiClient();
options => context.Services.AddOAuthClient();
{ context.Services.AddLoginClient();
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");
});
} }
} }

7
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() public virtual string SerializeToJson()
{ {
Validate();
return WeChatObjectSerializeExtensions.SerializeToJson(this); return WeChatObjectSerializeExtensions.SerializeToJson(this);
} }
protected virtual void Validate()
{
}
} }

61
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<HttpClient> 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<HttpClient> 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<HttpClient> 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);
}
}
Loading…
Cancel
Save