DotNet实现简单微信SDK
目录
概述
上一篇文章C#实现微信扫码登录(绕过微信开发平台) - ihuadz 提到封装微信接口,本篇文章将从以下方面介绍如何使用C#实现简单的微信SDK。
仓库地址:https://github.com/ihuadz/QI.WxSdk.git
- 核心类库
- 配置
- 具体实现
- 如何使用
核心类库介绍
- WebApiClient
WebApiClient 是一个集高性能高可扩展性于一体的声明式http客户端库,具体使用方法可以查看一下官方文档
其他的都是使用dotnet提供的类库
配置
配置文件长这样,可配置多个小程序
# 微信应用(公众号/小程序)
WeixinSetting:
# 应用配置数组,可配置多个
App:
- AppId: xxxxxxxxxxxxxx
AppSecret: xxxxxxxxxxxxxxxxxxxxxxx
Name: xxxxxxxxxxxxxxx
- AppId: xxxxxxxxxxxxxx
AppSecret: xxxxxxxxxxxxxxxxxxxxxxx
Name: xxxxxxxxxxxxxxx
具体实现
封装代码太多,文章内就放出核心代码,全部sdk查看概述。
- IWxApiBase
/// <summary>
/// 微信接口映射API
/// </summary>
[JsonNetReturn(EnsureMatchAcceptContentType = false)]
public interface IWxApiBase
{
}
- 获取Access Token
// <summary>
/// 获取全局接口调用凭据, 用于小程序和公众号
/// </summary>
[HttpHost("https://api.weixin.qq.com/cgi-bin/")]
public interface IWxTokenApi : IWxApiBase
{
/// <summary>
/// 获取全局接口调用 Access token
/// </summary>
/// <remarks>
/// 用于小程序和公众号
/// https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
/// https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getAccessToken.html
/// </remarks>
/// <param name="appId">公众号或小程序的应用id</param>
/// <param name="secret">应用密钥,即appsecret</param>
/// <param name="grant_type">授权类型,获取access_token填写client_credential</param>
/// <returns></returns>
[HttpGet("token")]
Task<TokenApiResult> GetAsync([Required] string appId, [Required] string secret, string grant_type = "client_credential");
}
- 将AccessToken缓存
/// <summary>
/// 检查应用配置数据
/// </summary>
protected virtual void CheckAppSetting()
{
if (CurApp == null) throw new WxException("应用配置不能空");
if (string.IsNullOrEmpty(CurApp.AppId)) throw new WxException("应用AppId能空");
if (string.IsNullOrEmpty(CurApp.AppSecret)) throw new WxException("应用AppSecret能空");
}
/// <summary>
/// 获取Access Token
/// </summary>
/// <remarks>如果可能,会进行缓存</remarks>
/// <returns></returns>
public virtual async Task<string> GetAccessTokenAsync()
{
CheckAppSetting();
//获取token,先查询缓存
string token = await GetAccessTokenFromCacheAsync();
if (!string.IsNullOrEmpty(token)) return token;
//如果缓存中没有,调用Wx Api获取Token
IWxTokenApi tokenApi = GetService<IWxTokenApi>();
TokenApiResult result = await tokenApi.GetAsync(CurApp.AppId, CurApp.AppSecret);
//缓存token
await SetAccessTokenToCacheAsync(result.AccessToken, result.Expires);
return result.AccessToken;
}
- 最主要的是这一步,使用WebApiClient过滤器将access_token设置到每次请求微信的url中
/// <summary>
/// WebApiClient过滤器,自动设置url的access_token请求参数
/// </summary>
public class AccessTokenApiFilter : ApiFilterAttribute
{
/// <summary>
/// 请求
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public override async Task OnRequestAsync(ApiRequestContext context)
{
var tokenManager = context.HttpContext.ServiceProvider.GetRequiredService<ITokenManager>();
string accessToken = await tokenManager.GetAccessTokenAsync();
context.HttpContext.RequestMessage.AddUrlQuery("access_token", accessToken);
}
/// <summary>
/// 响应
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public override Task OnResponseAsync(ApiResponseContext context)
{
if(context.Result is ApiResultBase apiResult && apiResult!=null)
{
//如果请求的accesstoken过期,清除当前缓存的过期token
if (apiResult.IsAccessTokenInvalid)
{
var tokenManager = context.HttpContext.ServiceProvider.GetRequiredService<ITokenManager>();
tokenManager.ClearAccessTokenAsync();
}
}
return Task.CompletedTask;
}
}
以上次文章中使用到的请求短链为例,实现请求微信端。
/// <summary>
/// 小程序 URL Link, URL Scheme 接口
/// </summary>
public interface IWxMpUrllinkApi : IWxApiWithAccessTokenFilter
{
/// <summary>
/// 获取小程序 URL Link
/// </summary>
/// <remarks>
/// https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/url-link/urllink.generate.html
/// https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/url-link.html
/// </remarks>
/// <param name="input">请求数据</param>
/// <returns></returns>
[HttpPost("https://api.weixin.qq.com/wxa/generate_urllink")]
ITask<GenerateUrlLinkResult> GenerateUrllinkAsync([JsonNetContent] GenerateUrlLinkInput input);
}
IWxApiWithAccessTokenFilter
/// <summary>
/// WebApiClient过滤器,自动设置url的access_token请求参数
/// </summary>
[JsonNetReturn(EnsureMatchAcceptContentType = false)]
[AccessTokenApiFilter]
public interface IWxApiWithAccessTokenFilter
{
}
然后就是WxMpApiService,这里就只放短链相关
/// <summary>
/// 微信小程序接口聚合服务, 生命周期为Scoped
/// </summary>
public class WxMpApiService : WxApiServiceBase
{
/// <summary>
/// 小程序 URL Link, URL Scheme 接口
/// </summary>
public IWxMpUrllinkApi IUrllinkApi => GetService<IWxMpUrllinkApi>();
}
WxApiServiceBase 接口聚合服务 基类
/// <summary>
/// Wx接口聚合服务 基类
/// </summary>
public class WxApiServiceBase
{
/// <summary>
/// 微信接口集合服务
/// </summary>
/// <param name="tokenManager"></param>
public WxApiServiceBase(ITokenManager tokenManager)
{
TokenManager = tokenManager;
}
/// <summary>
/// 微信AccessToken管理器
/// </summary>
public virtual ITokenManager TokenManager { get; }
/// <summary>
/// 得到服务对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
protected virtual T GetService<T>()
{
return TokenManager.GetService<T>();
}
/// <summary>
/// 设置当前的应用
/// </summary>
/// <param name="wxApp"></param>
public virtual void SetCurApp(WxAppSetting wxApp)
{
TokenManager.SetCurApp(wxApp);
}
/// <summary>
/// 设置当前的应用,根据Appid从WxContext中查找
/// </summary>
/// <param name="appId"></param>
public virtual void SetCurApp(string appId)
{
TokenManager.SetCurApp(appId);
}
/// <summary>
/// 得到会话当前AppId
/// </summary>
/// <returns></returns>
public virtual string GetCurAppId()
{
return TokenManager?.GetCurAppId() ?? string.Empty;
}
/// <summary>
/// 当前应用
/// </summary>
/// <returns></returns>
public virtual WxAppSetting GetCurApp()
{
return TokenManager.GetCurApp();
}
}
至于ITokenManager,自己设计一下就好,都是读取配置和缓存AccessToken的一些操作,也可以查看源码概述。
最后就是如何使用了。添加一个扩展类,将封装好的Api注册
/// <summary>
/// 添加WxSdk 接口、服务,IWxSession会话
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddWxSdkAll(this IServiceCollection services)
{
//注册接口,服务
services.AddWxSdkApiAndServices();
//注册token管理器
services.AddWxSdkTokenManager();
return services;
}
/// <summary>
/// 注册token管理器,会话服务
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddWxSdkTokenManager(this IServiceCollection services)
{
//添加WxSession
services.AddScoped<ITokenManager, TokenManager>();
return services;
}
/// <summary>
/// 添加WxSdk 接口、服务
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddWxSdkApiAndServices(this IServiceCollection services)
{
services
.AddWebApiClient()
.UseJsonFirstApiActionDescriptor();
//添加Wx上下文
services.AddSingleton<WxConfig>();
//添加微信API映射
//公众接口
services.AddHttpApi<IWxTokenApi>();
//注册聚合/扩展服务 -公众号
services.AddScoped<WxPaApiService>();
//小程序接口
services.AddHttpApi<IWxMpUrllinkApi>();
//注册聚合/扩展服务 -小程序
services.AddScoped<WxMpApiService>();
return services;
}
如何使用
在你的应用中添加注册
//注册微信Sdk集成
services.AddWxSdkAll();
在service里注入后调用
//请求微信短链接口
var urlResult = await _wxMpService.IUrllinkApi.GenerateUrllinkAsync(new GenerateUrlLinkInput()
{
Path = path,
Query = query,
EnvironmentVersion = environmentVersion,
ExpireTimestamp = DateTime.Now.AddMinutes(10).ConvertToTimeStamp()
});