如果说用Asp.Net开发微信后台是非主流,那么Asp.Net Web API的微信后台绝对是不走寻常路。

需要说明的是,本人认为Asp.Net Web API在开发很多不同的请求方法的Restful服务的时候是利器,可在开发微信后台的时候,因为微信调用我们这个后台的时候来来去去就一个方法,所以Web API有点杀鸡用牛刀的感觉。

而且由于Web API其实是微软封装了大量的类库,所以会导致后台相当臃肿。所以,不建议Asp.Net Web API开发微信后台。

如果好奇心太强实在想试一下,可以参看以下内容。

首先登陆微信公众平台,在左侧栏底下点击开发者中心填写服务器配置。

目前仅支持80端口,所以发布的时候需要在iis配置清楚。

创建一个Web API项目,然后添加controller,命名为:WechatController。

在WechatController类下添加以下一个方法:

        [HttpGet]                                        //标明HttpGet注解属性明确声明这个方法仅仅接受Get请求
[ActionName("getMsg")]                               //ActionName注解属性覆盖了方法名,这个方法名将会映射到“/api/wechat/getmsg”(如果没有修改默认的路由规则的话)
public HttpResponseMessage WetChatVerify(HttpRequestMessage content)     //HttpRequestMessage 和HttpResponseMessage,分别用于封装Requset和Response
{
string echostr = (from kvp in content.GetQueryNameValuePairs()
where kvp.Key == "echostr"
select kvp.Value).FirstOrDefault(); string signature = (from kvp in content.GetQueryNameValuePairs()
where kvp.Key == "signature"
select kvp.Value).FirstOrDefault(); string timestamp = (from kvp in content.GetQueryNameValuePairs()
where kvp.Key == "timestamp"
select kvp.Value).FirstOrDefault(); string nonce = (from kvp in content.GetQueryNameValuePairs()
where kvp.Key == "nonce"
select kvp.Value).FirstOrDefault(); string returnStr="";
if (string.IsNullOrEmpty(echostr) | string.IsNullOrEmpty(signature) | string.IsNullOrEmpty(timestamp) | string.IsNullOrEmpty(nonce))
{
returnStr="error";
} if (CheckSignature(signature, timestamp, nonce))
{
log.Info("验证成功,返回:" + echostr);
returnStr=echostr;
} HttpResponseMessage result = new HttpResponseMessage();
result.Content = new StringContent(returnStr);
return result;
}

CheckSignature的代码如下:

        /// <summary>
/// 验证微信签名
/// </summary>
private bool CheckSignature(string signature, string timestamp, string nonce)
{
String[] ArrTmp = { Common.Common.Token, timestamp, nonce }; Array.Sort(ArrTmp);
String tmpStr = String.Join("", ArrTmp); tmpStr = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1").ToLower(); if (tmpStr == signature)
{
return true;
}
else
{
return false;
}
}

微信将会发送一个请求到后台,这个请求根据你在其开发平台填写的信息,类型可以是如下:

http://【server】/api/wechat/getMsg?signature=【signature】&echostr=【echostr】&timestamp=【timestamp】&nonce=【nonce】

只要按照CheckSignature的步骤将Token以及获取到的timestamp,nonce串联并用sha1加密,如果所得结果跟signature一致,就原样返回echostr,如此微信开发平台就会认为服务器配置成功了。

我们知道Web API的返回类型很灵活,可以返回string类型也可以int类型,当然也可以复杂一点采用上面的HttpResponseMessage类型,不过如果返回的是string类型,就有两个问题:

1、echostr不能原样返回,会自动给你加上双引号,所以微信开发平台会一直说验证失败,取巧一点的话,因为现在的echostr都是数字,可以返回整形;

2、返回的文字信息如果需要换行,直接返回string类型的话,“\n”就不会当作是换行符处理而回直接在消息中显示出来。这关乎下面的一些内容了……

验证成功之后,再写另外一个方法来接收并处理信息。

        [HttpPost]
[ActionName("getMsg")]
public HttpResponseMessage HandleMsgFromWeChat(HttpRequestMessage request)
{
List<KeyValuePair<string, string>> query = Request.GetQueryNameValuePairs().ToList();
string xmlContent = request.Content.ReadAsStringAsync().Result;
       string response = string.Empty; WeChatMessage msg = WeChatHelper.GetWxMessage(xmlContent); if (msg.MsgType.Trim() == "text")//用户发送一些文字信息
{
response = “oh my lady gaga”;
}
if (msg.MsgType.Trim() == "event")//点击菜单或者新增/取消关注
{
switch (msg.EventName.Trim().ToLower())
{
case "click":      //点击菜单
response = "haha";
break;
case "subscribe":    //用户新增关注(可以返回一些欢迎信息之类)                                  
response = “wawa”;
break;
case "unsubscribe":   //用户取消关注(一般不需要去返回什么信息)
default:
break;
}
} HttpResponseMessage result = new HttpResponseMessage();
result.Content = new StringContent(response);
return result;
}
    //自定义一个微信消息实体类
