《微信企业号开发日志》之接收普通消息

接收普通消息

普通消息是指员工向企业号应用发送的消息,包括文本、图片、语音、视频、地理位置等类型。普通消息会推送到每个应用在管理端设置的URL(以下假设该URL为http://api.3dept.com)。

  • 请求说明

Http请求方式: POST

http://api.3dept.com/?msg_signature=ASDFQWEXZCVAQFASDFASDFSS&timestamp=13500001234&nonce=123412323

 

text消息

<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1348831860</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[this is a test]]></Content> <MsgId>1234567890123456</MsgId> <AgentID>1</AgentID> </xml>

参数 说明
ToUserName 企业号CorpID
FromUserName 员工UserID
CreateTime 消息创建时间(整型)
MsgType 消息类型,此时固定为:text
Content 文本消息内容
MsgId 消息id,64位整型
AgentID 企业应用的id,整型。可在应用的设置页面查看

 

image消息

<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1348831860</CreateTime> <MsgType><![CDATA[image]]></MsgType> <PicUrl><![CDATA[this is a url]]></PicUrl> <MediaId><![CDATA[media_id]]></MediaId> <MsgId>1234567890123456</MsgId> <AgentID>1</AgentID> </xml>

参数 说明
ToUserName 企业号CorpID
FromUserName 员工UserID
CreateTime 消息创建时间(整型)
MsgType 消息类型,此时固定为:image
PicUrl 图片链接
MediaId 图片媒体文件id,可以调用获取媒体文件接口拉取数据
MsgId 消息id,64位整型
AgentID 企业应用的id,整型。可在应用的设置页面查看

 

voice消息

<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1357290913</CreateTime> <MsgType><![CDATA[voice]]></MsgType> <MediaId><![CDATA[media_id]]></MediaId> <Format><![CDATA[Format]]></Format> <MsgId>1234567890123456</MsgId> <AgentID>1</AgentID> </xml>

参数 说明
ToUserName 企业号CorpID
FromUserName 员工UserID
CreateTime 消息创建时间(整型)
MsgType 消息类型,此时固定为:voice
MediaId 语音媒体文件id,可以调用获取媒体文件接口拉取数据
Format 语音格式,如amr,speex等
MsgId 消息id,64位整型
AgentID 企业应用的id,整型。可在应用的设置页面查看

 

video消息

<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1357290913</CreateTime> <MsgType><![CDATA[video]]></MsgType> <MediaId><![CDATA[media_id]]></MediaId> <ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId> <MsgId>1234567890123456</MsgId> <AgentID>1</AgentID> </xml>

参数 说明
ToUserName 企业号CorpID
FromUserName 员工UserID
CreateTime 消息创建时间(整型)
MsgType 消息类型,此时固定为:video
MediaId 视频媒体文件id,可以调用获取媒体文件接口拉取数据
ThumbMediaId 视频消息缩略图的媒体id,可以调用获取媒体文件接口拉取数据
MsgId 消息id,64位整型
AgentID 企业应用的id,整型。可在应用的设置页面查看

 

location消息

<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1351776360</CreateTime> <MsgType><![CDATA[location]]></MsgType> <Location_X>23.134521</Location_X> <Location_Y>113.358803</Location_Y> <Scale>20</Scale> <Label><![CDATA[位置信息]]></Label> <MsgId>1234567890123456</MsgId> <AgentID>1</AgentID> </xml>

参数 说明
ToUserName 企业号CorpID
FromUserName 员工UserID
CreateTime 消息创建时间(整型)
MsgType 消息类型,此时固定为:location
Location_X 地理位置纬度
Location_Y 地理位置经度
Scale 地图缩放大小
Label 地理位置信息
MsgId 消息id,64位整型
AgentID 企业应用的id,整型。可在应用的设置页面查看

 

 

---------------------------------------日志开始----------------------------------------------------------

整个被动响应的代码图如下

《微信企业号开发日志》之接收普通消息_第1张图片

 

根据以上信息,我们创建如下几个类,

《微信企业号开发日志》之接收普通消息_第2张图片

分组代码图:

《微信企业号开发日志》之接收普通消息_第3张图片

 

类图:

《微信企业号开发日志》之接收普通消息_第4张图片

 

RequestBase为所有接受信息基类,普通消息可直接继承

RequestEvent继承RequestBase,为事件消息的基类

微信接收信息分两种:

