Skip to content

Commit

Permalink
Merge pull request #62 from EasyAbp/encryptor-encrypt-method
Browse files Browse the repository at this point in the history
Add `EncryptAsync` in `IWeChatNotificationEncryptor`
  • Loading branch information
gdlcf88 committed Dec 24, 2022
2 parents 231f7d1 + 00c7696 commit cb12487
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 23 deletions.
2 changes: 1 addition & 1 deletion common.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Version>2.0.0-rc.17</Version>
<Version>2.0.0-rc.18</Version>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>EasyAbp Team</Authors>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ namespace EasyAbp.Abp.WeChat.Common.Infrastructure.Encryption;

public interface IWeChatNotificationEncryptor
{
Task<TModel> DecryptPostDataAsync<TModel>(string token, string encodingAesKey, string appId,
string msgSignature, string timestamp, string notice, string postData) where TModel : ExtensibleObject, new();
Task<string> EncryptAsync(string token, string encodingAesKey, string appId, string xml);

Task<TModel> DecryptAsync<TModel>(string token, string encodingAesKey, string appId, string msgSignature,
string timestamp, string nonce, string encryptedXml) where TModel : ExtensibleObject, new();
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
Expand All @@ -15,15 +16,36 @@ public class WeChatNotificationEncryptor : IWeChatNotificationEncryptor, ITransi
{
private readonly IJsonSerializer _jsonSerializer;

protected static readonly Random Random = new();

public WeChatNotificationEncryptor(IJsonSerializer jsonSerializer)
{
_jsonSerializer = jsonSerializer;
}

public virtual async Task<TModel> DecryptPostDataAsync<TModel>(string token, string encodingAesKey, string appId,
string msgSignature, string timestamp, string notice, string postData) where TModel : ExtensibleObject, new()
public virtual Task<string> EncryptAsync(string token, string encodingAesKey, string appId, string xml)
{
var crypt = new WXBizMsgCrypt(token, encodingAesKey, appId);

string encryptedXml = null;

var errCode = crypt.EncryptMsg(xml,
((int)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds).ToString(),
GenerateNonce(), ref encryptedXml);

if (errCode != 0)
{
throw new UserFriendlyException($"加密失败,错误码: {errCode}");
}

return Task.FromResult(encryptedXml);
}

public virtual Task<TModel> DecryptAsync<TModel>(string token, string encodingAesKey, string appId,
string msgSignature, string timestamp, string nonce, string encryptedXml)
where TModel : ExtensibleObject, new()
{
if (postData == null)
if (encryptedXml == null)
{
throw new UserFriendlyException("没有找到加密内容");
}
Expand All @@ -35,21 +57,20 @@ public WeChatNotificationEncryptor(IJsonSerializer jsonSerializer)
var errCode = crypt.DecryptMsg(
msgSignature,
timestamp,
notice,
postData,
nonce,
encryptedXml,
ref decryptXml);

if (errCode != 0)
{
throw new BusinessException($"解密失败,错误码: {errCode}");
throw new UserFriendlyException($"解密失败,错误码: {errCode}");
}

var doc = XDocument.Parse(decryptXml);
var node_cdata = doc.DescendantNodes().OfType<XCData>().ToList();

foreach (var node in node_cdata)
foreach (var node in doc.DescendantNodes().OfType<XCData>().ToList())
{
node.Parent.Add(node.Value);
node.Parent!.Add(node.Value);
node.Remove();
}

Expand All @@ -63,6 +84,13 @@ public WeChatNotificationEncryptor(IJsonSerializer jsonSerializer)
model.SetProperty(pair.Key, pair.Value);
}

return model;
return Task.FromResult(model);
}

protected virtual string GenerateNonce()
{
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

return new string(Enumerable.Repeat(chars, 32).Select(s => s[Random.Next(s.Length)]).ToArray());
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using EasyAbp.Abp.WeChat.Common.Infrastructure.Encryption;
using EasyAbp.Abp.WeChat.Common.Infrastructure.Options;
using EasyAbp.Abp.WeChat.Common.Infrastructure.Services;
using EasyAbp.Abp.WeChat.Common.Models;
using EasyAbp.Abp.WeChat.OpenPlatform.RequestHandling.Dtos;
using EasyAbp.Abp.WeChat.OpenPlatform.ThirdPartyPlatform.Options;
using EasyAbp.Abp.WeChat.OpenPlatform.ThirdPartyPlatform.Services;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
Expand All @@ -18,6 +21,7 @@ public class ReleaseTestWeChatThirdPartyPlatformAppEventHandler : IWeChatThirdPa
{
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<ReleaseTestWeChatThirdPartyPlatformAppEventHandler> _logger;

public virtual string MsgType => "text";
public int Priority => -10000;

Expand All @@ -34,7 +38,7 @@ public class ReleaseTestWeChatThirdPartyPlatformAppEventHandler : IWeChatThirdPa
{
if (ReleaseTestConsts.OfficialAppIds.Contains(authorizerAppId))
{
return await HandleOfficialReleaseTestAsync(componentAppId, model);
return await HandleOfficialReleaseTestAsync(componentAppId, authorizerAppId, model);
}

if (ReleaseTestConsts.MiniProgramsAppIds.Contains(authorizerAppId))
Expand All @@ -46,20 +50,31 @@ public class ReleaseTestWeChatThirdPartyPlatformAppEventHandler : IWeChatThirdPa
}

protected virtual async Task<AppEventHandlingResult> HandleOfficialReleaseTestAsync(string componentAppId,
WeChatAppEventModel model)
string authorizerAppId, WeChatAppEventModel model)
{
var content = model.GetProperty<string>("Content");

if (content == "TESTCOMPONENT_MSG_TYPE_TEXT")
{
return new AppEventHandlingResult(true, null,
var xml =
$"<xml>"
+ $"<ToUserName><![CDATA[{model.FromUserName}]]></ToUserName>"
+ $"<FromUserName><![CDATA[{model.ToUserName}]]></FromUserName>"
+ $"<CreateTime>{(int)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds}</CreateTime>"
+ $"<MsgType><![CDATA[text]]></MsgType>"
+ $"<Content><![CDATA[TESTCOMPONENT_MSG_TYPE_TEXT_callback]]></Content>"
+ $"</xml>");
+ $"</xml>";

var encryptor = _serviceProvider.GetRequiredService<IWeChatNotificationEncryptor>();
var optionsProvider = _serviceProvider
.GetRequiredService<IAbpWeChatOptionsProvider<AbpWeChatThirdPartyPlatformOptions>>();

var options = await optionsProvider.GetAsync(componentAppId);

var encryptedXml =
await encryptor.EncryptAsync(options.Token, options.EncodingAesKey, authorizerAppId, xml);

return new AppEventHandlingResult(true, null, encryptedXml);
}

if (!content.StartsWith("QUERY_AUTH_CODE:"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public virtual async Task<AppEventHandlingResult> NotifyAppAsync(NotifyAppInput
protected virtual async Task<T> DecryptMsgAsync<T>(AbpWeChatThirdPartyPlatformOptions options,
WeChatEventRequestModel request) where T : ExtensibleObject, new()
{
return await _weChatNotificationEncryptor.DecryptPostDataAsync<T>(
return await _weChatNotificationEncryptor.DecryptAsync<T>(
options.Token,
options.EncodingAesKey,
options.AppId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ public async Task Should_Handle_Release_Test_Official_User_Message()
await handler.HandleAsync(AbpWeChatOpenPlatformTestsConsts.AppId, OfficialAuthorizerAppId, eventModel);

result.Success.ShouldBeTrue();
result.SpecifiedResponseContent.ShouldContain(
"<Content><![CDATA[TESTCOMPONENT_MSG_TYPE_TEXT_callback]]></Content>");
result.SpecifiedResponseContent.ShouldStartWith("<xml><Encrypt><![CDATA[");
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,46 @@ namespace EasyAbp.Abp.WeChat.OpenPlatform.Tests.ThirdPartyPlatform;
public class WeChatNotificationEncryptorTest : AbpWeChatOpenPlatformTestBase
{
[Fact]
public async Task Should_Decrypt_PostData()
public async Task Should_Encrypt_Xml()
{
var encryptor = GetRequiredService<IWeChatNotificationEncryptor>();


var options = new AbpWeChatThirdPartyPlatformOptions
{
Token = AbpWeChatOpenPlatformTestsConsts.Token,
AppId = AbpWeChatOpenPlatformTestsConsts.AppId,
EncodingAesKey = AbpWeChatOpenPlatformTestsConsts.EncodingAesKey
};

var encryptedXml = await encryptor.EncryptAsync(
options.Token,
options.EncodingAesKey,
options.AppId,
"<xml><ToUserName><![CDATA[wx5823bf96d3bd56c7]]></ToUserName>" +
"<FromUserName><![CDATA[mycreate]]></FromUserName>" +
"<CreateTime>1409659813</CreateTime>" +
"<MsgType><![CDATA[text]]></MsgType>" +
"<Content><![CDATA[hello]]></Content>" +
"<MsgId>4561255354251345929</MsgId>" +
"<AgentID>218</AgentID>" +
"</xml>");

encryptedXml.ShouldStartWith("<xml><Encrypt><![CDATA[");
}

[Fact]
public async Task Should_Decrypt_Xml()
{
var encryptor = GetRequiredService<IWeChatNotificationEncryptor>();

var options = new AbpWeChatThirdPartyPlatformOptions
{
Token = AbpWeChatOpenPlatformTestsConsts.Token,
AppId = AbpWeChatOpenPlatformTestsConsts.AppId,
EncodingAesKey = AbpWeChatOpenPlatformTestsConsts.EncodingAesKey
};

var model = await encryptor.DecryptPostDataAsync<WeChatAppEventModel>(
var model = await encryptor.DecryptAsync<WeChatAppEventModel>(
options.Token,
options.EncodingAesKey,
options.AppId,
Expand Down

0 comments on commit cb12487

Please sign in to comment.