public class WeChatMessage
{
public string FromUserName { get; set; }
public string ToUserName { get; set; }
public string MsgType { get; set; }
public string EventName { get; set; }
public string EventKey { get; set; }
public string Content { get; set; }
} //发送图文消息的列表项
public class ArticleItem
{
public string title { get; set; }
public string description { get; set; }
public string picurl { get; set; }
public string url { get; set; }
} public class WeChatHelper
{
/// <summary>
/// 获取微信信息。
/// </summary>
/// <returns></returns>
public static WeChatMessage GetWxMessage(string xmlStr)
{
WeChatMessage wx = new WeChatMessage();
XmlDocument xml = new XmlDocument();
xml.LoadXml(xmlStr);
wx.ToUserName = xml.SelectSingleNode("xml").SelectSingleNode("ToUserName").InnerText;
wx.FromUserName = xml.SelectSingleNode("xml").SelectSingleNode("FromUserName").InnerText;
wx.MsgType = xml.SelectSingleNode("xml").SelectSingleNode("MsgType").InnerText;
if (wx.MsgType.Trim() == "text")
{
wx.Content = xml.SelectSingleNode("xml").SelectSingleNode("Content").InnerText;
}
if (wx.MsgType.Trim() == "event")
{
wx.EventName = xml.SelectSingleNode("xml").SelectSingleNode("Event").InnerText;
wx.EventKey = xml.SelectSingleNode("xml").SelectSingleNode("EventKey").InnerText;
}
return wx;
} /// <summary>
/// 发送文字消息
/// </summary>
public static string SendTextMessage(string fromUserName,string toUserName,string content)
{
StringBuilder sb = new StringBuilder(); sb.AppendFormat("<xml><ToUserName><![CDATA[{0}]]></ToUserName>", fromUserName);
sb.AppendFormat("<FromUserName><![CDATA[{0}]]></FromUserName>", toUserName);
sb.AppendFormat("<CreateTime>{0}</CreateTime>", DateTime.Now);
sb.Append("<MsgType><![CDATA[text]]></MsgType>");
sb.AppendFormat("<Content><![CDATA[{0}]]></Content>", content);
sb.Append("<FuncFlag>0</FuncFlag></xml>"); return sb.ToString();
} /// <summary>
/// 发送图文列表信息,如果列表为空,会转为发送“没有搜索到内容”的文字信息
/// </summary>
public static string SendImageListMessage(string fromUserName, string toUserName, List<ArticleItem> itemList)
{
if (itemList == null || itemList.Count == )
{
return SendTextMessage(fromUserName, toUserName, "没有搜索到相关内容");
} StringBuilder sb = new StringBuilder(); sb.Append("<xml>");
sb.AppendFormat("<ToUserName><![CDATA[{0}]]></ToUserName>", fromUserName);
sb.AppendFormat("<FromUserName><![CDATA[{0}]]></FromUserName>", toUserName);
sb.AppendFormat("<CreateTime>{0}</CreateTime>", DateTime.Now);
sb.Append("<MsgType><![CDATA[news]]></MsgType>");
sb.AppendFormat("<ArticleCount>{0}</ArticleCount>", itemList.Count);
sb.Append("<Articles>");
foreach (ArticleItem item in itemList)
{
sb.Append("<item>");
sb.AppendFormat("<Title><![CDATA[{0}]]></Title> ", item.title);
sb.AppendFormat("<Description><![CDATA[{0}]]></Description>", item.description);
sb.AppendFormat("<PicUrl><![CDATA[{0}]]></PicUrl>", item.picurl);
sb.AppendFormat("<Url><![CDATA[{0}]]></Url>", item.url);
sb.Append("</item>");
}
sb.Append("</Articles>");
sb.Append("</xml>"); return sb.ToString();
} //http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96access_token
public static string GetAccessToken()
{
string accessToken = string.Empty;
//http请求方式: GET
//https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
string query=string.Format("grant_type=client_credential&appid={0}&secret={1}",Common.AppID,Common.AppSecret);
string result = WebApiRequest.GetRequest("https://api.weixin.qq.com", "/cgi-bin/token", query);
//result返回说明
//正常情况下,微信会返回下述JSON数据包给公众号:
//{"access_token":"ACCESS_TOKEN","expires_in":7200}
//参数 说明
//access_token 获取到的凭证
//expires_in 凭证有效时间,单位:秒
//错误时微信会返回错误码等信息,JSON数据包示例如下(该示例为AppID无效错误):
//{"errcode":40013,"errmsg":"invalid appid"}
JObject jOb = JObject.Parse(result);
if (jOb["access_token"] != null)
{
accessToken = jOb["access_token"].ToString(); ;
}
return accessToken;
}
}

