- /// <summary>
- /// 将微信POST过来的数据转化成实体对象
- /// </summary>
- /// <param name="token"></param>
- /// <returns></returns>
- public static ReceiveMessageBase ConvertMsgToObject(string msgBody = "")
- {
- if (string.IsNullOrWhiteSpace(msgBody))
- {
- Stream s = System.Web.HttpContext.Current.Request.InputStream;
- byte[] b = new byte[s.Length];
- s.Read(b, 0, (int)s.Length);
- msgBody = Encoding.UTF8.GetString(b);
- }
- string CorpToken = AppIdInfo.GetToken();
- string corpId = AppIdInfo.GetCorpId();
- string encodingAESKey = AppIdInfo.GetEncodingAESKey();
- WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(CorpToken, encodingAESKey, corpId);
- string msg_signature = HttpContext.Current.Request.QueryString["msg_signature"];
- string timestamp = HttpContext.Current.Request.QueryString["timestamp"];
- string nonce = HttpContext.Current.Request.QueryString["nonce"];
- string sMsg = ""; // 解析之后的明文
- int flag = wxcpt.DecryptMsg(msg_signature, timestamp, nonce, msgBody, ref sMsg);
- if (flag == 0)
- {
- msgBody = sMsg;
- LogInfo.Info("解密后的消息为" + sMsg);
- }
- else
- {
- LogInfo.Error("解密消息失败!flag=" + flag);
- }
- if (string.IsNullOrWhiteSpace(msgBody))
- {
- return null;
- }
- XmlDocument doc = null;
- MsgType msgType = MsgType.UnKnown;
- EventType eventType = EventType.UnKnown;
- ReceiveMessageBase msg = new ReceiveMessageBase();
- msg.MsgType = msgType;
- msg.MessageBody = msgBody;
- XmlNode node = null;
- XmlNode tmpNode = null;
- try
- {
- doc = new XmlDocument();
- doc.LoadXml(msgBody);//解密后才是需要处理的XML数据,读取XML字符串
- XmlElement rootElement = doc.DocumentElement;
- XmlNode msgTypeNode = rootElement.SelectSingleNode("MsgType");//获取字符串中的消息类型
- node = rootElement.SelectSingleNode("FromUserName");
- if (node != null)
- {
- msg.FromUserName = node.InnerText;
- }
- node = rootElement.SelectSingleNode("AgentID");
- if (node != null)
- {
- msg.AgentID = Convert.ToInt32(node.InnerText);
- }
- node = rootElement.SelectSingleNode("ToUserName");
- if (node != null)
- {
- msg.ToUserName = node.InnerText;
- }
- node = rootElement.SelectSingleNode("CreateTime");
- if (node != null)
- {
- msg.CreateTime = Convert.ToInt64(node.InnerText);
- }
- #region 获取具体的消息对象
- string strMsgType = msgTypeNode.InnerText;
- string msgId = string.Empty;
- string content = string.Empty;
- tmpNode = rootElement.SelectSingleNode("MsgId");
- if (tmpNode != null)
- {
- msgId = tmpNode.InnerText.Trim();
- }
- string strMsgType2 = strMsgType.Trim().ToLower();
- switch (strMsgType2)
- {
- case "text"://接收普通消息 text消息
- msgType = MsgType.Text;
- tmpNode = rootElement.SelectSingleNode("Content");
- if (tmpNode != null)
- {
- content = tmpNode.InnerText.Trim();
- }
- TextReceiveMessage txtMsg = new TextReceiveMessage(msg)
- {
- MsgType = msgType,
- MsgId = Convert.ToInt64(msgId),
- Content = content
- };
- txtMsg.AfterRead();
- return txtMsg;
- case "image"://接收普通消息 image消息
- msgType = MsgType.Image;
- ImageReceiveMessage imgMsg = new ImageReceiveMessage(msg)
- {
- MsgId = Convert.ToInt64(msgId),
- MsgType = msgType,
- MediaId = rootElement.SelectSingleNode("MediaId").InnerText,
- PicUrl = rootElement.SelectSingleNode("PicUrl").InnerText
- };
- imgMsg.AfterRead();
- return imgMsg;
- case "voice"://接收普通消息 voice消息
- msgType = MsgType.Voice;
- XmlNode node1 = rootElement.SelectSingleNode("Recognition");
- if (node1 != null)
- {
- msgType = MsgType.VoiceResult;
- }
- VoiceReceiveMessage voiceMsg = new VoiceReceiveMessage(msg)
- {
- MsgId = Convert.ToInt64(msgId),
- MsgType = msgType,
- Recognition = node1 == null ? string.Empty : node1.InnerText.Trim(),
- Format = rootElement.SelectSingleNode("Format").InnerText,
- MediaId = rootElement.SelectSingleNode("MediaId").InnerText
- };
- voiceMsg.AfterRead();
- return voiceMsg;
- case "video"://接收普通消息 video消息
- msgType = MsgType.Video;
- VideoReceiveMessage videoMsg = new VideoReceiveMessage(msg)
- {
- MediaId = rootElement.SelectSingleNode("MediaId").InnerText,
- MsgId = Convert.ToInt64(msgId),
- MsgType = msgType,
- ThumbMediaId = rootElement.SelectSingleNode("ThumbMediaId").InnerText
- };
- videoMsg.AfterRead();
- return videoMsg;
- case "location"://接收普通消息 location消息
- msgType = MsgType.Location;
- LocationReceiveMessage locationMsg = new LocationReceiveMessage(msg)
- {
- MsgId = Convert.ToInt64(msgId),
- MsgType = msgType,
- Label = rootElement.SelectSingleNode("Label").InnerText,
- Location_X = rootElement.SelectSingleNode("Location_X").InnerText,
- Location_Y = rootElement.SelectSingleNode("Location_Y ").InnerText,
- Scale = rootElement.SelectSingleNode("Scale").InnerText
- };
- locationMsg.AfterRead();
- return locationMsg;
- case "event":// 接收事件
- msgType = MsgType.Event;
- eventType = EventType.UnKnown;
- msg.MsgType = msgType;
- XmlNode eventNode = rootElement.SelectSingleNode("Event");
- if (eventNode != null)
- {
- string eventtype = eventNode.InnerText.Trim().ToLower();
- switch (eventtype)
- {
- case "subscribe": //接收事件 成员关注
- eventType = EventType.Subscribe;
- SubscribeEventMessage subEvt = new SubscribeEventMessage(msg)
- {
- EventType = EventType.Subscribe,
- MsgType = msgType,
- };
- subEvt.AfterRead();
- return subEvt;
- case "unsubscribe": //接收事件 取消关注事件
- eventType = EventType.UnSubscribe;
- UnSubscribeEventMessage unSubEvt = new UnSubscribeEventMessage(msg)
- {
- EventType = eventType,
- MsgType = msgType,
- };
- unSubEvt.AfterRead();
- return unSubEvt;
- case "location"://接收事件 上报地理位置事件
- eventType = EventType.Location;
- UploadLocationEventMessage locationEvt = new UploadLocationEventMessage(msg)
- {
- EventType = eventType,
- Latitude = rootElement.SelectSingleNode("Latitude").InnerText,
- Longitude = rootElement.SelectSingleNode("Longitude").InnerText,
- MsgType = msgType,
- Precision = rootElement.SelectSingleNode("Precision").InnerText,
- };
- locationEvt.AfterRead();
- return locationEvt;
- case "click": //接收事件 上报菜单事件 点击菜单拉取消息的事件推送
- eventType = EventType.Click;
- MenuEventMessage menuEvt = new MenuEventMessage(msg)
- {
- EventKey = rootElement.SelectSingleNode("EventKey").InnerText,
- EventType = eventType,
- MsgType = msgType,
- };
- menuEvt.AfterRead();
- return menuEvt;
- case "view": //接收事件 上报菜单事件 点击菜单跳转链接的事件推送
- eventType = EventType.VIEW;
- MenuEventVIEWEventMessage menuVIEWEvt = new MenuEventVIEWEventMessage(msg)
- {
- EventKey = rootElement.SelectSingleNode("EventKey").InnerText,
- EventType = eventType,
- MsgType = msgType,
- };
- menuVIEWEvt.AfterRead();
- return menuVIEWEvt;
- case "scancode_push"://接收事件 上报菜单事件 扫码推事件的事件推送
- eventType = EventType.scancode_push;
- ScanCodePushEventMessage scanCodePushEventMessage = new ScanCodePushEventMessage(msg)
- {
- EventKey = rootElement.SelectSingleNode("EventKey").InnerText,
- EventType = eventType,
- MsgType = msgType,
- ScanCodeInfo = new ScanCodeInfo(rootElement.SelectSingleNode("ScanCodeInfo"))
- };
- scanCodePushEventMessage.AfterRead();
- return scanCodePushEventMessage;
- case "scancode_waitmsg"://接收事件 上报菜单事件 扫码推事件且弹出“消息接收中”提示框的事件推送
- eventType = EventType.scancode_waitmsg;
- ScanCodeWaitMsgEventMessage scanCodeWaitMsgEventMessage = new ScanCodeWaitMsgEventMessage(msg)
- {
- EventKey = rootElement.SelectSingleNode("EventKey").InnerText,
- EventType = eventType,
- MsgType = msgType,
- ScanCodeInfo = new ScanCodeInfo(rootElement.SelectSingleNode("ScanCodeInfo"))
- };
- scanCodeWaitMsgEventMessage.AfterRead();
- return scanCodeWaitMsgEventMessage;
- case "pic_sysphoto"://接收事件 上报菜单事件 弹出系统拍照发图的事件推送
- eventType = EventType.pic_sysphoto;
- PicSysPhotoEventMessage picSysPhotoEventMessage = new PicSysPhotoEventMessage(msg)
- {
- EventKey = rootElement.SelectSingleNode("EventKey").InnerText,
- MsgType = msgType,
- SendPicsInfo = new SendPicsInfo(rootElement.SelectSingleNode("SendPicsInfo"))
- };
- picSysPhotoEventMessage.AfterRead();
- return picSysPhotoEventMessage;
- case "pic_photo_or_album"://接收事件 上报菜单事件 弹出拍照或者相册发图的事件推送
- eventType = EventType.pic_photo_or_album;
- PicPhotoOrAlbumEventMessage picPhotoOrAlbumEventMessage = new PicPhotoOrAlbumEventMessage(msg)
- {
- EventType = eventType,
- EventKey = rootElement.SelectSingleNode("EventKey").InnerText,
- MsgType = msgType,
- SendPicsInfo = new SendPicsInfo(rootElement.SelectSingleNode("SendPicsInfo"))
- };
- picPhotoOrAlbumEventMessage.AfterRead();
- return picPhotoOrAlbumEventMessage;
- case "pic_weixin"://接收事件 上报菜单事件 弹出微信相册发图器的事件推送
- eventType = EventType.pic_weixin;
- PicWeiXinEventMessage picWeiXinEventMessage = new PicWeiXinEventMessage(msg)
- {
- EventType = eventType,
- EventKey = rootElement.SelectSingleNode("EventKey").InnerText,
- MsgType = msgType,
- SendPicsInfo = new SendPicsInfo(rootElement.SelectSingleNode("SendPicsInfo"))
- };
- picWeiXinEventMessage.AfterRead();
- return picWeiXinEventMessage;
- case "location_select"://接收事件 上报菜单事件 弹出地理位置选择器的事件推送
- eventType = EventType.location_select;
- LocationSelectEventMessage locationSelectEventMessage = new LocationSelectEventMessage(msg)
- {
- EventType = eventType,
- EventKey = rootElement.SelectSingleNode("EventKey").InnerText,
- MsgType = msgType,
- SendLocationInfo = new SendLocationInfo(rootElement.SelectSingleNode("SendLocationInfo"))
- };
- locationSelectEventMessage.AfterRead();
- return locationSelectEventMessage;
- case "enter_agent": //接收事件 成员进入应用的事件推送
- eventType = EventType.enter_agent;
- EnterAgentEventMessage EnterAgentEventMessage = new EnterAgentEventMessage(msg)
- {
- MsgType = msgType,
- };
- EnterAgentEventMessage.AfterRead();
- return EnterAgentEventMessage;
- default:
- LogInfo.Error("事件类型" + eventtype + "未处理");
- break;
- }
- }
- break;
- default:
- LogInfo.Error("消息类型" + strMsgType2 + "未处理");
- break;
- }
- msg.MsgType = msgType;
- #endregion
- }
- catch (Exception ex)
- {
- LogInfo.Error("处理消息异常:" + msgBody, ex);
- }
- finally
- {
- if (doc != null)
- {
- doc = null;
- }
- }
- msg.MsgType = msgType;
- return msg;
- }
发送被动响应文本消息:
- /// <summary>
- /// 发送被动响应文本消息,需要先加密在发送
- /// </summary>
- /// <param name="fromUserName">发送方</param>
- /// <param name="toUserName">接收方</param>
- /// <param name="content">文本内容</param>
- public static void SendTextReplyMessage(string fromUserName, string toUserName, string content)
- {
- TextReplyMessage msg = new TextReplyMessage()
- {
- CreateTime = Tools.ConvertDateTimeInt(DateTime.Now),
- FromUserName = fromUserName,
- ToUserName = toUserName,
- Content = content
- };
- /* LogInfo.Info("发送信息2sMsg=" + content);//也可以使用微信的接口发送消息
- TextMsg data = new TextMsg(content);
- data.agentid = "7";
- data.safe = "0";
- // data.toparty = "@all";
- // data.totag = "@all";
- data.touser = toUserName;
- BLLMsg.SendMessage(data);*/
- string CorpToken = AppIdInfo.GetToken();
- string corpId = AppIdInfo.GetCorpId();
- string encodingAESKey = AppIdInfo.GetEncodingAESKey();
- WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(CorpToken, encodingAESKey, corpId);
- string msg_signature = HttpContext.Current.Request.QueryString["msg_signature"];
- string timestamp = HttpContext.Current.Request.QueryString["timestamp"];
- string nonce = HttpContext.Current.Request.QueryString["nonce"];
- string encryptResponse = "";//加密后的文字
- string sMsg = msg.ToXmlString();//加密前的文字
- int isok = wxcpt.EncryptMsg(sMsg, timestamp, nonce, ref encryptResponse);//
- LogInfo.Info("发送信息sMsg=" + sMsg);
- // LogInfo.Info("发送信息encryptResponse=" + encryptResponse);
- if (isok == 0 && !string.IsNullOrEmpty(encryptResponse))
- {
- HttpContext.Current.Response.ContentEncoding = Encoding.UTF8;
- HttpContext.Current.Response.Write(encryptResponse);//被动相应消息不需要调用微信接口
- }
- else {
- LogInfo.Info("发送信息失败isok=" + isok);
- }
- }
注释掉的代码就是主动发送消息,具体可参考微信企业号开发:主动发送消息
使用注释掉的代码也可以给用户发送消息,但这种方式不叫被动响应消息
被动响应消息实体
- /// <summary>
- /// 被动响应消息类
- /// </summary>
- public abstract class ReplyMessage
- {
- public string ToUserName { get; set; }
- public string FromUserName { get; set; }
- public long CreateTime { get; set; }
- /// <summary>
- /// 将对象转化为Xml消息
- /// </summary>
- /// <returns></returns>
- public abstract string ToXmlString();
- }
- /// <summary>
- /// 被动响应文本消息
- /// </summary>
- public class TextReplyMessage : ReplyMessage
- {
- /// <summary>
- /// 回复的消息内容(换行:在content中能够换行,微信客户端就支持换行显示)
- /// </summary>
- public string Content { get; set; }
- /// <summary>
- /// 将对象转化为Xml消息
- /// </summary>
- /// <returns></returns>
- public override string ToXmlString()
- {
- string s = "<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime><MsgType><![CDATA[{3}]]></MsgType><Content><![CDATA[{4}]]></Content></xml>";
- s = string.Format(s,
- ToUserName ?? string.Empty,
- FromUserName ?? string.Empty,
- CreateTime.ToString(),
- "text",
- Content ?? string.Empty
- );
- return s;
- }
- }
配置的URL网页的代码:
- public class TestWeixin : IHttpHandler {
- public void ProcessRequest (HttpContext context) {
- if (context.Request.HttpMethod.ToLower() == "post")
- {
- try
- {
- System.IO.Stream s = context.Request.InputStream;
- byte[] b = new byte[s.Length];
- s.Read(b, 0, (int)s.Length);
- string postStr = System.Text.Encoding.UTF8.GetString(b);
- if (!string.IsNullOrEmpty(postStr))
- {
- Execute(postStr);
- }
- }catch(Exception e)
- {
- new AppException("收到信息异常" + e.Message);
- }
- }
- else //开启应用的回调模式调用 ,代码省略
- {
- }
- }
- private void Execute(string postStr)
- {
- ReceiveMessageBase basemsg = ConvertMsgToObject(postStr);
- if (basemsg.MsgType ==.MsgType.Text)
- {
- TextReceiveMessage txtMsg = basemsg as TextReceiveMessage;
- if (txtMsg != null)
- {
- SendTextReplyMessage(txtMsg.ToUserName, txtMsg.FromUserName, "收到文本消息:" + txtMsg.Content);//发送被动消息
- }
- }
- }
- public bool IsReusable {
- get {
- return false;
- }
- }