Skip to content

Commit

Permalink
Merge pull request #71 from EasyAbp/sharable-caches
Browse files Browse the repository at this point in the history
Share tokens and tickets with `IAbpWeChatSharableCache`
  • Loading branch information
gdlcf88 committed Jan 13, 2023
2 parents 55a2a98 + 0644bc8 commit a051c7f
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 71 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.2.0</Version>
<Version>2.3.0</Version>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>EasyAbp Team</Authors>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Threading.Tasks;
using System.Threading.Tasks;
using EasyAbp.Abp.WeChat.Common.Infrastructure.AccessToken;
using EasyAbp.Abp.WeChat.Common.SharedCache.StackExchangeRedis.Settings;
using Microsoft.Extensions.Caching.Distributed;
Expand All @@ -10,14 +9,14 @@

namespace EasyAbp.Abp.WeChat.Common.SharedCache.StackExchangeRedis.Infrastructure.AccessToken;

public class SharedStackExchangeRedisAccessTokenCache : IAccessTokenCache, ITransientDependency
public class SharedStackExchangeRedisAbpWeChatSharableCache : IAbpWeChatSharableCache, ITransientDependency
{
public static string CachePrefix { get; set; } = "WeChatTokens:";
public static string SettingName { get; set; } = SharedCacheStackExchangeRedisSettings.RedisConfiguration;

private readonly ISettingProvider _settingProvider;

public SharedStackExchangeRedisAccessTokenCache(ISettingProvider settingProvider)
public SharedStackExchangeRedisAbpWeChatSharableCache(ISettingProvider settingProvider)
{
_settingProvider = settingProvider;
}
Expand All @@ -29,14 +28,18 @@ public virtual async Task<string> GetOrNullAsync(string key)
return await redisCache.GetStringAsync(await GetKeyAsync(key));
}

public virtual async Task SetAsync(string key, string value)
public virtual async Task SetAsync(string key, string value, DistributedCacheEntryOptions options)
{
var redisCache = await CreateAbpRedisCacheAsync();

await redisCache.SetStringAsync(await GetKeyAsync(key), value, new DistributedCacheEntryOptions
if (value is null)
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(115)
});
await redisCache.RemoveAsync(await GetKeyAsync(key));
}
else
{
await redisCache.SetStringAsync(await GetKeyAsync(key), value, options);
}
}

protected virtual Task<string> GetKeyAsync(string key)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed;
using Volo.Abp.Caching;
Expand All @@ -7,11 +6,11 @@
namespace EasyAbp.Abp.WeChat.Common.Infrastructure.AccessToken;

[Dependency(TryRegister = true)]
public class DefaultAccessTokenCache : IAccessTokenCache, ITransientDependency
public class DefaultAbpWeChatSharableCache : IAbpWeChatSharableCache, ITransientDependency
{
protected IDistributedCache<string> DistributedCache { get; }

public DefaultAccessTokenCache(IDistributedCache<string> distributedCache)
public DefaultAbpWeChatSharableCache(IDistributedCache<string> distributedCache)
{
DistributedCache = distributedCache;
}
Expand All @@ -21,11 +20,8 @@ public virtual Task<string> GetOrNullAsync(string key)
return DistributedCache.GetAsync(key);
}

public virtual Task SetAsync(string key, string value)
public virtual Task SetAsync(string key, string value, DistributedCacheEntryOptions options)
{
return DistributedCache.SetAsync(key, value, new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(115)
});
return DistributedCache.SetAsync(key, value, options);
}
}
Original file line number Diff line number Diff line change
@@ -1,35 +1,39 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed;
using Newtonsoft.Json.Linq;
using Volo.Abp.DependencyInjection;

