您的位置:首页 > 移动开发 > 微信开发

C#开发微信公众号之消息自动回复

2015-09-24 23:23 781 查看
作为计算机学院的学生的学生,时刻在打计算机学院官网的主意,前段时间我的一个好基友在我面前炫耀他的能够查课表的公众号(服务模拟登录返回数据),把我眼红得,所以我暗自下决心,自己一定要弄个微信公众号来玩玩儿。经过各种网上查资料,各种走弯路,还是实现了微信公众号机器人聊天功能。虽然这个很简单,但是网上完善而又详细的资料很难找,而且官网的开发文档只针对php语言发布了Demo,开发者文档简直坑爹,不过我还是忍不住分享出来,嘿嘿,下面我就开始分享我的经验了。

1、开发准备:你需要一台服务器或者虚拟主机,一个微信号,然后到微信公众平台注册一个账号,并且申请一个订阅号。PS:订阅号可以每天群发消息,服务号一个月只能发一次。所以首选订阅号,不要问我为什么,一个字,爽。

2、当你申请公众号成功了就可以群发消息了,不过这些只能手动群发,还有就是针对用户回复的消息不能做出只能的响应,要响应的话必须手动添加关键字回复,所以这样肯定是不行的,这个时候就需要进入开发这中心进行相关的配置,如下图:



具体详情点击我

很多人会卡在服务器验证这关,因为总是显示taken验证失败,那是因为开发者服务器没有返回数据或者返回的数据微信服务器不能识别,大家仔细看红框里的:



如果你很久都没有验证成功,你可以直接返回echostr参数内容,这样达到欺骗微信服务器的效果(不建议这样做,因为没有验证taken,安全性非常低,但是作为初学者,咱先把功能实现了再说,嘿嘿)。当然我整熟了后也是验证了的。

3、当你验证服务器成功了后,就可以开始开发服务器端了。

我先来一段服务器欺骗的接口代码(我用的是.ashx一般处理文件):

<%@ WebHandler Language="C#" Class="Login" %>

using System;
using System.Web;

public class Login : IHttpHandler
{

public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
string echoString = HttpContext.Current.Request.QueryString["echoStr"];
context.Response.Write(echoString);
}

public bool IsReusable
{
get
{
return false;
}
}

}


直接撂到服务器上运行,不过你会发现网页会报错,不过不用担心,你按照报错的来修改web.config文件,就成功了。

好了,以上就是开发准备,接下来我将开始进入开发微信公众号服务端正题。

思路:

1、首先你得有一个图灵机器人的接口,这个时候你就要到图灵机器人官网注册账号,申请账号(希望你自己申请一个接口,不要用博主的,谢谢合作)。

2、服务器端接受到微信服务器发送过来的消息后,开发者写的接口直接爬取图灵接口所返回的数据,然后解析,转化成微信服务能够识别的数据格式,最后返回给微信服务器,这样微信服务器就会自动转发给指定openId的用户。

一、weixinapi.ashx(我用的是明文模式,所以把加密的代码注释了):

using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Web;
using System.Xml;
using WeiXinApi.Util;

