目录
(一) 微信公众号开发之 VS 远程调试
(二) 微信公众号开发之基础梳理
(三) 微信公众号开发之自动消息回复和自定义菜单
(四) 微信公众号开发之网页授权获取用户基本信息
(五) 微信公众号开发之网页中及时获取当前用户 Openid 及注意事项
(六) 微信公众号开发之扫码支付
(七) 微信公众号开发之公众号支付
(八) 微信公众号开发之现金红包
(九) 微信公众号开发之回复图文消息 (被动)
题记:
.NET Core 经过几年的发展, 已经可以说是遍地开花了, 现在如果还不展开. NET Core 探索之路, 那未免也太有点落后于. NET 的时代潮流了.
前几篇已经提及到了关注和回复消息事件, 但此前都局限于回复文本消息. 那么, 如果有个需求是, 用户发送特定字符, 如何回复特定的图文消息给用户呢?
首先我们来看看实现后的效果如下:
实现过程
回复图片消息
我们先看一下 回复图文消息的 xml 字符格式
- <xml>
- <ToUserName><![CDATA[toUser] ]></ToUserName>
- <FromUserName><![CDATA[fromUser] ]></FromUserName>
- <CreateTime>12345678</CreateTime>
- <MsgType><![CDATA[image] ]></MsgType>
- <Image><MediaId><![CDATA[media_id] ]></MediaId></Image>
- </xml>
根据这个 xml 格式, 我们很清楚已经知道这个地方需要用到几个必要的参数, 包括: OpenID, 微信号, 创建时间, 封面图片以及 Mediald 这些.
我们这个是在. NET Core2.1 上实现的, 这里稍微说明下, 此前我们在. NET 4.5 中使用的一般处理程序是这样写的:
- public void ProcessRequest(HttpContext context)
- {
- //TODO
- }
ASP.NET Core 中提供了一个 IHttpContextAccessor 接口, HttpContextAccessor 默认实现了它简化了访问 HttpContext.
它必须在程序启动时在 ConfigureServices 中注册, 这样在程序中就能获取到 HttpContextAccessor, 并用来访问 HttpContext.
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
然后我们在控制器中注入进来
- private readonly IHttpContextAccessor _accessor;
- public HandlerController(IHttpContextAccessor accessor)
- {
- _accessor = accessor;
- }
- [Route("ProcessRequest")]
- public void ProcessRequest()
- {
- var context = _accessor.HttpContext;
- context.Response.ContentType = "text/plain";
- string responseMsg = Response(context.Request);
- context.Response.Clear();
- context.Response.ContentType = "UTF-8";
- context.Response.WriteAsync(responseMsg);
- }
好了, 前面是一些铺垫, 代码部分和之前. NET 相差无几, 玩. NET Core 记住一句话: 无处不在的依赖注入.
这里, 我们提前将一些用到的关键词以及上面提到的必要参数放到 appsetting.JSON 配置中, 方面后面修改.
- "new_images_messages": {
- "keyword": "触发的关键字",
- "validTime": "2018-12-28",
- "title": "文章标题",
- "description": "描述",
- "picUrl": "图片 url",
- "url": "图文消息的 url"
- }
另外, 我这里采用读取配置的方式封装了一层, 在 Startup 中 DI 进 IConfiguration 接口
注: 需要引入
- using Microsoft.Extensions.Configuration;
- public Startup(IConfiguration configuration)
- {
- Configuration = configuration;
- }
- public IConfiguration Configuration { get; }
然后新建一个 ConfigurationKeys 类, 专门存放配置文件中不同类型的数据值:
- public static string NEW_IMAGES_MESSAGES_TITLE = "new_images_messages:title";
- public static string NEW_IMAGES_MESSAGES_DES = "new_images_messages:description";
- public static string NEW_IMAGES_MESSAGES_PIC = "new_images_messages:picUrl";
- public static string NEW_IMAGES_MESSAGES_URL = "new_images_messages:url";
- public static string NEW_IMAGES_MESSAGES_KEYWORD = "new_images_messages:keyword";
- public static string NEW_IMAGES_MESSAGES_VALIDTIME = "new_images_messages:validTime";
使用时首先在控制器中注入配置接口
- private readonly IConfiguration _config;
- public EventHandler(IConfiguration config)
- {
- _config = config;
- }
与发过来消息做对比
- // 判断接收到的文本消息是否是配置文件中的触发关键词
- if (content == _config[ConfigurationKeys.NEW_IMAGES_MESSAGES_KEYWORD])
- {
- _logger.LogInformation("答复图文消息");
- response =ReArticle(tm.FromUserName, tm.ToUserName);
- }
- public string ReArticle(string fromUserName, string toUserName)
- {
- var title = _config[ConfigurationKeys.NEW_IMAGES_MESSAGES_TITLE];
- var description = _config[ConfigurationKeys.NEW_IMAGES_MESSAGES_DES];
- var picUrl = _config[ConfigurationKeys.NEW_IMAGES_MESSAGES_PIC];
- var url = _config[ConfigurationKeys.NEW_IMAGES_MESSAGES_URL];
- return new NewsMessage().Template(fromUserName, toUserName, title, description, picUrl, url);
- }
这里需要将模板提前配置好, 所以这里新建了一个 Template 方法
- public string Template(string fromUserName, string toUserName, string title, string description, string picUrl, string url)
- {
- string xml = "<xml><ToUserName><![CDATA[" + fromUserName + "]]></ToUserName><FromUserName><![CDATA[" + toUserName + "]]></FromUserName>";
- xml += "<CreateTime>" + FileUtility.DateTimeToUnixTimestamp(DateTime.Now) + "</CreateTime>";
- xml +="<MsgType><![CDATA[news]]></MsgType><Content><![CDATA[]]></Content><ArticleCount>1</ArticleCount><Articles>";
- xml += "<item><Title><![CDATA[" + title + "]]></Title><Description><![CDATA[" + description +"]]></Description><PicUrl><![CDATA[" + picUrl + "]]></PicUrl><Url><![CDATA[" + url +"]]></Url></item>";
- xml += "</Articles><FuncFlag>0</FuncFlag></xml>";
- return xml;
- }
上述的时间转换方法
- public static long DateTimeToUnixTimestamp(DateTime dateTime)
- {
- var start = new DateTime(1970, 1, 1, 0, 0, 0, dateTime.Kind);
- return Convert.ToInt64((dateTime - start).TotalSeconds);
- }
至此, 已经全部实现, 那如果项目已经上线, 需要增加这个功能项, 但是又不能破坏现有服务器, 如何进行调试呢, 可以借助微信的测试号, 用于在线调试公众号.
地址: 微信测试号
进入测试号里面, 有 appID,appsecret 我们需要将这两个信息替换本地的 TokenContext 中的值. 然后 URL 可以借助花生壳等内网穿透的工具 映射到本地 进行开发调试.
整体做完就可以实现开始的展示图的效果了.
End
来源: https://www.cnblogs.com/zhangxiaoyong/p/10161188.html