Asp.Net Web API开发微信后台

时间:2023-02-16 14:35:07

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

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

而且由于Web API其实是微软封装了大量的类库,所以会导致后台相当臃肿。所以,不建议Asp.Net 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&num;开发微信门户及应用&lpar;47&rpar; - 整合Web API、微信后台管理及前端微信小程序的应用方案

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

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

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

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

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

  4. &lbrack;目录&rsqb;ASP&period;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&period;net Web Api开发Help Page配置和扩展

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

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

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

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

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

  8. ASP&period;NET Web API实现微信公众平台开发(二)access&lowbar;token与定时任务

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

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

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

随机推荐

  1. 《徐徐道来话Java》(2):泛型和数组,以及Java是如何实现泛型的

    数组和泛型容器有什么区别 要区分数组和泛型容器的功能,这里先要理解三个概念:协变性(covariance).逆变性(contravariance)和无关性(invariant). 若类A是类B的子类, ...

  2. Shell编程基础教程4--控制流结构

    4.控制流结构    4.1.控制结构            4.2.if then else语句        格式: if 条件1 //如果条件1为真 then 命令1 //那么,执行命令1 el ...

  3. hdu 4857 逃生

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4857 逃生 Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能 ...

  4. 根据Entity Framework6&period;X 数据生成代码&lpar;仅获取表名&rpar;

    近来学习ASP.NET MVC ,一直在看韩迎龙(Kencery)的ASP.NET MVC+EF框架+EasyUI实现权限管理.在第九节(TT模板的学习)卡住了,作者使用EF5.0做数据源,而我使用的 ...

  5. ArcEngine栅格和矢量渲染(含可视化颜色带)

    使用ArcEngine9.3开发的栅格和矢量的渲染. 开发环境:ArcEngine9.3,VS2008. 功能:栅格(拉伸和分级)和矢量(简单.唯一值.分级.比例)渲染. 开发界面如图所示. 图1 主 ...

  6. C&num; File类的操作

    原文:C# File类的操作 File类,是一个静态类,主要是来提供一些函数库用的.静态实用类,提供了很多静态的方法,支持对文件的基本操作,包括创建,拷贝,移动,删除和打开一个文件.File类方法的参 ...

  7. Java 课程设计 &quot&semi;Give it up&quot&semi;小游戏(团队)

    JAVA课程设计 "永不言弃"小游戏(From :Niverse) 通过Swing技术创建游戏的登陆注册界面,使用mySQL数据库技术完成用户的各项信息保存和游戏完成后的成绩保存. ...

  8. 学习pthreads,管理线程的栈

    进程的地址空间分成代码段,静态数据段,堆和栈段.线程栈的位置和大小是从它所属的进程的栈中切分出来的.每个栈必须足够大,以容纳所有对等线程的函数的执行以及它们将会调用的例程链.或许你会问为什么要进行线程 ...

  9. python excel表格操作

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  10. PrintWriter中的write与println方法居然就是这些区别

    为什么循环中分别用write方法和println方法效果一样呢? import java.io.*; public class WriteLog { private BufferedReader bf ...