此文将分两篇讲解,主要分为以下几步

  1. 签名校验;
  2. 首次提交验证申请;
  3. 接收消息;
  4. 被动响应消息(返回XML);
  5. 映射图灵消息及微信消息;

其实图灵机器人搭载微信公众号很简单,只需要把图灵的地址配到公众后台就可以了。

不过这样做之后也就没有任何扩展的可能了,因此自己实现一套!

一、签名校验

在开发者首次提交验证申请时,微信服务器将发送GET请求到填写的URL上,并且带上四个参数(signature、timestamp、nonce、echostr),开发者通过对签名(即signature)的效验,来判断此条消息的真实性。

此后,每次开发者接收用户消息的时候,微信也都会带上前面三个参数(signature、timestamp、nonce)访问开发者设置的URL,开发者依然通过对签名的效验判断此条消息的真实性。效验方式与首次提交验证申请一致。

根据微信开发者平台中的描述,我们在首次提交验证申请及接收用户消息时,都需要校验签名以确保消息来源真实。

参与签名的参数为timestampnoncetoken(即开发者中心中配置的Token令牌)

加密/校验流程如下:

  1. 将token、timestamp、nonce三个参数进行字典序排序(此处注意:是三个参数的值,而不是按参数名排序)
  2. 将三个参数字符串拼接成一个字符串进行sha1加密
  3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

由于这个东西在接收消息时是通用的,我们可以使用授权过滤器AuthorizeAttribute来实现。

using System.Configuration;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
using System.Linq;
using System.Web.Http.Controllers; using Efh.Core.Security; namespace Efh.Blog.Web.Areas.WeiXin.Filter
{
public class WXAuthorizeAttribute : AuthorizeAttribute
{
/// <summary>
/// 签名Key
/// </summary>
private string _wxToken = ConfigurationManager.AppSettings["WXToken"]; /// <summary>
/// 是否通过授权
/// </summary>
/// <param name="actionContext">上下文</param>
/// <returns>是否成功</returns>
protected override bool IsAuthorized(HttpActionContext actionContext)
{
var requestQueryPairs = actionContext.Request.GetQueryNameValuePairs().ToDictionary(k => k.Key, v => v.Value);
if (requestQueryPairs.Count == 0
|| !requestQueryPairs.ContainsKey("timestamp")
|| !requestQueryPairs.ContainsKey("signature")
|| !requestQueryPairs.ContainsKey("nonce"))
{
return false;
} string[] waitEncryptParamsArray = new[] { _wxToken, requestQueryPairs["timestamp"], requestQueryPairs["nonce"] }; string waitEncryptParamStr = string.Join("", waitEncryptParamsArray.OrderBy(m => m)); string encryptStr = HashAlgorithm.SHA1(waitEncryptParamStr); return encryptStr.ToLower().Equals(requestQueryPairs["signature"].ToLower());
} /// <summary>
/// 处理未授权请求
/// </summary>
/// <param name="actionContext">上下文</param>
protected sealed override void HandleUnauthorizedRequest(HttpActionContext actionContext)
{
actionContext.Response = actionContext.Request.CreateResponse(
HttpStatusCode.Unauthorized, new { status = "sign_error" });
}
}
}

将该特性声明在我们的微信Controller或者Action上,我们的签名校验便完成了。

二、首次提交验证申请

首次提交验证申请,微信服务器来调的时候是Get请求,而且要求我们将echostr原样返回。

注意,是原样返回。不是XML,也不是Json,<string>echostr</string>和"echostr"都是不行的!

囊中羞涩,本人使用的是虚拟主机搭载在原有的项目中,故新建微信区域(WeiXin)来实现。WeiXinAreaRegistration.cs文件如下:

public class WeiXinAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "WeiXin";
}
} public override void RegisterArea(AreaRegistrationContext context)
{
context.Routes.MapHttpRoute(
"WeiXinProcessor",
"WeiXin/{controller}",
new { controller = "Processor" }
);
}
}

新建Processor控制器,实现如下:

