微信公众号开发--消息接收与回复
在上篇文章中已经说明如何接入微信服务器,此篇直接接着上篇文章介绍公众号的消息接收与回复,可以结合上篇文章阅读本文,微信公众号开发–服务器接入。
微信公众号开发接口文档: https://mp.weixin.qq.com
1.如何接收公众号的消息
在接入验证微信服务器时,公众号平台是通过我们填写的URL发送Get请求与我们的开发平台验证,接收消息也是通过该URL,当微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到我们填写的URL上。其中消息分为普通消息和事件消息,普通消息包含文本,图片,语音等消息,事件消息包含用户关注,取消关注等消息, 具体可以阅读微信公众号的开发API。
2.如何回复用户消息
当用户发送消息给公众号时(即接收公众号的消息),会产生一个POST请求,我们回复的消息处理成特定的XML包来对该消息进行响应。
3.消息接收与回复
3.1接收消息
public void Wx(string signature, string timestamp, string nonce, string echostr)
{
//Post请求处理
if (System.Web.HttpContext.Current.Request.HttpMethod.ToUpper() == "POST")
{
Stream requestStream = System.Web.HttpContext.Current.Request.InputStream;
byte[] requestByte = new byte[requestStream.Length];
requestStream.Read(requestByte, 0, (Int32)requestStream.Length);
string requestStr = Encoding.UTF8.GetString(requestByte);
if (!string.IsNullOrEmpty(requestStr))
{
//封装请求类
XmlDocument requestDocXml = new XmlDocument();
requestDocXml.LoadXml(requestStr);
XmlElement rootElement = requestDocXml.DocumentElement;
NewsModel newsModel = new NewsModel();
newsModel.ToUserName = rootElement.SelectSingleNode("ToUserName").InnerText;
newsModel.FromUserName = rootElement.SelectSingleNode("FromUserName").InnerText;
newsModel.CreateTime = rootElement.SelectSingleNode("CreateTime").InnerText;
newsModel.MsgType = rootElement.SelectSingleNode("MsgType").InnerText;
switch (newsModel.MsgType)
{
case "text"://文本
newsModel.Content = rootElement.SelectSingleNode("Content").InnerText;
break;
case "image"://图片
newsModel.PicUrl = rootElement.SelectSingleNode("PicUrl").InnerText;
break;
case "event"://事件
newsModel.Event = rootElement.SelectSingleNode("Event").InnerText;
if (newsModel.Event == "subscribe")//关注类型
{
newsModel.EventKey = rootElement.SelectSingleNode("EventKey").InnerText;
}
break;
default:
break;
}
ResponseXML(newsModel); //回复消息
//bs.Close();
//return Encoding.UTF8.GetString(buff);
}
}
}
3.2回复消息
private void ResponseXML(NewsModel newsModel)
{
string XML = "";
switch (newsModel.MsgType)
{
case "text"://文本回复
XML = ReText(newsModel.FromUserName, newsModel.ToUserName, newsModel.Content);
break;
case "image"://图片回复
XML = ReImage(newsModel.FromUserName, newsModel.ToUserName, newsModel.PicUrl);
break;
case "event"://事件回复
XML = ReEvent(newsModel.FromUserName, newsModel.ToUserName, newsModel.Event);
break;
default://默认回复
break;
}
System.Web.HttpContext.Current.Response.Write(XML);
System.Web.HttpContext.Current.Response.End();
}
#endregion
#region 文本格式
/// <summary>
/// 回复文本
/// </summary>
/// <param name="FromUserName">发送给谁(openid)</param>
/// <param name="ToUserName">来自谁(公众账号ID)</param>
/// <param name="Content">回复类型文本</param>
/// <returns>拼凑的XML</returns>
public static string ReText(string FromUserName, string ToUserName, string Content)
{
string XML = "<xml><ToUserName><![CDATA[" + FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + ToUserName + "]]></FromUserName>";//发送给谁(openid),来自谁(公众账号ID)
XML += "<CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime>";//回复时间戳
XML += "<MsgType><![CDATA[text]]></MsgType>";//回复类型文本
XML += "<Content><![CDATA[" + Content + "]]></Content><FuncFlag>0</FuncFlag></xml>";//回复内容 FuncFlag设置为1的时候,自动星标刚才接收到的消息,适合活动统计使用
return XML;
}
#endregion
#region 图片格式
public static string ReImage(string FromUserName, string ToUserName, string PicUrl)
{
//回复用户图片信息,需要使用素材管理,必须含有参数 access_token,media_id
//现在公众号接收到消息,先回复文本消息。
string XML = "<xml><ToUserName><![CDATA[" + FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + ToUserName + "]]></FromUserName>";//发送给谁(openid),来自谁(公众账号ID)
XML += "<CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime>";//回复时间戳
//XML += "<MsgType><![CDATA[image]]></MsgType>";//回复类型文本
//XML += "<PicUrl><![CDATA[" + PicUrl + "]]></PicUrl>";
XML += "<MsgType><![CDATA[text]]></MsgType>";
XML += "<Content><![CDATA[亲,已经接收到您的图片,图片消息回复接口暂时未开通。]]></Content>";
XML += "<FuncFlag>0</FuncFlag></xml>";//回复内容 FuncFlag设置为1的时候,自动星标刚才接收到的消息,适合活动统计使用
return XML;
}
#endregion
#region 事件格式
public static string ReEvent(string FromUserName, string ToUserName, string Event)
{
string XML = "<xml><ToUserName><![CDATA[" + FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + ToUserName + "]]></FromUserName>";//发送给谁(openid),来自谁(公众账号ID)
XML += "<CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime>";//回复时间戳
XML += "<MsgType><![CDATA[text]]></MsgType>";//回复类型文本
if (Event == "subscribe")
{
XML += "<Content><![CDATA[感谢关注,茫茫人海中,能与您在此相识是我的荣幸。]]></Content><FuncFlag>0</FuncFlag></xml>";//回复内容 FuncFlag设置为1的时候,自动星标刚才接收到的消息,适合活动统计使用
}
else {
XML += "<Content><![CDATA[谢谢您的包容,祝您生活愉快,身体健康。]]></Content><FuncFlag>0</FuncFlag></xml>";
}
return XML;
}
#endregion
#region 时间戳处理
/// <summary>
/// DateTime时间格式转换为Unix时间戳格式
/// </summary>
/// <param name="time"> DateTime时间格式</param>
/// <returns>Unix时间戳格式</returns>
public static int ConvertDateTimeInt(System.DateTime time)
{
System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
return (int)(time - startTime).TotalSeconds;
}
#endregion
在接收消息时,代码有针对消息类别的识别,以及回复消息的XML格式等,这些是根据微信公众号开发文档所规定格式,可以综合开发文档看上面的代码。该项目工程在我的GitHub中,感兴趣可以下载源码或者加入 https://github.com/wangqilong1225/WeChat
4.最后求关注
本以为可以开发出一个完整功能的公众号,当想去处理公众号底部菜单栏等功能时,发现这些接口必须要经过微信的认证才有权限开发,而微信认证需要300RMB,有点心疼,所以开发到此先暂停了,后面有机会(钱),再继续下去。最后感兴趣的小伙伴可以关注下我的公众号,谢谢。