惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Attack and Defense Labs
Attack and Defense Labs
The GitHub Blog
The GitHub Blog
C
Check Point Blog
博客园_首页
MongoDB | Blog
MongoDB | Blog
N
Netflix TechBlog - Medium
F
Full Disclosure
Microsoft Security Blog
Microsoft Security Blog
爱范儿
爱范儿
Recent Announcements
Recent Announcements
阮一峰的网络日志
阮一峰的网络日志
G
GRAHAM CLULEY
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
T
Threat Research - Cisco Blogs
C
Cybersecurity and Infrastructure Security Agency CISA
V
Vulnerabilities – Threatpost
K
Kaspersky official blog
博客园 - 司徒正美
S
Schneier on Security
T
The Exploit Database - CXSecurity.com
Project Zero
Project Zero
云风的 BLOG
云风的 BLOG
Cisco Talos Blog
Cisco Talos Blog
Know Your Adversary
Know Your Adversary
雷峰网
雷峰网
V
V2EX - 技术
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Spread Privacy
Spread Privacy
罗磊的独立博客
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
S
Security Affairs
SecWiki News
SecWiki News
Schneier on Security
Schneier on Security
O
OpenAI News
Jina AI
Jina AI
PCI Perspectives
PCI Perspectives
Cyberwarzone
Cyberwarzone
Y
Y Combinator Blog
Apple Machine Learning Research
Apple Machine Learning Research
B
Blog RSS Feed
I
InfoQ
D
Docker
P
Palo Alto Networks Blog
Recorded Future
Recorded Future
M
MIT News - Artificial intelligence
博客园 - Franky
B
Blog
Scott Helme
Scott Helme
博客园 - 叶小钗
D
DataBreaches.Net

博客园 - Wuya

Avalonia中的动画 .net微信公众号开发——模板消息 .net微信公众号开发——群发消息 .net微信公众号开发——基础接口 .net微信公众号开发——快速入门 Android Studio开发入门-引用jar及so文件 随机抽样一致性算法(RANSAC)示例及源代码 提高文本框加载大文本的速度 我不是蜘蛛侠,也不是蝙蝠侠,只是路人甲 背景建模与前景检测之四(Background Generation And Foreground Detection Phase 4) - Wuya 解决Windows7无法安装SP1补丁包及无法显示Windows功能列表的方法 使用Lingobit Localizer汉化.net程序(Translate .net program using Lingobit Localizer) javascript获取到textarea文本框中的回车换行符 随机抽样一致性算法(RANSAC) 返修&售后服务管理网站设计与源码 源代码下载 - Wuya 解决EPSON R230打印机驱动程序安装错误 - Wuya - 博客园 OpenCV(EmguCV)2.1新特性介绍之图像差异StereoSGBM与设置窗口属性SetWindowProperty(StereoSGBM Of OpenCV 2.1) OpenCV(EmguCV)2.1新特性介绍之图像分割GrabCut(GrabCut Of OpenCV 2.1) - Wuya 背景建模与前景检测之三(Background Generation And Foreground Detection Phase 3)
.net微信公众号开发——消息与事件
Wuya · 2015-03-11 · via 博客园 - Wuya

作者:王先荣
    本文介绍如何处理微信公众号开发中的消息与事件,包括:(1)消息(事件)概况;(2)验证消息的真实性;(3)解析消息;(4)被动回复消息;(5)发送其他消息。
    开源项目地址:http://git.oschina.net/xrwang2/xrwang.weixin.PublicAccount
    本文源代码比较分散,主要在:
    http://git.oschina.net/xrwang2/xrwang.weixin.PublicAccount/blob/master/xrwang.net/WeixinInterface.ashx
    http://git.oschina.net/xrwang2/xrwang.weixin.PublicAccount/blob/master/xrwang.net/Example/ParseRequestMessage.aspx.cs
    http://git.oschina.net/xrwang2/xrwang.weixin.PublicAccount/tree/master/PublicAccount/RequestMessage
    http://git.oschina.net/xrwang2/xrwang.weixin.PublicAccount/tree/master/PublicAccount/ResponseMessage
    本文的演示地址:
    (1)http://xrwang.net/Example/ParseRequestMessage.aspx
    (2)关注我的公众号,并发送消息

测试号

 

测试号权限多,几乎可以测试公众平台的所有功能。

我的公众号

xrwang

 

个人订阅号,功能较少,不过我会特别优化。

1 消息(事件)概况
    当普通微信用户向公众号发消息或者微信服务器向公众号推送事件时,微信服务器将POST消息(事件)的XML数据包到开发者填写的公众号服务器URL上;公众号服务器然后对消息作出响应。
1.1 消息的流转过程
    为了便于区分,我们将微信服务器发往公众号服务器的消息称为请求(Request)消息;将公众号服务器发往微信服务器的消息称为响应(Response)消息;将推送事件看成特殊的请求消息。
    请求与响应消息的流转过程如下图所示:

1.2 请求消息
    请求消息有很多种,我们为其一一建立了对应的类,类层次结构如下图所示:

有些请求消息,我们可以做出响应,有些则不能,详见下表:

