作者:王先荣
最近在学习微信公众号开发,将学习的成果做成了一个类库,方便重复使用。
现在微信公众号多如牛毛,开发微信的高手可以直接无视这个系列的文章了。
使用该类库的流程及寥寥数行代码得到的结果如下。
本文的源代码主要在:http://git.oschina.net/xrwang2/xrwang.weixin.PublicAccount/blob/master/xrwang.net/WeixinInterface.ashx以及http://git.oschina.net/xrwang2/xrwang.weixin.PublicAccount/blob/master/xrwang.net/Global.asax
1 引用微信公众号类库
引用xrwang.weixin.PublicAccount。
2 添加公众号信息
添加提供服务的公众号的信息,包括:原始id、AppId、AppSecret、EncodingAESKey。代码如下:
AccountInfoCollection.SetAccountInfo(new AccountInfo("YourOriginalId", "AppId", "AppSecret", "Token", "EncodingAESKey"));
如果需要同时给多个公众号提供服务,重复上面这行代码就可以了。
注:由于微信服务器的原因,如果在一个站点中要同时给多个公众号提供服务,有两种方法:如果用同一页面处理多个公众号,那么Token必须一致(1)可以在接口配置信息的URL中加入区分公众号的参数(例如:http://www.xrwang.net/WeixinInterface.ashx?username=gh_5dbae931ec49);(2)针对每个公众号单独建立一个页面来处理。我目前采用了第一种方式,这样更简便。
我喜欢将添加公众号信息的工作放到Gobal.asax的Application_Start方法中。
3 与微信服务器通信
我添加了名为“WeixinInterface.ashx”的一般处理页,并在其中与微信服务器进行通信,包括:校验请求、处理请求、回复适当的响应。代码如下:
public void ProcessRequest(HttpContext context)
{
string result = string.Empty;
if (Validate(context))
{
if (context.Request.HttpMethod == WebRequestMethods.Http.Get)
result = HandleGet(context);
else if (context.Request.HttpMethod == WebRequestMethods.Http.Post)
result = HandlePost(context);
}
else
Message.Insert(new Message(MessageType.Exception, "校验消息失败。\r\n地址:" + context.Request.RawUrl));
context.Response.Write(result);
}
3.1 校验请求
首先,我们需要校验接收到的请求是否来自微信服务器,方法如下:
/// <summary>
/// 验证消息的有效性
/// </summary>
/// <param name="context"></param>
/// <returns>如果消息有效,返回true;否则返回false。</returns>
private bool Validate(HttpContext context)
{
string token = AccountInfoCollection.First.Token; //由于在校验微信签名时,微信未传入公众号,因此这里用第一个公众号的TOKEN
string signature = RequestEx.TryGetQueryString("signature");
string timestamp = RequestEx.TryGetQueryString("timestamp");
string nonce = RequestEx.TryGetQueryString("nonce");
if (string.IsNullOrWhiteSpace(signature) || string.IsNullOrWhiteSpace(timestamp) || string.IsNullOrWhiteSpace(nonce))
return false;
return xrwang.weixin.PublicAccount.Utility.CheckSignature(signature, token, timestamp, nonce);
}