asp.net微信开发(自定义会话管理) 和微信用户的沟通少不了,总觉得看起来微信官网后台管理中的会话回复消息有点呆板,所以我这里就自定义了一个会话管理功能,最终效果图如下: 因为我试使用富文本文件CKEDITOR来进行编写,你看到稳中可能会有

字段,后台获取数据内容时,替换为空字符即可:如下 string txtcontent = this.txtMessage.Value.ToString().Replace("

", ""); StringBuilder sb = new StringBuilder(); sb.Append(txtcontent.Replace("

\r\n", "")); 在我个人理解,做会话管理,无非就是将用户对话信息(用户发过来的数据,发给用户的数据)存入数据库,根据用户的数据时间和回复用户数据的时间来和当天系统的时间做对比,如果大于多少分钟或者多少个小时就不可以再主动和用户对话,就算我这里是根据微信官网48小时来进行限制的,超过48小时禁用控件,如下图: 废话少说,上代码:需要用到的两个类,数据库也要创建和类相同的名字(至少我试这么做的) /// /// 微信会话记录类,用户存储会话记录列表 /// public class WeixinKeFuInfo { public int UId { get; set; }//编号 public string UserOpenId { get; set; }//用户的OpenID public string UserContent { get; set; }//用户内容 public string CreaterDate { get; set; }//创建时间 } /// /// 与微信用户会话的消息记录类 /// public class WxMessageInfo { public int msgId { get; set; }//消息ID public string FromUser { get; set; }//发送用户 public string ToUser { get; set; }//接收用户 public string Content { get; set; }//发送内容 public string FaSongDate { get; set; }//发送时间 public string UId { get; set; }//会话用户的UId,微信会话记录类外键 } /// /// 发送文本。。。。。。。。。。。。。还记得这个方法吗?就是根据用户发送过来的消息类型进行判断后,如果是文本就回复发送此方法内的内容 /// /// private void SendTextCase(RequestXML requestXML) {       WeixinKeFuService wkfs = new WeixinKeFuService();//自己写的服务类 //根据openId查询数据库会话记录是否存在 WeixinKeFuInfo wkfinfoinfo = wkfs.GetWeixinKeFuInfoByOpenId(requestXML.FromUserName.ToString()); if (wkfinfoinfo != null) { //如果存在直接保存消息记录 WxMessageService wms = new WxMessageService(); WxMessageInfo wminfo = new WxMessageInfo(); wminfo.FromUser = requestXML.FromUserName.ToString(); wminfo.ToUser = "我"; wminfo.Content = requestXML.Content.ToString(); wminfo.FaSongDate = System.DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"); wminfo.UId = wkfinfoinfo.UId.ToString(); wms.AddWxMessageInfo(wminfo); } else { //如果不存在新建会话记录 WeixinKeFuInfo wkfinfo = new WeixinKeFuInfo(); wkfinfo.UserOpenId = requestXML.FromUserName.ToString(); wkfinfo.UserContent = requestXML.Content.ToString(); wkfinfo.CreaterDate = System.DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"); wkfs.AddWeixinKeFuInfo(wkfinfo); string responseContent = FormatTextXML(requestXML.FromUserName, requestXML.ToUserName, "正在接入.请稍候....."); HttpContext.Current.Response.ContentType = "text/xml"; HttpContext.Current.Response.ContentEncoding = Encoding.UTF8; HttpContext.Current.Response.Write(responseContent); HttpContext.Current.Response.End(); }   } 以上代码实现了数据库的插入,那么取出来,显示的页面,核心代码:WeiXinSessionList.aspx,前台代码如下: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WeiXinSessionList.aspx.cs" Inherits="DQWebSite.Administrator.WeiXinSessionList" %>
位置:
根据微信公众平台规定,用户主送发起会话后,48小时之内可与该用户进行无限次会话,超过48小时不能主动会话。
<%-- --%> <%-- --%>

openId昵称 性别初始内容 接入时间 近期会话 会话状态 已过时间 会话操作
<%# Eval("UserOpenId")%> <%# (Eval("UserContent").ToString().Length>10)?Eval("UserContent").ToString().Substring(0,10)+"..":Eval("UserContent") %> <%# Eval("CreaterDate")%> );">启动会话 <%-- 新建 --%>
确定 >>| > < |<< 当前第 页/ 共搜索到 条记录.
WeiXinSessionList.aspx.cs后台代码如下: PagedDataSource pds = new PagedDataSource(); protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { BindGustBookList(); this.DataBind(); UsersInfo user = Session["Users"] as UsersInfo; if (user != null && user.RolsId == 1) { this.BtnDelete.Enabled = true; } else { this.BtnDelete.Enabled = false; } } } private void BindGustBookList() { WeixinKeFuService wkf = new WeixinKeFuService(); List wkflists = wkf.GetAllWeixinKeFuInfoList(); //if (this.DDLState.SelectedValue.Equals("1")) //{ // lists = gbs.GetAllGustBookListByState(); //} //else if (this.DDLState.SelectedValue.Equals("2")) //{ // lists = gbs.GetAllGustBookListByState2(); //} //else //{ // lists = gbs.GetAllGustBookList(); //} pds.DataSource = wkflists; pds.AllowPaging = true; pds.PageSize = 20;//每页显示为20条 int CurrentPage; if (!String.IsNullOrWhiteSpace(this.txtPageIndex.Text.ToString().Trim())) { CurrentPage = Convert.ToInt32(this.txtPageIndex.Text.ToString().Trim()); } else if (Request.QueryString["Page"] != null) { CurrentPage = Convert.ToInt32(Request.QueryString["Page"]); } else { CurrentPage = 1; } pds.CurrentPageIndex = CurrentPage - 1;//当前页的索引就等于当前页码-1; if (!pds.IsFirstPage) { //Request.CurrentExecutionFilePath 为当前请求的虚拟路径 this.lnkTop.NavigateUrl = Request.CurrentExecutionFilePath + "?Page=" + Convert.ToString(CurrentPage - 1); this.lnkFist.Enabled = this.lnkTop.Enabled = true; this.lnkNext.Enabled = this.lnkLast.Enabled = true; } else { this.lnkFist.Enabled = this.lnkTop.Enabled = false; this.lnkNext.Enabled = this.lnkLast.Enabled = true; this.lnkFist.Attributes.Add("style", "color:#ced9df;"); this.lnkTop.Attributes.Add("style", "color:#ced9df;"); this.lnkNext.Attributes.Remove("style"); this.lnkLast.Attributes.Remove("style"); } if (!pds.IsLastPage) { //Request.CurrentExecutionFilePath 为当前请求的虚拟路径 this.lnkNext.NavigateUrl = Request.CurrentExecutionFilePath + "?Page=" + Convert.ToString(CurrentPage + 1); this.lnkFist.Enabled = this.lnkTop.Enabled = true; this.lnkNext.Enabled = this.lnkLast.Enabled = true; } else { this.lnkNext.Enabled = this.lnkLast.Enabled = false; this.lnkFist.Enabled = this.lnkTop.Enabled = true; this.lnkNext.Attributes.Add("style", "color:#ced9df;"); this.lnkLast.Attributes.Add("style", "color:#ced9df;"); this.lnkFist.Attributes.Remove("style"); this.lnkTop.Attributes.Remove("style"); } this.lnkFist.NavigateUrl = Request.CurrentExecutionFilePath + "?Page=" + Convert.ToString(1);//跳转至首页 this.lnkLast.NavigateUrl = Request.CurrentExecutionFilePath + "?Page=" + Convert.ToString(pds.PageCount);//跳转至末页 this.RepeaterGustBookList.DataSource = pds; this.RepeaterGustBookList.DataBind(); this.lbCountData.Text = wkflists.Count.ToString(); this.lbPageIndex.Text = (pds.CurrentPageIndex + 1).ToString(); this.lbPageSize.Text = "每页" + pds.PageSize.ToString() + "条记录"; this.lbCountPage.Text = pds.PageCount.ToString(); this.txtPageIndex.Text = (pds.CurrentPageIndex + 1).ToString(); if (int.Parse(wkflists.Count.ToString()) <= int.Parse(pds.PageSize.ToString())) { this.lnkFist.Visible = this.lnkTop.Visible = this.lnkNext.Visible = this.lnkLast.Visible = this.txtPageIndex.Visible = this.LinkBtnToPage.Visible = false; } else { this.lnkFist.Visible = this.lnkTop.Visible = this.lnkNext.Visible = this.lnkLast.Visible = this.txtPageIndex.Visible = this.LinkBtnToPage.Visible = true; } } /// /// 删除选中 /// /// /// protected void BtnDelete_Click(object sender, EventArgs e) { Boolean bools = false; foreach (RepeaterItem di in this.RepeaterGustBookList.Items) { CheckBox checkIn = (CheckBox)di.FindControl("CheckIn"); if (checkIn.Checked) { bools = true; Label lbGustNo = di.FindControl("lbUId") as Label; WeixinKeFuService wkf = new WeixinKeFuService(); int num = wkf.DeleteWeixinKeFuInfo(int.Parse(lbGustNo.Text.ToString())); if (num > 0) { ScriptManager.RegisterClientScriptBlock(this.Page, this.GetType(), "", "alert('删除成功!');location='WeiXinSessionList.aspx'", true); } else { ScriptManager.RegisterClientScriptBlock(this.Page, this.GetType(), "", "alert('删除失败!');location='WeiXinSessionList.aspx'", true); } } } if (!bools) { ScriptManager.RegisterClientScriptBlock(this.Page, this.GetType(), "", "alert('未选中删除项!');location='WeiXinSessionList.aspx'", true); } } /// /// 全选全不选 /// /// /// protected void CheckAll_CheckedChanged(object sender, EventArgs e) { CheckBox checkAll = (CheckBox)sender; foreach (RepeaterItem d in this.RepeaterGustBookList.Items) { CheckBox checkIn = (CheckBox)d.FindControl("CheckIn"); checkIn.Checked = checkAll.Checked; } } protected void LinkBtnLook_Click(object sender, EventArgs e) { BindGustBookList(); } /// /// 绑定事件 /// /// /// protected void RepeaterGustBookList_ItemDataBound(object sender, RepeaterItemEventArgs e) { if (e.Item.ItemType == ListItemType.Header) { CheckBox checkAll = e.Item.FindControl("CheckAll") as CheckBox; checkAll.AutoPostBack = true; } if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { WeixinKeFuInfo wkf = e.Item.DataItem as WeixinKeFuInfo; Label lbUId = e.Item.FindControl("lbUId") as Label; lbUId.Text = wkf.UId.ToString(); WxMessageService wms = new WxMessageService(); WxMessageInfo wminfo = wms.GetTopLastFaSongDateByUId(lbUId.Text.ToString()); if(wminfo!=null&&!String.IsNullOrWhiteSpace(wminfo.FaSongDate.ToString())) { Label lblastDate = e.Item.FindControl("lblastDate") as Label; lblastDate.Text = wminfo.FaSongDate.ToString(); DateTime datesystemss = DateTime.Parse(System.DateTime.Now.ToString()); DateTime lastLoingDatess = DateTime.Parse(lblastDate.Text.ToString()); TimeSpan ts11 = new TimeSpan(datesystemss.Ticks); TimeSpan ts22 = new TimeSpan(lastLoingDatess.Ticks); TimeSpan ts33 = ts11.Subtract(ts22).Duration(); Label lbState = e.Item.FindControl("lbState") as Label; string chaoshifenzhong = ts33.TotalMinutes.ToString(); if (double.Parse(chaoshifenzhong) <=10) { lbState.Text = "会话中"; lbState.Attributes.Add("style","color:red;"); } else { lbState.Text = "已结束"; } Label lbChaoshi = e.Item.FindControl("lbChaoshi") as Label; DateTime datesystem = DateTime.Parse(System.DateTime.Now.ToString()); DateTime lastLoingDate = DateTime.Parse(lblastDate.Text.ToString()); TimeSpan ts1 = new TimeSpan(datesystem.Ticks); TimeSpan ts2 = new TimeSpan(lastLoingDate.Ticks); TimeSpan ts3 = ts1.Subtract(ts2).Duration(); lbChaoshi.Text = ts3.Days.ToString() + "天" + ts3.Hours.ToString() + "小时" + ts3.Minutes.ToString() + "分钟"; } //////根据用户的openId获取用户昵称 //WeiXinServer wxs = new WeiXinServer(); /////从缓存读取accesstoken //string Access_token = Cache["Access_token"] as string; //if (Access_token == null) //{ // //如果为空,重新获取 // Access_token = wxs.GetAccessToken(); // //设置缓存的数据7000秒后过期 // Cache.Insert("Access_token", Access_token, null, DateTime.Now.AddSeconds(7000), System.Web.Caching.Cache.NoSlidingExpiration); //} //string Access_tokento = Access_token.Substring(17, Access_token.Length - 37); //string jsonres = ""; //jsonres = "http://api.weixin.qq.com/cgi-bin/user/info?access_token=" + Access_tokento + "&openid=" + wkf.UserOpenId; //HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(jsonres); //myRequest.Method = "GET"; //HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse(); //StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8); //string content = reader.ReadToEnd(); //reader.Close(); ////使用前需药引用Newtonsoft.json.dll文件 //JObject jsonObj = JObject.Parse(content); //Label lbNikeName = e.Item.FindControl("lbNikeName") as Label; //Label lbSex = e.Item.FindControl("lbSex") as Label; //lbNikeName.Text = jsonObj["nickname"].ToString(); //if (jsonObj["sex"].ToString().Equals("1")) //{ // lbSex.Text = "男"; //} //else //{ // lbSex.Text = "女"; //} } } /// /// 输入页码提交跳转 /// /// /// protected void LinkBtnToPage_Click(object sender, EventArgs e) { if (String.IsNullOrWhiteSpace(this.txtPageIndex.Text.ToString().Trim())) { ScriptManager.RegisterClientScriptBlock(this.Page, this.GetType(), "", "alert('页码不能为空!')", true); this.txtPageIndex.Focus(); return; } if (IsNum(this.txtPageIndex.Text.ToString().Trim())) { ScriptManager.RegisterClientScriptBlock(this.Page, this.GetType(), "", "alert('页码数只能输入数字!')", true); this.txtPageIndex.Focus(); this.txtPageIndex.Text = this.lbPageIndex.Text.ToString(); return; } if (int.Parse(this.txtPageIndex.Text.ToString().Trim()) > int.Parse(this.lbCountPage.Text.ToString().Trim())) { ScriptManager.RegisterClientScriptBlock(this.Page, this.GetType(), "", "alert('所输页数不能大于总页数!')", true); this.txtPageIndex.Focus(); this.txtPageIndex.Text = this.lbPageIndex.Text.ToString(); return; } BindGustBookList(); } /// /// 判断是否是数字 /// /// /// public static bool IsNum(string text) // { for (int i = 0; i < text.Length; i++) { if (!Char.IsNumber(text, i)) { return true; //输入的不是数字 } } return false; //否则是数字 } 此代码已包含,后台分页功能,仔细研究下,即可使用. 点击开启会话的页面:MessageWindow.aspx如下: <%@ Page Language="C#" AutoEventWireup="true" ValidateRequest="false" CodeBehind="MessageWindow.aspx.cs" Inherits="DQWebSite.Administrator.MessageWindow" %>
  • <%# Eval("ToUser") %>说:
    <%# Eval("Content") %> [<%# Eval("FaSongDate") %>]
发送
该推送功能直接将信息推送到对方用户微信,谨慎发言
MessageWindow.aspx.cs的核心代码如下: protected void Page_Load(object sender, EventArgs e) { if(!Page.IsPostBack) { if(Request.QueryString["id"]!=null) { WeixinKeFuService wkfs = new WeixinKeFuService(); WeixinKeFuInfo wkfinfo = wkfs.GetWeixinKeFuInfoByid(int.Parse(Request.QueryString["id"].ToString())); this.lbduihuamsg.Text = wkfinfo.UserOpenId.ToString(); this.lbduihua1.Text = "正在于"; this.lbduihua2.Text = "对话中......."; WxMessageService wms = new WxMessageService(); WxMessageInfo wminfo = wms.GetTopLastFaSongDateByUId(wkfinfo.UId.ToString()); if (wminfo != null) { DateTime datesystemss = DateTime.Parse(System.DateTime.Now.ToString()); DateTime lastLoingDatess = DateTime.Parse(wminfo.FaSongDate.ToString()); TimeSpan ts11 = new TimeSpan(datesystemss.Ticks); TimeSpan ts22 = new TimeSpan(lastLoingDatess.Ticks); TimeSpan ts33 = ts11.Subtract(ts22).Duration(); string chaodays = ts33.TotalDays.ToString(); if (double.Parse(chaodays) >=2) { this.LinkBtnSubSend.Enabled = false; this.errmsg.InnerText = "会话已结束!超过48小时不能主动推送信息给该用户!"; this.lbduihua1.Text = "已经于"; this.lbduihua2.Text = "失去连接.....除非该用户主动会话才能重新建立连接!"; this.txtMessage.Attributes.Add("readonly","true"); } } BindMsgList(); this.DataBind(); } } } private void BindMsgList() { string id = Request.QueryString["id"].ToString(); WxMessageService wms = new WxMessageService(); List wmlist = wms.GetAllMessageList(id); if(wmlist.Count>0) { this.RepeaterMessageList.DataSource = wmlist; this.RepeaterMessageList.DataBind(); } } protected void timeTick_Tick(object sender, EventArgs e) { BindMsgList(); } /// /// 推送消息到用户 /// /// /// protected void LinkBtnSubSend_Click(object sender, EventArgs e) { if(String.IsNullOrWhiteSpace(this.txtMessage.Value.ToString().Trim())) { this.errmsg.InnerText = "发送的内容不能为空!"; this.txtMessage.Focus(); return; } if (this.txtMessage.Value.ToString().Length < 5 || this.txtMessage.Value.ToString().Length > 200) { this.errmsg.InnerText = "发送内容应在5-200个字符之间!"; this.txtMessage.Focus(); return; } //如果存在直接保存消息记录 WxMessageService wms = new WxMessageService(); WxMessageInfo wminfo = new WxMessageInfo(); wminfo.FromUser = "我"; wminfo.ToUser = this.lbduihuamsg.Text.ToString(); wminfo.Content = this.txtMessage.Value.ToString().Trim(); wminfo.FaSongDate = System.DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"); wminfo.UId = Request.QueryString["id"].ToString(); wms.AddWxMessageInfo(wminfo); WeiXinServer wxs = new WeiXinServer(); string res = ""; ///从缓存读取accesstoken string Access_token = Cache["Access_token"] as string; if(Access_token==null) { //如果为空,重新获取 Access_token = wxs.GetAccessToken(); //设置缓存的数据7000秒后过期 Cache.Insert("Access_token", Access_token, null, DateTime.Now.AddSeconds(7000), System.Web.Caching.Cache.NoSlidingExpiration); } string Access_tokento = Access_token.Substring(17, Access_token.Length - 37); string txtcontent = this.txtMessage.Value.ToString().Replace("

", ""); StringBuilder sb = new StringBuilder(); sb.Append(txtcontent.Replace("

\r\n", "")); string posturl = "http://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + Access_tokento; string postData = "{\"touser\":\"" + this.lbduihuamsg.Text.ToString() + "\",\"msgtype\":\"text\",\"text\":{\"content\":\"" + sb.ToString() + "\"}}"; res = wxs.GetPage(posturl, postData); //使用前需药引用Newtonsoft.json.dll文件 JObject jsonObj = JObject.Parse(res); ///获取返回结果的正确|true|false string isright = jsonObj["errcode"].ToString();//0 string istrueorfalse = jsonObj["errmsg"].ToString();//ok if (isright.Equals("0") && istrueorfalse.Equals("ok")) { this.errmsg.InnerText = "消息推送成功!消息已送达微信用户!"; this.txtMessage.Value = ""; } else { this.errmsg.InnerText = "消息推送失败!消息已保存至数据库!"; } } protected void RepeaterMessageList_ItemDataBound(object sender, RepeaterItemEventArgs e) { if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { WxMessageInfo wminfo = e.Item.DataItem as WxMessageInfo; Image Imagelaba = e.Item.FindControl("Imagelaba") as Image; Label lbFromUser = e.Item.FindControl("lbFromUser") as Label; lbFromUser.Text = wminfo.FromUser.ToString(); if (wminfo.FromUser.ToString().Equals("我")) { Imagelaba.ImageUrl = "images/fa.gif"; } else { Imagelaba.ImageUrl = "images/shou.gif"; } } } 本文已被整理到了《ASP.NET微信开发教程汇总》,欢迎大家学习阅读。 以上就是会话管理功能的全部核心代码,仅供参考,希望对大家的学习有所帮助。