以上就搭建了一个简易的微信后台框架了。跟微信相关的内容大概也差不多了。想扩展内容、增加数据库支持等等,按照往常C#程序开发那样子做就好了。

Asp.Net Web API开发微信后台的更多相关文章

  1. C#开发微信门户及应用(47) - 整合Web API、微信后台管理及前端微信小程序的应用方案

    在微信开发中,我一直强调需要建立一个比较统一的Web API接口体系,以便实现数据的集中化,这样我们在常规的Web业务系统,Winform业务系统.微信应用.微信小程序.APP等方面,都可以直接调用基 ...

  2. ASP.NET Web API实现微信公众平台开发(一)服务器验证

    最近朋友的微信公众号准备做活动,靠固定的微信公众平台模版搞定不了,于是请我代为开发微信后台.鉴于我也是第一次尝试开发微信后台,所以也踩了不少坑,此系列博客将会描述微信公众号各项功能的实现. 先决条件 ...

  3. 水果项目第3集-asp.net web api开发入门

    app后台开发,可以用asp.net webservice技术. 也有一种重量级一点的叫WCF,也可以用来做app后台开发. 现在可以用asp.net web api来开发app后台. Asp.net ...

  4. [目录]ASP.NET web api开发实战

    第一章:Restful web service v.s. RPC style web service 第二章:ASP.NET web api v.s. WCF v.s. ASP.NET web ser ...

  5. Asp.net Web Api开发Help Page配置和扩展

    为了方面APP开发人员,服务端的接口都应当提供详尽的API说明.但每次有修改,既要维护代码,又要维护文档,一旦开发进度紧张,很容易导致代码与文档不一致. Web API有一个Help Page插件,可 ...

  6. asp.net web api集成微信服务(使用Senparc微信SDK)

    /// <summary> /// 微信请求转发控制器 /// </summary> [RoutePrefix("weixin")] public clas ...

  7. asp.net web api集成微信服务(使用Senparc微信SDK)- z

    /// <summary> /// 微信请求转发控制器 /// </summary> [RoutePrefix("weixin")] public clas ...

  8. ASP.NET Web API实现微信公众平台开发(二)access_token与定时任务

    承接上一篇,今天主要讲述如何实现定时获取微信access_token功能的实现. access_token 首先我们根据微信的开发指南,任何对微信的操作都要使用合法获取的access_token,微信 ...

  9. ASP.NET Web API实现微信公众平台开发(三)自定义菜单

    承接之前的流程,在完成服务器绑定和获取access_token之后,本文主要讲述如何实现微信自定义菜单. 官方示例效果 开始之前 .自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单. ...

随机推荐

  1. vyos (一) 基础配置

    http://www.lowefamily.com.au/2015/11/29/using-a-vyos-router-with-hyper-v/1/ http://thomasvochten.com ...

  2. dedecms 文章页调用来源合适时间的方法

    时间: 一:{dede:field.pubdate function="MyDate('Y-m-d H:i',@me)"/} 二:{dede:field name='pubdate ...

  3. 百度地图API示例之小实践 添加代理商标注

    地图坐标无非是经度纬度. 每个代理商都有他的经度纬度参数,就能够在地图上标注出来了. 效果如下: 功能包括 标记代理商 显示导航 显示距离 测量距离 点击选中等 其中测距用到的是自定义控件 地图根据城 ...

  4. ArrayList总结

    ArrayList 1.extends AbstractList 实现List<E>->Collection<e>->Iterable,RandomAccess,S ...

  5. Javascript 命名空间模式

    命名空间是通过为项目或库创建一个全局对象,然后将所有功能添加到该全局变量中.通过减少程序中全局变量的数量,实现单全局变量,从而在具有大量函数.对象和其他变量的情况下不会造成全局污染,同时也避免了命名冲 ...

  6. Run JavaScript on your PeopleSoft pages conditionally

    Here, PeopleCode sets the logic that determines when the JavaScript code will run. This is not as si ...

  7. ContactsContract中涉及数据库中的一些列属性值【Written By KillerLegend】

    ContactsContract.Data   http://developer.android.com/reference/android/provider/ContactsContract.Dat ...

  8. GOOGLE 离线完整安装包下载地址

    https://support.google.com/chrome/answer/126299?hl=zh-Hans 官方链接介绍 https://www.google.com/chrome/brow ...

  9. How to display SSRS report based on customer/Vendor specific language [AX2012]

    Common requirement is to show the reports in customer’s language. [example : Quotations, sales confi ...

  10. 6.html5分组元素

    何为分组元素,首先先看下面这个例子: <span>scolia<span>scolia</span></span> <span>scolia ...