一种是接收普通消息(直接继承RequestBase)

另一种是接收事件(继承RequestEvent)

 

微信的消息类型结构如图所示

《微信企业号开发日志》之接收普通消息_第5张图片

 

 

RequestBase.cs

《微信企业号开发日志》之接收普通消息_第6张图片

    /// <summary>
    /// 接受消息基类
    /// </summary>
    public class RequestBase
    {

        public bool LoadStatus = true;
        public string ErrorMsg = String.Empty;

        /// <summary>
        /// 如果消息类型或消息事件没处理,通过这个构造实例化XML_Request对象
        /// </summary>
        /// <param name="table"></param>
        /// <param name="LoaderrorMsg"></param>
        public RequestBase(Dictionary<string, string> table, string LoaderrorMsg)
        {
            this.ToUserName = table["ToUserName"];
            this.FromUserName = table["FromUserName"];
            this.CreateTime = table["CreateTime"];
            this.MsgType = table["MsgType"];
            this.AgentID = table["AgentID"];

            LoadStatus = false;
            ErrorMsg = LoaderrorMsg;
        }

        public RequestBase(Dictionary<string, string> table)
        {
            this.ToUserName = table["ToUserName"];
            this.FromUserName = table["FromUserName"];
            this.CreateTime = table["CreateTime"];
            this.MsgType = table["MsgType"];
            this.AgentID = table["AgentID"];
        }


        /// <summary>
        /// 微信企业号 
        /// </summary>
        public string ToUserName { set; get; }
        /// <summary>
        /// 员工UserID 
        /// </summary>
        public string FromUserName { set; get; }
        /// <summary>
        /// 消息创建时间 (整型) 
        /// </summary>
        public string CreateTime { set; get; }
        /// <summary>
        /// 消息类型
        /// </summary>
        public string MsgType { set; get; }
        /// <summary>
        /// 应用程序ID
        /// </summary>
        public string AgentID { set; get; }
    }

 

RequestText.cs

《微信企业号开发日志》之接收普通消息_第7张图片

    /// <summary>
    /// 文本消息
    /// </summary>
    public class RequestText : RequestBase
    {
        /*
     <xml>
         <ToUserName><![CDATA[wx78fc2f1a2c006ec1]]></ToUserName>
         <FromUserName><![CDATA[[email protected]]]></FromUserName>
         <CreateTime>1413269690</CreateTime>
         <MsgType><![CDATA[text]]></MsgType>
         <Content><![CDATA[22]]></Content>
         <MsgId>4634274969423970332</MsgId>
         <AgentID>1</AgentID>
     </xml>
         
         */

        public RequestText(Dictionary<string, string> table)
            : base(table)
        {
            this.Content = table["Content"];
            this.MsgId = table["MsgId"];

        }

        public string Content { set; get; }
        public string MsgId { set; get; }

    }

RequestEvent.cs

《微信企业号开发日志》之接收普通消息_第8张图片

    /// <summary>
    /// 上报菜单事件
    /// </summary>
    public class RequestEvent : RequestBase
    {
        public RequestEvent(Dictionary<string, string> table)
            : base(table)
        {
            this.Event = table["Event"];
        }

        public string Event { set; get; }
    }

RequestEvent_Click.cs

《微信企业号开发日志》之接收普通消息_第9张图片

    /// <summary>
    /// 上报菜单点击事件
    /// </summary>
    public class RequestEvent_Click : RequestEvent
    {
        /*
    <xml>
        <ToUserName><![CDATA[toUser]]></ToUserName>
        <FromUserName><![CDATA[FromUser]]></FromUserName>
        <CreateTime>123456789</CreateTime>
        <MsgType><![CDATA[event]]></MsgType>
        <Event><![CDATA[CLICK]]></Event>
        <EventKey><![CDATA[EVENTKEY]]></EventKey>
        <AgentID>1</AgentID>
    </xml>
         */

        public RequestEvent_Click(Dictionary<string, string> table)
            : base(table)
        {

            //this.ToUserName = table["ToUserName"];
            //this.FromUserName = table["FromUserName"];
            //this.CreateTime = table["CreateTime"];
            //this.MsgType = table["MsgType"];
            this.EventKey = table["EventKey"];
        }

        public string EventKey { set; get; }
    }

LoadXML.cs,把XML子付出啊转换为对应的消息类型