namespace WeiXinApi
{
/// <summary>
/// weixinapi 的摘要说明
/// </summary>
public class weixinapi : IHttpHandler
{

string sToken = null;
string sAppID = null;
string sEncodingAESKey = null;

public void ProcessRequest(HttpContext context)
{
try
{
Stream stream = context.Request.InputStream;
byte[] byteArray = new byte[stream.Length];
stream.Read(byteArray, 0, (int)stream.Length);
string postXmlStr = System.Text.Encoding.UTF8.GetString(byteArray);
if (!string.IsNullOrEmpty(postXmlStr))
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(postXmlStr);
//if (string.IsNullOrWhiteSpace(sToken))
//{
//    DataTable dt = ConfigDal.GetConfig(WXMsgUtil.GetFromXML(doc, "ToUserName"));
//    DataRow dr = dt.Rows[0];
//    sToken = dr["Token"].ToString();
//    sAppID = dr["AppID"].ToString();
//    sEncodingAESKey = dr["EncodingAESKey"].ToString();
//}

//if (!string.IsNullOrWhiteSpace(sAppID))  //没有AppID则不解密(订阅号没有AppID)
//{
//    //解密
//    WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(sToken, sEncodingAESKey, sAppID);
//    string signature = context.Request["msg_signature"];
//    string timestamp = context.Request["timestamp"];
//    string nonce = context.Request["nonce"];
//    string stmp = "";
//    int ret = wxcpt.DecryptMsg(signature, timestamp, nonce, postXmlStr, ref stmp);
//    if (ret == 0)
//    {
//        doc = new XmlDocument();
//        doc.LoadXml(stmp);

//        try
//        {
//            responseMsg(context, doc);
//        }
//        catch (Exception ex)
//        {
//            FileLogger.WriteErrorLog(context, ex.Message);
//        }
//    }
//    else
//    {
//        FileLogger.WriteErrorLog(context, "解密失败,错误码:" + ret);
//    }
//}
//else
//{
//    responseMsg(context, doc);
//}

responseMsg(context, doc);
}
else
{
valid(context);
}
}
catch (Exception ex)
{
//    FileLogger.WriteErrorLog(context, ex.Message);
}
}

public void valid(HttpContext context)
{
var echostr = context.Request["echoStr"].ToString();
if (checkSignature(context) && !string.IsNullOrEmpty(echostr))
{
context.Response.Write(echostr);
context.Response.Flush();//推送...不然微信平台无法验证token
}
}

public bool checkSignature(HttpContext context)
{
var signature = context.Request["signature"].ToString();
var timestamp = context.Request["timestamp"].ToString();
var nonce = context.Request["nonce"].ToString();
var token = "qweq";
string[] ArrTmp = { token, timestamp, nonce };
Array.Sort(ArrTmp);     //字典排序
string tmpStr = string.Join("", ArrTmp);
tmpStr = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1");
tmpStr = tmpStr.ToLower();
if (tmpStr == signature)
{
return true;
}
else
{
return false;
}
}

public void responseMsg(HttpContext context, XmlDocument xmlDoc)
{
string result = "";
string msgType = WeiXinXML.GetFromXML(xmlDoc, "MsgType");
switch (msgType)
{
case "event":
switch (WeiXinXML.GetFromXML(xmlDoc, "Event"))
{
case "subscribe": //订阅
break;
case "unsubscribe": //取消订阅
break;
case "CLICK":
//DataTable dtMenuMsg = MenuMsgDal.GetMenuMsg(WXMsgUtil.GetFromXML(xmlDoc, "EventKey"));
//if (dtMenuMsg.Rows.Count > 0)
//{
//    List<Dictionary<string, string>> dictList = new List<Dictionary<string, string>>();
//    foreach (DataRow dr in dtMenuMsg.Rows)
//    {
//        Dictionary<string, string> dict = new Dictionary<string, string>();
//        dict["Title"] = dr["Title"].ToString();
//        dict["Description"] = dr["Description"].ToString();
//        dict["PicUrl"] = dr["PicUrl"].ToString();
//        dict["Url"] = dr["Url"].ToString();
//        dictList.Add(dict);
//    }
//    result = WXMsgUtil.CreateNewsMsg(xmlDoc, dictList);
//}
//else
//{
//    result = WXMsgUtil.CreateTextMsg(xmlDoc, "无此消息哦");
//}
break;
default:
break;
}
break;
case "text":
string text = WeiXinXML.GetFromXML(xmlDoc, "Content");
if (text == "这个开发者好帅" || text == "土豪是傻逼" || text == "不按规则也能聊天")
{
if (text == "土豪是傻逼")
{
result = WeiXinXML.CreateTextMsg(xmlDoc, "这个傻逼喜欢吃芹菜!");
}
else if (text == "这个开发者好帅")
{
result = WeiXinXML.CreateTextMsg(xmlDoc, "你说了句大实话啊!哈哈!");
}
else
{
result = WeiXinXML.CreateTextMsg(xmlDoc, TuLing.GetTulingMsg(text));
}
}
else
{
if (text.Contains("t"))
{
text = text.Replace("t","");
result = WeiXinXML.CreateTextMsg(xmlDoc, TuLing.GetTulingMsg(text));
}
else
{
result = WeiXinXML.CreateTextMsg(xmlDoc, "你回复错误导致了土豪成为了傻逼,除非你回复:这个开发者好帅  或者回复:土豪是傻逼 或者你想和机器人聊天请回复格式:t+你好(例如:t我饿了)");
}
}

break;
default:
break;
}

//if (!string.IsNullOrWhiteSpace(sAppID)) //没有AppID则不加密(订阅号没有AppID)
//{
//    //加密
//    WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(sToken, sEncodingAESKey, sAppID);
//    string sEncryptMsg = ""; //xml格式的密文
//    string timestamp = context.Request["timestamp"];
//    string nonce = context.Request["nonce"];
//    int ret = wxcpt.EncryptMsg(result, timestamp, nonce, ref sEncryptMsg);
//    if (ret != 0)
//    {
//        FileLogger.WriteErrorLog(context, "加密失败,错误码:" + ret);
//        return;
//    }

//    context.Response.Write(sEncryptMsg);
//    context.Response.Flush();
//}
//else
// {
context.Response.Write(result);
context.Response.Flush();
//   }
}
public bool IsReusable
{
get
{
return false;
}
}
}
}


