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

.net mvc 微信开发笔记(四)------STREAM,POST/GET,XML解析,获取用户普通消息

2014-07-27 11:54 411 查看
这一节我们以“获取用户普通消息”和“发送被动响应消息”为例,

微信开发,需要设计到网络编程,涉及到一个概念,c#里叫做stream,字面意思是“河,水流”,我们日常称为“流”。

那什么是流呢?

流,简单来说就是建立在面向对象基础上的一种抽象的处理数据的工具。在流中,定义了一些处理数据的基本操作,如读取数据,写入数据等,程序员是对流进行所有操作的,而不用关心流的另一头数据的真正流向。

换句话说,我们在与微信服务器发信息时,需要把数据写进流里。相反的,微信给我们发送信息,我们也用从流里取数据。

微软提供了StreamReader和StreamWriter类帮我们实现在流上读写字符串的功能。

详细见:点这里

如果你是新手,还看不懂上边可以跳过。。

让我们分析一下开发者与微信服务器的通信过程:

一.微信主动发送给开发者信息

二.开发者主动发送给微信信息

第一类过程:

API主要是涉及到两种请求方式POST/GET

对于GET请求,目前发现只有网址介入的时候用到,参见:点这里

而对于POST请求,东西就比较多了。因为微信随时可能给发送我们信息,所以我们需要有一个接口随时监听。

以“接收用户普通消息”为例

这里假设我的网址接入地址是:www.xxxx.com/home/index

所以我要在homecontroller控制器底下新建一个index方法(注意类型是httppost)。

[HttpPost]
public void Index()
{

}
建好之后,接受服务器信息,并从流中读取数据。代码修改如下:

[HttpPost]
public void Index()
{
//获取流
Stream s = System.Web.HttpContext.Current.Request.InputStream;
//转换成Byte数组
byte[] b = new byte[s.Length];
//读取流
s.Read(b, 0, (int)s.Length);
//转化成utf8编码
string postStr = Encoding.UTF8.GetString(b);
//写入log(后边再讲)
//WriteLog();

}
是不是很简单?我们还可以将postStr写入日志,当有用户给公共主页发送信息时候,消息将会被保存,postStr数据格式如下:

普通文本消息为例



让我们继续操作,微信主动发来的主要是XML格式。我们尝试解析一下:

首先我们建一个实体,在Model底下添加类RequestXML,这里边规范了所有微信可能发来的用户消息

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; }
}
}


新建一个方法,参数为上边的postStr

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": //事件推送 支持V4.5+
break;
}

//消息回复
ResponseMsg(requestXML);
}
这时候会根据用户发来的消息,自动判断消息类型,再将信息存储在requestXML对象中。

拿到requestXML,我们需要根据不同类型回复

private void ResponseMsg(RequestXML requestXML)
{
try
{
string resxml = "";
//主要是调用数据库进行关键词匹配自动回复内容,可以根据自己的业务情况编写。
//1.通常有,没有匹配任何指令时,返回帮助信息
// AutoResponse mi = new AutoResponse(requestXML.Content, requestXML.FromUserName);

switch (requestXML.MsgType)
{
case "text":
//在这里执行一系列操作,从而实现自动回复内容.
// WriteLog(requestXML.Content);
resxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA["+requestXML.Content+"]]></Content></xml>";
// resxml += mi.GetRePic(requestXML.FromUserName);

break;
case "location":

break;

case "image":
//图文混合的消息 具体格式请见官方API“回复图文消息”
break;
}

System.Web.HttpContext.Current.Response.Write(resxml);
//  WriteToDB(requestXML, resxml, mi.pid);
}
catch (Exception ex)
{
//WriteTxt("异常:" + ex.Message + "Struck:" + ex.StackTrace.ToString());
//wx_logs.MyInsert("异常:" + ex.Message + "Struck:" + ex.StackTrace.ToString());
}
}


OK,接受用户普通消息并回复功能完成。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