博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用web api开发微信公众号,调用图灵机器人接口(一)
阅读量:5283 次
发布时间:2019-06-14

本文共 5182 字,大约阅读时间需要 17 分钟。

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

  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    {        ///         /// 签名Key        ///         private string _wxToken = ConfigurationManager.AppSettings["WXToken"];        ///         /// 是否通过授权        ///         /// 上下文        /// 
是否成功
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()); } /// /// 处理未授权请求 /// /// 上下文 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
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;//我们的用户标识

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

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

转载于:https://www.cnblogs.com/efenghuo/p/4244805.html

你可能感兴趣的文章
Day13
查看>>
tensorflow saver简介+Demo with linear-model
查看>>
Luogu_4103 [HEOI2014]大工程
查看>>
Oracle——SQL基础
查看>>
项目置顶随笔
查看>>
Redis的安装与使用
查看>>
P1970 花匠
查看>>
java语言与java技术
查看>>
NOIP2016提高A组五校联考2总结
查看>>
iOS 项目的编译速度提高
查看>>
table中checkbox选择多行
查看>>
Magento开发文档(三):Magento控制器
查看>>
性能调优攻略
查看>>
ie6解决png图片透明问题
查看>>
瞬间的永恒
查看>>
2019-8-5 考试总结
查看>>
JS中实现字符串和数组的相互转化
查看>>
web service和ejb的区别
查看>>
Windows Azure Cloud Service (29) 在Windows Azure发送邮件(下)
查看>>
微信上传素材返回 '{"errcode":41005,"errmsg":"media data missing"}',php5.6返回
查看>>