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

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

主要功能介绍如下:

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

2)分发层。由接口层传入请求,然后具体分析请求类型,分发至不同的处理器

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

4)数据层。我们在实现某个应用时可能需要访问数据,可以是数据库或者是文件。如果是简单应用,可能没有这一层。

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

java 微信公众号 服务器配置 java微信公众号开发框架_java 微信公众号 服务器配置

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

java 微信公众号 服务器配置 java微信公众号开发框架_字符串_02

根据流程图,我们能够清晰的了解整个流程,消息处理的具体实现步骤。

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

一、接收HTTP请求

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

这里我们使用了HttpHandler。因为其灵活性高,性能好。

具体实现如下。

public classWeiXinHttpHandler:IHttpHandler
{/// 
///
/// 
public boolIsReusable
{get { return true; }
}/// 
///处理请求/// 
/// 
public voidProcessRequest(HttpContext context)
{//由微信服务接收请求,具体处理请求
WeiXinService wxService = newWeiXinService(context.Request);string responseMsg =wxService.Response();
context.Response.Clear();
context.Response.Charset= "UTF-8";
context.Response.Write(responseMsg);
context.Response.End();
}
}

如果是HTTPHandler,需要在配置文件中,配置具体的应用。具体的节点配置,我们不作说明。直接给出例子,配置HttpHandler节点如下

二、分发请求

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

1)验证签名

如果是首次请求,需要验证签名。就相当于一次HTTP握手。之前在上一章中,设置的服务器URL以及token值,这个功能就是检验是否链接成功。

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

业务逻辑:

加密/校验流程:

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

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

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

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

private functioncheckSignature()
{$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#版本:
/// 
///检查签名/// 
/// 
/// 
private boolCheckSignature()
{string signature =Request.QueryString[SIGNATURE];string timestamp =Request.QueryString[TIMESTAMP];string nonce =Request.QueryString[NONCE];
List list = new List();
list.Add(TOKEN);
list.Add(timestamp);
list.Add(nonce);//排序
list.Sort();//拼串
string input = string.Empty;foreach (var item inlist)
{
input+=item;
}//加密
string new_signature =SecurityUtility.SHA1Encrypt(input);//验证
if (new_signature ==signature)
{return true;
}else{return false;
}
}
这里需要SHA1加密,具体的算法如下:
/// 
///SHA1加密/// 
/// 输入字符串
/// 加密后的字符串
public static string SHA1Encrypt(stringintput)
{byte[] StrRes =Encoding.Default.GetBytes(intput);
HashAlgorithm mySHA= newSHA1CryptoServiceProvider();
StrRes=mySHA.ComputeHash(StrRes);
StringBuilder EnText= newStringBuilder();foreach (byte Byte inStrRes)
{
EnText.AppendFormat("{0:x2}", Byte);
}returnEnText.ToString();
}

2)分发请求

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

因为有多种消息类型,我们通过工厂类来进行封装,然后每种消息都有专门的处理器来进行处理。具体实现逻辑:

/// 
///处理请求/// 
/// 
private stringResponseMsg()
{string requestXml = Common.ReadRequest(this.Request);
IHandler handler=HandlerFactory.CreateHandler(requestXml);if (handler != null)
{returnhandler.HandleRequest();
}return string.Empty;
}
处理请求的对外方法(HttpHandler调用的方法就是这个了),即:
/// 
///处理请求,产生响应/// 
/// 
public stringResponse()
{string method =Request.HttpMethod.ToUpper();//验证签名
if (method == "GET")
{if(CheckSignature())
{returnRequest.QueryString[ECHOSTR];
}else{return "error";
}
}//处理消息
if (method == "POST")
{returnResponseMsg();
}else{return "无法处理";
}
}

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

1)消息类型

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

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

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

java 微信公众号 服务器配置 java微信公众号开发框架_微信_03

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

这里给出类图,供参考。

java 微信公众号 服务器配置 java微信公众号开发框架_微信_04

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

java 微信公众号 服务器配置 java微信公众号开发框架_HTTP_05

4)具体业务处理

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

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

因为随着业务的增加,一个Handler可能要处理很多业务,如果所有的操作逻辑都写在这里,势必影响阅读,也不易于维护与扩展。

5)产生回复消息

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

一定要明确:回复的消息类型不一定要与请求的消息类型一样,比如,请求是文本,回复的可以是图文、音乐。

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

6)实例


classEventHandler : IHandler
{/// 
///请求的xml/// 
private string RequestXml { get; set; }/// 
///构造函数/// 
/// 
public EventHandler(stringrequestXml)
{this.RequestXml =requestXml;
}/// 
///处理请求/// 
/// 
public stringHandleRequest()
{string response = string.Empty;
EventMessage em=EventMessage.LoadFromXml(RequestXml);if (em.Event ==EventType.Subscribe)
{//注册用户
User user = newUser();
user.OpenID=em.FromUserName;
UserManager.Regester(user);//回复欢迎消息
TextMessage tm = newTextMessage();
tm.ToUserName=em.FromUserName;
tm.FromUserName=em.ToUserName;
tm.CreateTime=Common.GetNowTime();
tm.Content= "欢迎您关注xxx,我是小微。有什么我能帮助您的吗?";
response=tm.GenerateContent();
}returnresponse;
}
}

四、HTTP响应

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

下面是代码片段,具体可见一、Http请求

context.Response.Clear();
context.Response.Charset= "UTF-8";
context.Response.Write(responseMsg);
context.Response.End();