《微信企业号开发日志》之接收普通消息_第10张图片

    /// </summary>
    /// 消息工厂
    /// </summary>
    public class LoadXML
    {
        public static RequestBase GetRequest(string XML)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(XML);
            XmlNode root = doc.FirstChild;

            Dictionary<string, string> table = new Dictionary<string, string>();
            foreach (XmlNode v in root.ChildNodes)
            {
                table.Add(v.Name, v.InnerText);
            }
            RequestBase xmlRequest = null;

            switch (table["MsgType"])
            {
                case RequestMessageType.text:
                    {
                        xmlRequest = new RequestText(table);
                    }; break;
                case RequestMessageType.fevent:
                    {
                        switch (table["Event"])
                        {
                            case RequestMessageEventType.click:
                                {
                                    xmlRequest = new RequestEvent_Click(table);
                                }; break;
                            default:
                                {
                                    xmlRequest = new RequestBase(table, "此点击事件无效,服务器没有处理该事件的操作!\r\n事件类型:" + table["Event"]);
                                }; break;
                        }

                    }; break;
                default:
                    {
                        xmlRequest = new RequestBase(table, "服务器没有处理该消息的操作!\r\n消息类型:" + table["MsgType"]);
                    }; break;
            }
            return xmlRequest;
        }
    }

 

-----------------------------------------------------------功能实现-----------------------------------------------------------------------------------------

定义一个加密解密类,继承自WXBizMsgCrypt

《微信企业号开发日志》之接收普通消息_第11张图片

    /// <summary>
    /// 响应消息,处理中心
    /// </summary>
    public class WXBizMsgCryptAPI : WXBizMsgCrypt
    {
        #region 字段属性
        /// <summary>
        /// Token可由企业任意填写,用于生成签名
        /// </summary>
        public string Token { get; set; }

        /// <summary>
        /// EncodingAESKey用于消息体的加密,是AES密钥的Base64编码
        /// </summary>
        public string EncodingAESKey { get; set; }
        /// <summary>
        /// 集团ID
        /// </summary>
        public string CorpID { get; set; }
        /// <summary>
        /// 微信加密签名,msg_signature结合了企业填写的token、请求中的timestamp、nonce参数、加密的消息体 
        /// </summary>
        public string msg_signature { get; set; }
        /// <summary>
        /// 时间戳,对应URL参数的timestamp
        /// </summary>
        public string timestamp { get; set; }
        /// <summary>
        /// 随机串,对应URL参数的nonce
        /// </summary>
        public string nonce { get; set; }
        /// <summary>
        /// 加密的随机字符串,以msg_encrypt格式提供。需要解密并返回echostr明文,解密后有random、msg_len、msg、$CorpID四个字段,其中msg即为echostr明文 
        /// </summary>
        public string echostr { get; set; }

        #endregion 字段属性

        public WXBizMsgCryptAPI(string stoken, string sEncodingAESKey, string sCorpID, string signature, string stimestamp, string snonce)
            : base(stoken, sEncodingAESKey, sCorpID)
        {
            Token = stoken;
            EncodingAESKey = sEncodingAESKey;
            CorpID = sCorpID;
            msg_signature = signature;
            timestamp = stimestamp;
            nonce = snonce;
        }

        /// <summary>
        /// 检验消息的真实性,并且获取解密后的明文
        /// </summary>
        /// <param name="sReqData">密文,对应POST请求的数据</param>
        /// <param name="sMsg">解密后的原文,当return返回0时有效</param>
        /// <returns>成功0,失败返回对应的错误码</returns>
        public int DecryptMsg(string sReqData, ref string sMsg)
        {
            return this.DecryptMsg(msg_signature, timestamp, nonce, sReqData, ref sMsg);
        }

        /// <summary>
        /// 将企业号回复用户的消息加密打包
        /// </summary>
        /// <param name="sReplyMsg">企业号待回复用户的消息,xml格式的字符串</param>
        /// <param name="sEncryptMsg">加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串,当return返回0时有效</param>
        /// <returns>成功0,失败返回对应的错误码</returns>
        public int EncryptMsg(string sReplyMsg, ref string sEncryptMsg)
        {
            return this.EncryptMsg(sReplyMsg, timestamp, nonce, ref sEncryptMsg);
        }

        /// <summary>
        /// 获得加密后的XML,返回给微信服务器
        /// </summary>
        /// <param name="sReqTimeStamp"></param>
        /// <param name="sReqNonce"></param>
        /// <returns></returns>
        public string GetDocument(string sRespData, string sReqTimeStamp, string sReqNonce)
        {
            //string sRespData = xmlPost.GetXML();
            string sEncryptMsg = ""; //xml格式的密文

            int ret = EncryptMsg(sRespData, sReqTimeStamp, sReqNonce, ref sEncryptMsg);
            if (ret != 0)
            {
                System.Console.WriteLine("ERR: EncryptMsg Fail, ret: " + ret);
                return "";
            }
            // TODO:
            // 加密成功,企业需要将加密之后的sEncryptMsg返回
            return sEncryptMsg;
            // HttpUtils.SetResponse(sEncryptMsg);
        }

        /// <summary>
        /// 获得加密后的XML,返回给微信服务器
        /// </summary>
        /// <returns></returns>
        public string GetDocument(string sRespData)
        {
            //string sRespData = xmlPost.GetXML();
            string sEncryptMsg = ""; //xml格式的密文
            int ret = EncryptMsg(sRespData, ref sEncryptMsg);
            if (ret != 0)
            {
                System.Console.WriteLine("ERR: EncryptMsg Fail, ret: " + ret);
                return "";
            }
            // TODO:
            // 加密成功,企业需要将加密之后的sEncryptMsg返回
            return sEncryptMsg;
            // HttpUtils.SetResponse(sEncryptMsg);
        }

    }
 