消息类型 是否事件 能够被动回复 备注
文本 ×  
图片 ×  
声音 ×  
视频 × 未知 接收不到视频消息,不知道是否能被动回复
地理位置 ×  
链接 ×  
订阅  
取消订阅 ×  
扫描二维码 ×  
上报地理位置 ×  
点击菜单拉取消息  
点击菜单跳转链接 ×  
点击菜单扫码推 ×  
点击菜单扫码等待回复  
点击菜单系统发图 未知 接收不到系统发图事件;微信服务器会发送图片消息,可回复
点击菜单拍照或相册发图 × 微信服务器会发送图片消息,可回复
点击菜单微信发图 × 微信服务器会发送图片消息,可回复
点击菜单选择地理位置 × 微信服务器会发送地理位置消息,可回复
推送群发消息结果 ×  
推送发送模板消息结果 ×  

1.3 响应消息
    响应消息的类层次结构如下图所示:


2 验证消息的真实性
    公众号服务器接收到微信服务器的请求之后,第一件事情是验证消息的真实性。
    Utility.CheckSignature方法用于验证消息签名是否正确。
    示例如下:

    /// <summary>
    /// 验证消息的有效性
    /// </summary>
    /// <param name="context"></param>
    /// <returns>如果消息有效,返回true;否则返回false。</returns>
    private bool Validate(HttpContext context)
    {
        string username = RequestEx.TryGetQueryString("username");  //在接口配置的URL中加入了username参数,表示哪个微信公众号
        AccountInfo account = AccountInfoCollection.GetAccountInfo(username);
        if (account == null)
            return false;
        string token = account.Token;
        string signature = RequestEx.TryGetQueryString("signature");
        string timestamp = RequestEx.TryGetQueryString("timestamp");
        string nonce = RequestEx.TryGetQueryString("nonce");
        if (string.IsNullOrWhiteSpace(signature) || string.IsNullOrWhiteSpace(timestamp) || string.IsNullOrWhiteSpace(nonce))
            return false;
        return xrwang.weixin.PublicAccount.Utility.CheckSignature(signature, token, timestamp, nonce);
    }

验证消息真实性

3 解析消息

    如果消息签名通过验证,我们需要将XML格式的消息文本解析成请求消息对象,RequestMessageHelper类用于完成这项工作。

RequestMessageHelper helper = new RequestMessageHelper(context.Request);
if(helper.Message != null)
{
    //消息解析成功,对它进行处理
}

    消息解析成功之后,helper.Message为消息基类RequestBaseMessage,我们可以根据属性MsgType及Event判断到底是哪种消息(事件),并转换成适当的子类型。例如:

RequestBaseMessage bm=helper.Message;
switch(bm.MsgType)
{
    case RequestMessageTypeEnum.text:  //文本消息
        HandleTextMessage((RequestTextMessage)bm);
        break;
    case RequestMessageTypeEnum.image: //图片消息
        HandleImageMessage((RequestImageMessage)bm);
        break;
    //处理其他消息
    case RequestMessageTypeEnum.event:    //事件
        RequestEventMessage ev=(RequestEventMessage)bm;
        switch(ev.Event)
        {
            case RequestEventTypeEnum.subscribe:    //订阅
                HandleSubscribeMessage((RequestSubscribeMessage)ev);
                break;
            case RequestEventTypeEnum.unsubscribe:    //取消订阅
                HandleUnsubscribeMessage((RequestUnsubscribeMessage)ev);
                break;
            //处理其他事件
        }
        break;
    default:
        break;
}

处理消息

解析消息的细节请参看源代码:http://git.oschina.net/xrwang2/xrwang.weixin.PublicAccount/blob/master/PublicAccount/RequestMessage/RequestMessageHelper.cs

4 被动回复消息
    从微信服务器接收到消息(事件)之后,我们可以在5秒之内直接(被动)回复消息;也可以先直接回复空字符串,然后再在48小时内回复客服消息。
    先初始化ResponseXxxMessage,然后用ToXml方法得到响应消息内容。
    被动回复消息的示例如下:

    /// <summary>
    /// 处理微信的POST请求
    /// </summary>
    /// <param name="context"></param>
    /// <returns>返回xml响应</returns>
    private string HandlePost(HttpContext context)
    {
        RequestMessageHelper helper = new RequestMessageHelper(context.Request);
        if (helper.Message != null)
        {
            ResponseBaseMessage responseMessage = HandleRequestMessage(helper.Message);
            return responseMessage.ToXml(helper.EncryptType);
        }
        else
            return string.Empty;
    }

    /// <summary>
    /// 处理请求消息,返回响应消息
    /// </summary>
    /// <returns>返回响应消息</returns>
    private ResponseBaseMessage HandleRequestMessage(RequestBaseMessage requestMessage)
    {
        ResponseTextMessage response = new ResponseTextMessage(requestMessage.FromUserName, requestMessage.ToUserName, 
            DateTime.Now, string.Format("自动回复,请求内容如下:\r\n{0}", requestMessage));
        return response;
    }

被动回复消息

5 发送其他消息
    除了被动回复消息之外,我们还可以发送客服消息、群发消息、发送模板消息,这些内容将在后续文章中一一道来。

感谢您看完本文,希望对您有所帮助。