[WXAuthorize]
public class ProcessorController : ApiController
{
public HttpResponseMessage Get()
{
var requestQueryPairs = Request.GetQueryNameValuePairs().ToDictionary(k => k.Key, v => v.Value); return new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(requestQueryPairs["echostr"]),
};
}
}

上述我们便实现了首次微信的验证。

三、接收消息

微信将请求的消息分为六种:文本消息、图片消息、语音消息、视频消息、地理位置消息、链接消息,其实我们还可以将事件推送也理解为其中一种。

将响应的消息分为六种:

1. 回复文本消息

2. 回复图片消息

3. 回复语音消息

4. 回复视频消息

5. 回复音乐消息

6. 回复图文消息

。我们在这儿主要使用文本消息和图文消息。

分析后我们发现,ToUserNameFromUserNameCreateTimeMsgType是所有消息共有的参数。同时也是我们响应时必需的参数。

我们创建消息基类和消息类型枚举如下

public class BaseMsg
{
public string ToUserName { get; set; } public string FromUserName { get; set; } public long CreateTime { get; set; } public MsgType MsgType { get; set; }
} public enum MsgType
{
[XmlEnum("event")]
Event,
[XmlEnum("text")]
Text,
[XmlEnum("image")]
Image,
[XmlEnum("voice")]
Voice,
[XmlEnum("video")]
Video,
[XmlEnum("music")]
Music,
[XmlEnum("news")]
News
}

此处枚举字段标注的XmlEnum稍候解释。

而后按照各消息类型的非共有的参数,分别创建对应消息的实体类

文本消息:

[XmlRoot("xml")]
public class TextMsg : BaseMsg
{
public string Content { get; set; }
}

图文消息:

[XmlRoot("xml")]
public class NewsMsg : BaseMsg
{
public int ArticleCount { get; set; } [XmlArray("Articles")]
[XmlArrayItem("item")]
public List<NewsInfo> Articles { get; set; }
} public class NewsInfo
{
public string Title { get; set; } public string Description { get; set; } public string PicUrl { get; set; } public string Url { get; set; }
}

等等。

刚才下班,朋友喊了,勿勿忙忙就提交了。。。现在继续!

接下来我们就可以开始接收微信的消息了

微信是通过Post,从正文中以XML的格式将参数传递过来的

var requestContent = Request.Content.ReadAsStreamAsync().Result;

将正文参数读取出来后,转为Xml

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(requestContent);

这样,我们便可以读取到我们需要的内容了

string msgTypeStr = xmlDoc.SelectSingleNode("xml/MsgType").InnerText;//消息类型
string userName = xmlDoc.SelectSingleNode("xml/FromUserName").InnerText;//来源用户标识
string efhName = xmlDoc.SelectSingleNode("xml/ToUserName").InnerText;//我们的用户标识

而后,我们根据消息类型,进行进一步的处理。

静候片刻,第二篇马上奉上...

