zoukankan      html  css  js  c++  java
  • 《微信企业号开发日志》之接收普通消息

    接收普通消息

    普通消息是指员工向企业号应用发送的消息,包括文本、图片、语音、视频、地理位置等类型。普通消息会推送到每个应用在管理端设置的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,整型。可在应用的设置页面查看

     

     

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

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

    image

     

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

    image

    分组代码图:

    image

    类图:

    image

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

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

    微信接收信息分两种:

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

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

     

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

    image

     

     

    RequestBase.cs

    image

        /// <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

    image

        /// <summary>
        /// 文本消息
        /// </summary>
        public class RequestText : RequestBase
        {
            /*
         <xml>
             <ToUserName><![CDATA[wx78fc2f1a2c006ec1]]></ToUserName>
             <FromUserName><![CDATA[garson_zhang@163.com]]></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

    image

        /// <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

    image

        /// <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子付出啊转换为对应的消息类型

    image

        /// </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, "此点击事件无效,服务器没有处理该事件的操作!
    事件类型:" + table["Event"]);
                                    }; break;
                            }
    
                        }; break;
                    default:
                        {
                            xmlRequest = new RequestBase(table, "服务器没有处理该消息的操作!
    消息类型:" + table["MsgType"]);
                        }; break;
                }
                return xmlRequest;
            }
        }

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

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

    image

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

    image

    消息处理类CustomMessageHandler:

    image

        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("用户发送消息解密后的明文:
    {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, "此点击事件无效,服务器没有处理该事件的操作!
    事件类型:" + RequestMessageType.fevent);
                                    }; break;
                            }
                        }; break;
                    default:
                        {
                            OnErrorResponse(CurrentMessage.FromUserName, CurrentMessage.ToUserName, "服务器没有处理该消息的操作!
    消息类型:" + 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("
    您一共发送了{0}条消息
    ", CurrentMessageContext.Contents.Length);
                //foreach (string str in CurrentMessageContext.Contents)
                //{
                //    Recodes.AppendFormat("{0}
    ", str);
                //}
    
                Recodes.AppendFormat("
    <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
        }

    image

    MsgRecode

    image

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

    image

    MessageContextHandler

    image

        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
    
        }

    image

    MessageContext

    image

        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
    
        }

    image

    image

        /// <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微信接口验证
    ");
                    Txt.AppendFormat("signature:{0}
    ", signature);
                    Txt.AppendFormat("timestamp:{0}
    ", timestamp);
                    Txt.AppendFormat("nonce:{0}
    ", nonce);
                    Txt.AppendFormat("echostr:{0}
    ", echostr);
                    Txt.AppendFormat("EncodingAESKey:{0}
    ", EncodingAESKey);
                    Txt.AppendFormat("CorpID:{0}
    ", CorpID);
                    Txt.AppendFormat("CorpToken:{0}
    ", 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
    {0}
    XML
    {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);
            }

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

    源码下载地址:源码下载

    慎于行,敏于思!GGGGGG
  • 相关阅读:
    wap2app(五)-- 微信授权登录以及踩过的坑
    wap2app(六)-- wap2app的原生标题头无法隐藏
    创建对象的几种模式
    通过url动态获取图片大小方法总结
    wap2app(三)-- 添加引导页
    wap2app(二)-- 设置APP系统状态栏
    wap2app(一)-- 网站快速打包成app
    树叶飘落、雪花飘落等同时多个图片飘落
    基于bootstrap的双日历插件 daterangepicker
    FileProvider解决FileUriExposedException
  • 原文地址:https://www.cnblogs.com/GarsonZhang/p/4059059.html
Copyright © 2011-2022 走看看