微信公众平台开发教程(三) 基础框架搭建

微信公众平台开发教程(三) 基础框架搭建

上一章,咱们已经初步讲解了微信公众帐号开发的基本原理,今天咱们来探索设计实现。算法

首先咱们设计了模块层次图,固然图中只是给出一种实现方式,不局限于此。具体见下图。数据库

主要功能介绍以下:服务器

1)请求接口层。处理HTTP请求,及响应微信

2)分发层。由接口层传入请求,而后具体分析请求类型,分发至不一样的处理器微信公众平台

3)业务逻辑层。这里是咱们的具体业务逻辑了,根据请求,实现具体的业务逻辑。框架

4)数据层。咱们在实现某个应用时可能须要访问数据,能够是数据库或者是文件。若是是简单应用,可能没有这一层。ide

其实,具体的应用能够在这个结构上去扩展,能够扩展消息对象层、业务对象层、数据访问层、功能管理层等。这里只是提供一种思路,不局限于此。函数

 

 

根据层次图,设计流程图,具体讲述实现的各个过程。以便了解整个处理过程。以下图所示:性能

  

根据流程图,咱们可以清晰的了解整个流程,消息处理的具体实现步骤。ui

下面咱们针对每一个流程进行代码实现。

1、接收HTTP请求

咱们须要一个HttpHandler或者一个网页,来处理微信服务端HTTP请求。

这里咱们使用了HttpHandler。由于其灵活性高,性能好。

具体实现以下。

    public class WeiXinHttpHandler: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();
        }
    }

 

若是是HTTPHandler,须要在配置文件中,配置具体的应用。具体的节点配置,咱们不做说明。直接给出例子,配置HttpHandler节点以下

 

<httpHandlers>
   <add verb="*" path="WXService.ashx" type="namespace.WeiXinHttpHandler,WXWeb" validate="true"/>
</httpHandlers>

 

2、分发请求

 为了能功能封装,咱们也将此封装在了处理组件中。其实能够放置在HttpHandler中的。 

 1)验证签名

 若是是首次请求,须要验证签名。就至关于一次HTTP握手。以前在上一章中,设置的服务器URL以及token值,这个功能就是检验是否连接成功。

这个请求是GET请求。如下具体说明(官方):

业务逻辑:

加密/校验流程:

<1> 将token、timestamp、nonce三个参数进行字典序排序

<2> 将三个参数字符串拼接成一个字符串进行SHA1加密

 <3> 开发者得到加密后的字符串可与signature对比,标识该请求来源于微信 

而官方只提供了PHP的代码示例,不少东西在C#中并不是直译既得。因此这里面也有一些具体处理。先看官方的代码: 

    private function checkSignature()
    {
        $signature = $_GET["signature"];
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];    
                
        $token = TOKEN;
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr);
        $tmpStr = implode( $tmpArr );
        $tmpStr = sha1( $tmpStr );
        
        if( $tmpStr == $signature ){
            return true;
        }else{
            return false;
        }
    }

咱们将其翻译成C#版本: 

        /// <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;
            }
        }

这里须要SHA1加密,具体的算法以下:

        /// <summary>
        /// SHA1加密
        /// </summary>
        /// <param name="intput">输入字符串</param>
        /// <returns>加密后的字符串</returns>
        public static string SHA1Encrypt(string intput)
        {
            byte[] StrRes = Encoding.Default.GetBytes(intput);
            HashAlgorithm mySHA = new SHA1CryptoServiceProvider();
            StrRes = mySHA.ComputeHash(StrRes);
            StringBuilder EnText = new StringBuilder();
            foreach (byte Byte in StrRes)
            {
                EnText.AppendFormat("{0:x2}", Byte);
            }
            return EnText.ToString();
        }

2)分发请求

接下来就是具体的消息请求了,这里都是POST请求。

由于有多种消息类型,咱们经过工厂类来进行封装,而后每种消息都有专门的处理器来进行处理。具体实现逻辑:

        /// <summary>
        /// 处理请求
        /// </summary>
        /// <returns></returns>
        private string ResponseMsg()
        {
            string requestXml = Common.ReadRequest(this.Request);
            IHandler handler = HandlerFactory.CreateHandler(requestXml);
            if (handler != null)
            {
                return handler.HandleRequest();
            }

            return string.Empty;
        }

处理请求的对外方法(HttpHandler调用的方法就是这个了),即:

        /// <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 "没法处理";
            }
        }

 

3、消息处理器具体处理消息

1)消息类型

首先咱们来看下,具体的消息类型,其实上一张中已经明确给了消息的接口。

这里再看具体看一下,请求的消息类型有哪些,回复的消息类型有哪些等。

千万要注意,请求的消息是文本类型,回复的消息,不必定也是文本哦,能够是图文、音乐等任意一种可回复的消息。具体见下表所示。

 

2)根据具体的消息接口,设计消息类。

这里给出类图,供参考。

 

3)针对不一样的消息,会有不一样的处理器,来看下具体的类图。

  

4)具体业务处理 

每一个handler里面就是能够处理具体请求。输入的什么消息,访问那些数据,调用服务等,都在这里处理。

仍是建议你们对具体的业务进行单独封装,在Handler中,只提供调用的接口。

由于随着业务的增长,一个Handler可能要处理不少业务,若是全部的操做逻辑都写在这里,势必影响阅读,也不易于维护与扩展。 

5)产生回复消息

在处理完请求后,须要生成回复消息,响应到终端。消息格式,就是咱们介绍那些消息类型,但必须是可用于回复的,当前支持的有:文本、图文、音乐等。

必定要明确:回复的消息类型不必定要与请求的消息类型同样,好比,请求是文本,回复的能够是图文、音乐。

产生回复消息的过程,其实,就是特定的消息对象格式化为对应的XML的过程,而后将XML响应至微信服务器。

6)实例

这里以微信用户关注公众帐号,而后服务端处理处理事件请求,登记用户,并提示欢迎信息。

    class EventHandler : IHandler
    {
        /// <summary>
        /// 请求的xml
        /// </summary>
        private string RequestXml { get; set; }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="requestXml"></param>
        public EventHandler(string requestXml)
        {
            this.RequestXml = requestXml;
        }
        /// <summary>
        /// 处理请求
        /// </summary>
        /// <returns></returns>
        public string HandleRequest()
        {
            string response = string.Empty;
            EventMessage em = EventMessage.LoadFromXml(RequestXml);
            if (em.Event == EventType.Subscribe)
            {
                //注册用户
                User user = new User();
                user.OpenID = em.FromUserName;
                UserManager.Regester(user);

                //回复欢迎消息
                TextMessage tm = new TextMessage();
                tm.ToUserName = em.FromUserName;
                tm.FromUserName = em.ToUserName;
                tm.CreateTime = Common.GetNowTime();
                tm.Content = "欢迎您关注xxx,我是小微。有什么我能帮助您的吗?";
                response = tm.GenerateContent();
            }

            return response;
        }
    }

 

4、HTTP响应

 最后将处理结果返回至最初HttpHandler,响应给微信服务器,直接Response处理。这也是在最开始设计的HttpHandler中实现的。

下面是代码片断,具体可见1、Http请求 

            context.Response.Clear();
            context.Response.Charset = "UTF-8";
            context.Response.Write(responseMsg);
            context.Response.End();
相关文章
相关标签/搜索