《微信企业号开发日志》之接收普通消息_第12张图片

消息处理类CustomMessageHandler:

《微信企业号开发日志》之接收普通消息_第13张图片

 

    public class CustomMessageHandler
    {
        /// <summary>
        /// 微信企业号相应中心
        /// </summary>
        WXBizMsgCryptAPI apidata;

        /// <summary>
        /// 当前消息类
        /// </summary>
        RequestBase CurrentMessage;

        /// <summary>
        /// 要返回(响应)的xml文档
        /// </summary>
        public Response_Base ResponseDocument;

        /// <summary>
        /// 是否取消操作,当产生错误,或者异常发生的时候,不处理,直接返还错误消息
        /// </summary>
        private bool CancelHandle = false;


        /// <summary>
        /// 最大上下文消息数
        /// </summary>
        public int MaxMsgContextCount { get; set; }

        /// <summary>
        /// 最大命令数
        /// </summary>
        public int MaxCommandContextCount { get; set; }


        private static MessageContext MsgContext = new MessageContext(MsgContext_MsgContextChanged);

        /// <summary>
        /// 这里需要添加的命令
        /// </summary>
        /// <param name="CurrentMsg"></param>
        private static void MsgContext_MsgContextChanged(RequestBase CurrentMsg)
        {
            if (false)
                MsgContext.InsertCommandContext(CurrentMsg);
        }


        public MessageContextHandler CurrentMessageContext
        {
            get
            {
                return MsgContext.GetMessageContext(CurrentMessage.FromUserName);
            }
        }


        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="sapidata"></param>
        /// <param name="InputStream"></param>
        /// <param name="MaxMsgContextCount">最大上下文消息数</param>
        /// <param name="MaxCommandContextCount">最大上下文命令数</param>
        public CustomMessageHandler(WXBizMsgCryptAPI sapidata, System.IO.Stream InputStream, int MaxMsgContextCount, int MaxCommandContextCount)
        {
            MsgContext.MsgContextMaxCount = MaxMsgContextCount;
            MsgContext.MsgCommandMaxCount = MaxCommandContextCount;


            apidata = sapidata;

            InputStream.Position = 0;
            StreamReader reader = new StreamReader(InputStream);
            string sReqData = reader.ReadToEnd();//加密XML信息



            string sMsg = "";  // 解析之后的XML明文

            //本地调试的时候跳过解密,因为本地调试直接发送的就是未经过加密的xml明文
            int ret = apidata.DecryptMsg(sReqData, ref sMsg);
            
            //sMsg = sReqData;

            string tt = String.Format("用户发送消息解密后的明文:\r\n{0}", sMsg);
            CommonTools.WriteText(tt);


            if (ret != 0)
            {
                SetResponse.WriteContent("错误!");
                return;
            }

            CurrentMessage = LoadXML.GetRequest(sMsg);

            if (CurrentMessage.LoadStatus == false)
            {
                OnErrorResponse(CurrentMessage);
            }
            else
                MsgContext.InsertMsgContext(CurrentMessage);
        }

       



        /// <summary>
        /// 处理指令,响应
        /// </summary>
        public void Execute()
        {

            if (CancelHandle) return;//终止处理

            switch (CurrentMessage.MsgType.ToLower())
            {
                case RequestMessageType.text:
                    {
                        OnTextResponse(CurrentMessage as RequestText);
                    }; break;
                case RequestMessageType.fevent:
                    {
                        switch ((CurrentMessage as RequestEvent).Event.ToLower())
                        {
                            case RequestMessageEventType.click:
                                {
                                    OnEventResponse_Click(CurrentMessage as RequestEvent_Click);
                                }; break;
                            default:
                                {
                                    OnErrorResponse(CurrentMessage.FromUserName, CurrentMessage.ToUserName, "此点击事件无效,服务器没有处理该事件的操作!\r\n事件类型:" + RequestMessageType.fevent);
                                }; break;
                        }
                    }; break;
                default:
                    {
                        OnErrorResponse(CurrentMessage.FromUserName, CurrentMessage.ToUserName, "服务器没有处理该消息的操作!\r\n消息类型:" + CurrentMessage.MsgType);
                    }; break;
            }
        }

        


        public string Document { get; set; }


        #region 响应

        /// <summary>
        /// 回复text消息
        /// </summary>
        /// <param name="Content">指令</param>
        void OnTextResponse(RequestText currentMessage)
        {
            DoTextResponse(currentMessage.FromUserName, currentMessage.ToUserName, currentMessage.Content);
        }

        /// <summary>
        /// 相应点击菜单事件
        /// </summary>
        /// <param name="currentMessage"></param>
        void OnEventResponse_Click(RequestEvent_Click currentMessage)
        {
            DoTextResponse(currentMessage.FromUserName, currentMessage.ToUserName, currentMessage.EventKey);
        }

        /// <summary>
        /// 回复错误消息
        /// </summary>
        /// <param name="Content">指令</param>
        void OnErrorResponse(RequestBase currentMessage)
        {
            CancelHandle = true;
            SetDocument_Text(currentMessage.FromUserName, currentMessage.ToUserName, currentMessage.ErrorMsg);
        }

        /// <summary>
        /// 回复错误消息
        /// </summary>
        /// <param name="Content">指令</param>
        void OnErrorResponse(string FromUserName, string ToUserName ,string ErrorMsg)
        {
            CancelHandle = true;
            SetDocument_Text(FromUserName, ToUserName, ErrorMsg);
        }

        #endregion


        #region 指令处理
        /// <summary>
        /// 处理文本指令
        /// </summary>
        /// <param name="FromUserName"></param>
        /// <param name="ToUserName"></param>
        /// <param name="Content"></param>
        void DoTextResponse(string FromUserName, string ToUserName, string Content)
        {
            string xaData = XAData.GetXAData(FromUserName, Content);

            //string xaData = String.Format("你刚刚发送了:{0}", CurrentMessageContext.Contents[0]);

            StringBuilder Recodes = new StringBuilder();
            //Recodes.AppendFormat("\r\n您一共发送了{0}条消息\r\n", CurrentMessageContext.Contents.Length);
            //foreach (string str in CurrentMessageContext.Contents)
            //{
            //    Recodes.AppendFormat("{0}\r\n", str);
            //}

            Recodes.AppendFormat("\r\n<a href=\"http://xinaoknitting.wicp.net:8088/WX/AttendCardTime.aspx?U=" + CurrentMessage.FromUserName + "\">点击这里</a>查看当月考勤。");

            SetDocument_Text(FromUserName, ToUserName, xaData + Recodes.ToString());
        }

        /// <summary>
        /// 返回Text消
        /// </summary>
        /// <param name="FromUserName"></param>
        /// <param name="ToUserName"></param>
        /// <param name="xaData"></param>
        void SetDocument_Text(string FromUserName, string ToUserName, string xaData)
        {
            //生成text响应类
            Response_Text XML = new Response_Text(FromUserName, ToUserName, xaData);
            Document = apidata.GetDocument(XML.GetXML());
        }
        #endregion
    }

 

