最近的项目系之3——core3.0整合Senparc
1、前言
既然是.net下微信开发,自然少不了Senparc,可以说这个框架的存在, 至少节省了微信相关工作量的80%。事实上,项目开始前,还纠结了下是Java还是core,之所以最终选择core,除了情怀外,更重要的便是这个微信开发框架的存在。本项目的整合方式,极大程度上参考了Senparc官方的示例,官方示例可以说很全面、详细了。
2、整合方式
1)增加Senparc配置节
appsettings.json中添加如下配置节:
"SenparcSetting": {
"IsDebug": true,
"DefaultCacheNamespace": "Fuck"
//分布式缓存
//"Cache_Redis_Configuration": "#{Cache_Redis_Configuration}#",
//"Cache_Memcached_Configuration": "#{Cache_Memcached_Configuration}#",
//"SenparcUnionAgentKey": "#{SenparcUnionAgentKey}#"
},
"SenparcWeixinSetting": {
"IsDebug": true,
"Token": "Fuck",
"EncodingAESKey": "FuckKey",
"WeixinAppId": "FuckAppId",
"WeixinAppSecret": "FuckAppSecret"
},
SenparcSetting部分是Senparc底层的通用配置,目前我项目中暂未用到,如果用到则对应配置,如缓存的命名空间,用来防止多应用可能的缓存key冲突,分布式缓存连接等。
SenparcWeixinSetting是公众号相关的配置,Token、EncodingAESKey、WeixinAppId、WeixinAppSecret均分别对应公众号后台的账户信息,不多赘述。生产环境中,记得把上述IsDebug配置为false,减少调试信息及提高性能。
2) 微信消息处理器
增加自定义消息处理器,继承至MessageHandler<DefaultMpMessageContext>:
public class CustomMessageHandler : MessageHandler<DefaultMpMessageContext>
{
public CustomMessageHandler(Stream inputStream, PostModel postModel, int maxRecordCount = , bool onlyAllowEcryptMessage = false)
: base(inputStream, postModel, maxRecordCount, onlyAllowEcryptMessage)
{
OnlyAllowEcryptMessage = true;
//在指定条件下,不使用消息去重
base.OmitRepeatedMessageFunc = requestMessage =>
{
var textRequestMessage = requestMessage as RequestMessageText;
if (textRequestMessage != null && textRequestMessage.Content == "容错")
{
return false;
}
return true;
};
} public override IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage)
{
var responseMessage = this.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "您好,欢迎关注XXXX!"; return responseMessage;
}
}
重写的DefaultResponseMessage方法表示,系统收到微信用户收到的任何消息时,都自动回复"您好,欢迎关注XXXX!"的文本消息。MessageHandler<DefaultMpMessageContext>中可以重载的方法很多,主要是响应微信终端动作的一系列方法,比如用户发送文本、用户点击链接、用户发送图片、发送位置等,如果你需要处理对应事件,那就重载对应方法,我这里偷懒了,搞了个所有类型消息默认回复。
3)系统与微信通信
增加控制器,如下:
[AllowAnonymous]
public class WeixinController : Controller
{
private readonly IWebHostEnvironment _env;
private readonly SenparcWeixinSetting _weixinSetting; public WeixinController(IWebHostEnvironment env,
IOptions<SenparcWeixinSetting> weixinSetting)
{
_env = env;
_weixinSetting = weixinSetting.Value;
} [HttpGet]
[ActionName("Index")]
public Task<ActionResult> Get(string signature, string timestamp, string nonce, string echostr)
{
return Task.Factory.StartNew(() =>
{
if (CheckSignature.Check(signature, timestamp, nonce, _weixinSetting.Token))
{
return echostr; //返回随机字符串则表示验证通过
}
else
{
return $"failed:{signature},{CheckSignature.GetSignature(timestamp, nonce, _weixinSetting.Token)}。如果你在浏览器中看到这句话,说明此地址可以被作为微信公众账号后台的Url,请注意保持Token一致。";
}
})
.ContinueWith<ActionResult>(task => Content(task.Result));
} /// <summary>
/// 最简化的处理流程
/// </summary>
[HttpPost]
[ActionName("Index")]
public async Task<ActionResult> Post(PostModel postModel)
{
if (!CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, _weixinSetting.Token))
{
return new WeixinResult("参数错误!");
} postModel.Token = _weixinSetting.Token;
postModel.EncodingAESKey = _weixinSetting.EncodingAESKey;
postModel.AppId = _weixinSetting.WeixinAppId; var cancellationToken = new CancellationToken(); var messageHandler = new CustomMessageHandler(Request.GetRequestMemoryStream(), postModel, )
{
DefaultMessageHandlerAsyncEvent = DefaultMessageHandlerAsyncEvent.SelfSynicMethod
};
messageHandler.GlobalMessageContext.ExpireMinutes = ; //messageHandler.SaveRequestMessageLog();
await messageHandler.ExecuteAsync(cancellationToken);
//messageHandler.SaveResponseMessageLog(); return new FixWeixinBugWeixinResult(messageHandler);
} [HttpPost]
public ActionResult CreateMenu()
{
var menuFileInfo = _env.ContentRootFileProvider.GetFileInfo("menu.json");
using (var stream = menuFileInfo.CreateReadStream())
{
using (StreamReader streamReader = new StreamReader(stream))
{
var menuContent = streamReader.ReadToEnd();
MenuFull_ButtonGroup buttonGroup = JsonSerializer.Deserialize<MenuFull_ButtonGroup>(menuContent); var tokenResult = Senparc.Weixin.MP.CommonAPIs.CommonApi.GetToken(_weixinSetting.WeixinAppId, _weixinSetting.WeixinAppSecret);
if (tokenResult.errcode != ReturnCode.请求成功)
{
return Json(tokenResult);
} var menuResult = Senparc.Weixin.MP.CommonAPIs.CommonApi.CreateMenu(tokenResult.access_token, buttonGroup);
if (menuResult.errcode != ReturnCode.请求成功)
{
return Json(menuResult);
} return Json("设置成功");
}
}
} /// <summary>
/// 获取菜单接口
/// </summary>
/// <returns></returns>
[HttpGet]
public ActionResult GetMenu()
{
var tokenResult = Senparc.Weixin.MP.CommonAPIs.CommonApi.GetToken(_weixinSetting.WeixinAppId, _weixinSetting.WeixinAppSecret);
if (tokenResult.errcode != ReturnCode.请求成功)
{
return Json(tokenResult);
} var menuResult = Senparc.Weixin.MP.CommonAPIs.CommonApi.GetMenu(tokenResult.access_token); return Json(menuResult);
}
}
构造函数中,注入微信相关配置SenparcWeixinSetting,get方法,用来响应微信官方的URL校验,注意该方法公布出去的reset地址需要跟公众号后台配置的token校验地址一致。关于微信的token校验,相比前几年的一个变化是,开发者需要在域名对应根路径下放置一个微信后台提供下载的TXT文件,听起来绕是吧,那我往简单说,就是http://yourdomain/xxxx.txt需要能访问到公众号后台下载的那个xxxx.txt。可以根据具体部署情况灵活处理此要求,比如可以在反向代理层,也可以在应用中去处理,比如我这儿就是直接放在系统应用中处理,具体来说,如果在core中引用了UseStaticfile中间件,则core默认把wwwroot作为域名根目录公布出去,我们的前端文件就是这么被公布出去的,所以在开启Staticfile的情况下,直接把XXXX.txt文件放置到wwwroot目录中即可通过微信文件校验。说句题外话,微信这种校验方式,其实和Let's encrypt数字证书的校验是一样的,目的就是为了证明你确实是你声明的那个域名对应的服务器。
Post方法,用来接收微信服务器推送过来的微信终端的消息,其中就用到了上述自定义消息处理器。
CreateMenu用来提供创建微信菜单的api,我的做法是把微信菜单定义在menu.json中,然后代码读取并调用微信相关方法创建。之所以这样是因为菜单功能可能经常变化,所以做成配置化。生产环境中,记得给CreateMenu方法做鉴权,否则别人随便操你的菜单,那可不是好玩儿的。
GetMenu,获取当前微信菜单,这个不必多说。
4)微信相关服务&中间件注册
Startup.ConfigService中添加如下片段:
//微信相关服务
services.AddSenparcGlobalServices(Configuration)
.AddSenparcWeixinServices(Configuration);
这是注册Senparc微信相关服务
Startup.Config中添加如下片段注册Senparc相关中间件:
IRegisterService register = RegisterService.Start(env, senparcSetting.Value)
.UseSenparcGlobal();
register.RegisterTraceLog(() => ConfigTraceLog(monitorService));
register.UseSenparcWeixin(senparcWeixinSetting.Value, senparcSetting.Value)
.RegisterMpAccount(senparcWeixinSetting.Value, "Fuck XXXXXX");
最近的项目系之3——core3.0整合Senparc的更多相关文章
- 最近的项目系之2——core3.0整合Autofac
1.前言 core3.0与之前版本相比,有一些brokenchanges,那周边一些配套组件往往也难逃brokenchanges,Autofac也不例外.这里重点关注core整合Autofac,与之前 ...
- What?VS2019创建新项目居然没有.NET Core3.0的模板?Bug?
今天是个值得欢喜的日子,因为VS2019在今天正式发布了.作为微软粉,我已经用了一段时间的VS2019 RC版本了.但是,今天有很多小伙伴在我的<ASP.NET Core 3.0 上的gRPC服 ...
- .Net Core3.0 WebApi 项目框架搭建 五: 轻量型ORM+异步泛型仓储
.Net Core3.0 WebApi 项目框架搭建:目录 SqlSugar介绍 SqlSugar是国人开发者开发的一款基于.NET的ORM框架,是可以运行在.NET 4.+ & .NET C ...
- .Net Core3.0 WebApi 项目框架搭建:目录
一.目录 .Net Core3.0 WebApi 项目框架搭建 一:实现简单的Resful Api .Net Core3.0 WebApi 项目框架搭建 二:API 文档神器 Swagger .Net ...
- .Net Core3.0 WebApi 项目框架搭建 一:实现简单的Resful Api
.Net Core3.0 WebApi 项目框架搭建:目录 开发环境 Visual Studio 2019.net core 3.1 创建项目 新建.net core web项目,如果没有安装.net ...
- .Net Core3.0 WebApi 项目框架搭建 二:API 文档神器 Swagger
.Net Core3.0 WebApi 项目框架搭建:目录 为什么使用Swagger 随着互联网技术的发展,现在的网站架构基本都由原来的后端渲染,变成了:前端渲染.后端分离的形态,而且前端技术和后端技 ...
- .Net Core3.0 WebApi 项目框架搭建 三:读取appsettings.json
.Net Core3.0 WebApi 项目框架搭建:目录 appsettings.json 我们在写项目时往往会把一些经常变动的,可能会变动的参数写到配置文件.数据库中等可以存储数据且方便配置的地方 ...
- .Net Core3.0 WebApi 项目框架搭建 四:JWT权限验证
.Net Core3.0 WebApi 项目框架搭建:目录 什么是JWT 根据维基百科定义,JWT(读作 [/dʒɒt/]),即JSON Web Tokens,是一种基于JSON的.用于在网络上声明某 ...
- .Net Core3.0 WebApi 项目框架搭建 五:仓储模式
.Net Core3.0 WebApi 项目框架搭建:目录 理论介绍 仓储(Respository)是存在于工作单元和数据库之间单独分离出来的一层,是对数据访问的封装.其优点: 1)业务层不需要知道它 ...
随机推荐
- sublime插件开发教程3
今天就看下api的使用方法 中文的api文档 https://mux.alimama.com/posts/549.html#sublime.View sublime模块 方法 返回值 描述 set_t ...
- 织女星开发板RISC-V内核实现微秒级精确延时
前言 收到VEGA织女星开发板也有一段时间了,好久没玩了,想驱动个OLED屏,但是首先要实现IIC协议,而实现IIC协议,最基本的就是需要一个精确的延时函数,所以研究了一下如何来写一个精确的延时函数. ...
- NXP恩智浦VEGA织女星开发板免费申请!
前言 大概两周前申请了一块NXP恩智浦的开发板,今天终于收到了!在这里推荐给大家,官方网站刚上线一个月左右,目前申请的人还不算多,感兴趣的朋友可以申请一个,体验一下这个四核性能怪兽.大厂就是大气,包装 ...
- vuex动态引入store modules
主要解决的问题每次建一个module需要自己去主index.js里面去注册 为了偷懒,也为了避免团队开发时同时对index.js 进行修改引发冲突 所以在index.js中 动态的对子目录和模块进行注 ...
- Redis在Window下的安装部署
一.下载 由于redis官方不支持windows,所以需要在github上下载window的版本:下载地址.redis约定版次版本号(即第一个小数点后的数字)为偶数的版本是稳定版本(如2.8,3.0) ...
- 企业架构如何实施的简介(TOGAF深度好文)
本文来自企业架构学院: BangEA:如何实施企业架构? IT不仅是开展业务的手段,而且正在迅速演变为业务,IT绩效会直接影响企业的盈利能力,但很多企业并没有适时或充分的让IT组织参与业务的规划和决策 ...
- Django 资源 与 知识 Django中自建脚本并使用Django环境 model中的save()方法说明 filter()用法
Django 资源 与 知识 Django中自建脚本并使用Django环境 model中的save()方法说明 filter()用法 2018/11/06 Chenxin 资料说明 Django基础入 ...
- Ubuntu 18.04 安装 python 的 redis 库
安装 如果只是安装了 python2.x 或者 python3.x,直接安装即可,命令如下: pip install redis 如果是同时安装了 python2.x 和 python3.x 的,则需 ...
- npm install 提示 `gyp: No Xcode or CLT version detected!` MacOS 10.15
https://github.com/nodejs/node-gyp/issues/569 https://github.com/nodejs/node-gyp/issues/1927 解决链接:ht ...
- windows golang安装golang.org/x/net text grpc
使用git # 吧$GOPATH替换成自己的GOPATH git clone https://github.com/golang/net.git $GOPATH\src\golang.org\x\ne ...