namespace EasyAbp.Abp.WeChat.Common.Infrastructure.AccessToken
{
public class DefaultAccessTokenProvider : IAccessTokenProvider, ITransientDependency
{
private readonly IAccessTokenCache _accessTokenCache;
private readonly IAbpWeChatSharableCache _abpWeChatSharableCache;
private readonly IHttpClientFactory _httpClientFactory;

public DefaultAccessTokenProvider(
IAccessTokenCache accessTokenCache,
IAbpWeChatSharableCache abpWeChatSharableCache,
IHttpClientFactory httpClientFactory)
{
_accessTokenCache = accessTokenCache;
_abpWeChatSharableCache = abpWeChatSharableCache;
_httpClientFactory = httpClientFactory;
}

public virtual async Task<string> GetAsync(string appId, string appSecret)
{
var cacheKey = await GetCacheKeyAsync(appId);

var token = await _accessTokenCache.GetOrNullAsync(cacheKey);
var token = await _abpWeChatSharableCache.GetOrNullAsync(cacheKey);

if (token.IsNullOrWhiteSpace())
{
token = await RequestAccessTokenAsync(appId, appSecret);

await _accessTokenCache.SetAsync(cacheKey, token);
await _abpWeChatSharableCache.SetAsync(cacheKey, token, new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(115)
});
}

return token;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.Caching.Distributed;

namespace EasyAbp.Abp.WeChat.Common.Infrastructure.AccessToken;

public interface IAccessTokenCache
public interface IAbpWeChatSharableCache
{
Task<string> GetOrNullAsync([NotNull] string key);

Task SetAsync([NotNull] string key, [CanBeNull] string value);
Task SetAsync([NotNull] string key, [CanBeNull] string value, DistributedCacheEntryOptions options);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using EasyAbp.Abp.WeChat.Official.Options;
using Microsoft.Extensions.Caching.Distributed;
using Newtonsoft.Json.Linq;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;

namespace EasyAbp.Abp.WeChat.Official.JsTickets
Expand All @@ -17,45 +16,42 @@ public class DefaultJsTicketProvider : IJsTicketProvider, ITransientDependency
private readonly IHttpClientFactory _httpClientFactory;
private readonly IAccessTokenProvider _accessTokenProvider;
private readonly IAbpWeChatOptionsProvider<AbpWeChatOfficialOptions> _optionsProvider;
private readonly IDistributedCache<string> _distributedCache;
private readonly IAbpWeChatSharableCache _cache;

public DefaultJsTicketProvider(
IHttpClientFactory httpClientFactory,
IAccessTokenProvider accessTokenProvider,
IAbpWeChatOptionsProvider<AbpWeChatOfficialOptions> optionsProvider,
IDistributedCache<string> distributedCache)
IAbpWeChatSharableCache cache)
{
_httpClientFactory = httpClientFactory;
_accessTokenProvider = accessTokenProvider;
_optionsProvider = optionsProvider;
_distributedCache = distributedCache;
_cache = cache;
}

public virtual async Task<string> GetTicketJsonAsync(string appId, string appSecret)
{
var options = await _optionsProvider.GetAsync(appId);
var cacheKey = await GetCacheKeyAsync(appId);

var accessToken = await _accessTokenProvider.GetAsync(appId, appSecret);
var cachedValue = await _cache.GetOrNullAsync(cacheKey);

return await _distributedCache.GetOrAddAsync(await GetJsTicketAsync(options),
async () =>
{
var client = _httpClientFactory.CreateClient(AbpWeChatConsts.HttpClientName);
var requestUrl =
$"https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={accessToken}&type=jsapi";
if (cachedValue.IsNullOrEmpty())
{
cachedValue = await RequestTicketAsync(appId, appSecret);

return await (await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, requestUrl)))
.Content.ReadAsStringAsync();
},
() => new DistributedCacheEntryOptions
await _cache.SetAsync(cacheKey, cachedValue, new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(115)
});
}

return cacheKey;
}

protected virtual async Task<string> GetJsTicketAsync(IAbpWeChatOptions options)
protected virtual Task<string> GetCacheKeyAsync(string appId)
{
return $"WeChatJsTicket:{options.AppId}";
return Task.FromResult($"WeChatJsTicket:{appId}");
}

public virtual async Task<string> GetTicketAsync(string appId, string appSecret)
Expand All @@ -65,5 +61,17 @@ public virtual async Task<string> GetTicketAsync(string appId, string appSecret)

return jObj.SelectToken("$.ticket")!.Value<string>();
}

protected virtual async Task<string> RequestTicketAsync(string appId, string appSecret)
{
var accessToken = await _accessTokenProvider.GetAsync(appId, appSecret);

var client = _httpClientFactory.CreateClient(AbpWeChatConsts.HttpClientName);
var requestUrl =
$"https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={accessToken}&type=jsapi";

return await (await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, requestUrl)))
.Content.ReadAsStringAsync();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,32 @@
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;
using EasyAbp.Abp.WeChat.Common.Infrastructure.AccessToken;
using Microsoft.Extensions.Caching.Distributed;
using Volo.Abp.DependencyInjection;

namespace EasyAbp.Abp.WeChat.OpenPlatform.ThirdPartyPlatform.AccessToken;

public class AuthorizerAccessTokenCache : IAuthorizerAccessTokenCache, ITransientDependency
{
protected IAccessTokenCache AccessTokenCache { get; }
protected IAbpWeChatSharableCache AbpWeChatSharableCache { get; }

public AuthorizerAccessTokenCache(IAccessTokenCache accessTokenCache)
public AuthorizerAccessTokenCache(IAbpWeChatSharableCache abpWeChatSharableCache)
{
AccessTokenCache = accessTokenCache;
AbpWeChatSharableCache = abpWeChatSharableCache;
}

public virtual async Task<string> GetOrNullAsync(string componentAppId, string authorizerAppId)
{
return await AccessTokenCache.GetOrNullAsync(await GetCacheKeyAsync(componentAppId, authorizerAppId));
return await AbpWeChatSharableCache.GetOrNullAsync(await GetCacheKeyAsync(componentAppId, authorizerAppId));
}

public virtual async Task SetAsync(string componentAppId, string authorizerAppId, string accessToken)
{
await AccessTokenCache.SetAsync(await GetCacheKeyAsync(componentAppId, authorizerAppId), accessToken);
await AbpWeChatSharableCache.SetAsync(await GetCacheKeyAsync(
componentAppId, authorizerAppId), accessToken, new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(115)
});
}