《微信企业号开发日志》之接收普通消息_第14张图片

 

 

 

 

 

MsgRecode

《微信企业号开发日志》之接收普通消息_第15张图片

    /// <summary>
    /// 上下文消息标识
    /// </summary>
    public class MsgRecode
    {
        /// <summary>
        /// 微信企业号 
        /// </summary>
        public string ToUserName { set; get; }
        /// <summary>
        /// 员工UserID 
        /// </summary>
        public string FromUserName { set; get; }
        /// <summary>
        /// 消息创建时间 (整型) 
        /// </summary>
        public string CreateTime { set; get; }
        /// <summary>
        /// 消息类型
        /// </summary>
        public string MsgType { set; get; }
        /// <summary>
        /// 应用程序ID
        /// </summary>
        public string AgentID { set; get; }

        /// <summary>
        /// 消息内容
        /// </summary>
        public string Content { set; get; }
    }

《微信企业号开发日志》之接收普通消息_第16张图片

MessageContextHandler

《微信企业号开发日志》之接收普通消息_第17张图片

 

    public class MessageContextHandler
    {
        List<MsgRecode> lstMsgContext;//消息上下文
        List<MsgRecode> lstCommandContext;//命令上下文

        /// <summary>
        /// 用户名
        /// </summary>
        public string UserName { get; set; }

        /// <summary>
        /// 消息上下文
        /// </summary>
        public string[] Contents
        {
            get
            {
                return GetContent(lstMsgContext);
            }
        }

        /// <summary>
        /// 命令上下文
        /// </summary>
        public string[] Commands
        {
            get
            {
                return GetContent(lstCommandContext);
            }
        }

        public MessageContextHandler(string UserName, List<MsgRecode> MsgContextList, List<MsgRecode> CommandContextList)
        {
            this.UserName = UserName;
            lstMsgContext = MsgContextList;
            lstCommandContext = CommandContextList;
        }


        #region 自定义函数

        private string[] GetContent(List<MsgRecode> lst)
        {
            string[] tmp = new string[lst.Count];
            for (int i = 0; i < lst.Count; i++)
                tmp[i] = lst[i].Content;
            return tmp;
        }

        #endregion

    }

