1 公司提供接口,微信平台可以通过访问我们的接口,进行数据交互,通过xml。
2 http://mp.weixin.qq.com/ 微信服务号平台,输入用户名密码进入高级功能-开发者模式,
3 申请服务号之后,微信会提供appid和
4 接下里就是完成自己的接口部分的开发,然后接口的服务器配置地址输入微信服务号的服务器配置url,本地的项目地址是不行的,得是能访问的地址
5 接口的开发,接受xml,然后返回xml。
6 页面不需要写什么,但是注意编码,微信的编码是utf-8的,所以一定要注意,gb2312或者默认是无法访问的
<%@ Page Language="C#" ResponseEncoding="utf-8" ContentType="text/xml" AutoEventWireup="true" CodeBehind="weixin.aspx.cs" Inherits="weixin.weixin" %>
7 后台代码:
protected void Page_Load(object sender, EventArgs e) { if (Request.QueryString["city"] != null && Request.QueryString["city"].ToString() != "") { cityname = Request.QueryString["city"].ToString(); } weixinEntity wx = new weixinEntity(); string postStr = ""; if (Request.HttpMethod.ToLower() == "post" ) { Stream s = System.Web.HttpContext.Current.Request.InputStream; byte[] b = new byte[s.Length]; s.Read(b, 0, (int)s.Length); postStr = Encoding.UTF8.GetString(b); if (!string.IsNullOrEmpty(postStr)) //请求处理 { wx.Handle(postStr); } } else { wx.Auth(); } }
#region 微信请求类 RequestXML /// <summary> /// 微信请求类 /// </summary> public class RequestXML { private string toUserName = ""; /// <summary> /// 消息接收方微信号,一般为公众平台账号微信号 /// </summary> public string ToUserName { get { return toUserName; } set { toUserName = value; } } private string fromUserName = ""; /// <summary> /// 消息发送方微信号 /// </summary> public string FromUserName { get { return fromUserName; } set { fromUserName = value; } } private string createTime = ""; /// <summary> /// 创建时间 /// </summary> public string CreateTime { get { return createTime; } set { createTime = value; } } private string msgType = ""; /// <summary> /// 信息类型 地理位置:location,文本消息:text,消息类型:image /// </summary> public string MsgType { get { return msgType; } set { msgType = value; } } private string content = ""; /// <summary> /// 信息内容 /// </summary> public string Content { get { return content; } set { content = value; } } private string location_X = ""; /// <summary> /// 地理位置纬度 /// </summary> public string Location_X { get { return location_X; } set { location_X = value; } } private string location_Y = ""; /// <summary> /// 地理位置经度 /// </summary> public string Location_Y { get { return location_Y; } set { location_Y = value; } } private string scale = ""; /// <summary> /// 地图缩放大小 /// </summary> public string Scale { get { return scale; } set { scale = value; } } private string label = ""; /// <summary> /// 地理位置信息 /// </summary> public string Label { get { return label; } set { label = value; } } private string picUrl = ""; /// <summary> /// 图片链接,开发者可以用HTTP GET获取 /// </summary> public string PicUrl { get { return picUrl; } set { picUrl = value; } } private string eventtype = ""; /// <summary> /// 事件类型,CLICK/VIEW /// </summary> public string Eventtype { get { return eventtype; } set { eventtype = value; } } private string eventkey = ""; /// <summary> /// 事件KEY值,与自定义菜单接口中KEY值对应,设置的跳转URL /// </summary> public string Eventkey { get { return eventkey; } set { eventkey = value; } } } #endregion
public class weixinEntity:weixin { private string Token = "mf0605"; //换成自己的token public void Auth() { string echoStr = System.Web.HttpContext.Current.Request.QueryString["echoStr"]; if (CheckSignature()) //校验签名是否正确 { if (!string.IsNullOrEmpty(echoStr)) { System.Web.HttpContext.Current.Response.Write(echoStr); //返回原值表示校验成功 System.Web.HttpContext.Current.Response.End(); } } } private bool CheckSignature() { string signature = System.Web.HttpContext.Current.Request.QueryString["signature"]; string timestamp = System.Web.HttpContext.Current.Request.QueryString["timestamp"]; string nonce = System.Web.HttpContext.Current.Request.QueryString["nonce"]; //加密/校验流程: //1. 将token、timestamp、nonce三个参数进行字典序排序 string[] ArrTmp = { Token, timestamp, nonce }; Array.Sort(ArrTmp);//字典排序 //2.将三个参数字符串拼接成一个字符串进行sha1加密 string tmpStr = string.Join("", ArrTmp); tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1"); tmpStr = tmpStr.ToLower(); //3.开发者获得加密后的字符串可与signature对比,标识该请求来源于微信。 if (tmpStr == signature) { return true; } else { return false; } } public void Handle(string postStr) { //封装请求类 XmlDocument doc = new XmlDocument(); doc.LoadXml(postStr); XmlElement rootElement = doc.DocumentElement; //MsgType XmlNode MsgType = rootElement.SelectSingleNode("MsgType"); //接收的值--->接收消息类(也称为消息推送) RequestXML requestXML = new RequestXML(); requestXML.ToUserName = rootElement.SelectSingleNode("ToUserName").InnerText; requestXML.FromUserName = rootElement.SelectSingleNode("FromUserName").InnerText; requestXML.CreateTime = rootElement.SelectSingleNode("CreateTime").InnerText; requestXML.MsgType = MsgType.InnerText; //根据不同的类型进行不同的处理 switch (requestXML.MsgType) { case "text": //文本消息 requestXML.Content = rootElement.SelectSingleNode("Content").InnerText; break; case "image": //图片 requestXML.PicUrl = rootElement.SelectSingleNode("PicUrl").InnerText; break; case "location": //位置 requestXML.Location_X = rootElement.SelectSingleNode("Location_X").InnerText; requestXML.Location_Y = rootElement.SelectSingleNode("Location_Y").InnerText; requestXML.Scale = rootElement.SelectSingleNode("Scale").InnerText; requestXML.Label = rootElement.SelectSingleNode("Label").InnerText; break; case "link": //链接 break; case "event": //事件推送 requestXML.Eventtype = rootElement.SelectSingleNode("Event").InnerText; requestXML.Eventkey = rootElement.SelectSingleNode("EventKey").InnerText; break; } //消息回复 ResponseMsg(requestXML); } private void ResponseMsg(RequestXML requestXML) { try { string resxml = ""; resxml = GetXMLByEvent(requestXML); System.Web.HttpContext.Current.Response.Write(resxml); //WriteToDB(requestXML, resxml, mi.pid); } catch (Exception e) { string resxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[text]]></MsgType>"; resxml += "<Content><![CDATA["+ e.InnerException + e.Source + e.StackTrace + "]]></Content></xml>"; System.Web.HttpContext.Current.Response.Write(resxml); } } private string GetXMLByEvent(RequestXML requestXML) { string strxml = ""; #region switch (requestXML.MsgType) { case "event": string strkey = requestXML.Eventkey; string strdesc = "", strpage = ""; if (requestXML.Eventtype == "CLICK") { #region 菜单点击事件 switch (strkey) { case "SF_shenqingfagndai": strpage = "快速申请房贷"; strdesc = "利率低、放款快,搜房金融,贷款快人一步!<a href=\"http://8.sh.soufun.com/zt/201403/ershoufangdaikuan.html\">立即使用</a>"; break; case "SF_help": strpage = "使用帮助"; strdesc = "我们为您提供以下服务:" + "\n查询小区最新房价,<a href=\"http://m.soufun.com/pinggu/sh/\">立即查询</a>" + "\n查询学区房信息,<a href=\"http://m.soufun.com/schoolhouse/sh/\">立即查询</a>" + "\n您还可以直接输入以下数字查使用相应功能:\n【1】快速申请贷款"; break; default: break; } if (strdesc != "") { strxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[text]]></MsgType>"; strxml += "<Content><![CDATA[" + strdesc + "]]></Content></xml>"; WriteToDBDetail(requestXML.FromUserName, cityname, "0", strpage); } else { strxml = GetXMLbytype(requestXML, strkey); } #endregion } #region 订阅服务号 if (requestXML.Eventtype == "subscribe") { string subscribe_first = "非常感谢您关注***微信,我们为您提供以下服务:" + "\n查询小区最新房价,<a href=\"http://m.soufun.com/pinggu/sh/\">立即查询</a>" + "\n查询学区房信息,<a href=\"http://m.soufun.com/schoolhouse/sh/\">立即查询</a>" + "\n您还可以直接输入以下数字查使用相应功能:\n【1】快速申请贷款" + "\n【2】参加淘房团报名"; strxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[text]]></MsgType>"; strxml += "<Content><![CDATA[" + subscribe_first + "]]></Content></xml>"; } #endregion break; case "text": try { string strsearchkey = requestXML.Content; string searchUrl = "", searchtype = "",moreurl=""; #region 回复数字内容 switch (strsearchkey) { case "1": moreurl = "利率低、放款快,搜房金融,贷款快人一步!<a href=\"http://8.sh.soufun.com/zt/201403/ershoufangdaikuan.html\">立即使用</a>"; break; case "0": moreurl = "我们为您提供以下服务:"; break; default: #region 接口 string sql_search = "select top 1 * from WeiXinKeyType where username=‘" + requestXML.FromUserName + "‘ order by createtime desc;"; DataTable dt = SearchDB(sql_search); if (dt != null && dt.Rows.Count > 0) { searchtype = dt.Rows[0]["KeyType"].ToString(); } if (searchtype == "1") { #region 学校接口查学校 searchUrl = ConfigurationManager.AppSettings["SchoolSearchUrl"].ToString(); DataSet ds = GetInfoByKey(cityname, strsearchkey, 5, 1, searchUrl); DataTable dt1 = new DataTable(); if (ds.Tables.Contains("schoolinfo")) { dt1 = ds.Tables["schoolinfo"]; } if (dt1 != null && dt1.Rows.Count > 0) { strxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName>" + "<CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[news]]></MsgType>"; strxml += "<ArticleCount>" + dt1.Rows.Count + "</ArticleCount>"; #region 拼Articles strxml += "<Articles>"; for (int i = 0; i < dt1.Rows.Count; i++) { string title = dt1.Rows[i]["schoolname"].ToString() + "(" + dt1.Rows[i]["schooldistrict"].ToString() + "-" + dt1.Rows[i]["schoolcomarea"].ToString() + ")"; string picurl = dt1.Rows[i]["schoolimgurl"].ToString(); string url = "http://m.soufun.com/schoolhouse/sh/" + dt1.Rows[i]["schoolid"].ToString() + ".htm"; string desc = "类型:" + dt1.Rows[i]["schooltype"].ToString() + "/" + dt1.Rows[i]["schoolrank"].ToString() + "/" + dt1.Rows[i]["schoolnature"].ToString(); strxml += "<item><Title><![CDATA[" + title + "]]></Title><Description><![CDATA[" + desc + "]]></Description><PicUrl><![CDATA[" + picurl + "]]></PicUrl><Url><![CDATA[" + url + "]]></Url></item>"; } strxml += "</Articles>"; #endregion strxml += "</xml>"; WriteToDBDetail(requestXML.FromUserName, cityname, "1", strsearchkey); } else { strxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[text]]></MsgType>"; strxml += "<Content><![CDATA[dt没有数据" + searchUrl + "]]></Content></xml>"; } #endregion } if (searchtype == "2") { #region 楼盘接口查小区 searchUrl = ConfigurationManager.AppSettings["ProjSearchUrl"].ToString(); DataSet ds_proj = GetInfoByKey(cityname, strsearchkey, 5, 1, searchUrl); DataTable dt2 = new DataTable(); if (ds_proj.Tables.Contains("houseinfo")) { dt2 = ds_proj.Tables["houseinfo"]; } if (dt2 != null && dt2.Rows.Count > 0) { strxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName>" + "<CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[news]]></MsgType>"; strxml += "<ArticleCount>" + dt2.Rows.Count + "</ArticleCount>"; #region 拼Articles strxml += "<Articles>"; for (int i = 0; i < dt2.Rows.Count; i++) { string title = dt2.Rows[i]["projname"].ToString() + "(" + dt2.Rows[i]["district"].ToString() + "-" + dt2.Rows[i]["comarea"].ToString() + ")"; string picurl = dt2.Rows[i]["coverimg"].ToString(); string url = "http://m.soufun.com/xiaoqu/sh/" + dt2.Rows[i]["projcode"].ToString() + ".html"; string monthadd = ""; if (dt2.Rows[i]["monthadd"].ToString() == "null") { monthadd = "0.00"; } else { if (dt2.Rows[i]["monthadd"].ToString().Contains("-")) { monthadd = "跌↓" + dt2.Rows[i]["monthadd"].ToString().Replace("-", "") + "%"; } else { monthadd = "涨↑" + dt2.Rows[i]["monthadd"].ToString().Replace("-", "") + "%"; } } string desc = "最新均价:" + dt2.Rows[i]["price"].ToString() + "元/㎡,环比上月" + monthadd; strxml += "<item><Title><![CDATA[" + title + "]]></Title><Description><![CDATA[" + desc + "]]></Description><PicUrl><![CDATA[" + picurl + "]]></PicUrl><Url><![CDATA[" + url + "]]></Url></item>"; } strxml += "</Articles>"; #endregion strxml += "</xml>"; WriteToDBDetail(requestXML.FromUserName, cityname, "2", strsearchkey); } else { strxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[text]]></MsgType>"; strxml += "<Content><![CDATA[dt没有数据" + searchUrl + "]]></Content></xml>"; } #endregion } if (searchtype == "") { strxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[text]]></MsgType>"; strxml += "<Content><![CDATA[searchtype为空" + sql_search + "]]></Content></xml>"; } #endregion break; } if (moreurl != "") { strxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[text]]></MsgType>"; strxml += "<Content><![CDATA[" + moreurl + "]]></Content></xml>"; WriteToDBDetail(requestXML.FromUserName, cityname, "0", strsearchkey); } #endregion } catch(Exception e) { strxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>"+ ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[text]]></MsgType>"; strxml += "<Content><![CDATA[" + e.InnerException+e.Source+e.StackTrace + "]]></Content></xml>"; } break; case "image": //图文混合的消息 具体格式请见官方API“回复图文消息” break; } #endregion return strxml; } private string GetXMLbytype(RequestXML requestXML, string strkey) { string strxml = ""; if (strkey == "SF_school" || strkey=="school") { string school_first = "请输入学校名"; strxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[text]]></MsgType>"; strxml += "<Content><![CDATA[" + school_first + "]]></Content></xml>"; string strcon = ""; if (!WriteToDB(requestXML.FromUserName, cityname, "1", ref strcon)) { strxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[text]]></MsgType>"; strxml += "<Content><![CDATA[InsertToDBfalse_school" + strcon + "]]></Content></xml>"; } } #region 搜小区,返回提示 if (strkey == "SF_proj"||strkey=="proj") { string proj_first = "请输入小区名,如“上海康城”"; strxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[text]]></MsgType>"; strxml += "<Content><![CDATA[" + proj_first + "]]></Content></xml>"; string strcon = ""; if (!WriteToDB(requestXML.FromUserName, cityname, "2", ref strcon)) { strxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[text]]></MsgType>"; strxml += "<Content><![CDATA[InsertToDBfalse_proj" + strcon + "]]></Content></xml>"; } } #endregion return strxml; } private int ConvertDateTimeInt(DateTime time) { DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); return (int)(time - startTime).TotalSeconds; } public DataSet GetInfoByKey(string cityname, string keys, int pagesize, int page, string searchUrl) { DataSet ds = new DataSet(); try { System.Text.Encoding encode = System.Text.Encoding.GetEncoding("gb2312"); if (!string.IsNullOrEmpty(cityname)) { searchUrl += "city=" + System.Web.HttpUtility.UrlEncode(cityname, encode); } if (!string.IsNullOrEmpty(keys)) { searchUrl += "&keyword=" + System.Web.HttpUtility.UrlEncode(keys, encode); } searchUrl += "&pagesize=" + pagesize; searchUrl += "&page=" + page; SearchInterface.GetSearchData("", searchUrl, ref ds); } catch (Exception e) { BaseData.ErrorLog.WriteError(e); } return ds; } #region 数据库操作 private bool WriteToDB(string username,string city,string isshoolorproj,ref string strconn) { //todo城市 try { string sql_search = "select * from WeiXinKeyType where username=‘" + username + "‘ and city=‘" + city + "‘ order by createtime desc"; DataTable dt = SearchDB(sql_search); if (dt != null && dt.Rows.Count > 0) { string sql_update = "update WeiXinKeyType set KeyType=" + isshoolorproj + " where username=‘" + username + "‘ and city=‘" + city + "‘"; if (UpdateDB(sql_update, ref strconn)) { return true; } else { return false; } } else { string sql_insert = ""; if (isshoolorproj=="1") { sql_insert = "insert into WeiXinKeyType(city,username,KeyType,createtime) values (‘上海‘,‘" + username + "‘,1,‘" + DateTime.Now + "‘);"; } if (isshoolorproj == "2") { sql_insert = "insert into WeiXinKeyType(city,username,KeyType,createtime) values (‘上海‘,‘" + username + "‘,2,‘" + DateTime.Now + "‘);"; } return QueryNoRecords(BaseData.Base.BusinessType.WeiXinWrite, sql_insert, cityname, ref strconn); } } catch { return false; } } public bool WriteToDBDetail(string username, string city, string isshoolorproj,string keystr) { //todo城市 try { string sql_insert = ""; sql_insert = "insert into WeiXinKeyDetail(city,username,keystr,isschoolorproj,createtime) values (‘上海‘,‘" + username + "‘,‘" + keystr + "‘," + isshoolorproj + ",‘" + DateTime.Now + "‘);"; string strconn = ""; return QueryNoRecords(BaseData.Base.BusinessType.WeiXinWrite, sql_insert, cityname, ref strconn); } catch { return false; } } public string GetConnectionStr(BaseData.Base.BusinessType businesstype, string city) { string connstr = "",xmlkey=""; switch (businesstype) { case BaseData.Base.BusinessType.WeiXinRead: xmlkey = "weixin_SH_R"; break; case BaseData.Base.BusinessType.WeiXinWrite: xmlkey = "weixin_SH_W"; break; default: xmlkey = ""; break; } DataSet ds = new DataSet(); string xmlpath = ConfigurationManager.AppSettings["DbInterfaceConfig"]; ds.ReadXml(xmlpath); DataTable dt = ds.Tables["database"]; if (dt.Columns.IndexOf(xmlkey) > -1) connstr = Convert.ToString(dt.Rows[0][xmlkey]); return connstr; } static SqlCommand GetSqlCom(string constr) { SqlConnection sqlcon = new SqlConnection(constr); SqlCommand sqlcom = new SqlCommand(); sqlcon.Open(); sqlcom.Connection = sqlcon; return sqlcom; } public bool QueryNoRecords(BaseData.Base.BusinessType businesstype, string SqlString, string city,ref string strcon) { bool complete = false; SqlString = SqlString.ToLower(); string constr = GetConnectionStr(businesstype, city); strcon = constr; SqlCommand cm = GetSqlCom(constr); cm.CommandText = SqlString; try { if (cm.ExecuteNonQuery() > -1) { complete = true; } } catch (Exception ex) { } finally { if (null != cm.Connection && ConnectionState.Closed != cm.Connection.State) cm.Connection.Close(); } return complete; } private bool UpdateDB(string sql_update,ref string strcon) { return QueryNoRecords(BaseData.Base.BusinessType.WeiXinWrite, sql_update, cityname, ref strcon); } private DataTable SearchDB(string sql_search) { //todo城市 DataTable dt = new DataTable(); QueryRecords(BaseData.Base.BusinessType.WeiXinRead, sql_search, cityname, ref dt); return dt; } public bool QueryRecords(BaseData.Base.BusinessType businesstype, string SqlString, string city, ref DataTable dt) { bool complete = true; SqlString = SqlString.ToLower(); string constr = GetConnectionStr(businesstype, city); SqlCommand cm = GetSqlCom(constr); SqlDataAdapter da = new SqlDataAdapter(); cm.CommandText = SqlString; da.SelectCommand = cm; try { da.Fill(dt); } catch (Exception ex) { } finally { if (null != cm.Connection && ConnectionState.Closed != cm.Connection.State) cm.Connection.Close(); } return complete; } #endregion }