标签:
本篇主要围绕的是自定义Web服务器的架构搭建.
在上篇中"开发者中心"留下了两个词"URL"和"Token",URL指的是能够接收处理微信服务器发送的GET/POST请求的网址,该网址应该已部署到开发这的WEB服务器中,能被公网访问得到.Token是用作微信服务器与开发者Web服务器之间进行通信的安全签名,每次微信服务器和开发者Web服务器的通信都会含有该Token值经过加密后的信息,通过对比Token值,验证通信的安全性.Token用于防止未授权的第三方伪造身份,窃取信息.
实现URL接入:当微信服务器以get请求过来web服务器的时候,get请求会携带四个参数.
signature:微信加密签名,结合token,和请求中的timestamp,nonce参数.
timestamp:时间戳
nonce:随机数
echostr:随机字符串
开发者通过检验signature对请求进行校验,若来自微信服务器的get方式请求,原样返回echostr内容,则接入生效.成功连接上自定义服务器.
1.将token,timestamp,nonce三个参数进行字典排序
2.将三个参数字符串拼接成一个字符串进行sha1加密
3.获得加密后的字符串可与singnature对比,标识该请求来自微信服务器
/// <summary> /// Handler1 的摘要说明 /// </summary> public class Handler1 : IHttpHandler { /// <summary> /// /// </summary> public bool IsReusable { get { return true; } } /// <summary> /// 处理请求 /// </summary> /// <param name="context"></param> public void ProcessRequest(HttpContext context) { //由微信服务接收请求,具体处理请求 WeiXinService wxService = new WeiXinService(context.Request); string responseMsg = wxService.Response(); context.Response.Clear(); context.Response.Charset = "UTF-8"; context.Response.Write(responseMsg); context.Response.End(); } }
WeixinService:
public class WeiXinService { /// <summary> /// TOKEN /// </summary> private const string TOKEN = "YZR"; /// <summary> /// 签名 /// </summary> private const string SIGNATURE = "signature"; /// <summary> /// 时间戳 /// </summary> private const string TIMESTAMP = "timestamp"; /// <summary> /// 随机数 /// </summary> private const string NONCE = "nonce"; /// <summary> /// 随机字符串 /// </summary> private const string ECHOSTR = "echostr"; /// <summary> /// HttpRequest /// </summary> private HttpRequest Request { get; set; } /// <summary> /// 构造函数 /// </summary> /// <param name="request"></param> public WeiXinService(HttpRequest request) { this.Request = request; } /// <summary> /// 处理请求,产生响应 /// </summary> /// <returns></returns> public string Response() { string method = Request.HttpMethod.ToUpper(); //验证签名 if (method == "GET") { if (CheckSignature()) { return Request.QueryString[ECHOSTR];//随机字符串 } else { return "error"; } } //处理消息 if (method == "POST") { return ResponseMsg(); } else { return "无法处理"; } } /// <summary> /// 处理请求 /// </summary> /// <returns></returns> private string ResponseMsg() { string requestXml = Common.ReadRequest(this.Request);//得到Request的XML字符串信息 IHandler handler = HandlerFactory.CreateHandler(requestXml);//处理器 if (handler != null) { return handler.HandleRequest();//处理器处理请求 } return string.Empty; } /// <summary> /// 检查签名 /// </summary> /// <param name="request"></param> /// <returns></returns> private bool CheckSignature() { string signature = Request.QueryString[SIGNATURE];//签名 string timestamp = Request.QueryString[TIMESTAMP];//时间戳 string nonce = Request.QueryString[NONCE];//随机数 List<string> list = new List<string>(); list.Add(TOKEN); list.Add(timestamp); list.Add(nonce); //排序 list.Sort(); //拼串 string input = string.Empty; foreach (var item in list) { input += item; } //加密 string new_signature = SecurityUtility.SHA1Encrypt(input); //验证 if (new_signature == signature) { return true; } else { return false; } } }
成功实现URL接入之后,订阅号发送Message过来将是以post的方式,信息是xml格式进行传递.格式节点为:
/// 发送人
public const string FROM_USERNAME = "FromUserName";
/// 开发者微信号
public const string TO_USERNAME = "ToUserName";
// 消息内容
public const string CONTENT = "Content";
/// 消息创建时间 (整型)
public const string CREATE_TIME = "CreateTime";
/// 消息类型
public const string MSG_TYPE = "MsgType"; //消息类型
/// <summary> /// 读取请求对象的内容 /// 只能读一次 /// </summary> /// <param name="request">HttpRequest对象</param> /// <returns>XML字符串</returns> public static string ReadRequest(HttpRequest request) { string reqStr = string.Empty; using (Stream s = request.InputStream) { using (StreamReader reader = new StreamReader(s, Encoding.UTF8)) { reqStr = reader.ReadToEnd(); } } return reqStr; }
在微信服务器转发过来的消息有MsgType,比如文本,声音,视频,事件等,我们这里先以文本消息作为演示:
首先我们需要定义一个handler来处理这个文本处理类.
/// <summary> /// 文本信息处理类 /// </summary> public class TextHandler : IHandler { /// <summary> /// 请求的XML /// </summary> private string RequestXml { get; set; } /// <summary> /// 构造函数 /// </summary> /// <param name="requestXml">请求的xml</param> public TextHandler(string requestXml) { this.RequestXml = requestXml; } /// <summary> /// 处理请求 /// </summary> /// <returns></returns> public string HandleRequest() { string response = string.Empty; TextMessage tm = TextMessage.LoadFromXml(RequestXml); string content = tm.Content.Trim(); if (string.IsNullOrEmpty(content)) { response = "请输入内容"; } else { response = HandleOther(content); } tm.Content = response; //进行发送者、接收者转换 string temp = tm.ToUserName; tm.ToUserName = tm.FromUserName; tm.FromUserName = temp; response = tm.GenerateContent(); return response; } /// <summary> /// 处理其他消息 /// </summary> /// <param name="tm"></param> /// <returns></returns> private string HandleOther(string requestContent) { string response = string.Empty; if (requestContent.Contains("你好") || requestContent.Contains("您好")) { response = "您也好~"; } else { response = "我只能说,I am YZR"; } return response; } }
这样就完成了关键字的消息回复了,当然,因为这里是我们自己的web服务器,我们可以进行更多的操作,比如查询天气,和数据库交互等
也许文本消息你玩腻了,那么下篇会和大家交流一下,事件的处理.
啊Ran讲微信开发(.net) :订阅号+自定义服务器(URL接入,文本消息处理)
标签:
原文地址:http://www.cnblogs.com/Francis-YZR/p/4996345.html