《微信企业号开发日志》之接收普通消息_第18张图片

 

MessageContext

《微信企业号开发日志》之接收普通消息_第19张图片

    public delegate void CurrentMsgContextChanged(RequestBase CurrentMsg);

    /// <summary>
    /// 消息上下文
    /// </summary>
    public class MessageContext
    {
        Dictionary<string, List<MsgRecode>> dcMsgConText=new Dictionary<string,List<MsgRecode>>();
        Dictionary<string, List<MsgRecode>> dcCommandContext=new Dictionary<string,List<MsgRecode>>();

        public event CurrentMsgContextChanged MsgContextChanged;
        public MessageContext(CurrentMsgContextChanged msgContextChanged)
        {
            MsgContextChanged = msgContextChanged;
        }

 

        //消息上下文
        List<MsgRecode> GetMsgContentContext(string userName)
        {
            if (!dcMsgConText.ContainsKey(userName))
                dcMsgConText.Add(userName, new List<MsgRecode>());
            return dcMsgConText[userName];
        }
        //命令上下文
        List<MsgRecode> GetCommandContext(string userName)
        {
            if (!dcCommandContext.ContainsKey(userName))
                dcCommandContext.Add(userName, new List<MsgRecode>());
            return dcCommandContext[userName];
        }


        public MessageContextHandler GetMessageContext(string userName)
        {
            var Msg = GetMsgContentContext(userName);
            var Command = GetCommandContext(userName);

            MessageContextHandler handler = new MessageContextHandler(userName, Msg, Command);

            return handler;
        }



        private int _msgcontextmaxcount = 1;

        /// <summary>
        /// 最大上下文消息树
        /// </summary>
        public int MsgContextMaxCount
        {
            get
            {
                return _msgcontextmaxcount;
            }
            set
            {
                _msgcontextmaxcount = value > 0 ? value : 1;
            }
        }

        private int _msgcommandmaxcount = 1;

        /// <summary>
        /// 最大上下文命令数
        /// </summary>
        public int MsgCommandMaxCount
        {
            get
            {
                return _msgcommandmaxcount;

            }
            set
            {
                _msgcommandmaxcount = value > 0 ? value : 1;
            }
        }

        /// <summary>
        /// 添加消息记录
        /// </summary>
        /// <param name="request"></param>

        public void InsertMsgContext(RequestBase request)
        {
            MsgRecode mr = GetMsgContext(request);
            IntMsgContentContext(mr);
            if (MsgContextChanged != null)
                MsgContextChanged(request);
        }


        /// <summary>
        /// 添加消息记录
        /// </summary>
        /// <param name="request"></param>
        /// <param name="IsCommand">是否是命令,如果是命令,则为true,也可以用MsgContextChanged事件来调用</param>
        public void InsertMsgContext(RequestBase request, bool IsCommand)
        {
            MsgRecode mr = GetMsgContext(request);
            IntMsgContentContext(mr);
            if (IsCommand == true)
                InsertCommandContext(request);
        }





        /// <summary>
        /// 添加命令记录
        /// </summary>
        /// <param name="request"></param>
        public void InsertCommandContext(RequestBase request)
        {
            MsgRecode mr = GetMsgContext(request);
            IntCommandContext(mr);
        }


        #region 自定义辅助函数
       

        void IntMsgContentContext(MsgRecode mr)
        {
            var lstMsgContext = GetMsgContentContext(mr.FromUserName);
            while (lstMsgContext.Count >= MsgContextMaxCount)
                lstMsgContext.RemoveAt(lstMsgContext.Count);
            lstMsgContext.Insert(0, mr);
        }
        void IntCommandContext(MsgRecode mr)
        {
            var lstCommandContext = GetCommandContext(mr.FromUserName);
            while (lstCommandContext.Count >= MsgCommandMaxCount)
                lstCommandContext.RemoveAt(lstCommandContext.Count);
            lstCommandContext.Insert(0, mr);
        }

        private MsgRecode GetMsgContext(RequestBase request)
        {
            MsgRecode mr = new MsgRecode()
                        {
                            ToUserName = request.ToUserName,
                            FromUserName = request.FromUserName,
                            CreateTime = request.CreateTime,
                            MsgType = request.MsgType,
                            AgentID = request.AgentID
                        };
            if (request is RequestText)
                mr.Content = (request as RequestText).Content;
            return mr;
        }

        #endregion

    }

 