二、TuLing.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;

namespace WeiXinApi.Util
{
public class TuLing
{

public static string RequestTuling(string info)
{
info = HttpContext.Current.Server.UrlEncode(info);
string url = "http://www.tuling123.com/openapi/api?key=72a2b178d33d9f04d7c0e7b11f7e0279&info=" + info;
return RequestUrl(url, "get");
}

public static string GetTulingMsg(string info)
{
string jsonStr = RequestTuling(info);
if (GetJsonValue(jsonStr, "code") == "100000")
{
return GetJsonValue(jsonStr, "text");
}
if (GetJsonValue(jsonStr, "code") == "200000")
{
return GetJsonValue(jsonStr, "text") + GetJsonValue(jsonStr, "url");
}
return "不知道怎么回复你哎";
}

public static string RequestUrl(string url, string method)
{
// 设置参数
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
CookieContainer cookieContainer = new CookieContainer();
request.CookieContainer = cookieContainer;
request.AllowAutoRedirect = true;
request.Method = method;
request.ContentType = "text/html";
request.Headers.Add("charset", "utf-8");

//发送请求并获取相应回应数据
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
//直到request.GetResponse()程序才开始向目标网页发送Post请求
Stream responseStream = response.GetResponseStream();
StreamReader sr = new StreamReader(responseStream, Encoding.UTF8);
//返回结果网页(html)代码
string content = sr.ReadToEnd();
return content;
}

public static string GetJsonValue(string jsonStr, string key)
{
string result = string.Empty;
if (!string.IsNullOrEmpty(jsonStr))
{
key = "\"" + key.Trim('"') + "\"";
int index = jsonStr.IndexOf(key) + key.Length + 1;
if (index > key.Length + 1)
{
//先截逗号,若是最后一个,截“}”号,取最小值
int end = jsonStr.IndexOf(',', index);
if (end == -1)
{
end = jsonStr.IndexOf('}', index);
}

result = jsonStr.Substring(index, end - index);
result = result.Trim(new char[] { '"', ' ', '\'' }); //过滤引号或空格
}
}
return result;
}
}
}


三、WeiXinXML.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml;

namespace WeiXinApi.Util
{
public class WeiXinXML
{

public static string CreateTextMsg(XmlDocument xmlDoc, string content)
{
string strTpl = string.Format(@"<xml>
<ToUserName><![CDATA[{0}]]></ToUserName>
<FromUserName><![CDATA[{1}]]></FromUserName>
<CreateTime>{2}</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[{3}]]></Content>
</xml>", GetFromXML(xmlDoc, "FromUserName"), GetFromXML(xmlDoc, "ToUserName"),
DateTime2Int(DateTime.Now), content);

return strTpl;
}

public static int DateTime2Int(DateTime dt)
{
DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
return (int)(dt - startTime).TotalSeconds;
}

public static string GetFromXML(XmlDocument xmlDoc, string name)
{
XmlNode node = xmlDoc.SelectSingleNode("xml/" + name);
if (node != null && node.ChildNodes.Count > 0)
{
return node.ChildNodes[0].Value;
}
return "";
}
}
}


好,就这些。

微信开发者服务端源码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: