zoukankan      html  css  js  c++  java
  • 啊Ran讲微信开发(.net) :订阅号+自定义服务器(URL接入,文本消息处理)

      本篇主要围绕的是自定义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服务器,我们可以进行更多的操作,比如查询天气,和数据库交互等

    也许文本消息你玩腻了,那么下篇会和大家交流一下,事件的处理.

  • 相关阅读:
    设置开发环境
    安装开发软件
    学习路线
    预备知识
    Spring是什么
    yum安装nginx
    .net 哈希
    Excel文件处理Demo
    汉字处理组件
    Log4Net
  • 原文地址:https://www.cnblogs.com/Francis-YZR/p/4996345.html
Copyright © 2011-2022 走看看