普通消息是指员工向企业号应用发送的消息,包括文本、图片、语音、视频、地理位置等类型。普通消息会推送到每个应用在管理端设置的URL(以下假设该URL为http://api.3dept.com)。
Http请求方式: POST
http://api.3dept.com/?msg_signature=ASDFQWEXZCVAQFASDFASDFSS×tamp=13500001234&nonce=123412323
<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,整型。可在应用的设置页面查看 |
<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,整型。可在应用的设置页面查看 |
<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,整型。可在应用的设置页面查看 |
<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,整型。可在应用的设置页面查看 |
<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,整型。可在应用的设置页面查看 |
---------------------------------------日志开始----------------------------------------------------------
整个被动响应的代码图如下
根据以上信息,我们创建如下几个类,
分组代码图:
类图:
RequestBase为所有接受信息基类,普通消息可直接继承
RequestEvent继承RequestBase,为事件消息的基类
微信接收信息分两种:
一种是接收普通消息(直接继承RequestBase类)
另一种是接收事件(继承RequestEvent类)
微信的消息类型结构如图所示
RequestBase.cs
/// <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
/// <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
/// <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
/// <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子付出啊转换为对应的消息类型
/// </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
/// <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); } }
消息处理类CustomMessageHandler:
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 }
MsgRecode
/// <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; } }
MessageContextHandler
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 }
MessageContext
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 }
/// <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); }
源代码等稍后奉上!!!!如有疑问,请留言联系
源码下载地址:源码下载