使用web api开发微信公众号,调用图灵机器人接口(一)的更多相关文章

  1. 使用web api开发微信公众号,调用图灵机器人接口(二)

    此文将分两篇讲解,主要分为以下几步 签名校验; 首次提交验证申请; 接收消息; 被动响应消息(返回XML); 映射图灵消息及微信消息; 此篇为第二篇. 被动响应消息(返回XML) 上一篇中,我们已经可 ...

  2. 小机器人自动回复(python,可扩展开发微信公众号的小机器人)

    api来之图灵机器人.我们都知道微信公众号可以有自动回复,我们先用python脚本编写一个简单的自动回复的脚本,利用图灵机器人的api. http://www.tuling123.com/help/h ...

  3. Asp.Net Web API开发微信后台

    如果说用Asp.Net开发微信后台是非主流,那么Asp.Net Web API的微信后台绝对是不走寻常路. 需要说明的是,本人认为Asp.Net Web API在开发很多不同的请求方法的Restful ...

  4. 使用vue开发微信公众号下SPA站点的填坑之旅

    原文发表于本人博客,点击进入使用vue开发微信公众号下SPA站点的填坑之旅 本文为我创业过程中,开发项目的填坑之旅.作为一个技术宅男,我的项目是做一个微信公众号,前后端全部自己搞定,不浪费国家一分钱^ ...

  5. PHP开发微信公众号(一)二维码的获取

    要开发微信公众号,首先进行需要注册一个,然后认证.这就不用多说了. 当然如果没有,也可以去申请一个测试号来使用,地址:https://mp.weixin.qq.com/debug/cgi-bin/sa ...

  6. Java开发微信公众号(五)---微信开发中如何获取access_token以及缓存access_token

    获取access_token是微信api最重要的一个部分,因为调用其他api很多都需要用到access_token.比如自定义菜单接口.客服接口.获取用户信息接口.用户分组接口.群发接口等在请求的时候 ...

  7. vue开发微信公众号--开发准备

    由于工作项目的原因,需要使用vue开发微信公众号,但是这种微信公众号更多是将APP套了一个微信的壳子,除了前面的授权和微信有关系以外,其他的都和微信没多大的关系了,特此记录 开发流程 首先需要在电脑上 ...

  8. spring-boot-route(二十三)开发微信公众号

    在讲微信公众号开发之前,先来大概了解一下微信公众号.微信公众号大体上可以分为服务号和订阅号,订阅号和服务号的区别如下: 服务号可以申请微信支付功能. 服务号只能由企业申请,订阅号可以有企业或个人申请. ...

  9. Java开发微信公众号(四)---微信服务器post消息体的接收及消息的处理

    在前几节文章中我们讲述了微信公众号环境的搭建.如何接入微信公众平台.以及微信服务器请求消息,响应消息,事件消息以及工具处理类的封装:接下来我们重点说一下-微信服务器post消息体的接收及消息的处理,这 ...

随机推荐

  1. 计算机中的换行符、回车符、\n、\r、\n\r 怎么区分啊?

    '\r'是回车,前者使光标到行首,(carriage return)'\n'是换行,后者使光标下移一格,(line feed) \r 是回车,return\n 是换行,newline对于换行这个动作, ...

  2. php 导出

    //导出 //放在model层的类 <?phpnamespace frontend\models; use yii\base\model; /** * @copyright (c) 2014 a ...

  3. 解决 hibernate cannot define positional parameter after any named parameters have been defined

    解决 hibernate  cannot define positional parameter after any named parameters have been defined 把模糊查询的 ...

  4. 拟牛顿 DFP matlab

    function sevnn x=[1,0]'; [x,val]=dfp('fun','gfun',x) end function f=fun(x) f=100*(x(1)^2-x(2))^2+(x( ...

  5. fun()可拆分赋值 fun()可以拆, 变成 fun 和 括号, fun 可以赋值

    2. 函数名可以赋值给其他变量   --->   就是 func()可以拆 def fun (): print("哈哈") a = fun # 拆分 fun()的    fu ...

  6. Zeal——好用的离线 API 文档大全!

    介绍 作为一名程序员,工作中学习中免不了是要查询API文档的,毕竟我们能记住的东西有限,而且经常也会碰到某个API一时想不起来的情况,而每次还要打开网页去查询还是挺麻烦的,这时候拥有一个款好用的本地离 ...

  7. [咸恩静][Good Bye]

    歌词来源:http://music.163.com/#/song?id=35437298 作曲 : 安英民 [作曲 : 安英民] 作词 : 安英民/로코 [作词 : 安英民/lo-Ko] 나를 떠나버 ...

  8. Java 替换空格

    题目描述 请实现一个函数,将一个字符串中的空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 解一: 由于最近在学习Head F ...

  9. 如何1秒批量提取电脑文件夹中的所有文件、文件夹名字到txt/excel

    01  在工作,我们经常会遇到这样的情况,有时候我们在一个文件夹中放了很多的文件,或者是这个文件夹中有很多的子文件夹,每一个子文件夹的名字又不同,也没有什么样的规律, 02  但是我们要整理一下这个文 ...

  10. js检测是够断网

    方法 一 navigator.onLine   这个html5的 navigator的新特性可以很简单帮我们搞定 HTML5为此定义了一个navigator.onLine属性,这个属性值为true表示 ...