protected virtual async Task<string> GetCacheKeyAsync(string componentAppId, string authorizerAppId) =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Threading.Tasks;
using Volo.Abp.Caching;
using EasyAbp.Abp.WeChat.Common.Infrastructure.AccessToken;
using Microsoft.Extensions.Caching.Distributed;
using Volo.Abp.DependencyInjection;

namespace EasyAbp.Abp.WeChat.OpenPlatform.ThirdPartyPlatform.AuthorizerRefreshToken;
Expand All @@ -12,21 +13,22 @@ namespace EasyAbp.Abp.WeChat.OpenPlatform.ThirdPartyPlatform.AuthorizerRefreshTo
[Dependency(TryRegister = true)]
public class CacheAuthorizerRefreshTokenStore : IAuthorizerRefreshTokenStore, ITransientDependency
{
private readonly IDistributedCache<string> _cache;
private readonly IAbpWeChatSharableCache _cache;

public CacheAuthorizerRefreshTokenStore(IDistributedCache<string> cache)
public CacheAuthorizerRefreshTokenStore(IAbpWeChatSharableCache cache)
{
_cache = cache;
}

public virtual async Task<string> GetOrNullAsync(string componentAppId, string authorizerAppId)
{
return await _cache.GetAsync(await GetCacheKeyAsync(componentAppId, authorizerAppId));
return await _cache.GetOrNullAsync(await GetCacheKeyAsync(componentAppId, authorizerAppId));
}

public virtual async Task SetAsync(string componentAppId, string authorizerAppId, string authorizerRefreshToken)
{
await _cache.SetAsync(await GetCacheKeyAsync(componentAppId, authorizerAppId), authorizerRefreshToken);
await _cache.SetAsync(await GetCacheKeyAsync(componentAppId, authorizerAppId), authorizerRefreshToken,
new DistributedCacheEntryOptions());
}

protected virtual async Task<string> GetCacheKeyAsync(string componentAppId, string authorizerAppId) =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using EasyAbp.Abp.WeChat.Common.Infrastructure.AccessToken;
using EasyAbp.Abp.WeChat.OpenPlatform.ThirdPartyPlatform.ApiRequests;
using EasyAbp.Abp.WeChat.OpenPlatform.ThirdPartyPlatform.Models;
using EasyAbp.Abp.WeChat.OpenPlatform.ThirdPartyPlatform.VerifyTicket;
using Microsoft.Extensions.Caching.Distributed;
using Volo.Abp;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;

namespace EasyAbp.Abp.WeChat.OpenPlatform.ThirdPartyPlatform.ComponentAccessToken;

public class DefaultComponentAccessTokenProvider : IComponentAccessTokenProvider, ITransientDependency
{
private readonly IDistributedCache<string> _distributedCache;
private readonly IAbpWeChatSharableCache _cache;
private readonly IComponentVerifyTicketStore _componentVerifyTicketStore;
private readonly IWeChatThirdPartyPlatformApiRequester _apiRequester;

public DefaultComponentAccessTokenProvider(
IDistributedCache<string> distributedCache,
IAbpWeChatSharableCache cache,
IComponentVerifyTicketStore componentVerifyTicketStore,
IWeChatThirdPartyPlatformApiRequester apiRequester)
{
_distributedCache = distributedCache;
_cache = cache;
_componentVerifyTicketStore = componentVerifyTicketStore;
_apiRequester = apiRequester;
}
Expand All @@ -32,12 +32,24 @@ public virtual async Task<string> GetAsync(string componentAppId, string compone
Check.NotNullOrWhiteSpace(componentAppId, nameof(componentAppId));
Check.NotNullOrWhiteSpace(componentAppSecret, nameof(componentAppSecret));

return await _distributedCache.GetOrAddAsync($"ComponentAccessToken:{componentAppId}",
async () => await RequestComponentAccessTokenAsync(componentAppId, componentAppSecret),
() => new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(115)
});
var key = $"ComponentAccessToken:{componentAppId}";

var cachedValue = await _cache.GetOrNullAsync(key);

if (cachedValue.IsNullOrEmpty())
{
cachedValue = await RequestComponentAccessTokenAsync(componentAppId, componentAppSecret);

await _cache.SetAsync(
key,
cachedValue,
new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(115)
});
}

return cachedValue;
}

protected virtual async Task<string> RequestComponentAccessTokenAsync(
Expand Down

0 comments on commit a051c7f

Please sign in to comment.