《微信企业号开发日志》之接收普通消息_第20张图片

 

《微信企业号开发日志》之接收普通消息_第21张图片

 

    /// <summary>
    /// 被动响应消息基类
    /// </summary>
    public class Response_Base
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="msgType"></param>
        public Response_Base(string msgType)
        {
            this.MsgType = msgType;
        }

        ///// <summary>
        ///// 获得XML明文
        ///// </summary>
        ///// <returns></returns>
        //public abstract string GetXML();

        /// <summary>
        /// 员工UserID 
        /// </summary>
        public string ToUserName { get; set; }
        /// <summary>
        /// 企业号CorpID 
        /// </summary>
        public string FromUserName { get; set; }
        /// <summary>
        /// 消息创建时间(整型) 
        /// </summary>
        public string CreateTime { get; set; }

        /// <summary>
        /// 消息类型,:text,image,voice,video,news
        /// </summary>
        public string MsgType { get; set; }

        public virtual string GetXML()
        {
            throw new Exception("没有重写GetXML方法");
        }
    }

    /// <summary>
    /// 被动响应消息text
    /// </summary>
    public class Response_Text : Response_Base
    {
        /*
        <xml>
            <ToUserName><![CDATA[toUser]]></ToUserName>
            <FromUserName><![CDATA[fromUser]]></FromUserName> 
            <CreateTime>1348831860</CreateTime>
            <MsgType><![CDATA[text]]></MsgType>
            <Content><![CDATA[this is a test]]></Content>
        </xml>
         */

        string xmlformat = @" <xml>
            <ToUserName><![CDATA[{0}]]></ToUserName>
            <FromUserName><![CDATA[{1}]]></FromUserName> 
            <CreateTime>{2}</CreateTime>
            <MsgType><![CDATA[{3}]]></MsgType>
            <Content><![CDATA[{4}]]></Content>
        </xml>";


        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="toUser">员工UserID </param>
        /// <param name="fromUser">企业号CorpID </param>
        /// <param name="content">文本消息内容  </param>
        /// <param name="createTime">消息创建时间(整型),参考:APITools.GetCreateTime()</param>
        public Response_Text(string toUser, string fromUser, string content, string createTime)
            : base(RequestMessageType.text)
        {
            this.ToUserName = toUser;
            this.FromUserName = fromUser;
            this.Content = content;
            this.CreateTime = createTime;
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="toUser">员工UserID </param>
        /// <param name="fromUser">企业号CorpID </param>
        /// <param name="content">文本消息内容  </param>
        public Response_Text(string toUser, string fromUser, string content)
            : base(RequestMessageType.text)
        {
            this.ToUserName = toUser;
            this.FromUserName = fromUser;
            this.Content = content;
            this.CreateTime = CorpTools.GetCreateTime();

        }


        /// <summary>
        /// 获得XML文本
        /// </summary>
        /// <returns></returns>
        public override string GetXML()
        {
            return String.Format(xmlformat, ToUserName, FromUserName, CreateTime, MsgType, Content);
        }

        /// <summary>
        /// 文本消息内容 
        /// </summary>
        public string Content { get; set; }
    }

代码贴完了,接下来是接口调用:

public void ProcessRequest(HttpContext context)
        {
            WriteText("开始回调:" + context.Request.Url.ToString());


            //微信接入的测试
            string token = ConfigurationManager.AppSettings["CorpToken"];//从配置文件获取Token
            string CorpID = ConfigurationManager.AppSettings["CorpID"];//从配置文件获取Token
            string EncodingAESKey = ConfigurationManager.AppSettings["EncodingAESKey"];//从配置文件获取Token

            int MaxMsgContextCount = ConvertEx.ToInt(ConfigurationManager.AppSettings["MaxMsgContextCount"], 10);//最大上下文消息数
            int MaxCommandContextCount = ConvertEx.ToInt(ConfigurationManager.AppSettings["MaxCommandContextCount"], 3);//最大命令数
            

            string signature = context.Request["msg_signature"];
            string timestamp = context.Request["timestamp"];
            string nonce = context.Request["nonce"];


            if (context.Request.HttpMethod == "GET")//验证
            {
                WriteText("Get验证");
                

                string echostr = context.Request["echostr"];

                StringBuilder Txt=new StringBuilder();
                Txt.Append("Get微信接口验证\r\n");
                Txt.AppendFormat("signature:{0}\r\n", signature);
                Txt.AppendFormat("timestamp:{0}\r\n", timestamp);
                Txt.AppendFormat("nonce:{0}\r\n", nonce);
                Txt.AppendFormat("echostr:{0}\r\n", echostr);
                Txt.AppendFormat("EncodingAESKey:{0}\r\n", EncodingAESKey);
                Txt.AppendFormat("CorpID:{0}\r\n", CorpID);
                Txt.AppendFormat("CorpToken:{0}\r\n", token);

                CommonTools.WriteText(Txt.ToString());


                string sEchoStr = "";
                bool check = CheckSignatureQY.Check(signature, timestamp, nonce, echostr
                    , EncodingAESKey, CorpID, ref sEchoStr, token);//True表示成功
               
                //WriteText(check ? "True" : "False");

                //check为True成功,Flase失败,失败信息在SechoStr
                CommonTools.WriteText("结果为:" + (check ? "True" : "False"));
                CommonTools.WriteText("验证返回字符串为:" + sEchoStr);
                WriteContent(sEchoStr); //返回随机字符串则表示验证通过

                
            }

            else//消息
            {
                //记录发送的消息
                string url = context.Request.Url.ToString();

                context.Request.InputStream.Position = 0;
                StreamReader reader = new StreamReader(context.Request.InputStream);
                string sReqData = reader.ReadToEnd();//加密XML信息

                string str=String.Format("URL\r\n{0}\r\nXML\r\n{1}",url,sReqData);
                WriteText(str);

                WXBizMsgCryptAPI apidata = new WXBizMsgCryptAPI(token, EncodingAESKey, CorpID, signature, timestamp, nonce);

                CustomMessageHandler messageHandler = new CustomMessageHandler(apidata,context.Request.InputStream,MaxMsgContextCount,MaxCommandContextCount);
                try
                {
                    messageHandler.Execute();

                    WriteContent(messageHandler.Document);
                    return;
                }
                catch (Exception ex)
                {
                    WriteContent("");
                }
                finally
                {
                }
            }
        }

        private void WriteText(string p)
        {
            CommonTools.WriteText(p);
        }

       

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }




        private void WriteContent(string str)
        {
            HttpContext.Current.Response.Write(str);
        }

源代码等稍后奉上!!!!如有疑问,请留言联系

源码下载地址:源码下载

你可能感兴趣的:(日志)