微信API开发引擎|微信API|ASP.NET微信接口

lcqbetry 10年前

    采用C#语言开发的微信API引擎,内部,有基于事件驱动的微信接收回复处理模块。为C#开发微信接口,提供一种简单的引擎。功能还在进一步完善中,欢迎大家多多提供宝贵意见,另外也可以在此基础上进行开发。

接收微信消息处理程序


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using WeiNet.API.Event;
using WeiNet.API.entity;
/=============================================================
 

  版 本:WeiNet V1.0
 
作 者:李朝强
  说 明:接收消息的一般处理程序基类,完全基于事件驱动
 
时 间:2014/05/11
 
 
===========================================================/
namespace WeiNet.API.driver
{
    /// <summary>
    ///
    /// </summary>
    public class RecieveBase : IHttpHandler
    {
        #region 日志
        /// <summary>
        ///日志
        /// </summary>
        protected readonly log4net.ILog logger = log4net.LogManager.GetLogger(typeof(RecieveBase));
        #endregion

        #region 事件

        /// <summary>
        /// 当接收到文字信息时
        /// </summary>
        protected event OnRecieveEventHandler OnRecieveText;

        /// <summary>
        /// 接收图片事件
        /// </summary>
        protected event OnRecieveEventHandler OnReciveImage;

        /// <summary>
        /// 接收音频
        /// </summary>
        protected event OnRecieveEventHandler OnReciveVoice;

        /// <summary>
        /// 接收视频
        /// </summary>
        protected event OnRecieveEventHandler OnRecieveVideo;

        /// <summary>
        ///地理位置消息
        /// </summary>
        protected event OnRecieveEventHandler OnRecieveLocation;

        /// <summary>
        /// 链接消息
        /// </summary>
        protected event OnRecieveEventHandler OnRecieveLink;

        /// <summary>
        /// 事件消息
        /// </summary>
        protected event OnRecieveEventHandler OnRecieveEvent;


        /// <summary>
        /// 激活微信公众账号,验证签名
        /// </summary>
        protected event OnActiveEventHandler OnActive;

        /// <summary>
        /// 关注事件
        /// </summary>
        protected event OnCustomEvent OnSubscribe;

        /// <summary>
        /// 取消订阅
        /// </summary>
        protected event OnCustomEvent OnUnsubscribe;

        /// <summary>
        /// 用户已关注时的事件推送
        /// </summary>
        protected event OnCustomEvent OnScanSubscribe;


        /// <summary>
        /// 上报地理位置事件
        /// </summary>
        protected event OnCustomEvent OnLocation;

        /// <summary>
        ///点击菜单跳转链接时的事件推送
        /// </summary>
        protected event OnCustomEvent OnCustomViewEvent;

        /// <summary>
        ///点击菜单拉取消息时的事件推送
        /// </summary>
        protected event OnCustomEvent OnCustomClickEvent;


        #endregion

        #region 构造器
        /// <summary>
        /// 构造器
        /// </summary>
        public RecieveBase()
        {

        }
        #endregion

        #region 是否可以重用
        /// <summary>
        /// 是否可以重用
        /// </summary>
        public bool IsReusable
        {
            get { return false; }
        }
        #endregion

        #region 处理请求
        /// <summary>
        /// 处理请求
        /// </summary>
        /// <param name="context"></param>
        public void ProcessRequest(HttpContext context)
        {
            //1>授权
            if (context.Request.HttpMethod.ToUpper() == "GET"
                && !string.IsNullOrEmpty(context.Request["echostr"]))
            {
                WeiActiveEventArgs eActiveArgs = new WeiActiveEventArgs();
                eActiveArgs.Context = context;
                On_ActiveEvent(eActiveArgs);
            }
            //2>处理POST请求
            if (context.Request.HttpMethod.ToUpper() == "POST")
            {
                //事件参数
                WeiEventArgs e = new WeiEventArgs(context);

                On_RecieveEvent(e);
                On_RecieveImage(e);
                On_RecieveLink(e);
                On_RecieveLocation(e);
                On_RecieveVideo(e);
                On_RecieveVoice(e);
                On_RecieveText(e);
            }
        }
        #endregion


        /**
事件***/
        #region 事件调用
        /// <summary>
        /// 当接收到文字信息时触发事件
        /// </summary>
        /// <param name="e"></param>
        protected virtual void On_RecieveText(WeiEventArgs e)
        {
            //接收信息处理句柄
            if (OnRecieveText != null
                && e.MsgType == "text")
            {
                e.message = new textMessage(e.xml);
                OnRecieveText(this, e);
            }
        }

        /// <summary>
        /// 当接收到图片信息时触发事件
        /// </summary>
        /// <param name="e"></param>
        protected virtual void On_RecieveImage(WeiEventArgs e)
        {
            //接收信息处理句柄
            if (OnReciveImage != null
                && e.MsgType == "image")
            {
                e.message = new imageMessage(e.xml);
                OnReciveImage(this, e);
            }
        }


        /// <summary>
        /// 当接收音频消息时触发事件
        /// </summary>
        /// <param name="e"></param>
        protected virtual void On_RecieveVoice(WeiEventArgs e)
        {
            if (OnReciveVoice != null
                && e.MsgType == "voice")
            {
                e.message = new voiceMessage(e.xml);
                OnReciveVoice(this, e);
            }
        }

        /// <summary>
        /// 当接收视频消息时触发事件
        /// </summary>
        /// <param name="e"></param>
        protected virtual void On_RecieveVideo(WeiEventArgs e)
        {
            if (OnRecieveVideo != null
                && e.MsgType == "video")
            {
                e.message = new videoMessage(e.xml);
                OnRecieveVideo(this, e);
            }
        }

        /// <summary>
        /// 接收地理位置消息
        /// </summary>
        /// <param name="e"></param>
        protected virtual void On_RecieveLocation(WeiEventArgs e)
        {
            if (OnRecieveLocation != null
                && e.MsgType == "location")
            {
                e.message = new locationMessage(e.xml);
                OnRecieveLocation(this, e);
            }
        }


        /// <summary>
        /// 接收链接消息
        /// </summary>
        /// <param name="e"></param>
        protected virtual void On_RecieveLink(WeiEventArgs e)
        {
            if (OnRecieveLink != null
                && e.MsgType == "link")
            {
                e.message = new linkMessage(e.xml);
                OnRecieveLink(this, e);
            }
        }

        /// <summary>
        /// 事件消息
        /// </summary>
        /// <param name="e"></param>
        protected virtual void On_RecieveEvent(WeiEventArgs e)
        {
            if (OnRecieveEvent != null
                && e.MsgType == "event")
            {

                //1、事件消息参数
                WeiEventMsgArgs eventArgs = new WeiEventMsgArgs(e.xml);

                On_ScanSubscribe(eventArgs);
                On_Subscribe(eventArgs);
                On_Unsubscribe(eventArgs);
                On_Location(eventArgs);
                On_CustomClickEvent(eventArgs);
                On_CustomViewEvent(eventArgs);
                //2、处理事件
                e.message = e.message ?? new messageBase(e.xml);
                OnRecieveEvent(this, e);
            }
        }


        /// <summary>
        /// 验证微信平台签名事件
        /// </summary>
        /// <param name="e"></param>
        protected virtual void On_ActiveEvent(WeiActiveEventArgs e)
        {
            if (OnActive != null)
            {
                OnActive(this, e);
            }
        }

        /// <summary>
        /// 关注事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void On_Subscribe(WeiEventMsgArgs e)
        {
            if (null != OnSubscribe
                && e.Event == "subscribe")
            {
                e.message = new entity.Event.subscribe(e.xml);
                OnSubscribe(this, e);
            }
        }

        /// <summary>
        /// 取消订阅
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void On_Unsubscribe(WeiEventMsgArgs e)
        {
            if (null != OnUnsubscribe
                && e.Event == "unsubscribe")
            {
                e.message = new entity.Event.subscribe(e.xml);
                OnUnsubscribe(this, e);
            }
        }


        /// <summary>
        /// 用户已关注时的事件推送
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void On_ScanSubscribe(WeiEventMsgArgs e)
        {
            if (null != OnScanSubscribe
                && e.Event == "SCAN")
            {
                e.message = new entity.Event.subscribe(e.xml);
                OnScanSubscribe(this, e);
            }
        }

        /// <summary>
        /// 上报地理位置事件
        /// 说明:用户同意上报地理位置后,每次进入公众号会话时,都会在进入时上报地理位置,或在进入会话后每5秒上报一次地理位置,
        /// 公众号可以在公众平台网站中修改以上设置。上报地理位置时,微信会将上报地理位置事件推送到开发者填写的URL。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void On_Location(WeiEventMsgArgs e)
        {
            if (null != OnLocation
                && e.Event == "LOCATION")
            {
                e.message = new entity.Event.location(e.xml);
                OnLocation(this, e);
            }
        }

        /// <summary>
        /// 点击菜单拉取消息时的事件推送
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void On_CustomClickEvent(WeiEventMsgArgs e)
        {
            if (null != OnCustomClickEvent
                && e.Event == "CLICK")
            {
                e.message = new entity.Event.click(e.xml);
                OnCustomClickEvent(this, e);
            }
        }
        /// <summary>
        /// 点击菜单跳转链接时的事件推送
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void On_CustomViewEvent(WeiEventMsgArgs e)
        {
            if (null != OnCustomViewEvent
                && e.Event == "VIEW")
            {
                e.message = new entity.Event.view(e.xml);
                OnCustomViewEvent(this, e);
            }
        }
        #endregion


    }
}

[C#]实例:   

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using WeiNet.API.entity;
using WeiNet.API.Event;

namespace WeiNet.api
{
    /// <summary>
    /// WeiRecieve 的摘要说明
    /// </summary>
    public class WeiRecieve : WeiNet.API.driver.RecieveBase
    {
        #region 构造器
        /// <summary>
        /// 构造器
        /// </summary>
        public WeiRecieve()
        {
            //绑定事件
            OnActive += new API.Event.OnActiveEventHandler(WeiOnActiveEvent);

            OnRecieveEvent += new API.Event.OnRecieveEventHandler(WeiOnRecieveEvent);
            OnRecieveLink += new API.Event.OnRecieveEventHandler(WeiOnRecieveLink);
            OnRecieveLocation += new API.Event.OnRecieveEventHandler(WeiOnRecieveLink);
            OnRecieveText += new API.Event.OnRecieveEventHandler(WeiOnRecieveText);
            OnRecieveVideo += new API.Event.OnRecieveEventHandler(WeiOnRecieveVideo);
            OnReciveImage += new API.Event.OnRecieveEventHandler(WeiOnRecieveImage);
            OnReciveVoice += new API.Event.OnRecieveEventHandler(WeiOnRecieveVoice);

            //事件消息
            OnScanSubscribe += new API.Event.OnCustomEvent(WeiOnScanSubscribe);
            OnSubscribe += new API.Event.OnCustomEvent(WeiOnSubscribe);
            OnUnsubscribe += new API.Event.OnCustomEvent(WeiOnUnsubscribe);
            OnCustomClickEvent += new API.Event.OnCustomEvent(WeiOnCustomClickEvent);
            OnCustomViewEvent += new API.Event.OnCustomEvent(WeiOnCustomViewEvent);

        }
        #endregion

        /// <summary>
        ///验证签名,绑定公众账号
        /// </summary>
        /// <param name="e"></param>
        protected void WeiOnActiveEvent(object sender, API.Event.WeiActiveEventArgs e)
        {
            HttpContext context = e.Context;
            //1. 将token、timestamp、nonce三个参数进行字典序排序
            //2. 将三个参数字符串拼接成一个字符串进行sha1加密
            //3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
            Dictionary<string, string> dictQuery = new Dictionary<string, string>();
            dictQuery["token"] = WeiNet.API.consts.CONSTS.TOKEN;
            dictQuery["timestamp"] = context.Request["timestamp"];
            dictQuery["nonce"] = context.Request["nonce"];
            dictQuery.Reverse();
            string strEchostr = context.Request["echostr"];

            logger.Info("请求Url:" + context.Request.Url.ToString());
            //验证签名
            if (!WeiNet.API.auth.authUtil.CheckSignature(dictQuery, context.Request["signature"]))
            {
                logger.Info(strEchostr + "验证失败");
                //验证失败
                context.Response.Write("error:600002");
                return;
            }
            else
            {
                logger.Info("请求echostr:" + strEchostr);
                context.Response.Write(strEchostr);
            }

        }

        /// <summary>
        ///接收到文字信息
        /// </summary>
        /// <param name="e"></param>
        protected void WeiOnRecieveText(object sender, API.Event.WeiEventArgs e)
        {
            Reply(e);
        }

        /// <summary>
        /// 接收图片信息
        /// </summary>
        /// <param name="e"></param>
        protected void WeiOnRecieveImage(object sender, API.Event.WeiEventArgs e)
        {
            Reply(e);
        }

        /// <summary>
        /// 接收链接消息
        /// </summary>
        /// <param name="e"></param>
        protected void WeiOnRecieveLink(object sender, API.Event.WeiEventArgs e)
        {
            Reply(e);
        }

        /// <summary>
        /// 接收音频消息
        /// </summary>
        /// <param name="e"></param>
        protected void WeiOnRecieveVoice(object sender, API.Event.WeiEventArgs e)
        {
            Reply(e);
        }

        /// <summary>
        /// 接收视频消息
        /// </summary>
        /// <param name="e"></param>
        protected void WeiOnRecieveVideo(object sender, API.Event.WeiEventArgs e)
        {
            Reply(e);
        }

        /// <summary>
        /// 接收事件消息
        /// </summary>
        /// <param name="e"></param>
        protected void WeiOnRecieveEvent(object sender, API.Event.WeiEventArgs e)
        {
#if DEBUG
            logger.Info(string.Format("事件:接收事件消息,用户OpenID:{0},公众微信号:{1}", e.message.FromUserName, e.message.ToUserName));
#endif
            //假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。
            HttpContext.Current.Response.Write("");
        }

        /// <summary>
        /// 接收地理位置信息
        /// </summary>
        /// <param name="e"></param>
        protected void WeiOnRecieveLocation(object sender, API.Event.WeiEventArgs e)
        {
#if DEBUG
            logger.Info("接收地理位置信息");
#endif
        }

        /// <summary>
        /// 关注事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void WeiOnSubscribe(object sender, API.Event.WeiEventMsgArgs e)
        {
#if DEBUG
            logger.Info(string.Format("事件:关注事件,用户OpenID:{0},公众微信号:{1}", e.message.FromUserName, e.message.ToUserName));
#endif
            //假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。
            //HttpContext.Current.Response.Write("");
            //Reply(e);
            ReplyArticle(e);
        }

        /// <summary>
        /// 取消订阅事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void WeiOnUnsubscribe(object sender, API.Event.WeiEventMsgArgs e)
        {
#if DEBUG
            logger.Info(string.Format("事件:取消订阅事件,用户OpenID:{0},公众微信号:{1}", e.message.FromUserName, e.message.ToUserName));
#endif
            //假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。
            //HttpContext.Current.Response.Write("");
            Reply(e);
        }

        /// <summary>
        /// 扫描:用户已关注时的事件推送
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void WeiOnScanSubscribe(object sender, API.Event.WeiEventMsgArgs e)
        {
#if DEBUG

            logger.Info(string.Format("事件:用户已关注时的事件推送,用户OpenID:{0},公众微信号:{1}", e.message.FromUserName, e.message.ToUserName));
#endif
            //假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。
            HttpContext.Current.Response.Write("");
        }

        /// <summary>
        /// 上报地理位置事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void WeiOnLocation(object sender, API.Event.WeiEventMsgArgs e)
        {
#if DEBUG
            logger.Info(string.Format("事件:上报地理位置事件,用户OpenID:{0},公众微信号:{1}", e.message.FromUserName, e.message.ToUserName));
#endif
            //假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。
            HttpContext.Current.Response.Write("");
        }

        /// <summary>
        /// 自定义事件:点击菜单拉取消息时的事件推送
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void WeiOnCustomClickEvent(object sender, API.Event.WeiEventMsgArgs e)
        {
#if DEBUG
            logger.Info(string.Format("事件:点击菜单拉取消息时的事件推送,用户OpenID:{0},公众微信号:{1}", e.message.FromUserName, e.message.ToUserName));
#endif
            //假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。
            HttpContext.Current.Response.Write("");
        }

        /// <summary>
        /// 自定义事件:点击菜单跳转链接时的事件推送
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void WeiOnCustomViewEvent(object sender, API.Event.WeiEventMsgArgs e)
        {
#if DEBUG
            logger.Info(string.Format("事件:点击菜单跳转链接时的事件推送,用户OpenID:{0},公众微信号:{1}", e.message.FromUserName, e.message.ToUserName));
#endif
            //假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。
            HttpContext.Current.Response.Write("");
        }

        /// <summary>
        /// 测试:回复文本
        /// </summary>
        /// <param name="e"></param>
        private static void Reply(WeiEventArgs e)
        {
            //实例化一个文本消息实体
            textMessage message = new textMessage();
            message.FromUserName = e.message.ToUserName;//开发者微信号
            message.ToUserName = e.message.FromUserName;//接收方帐号(收到的OpenID) 
            message.Content = "郑州众远信息科技有限公司,欢迎你!!!";
            //回复文本消息
            WeiNet.API.message.Reply.WeiReply(message);
        }

        /// <summary>
        /// 测试:回复图文列表
        /// </summary>
        /// <param name="e"></param>
        private static void ReplyArticle(WeiEventArgs e)
        {
            List<WeiNet.API.entity.article> list = new List<article>();
            //声明文章列表
            WeiNet.API.entity.article article = new article();
            article.Title = "郑州众远信息技术有限公司";
            article.Description = "郑州众远信息技术有限公司";
            article.PicUrl = string.Empty;
            article.Url = "http://zy.234love.com";

            list.Add(article);

            WeiNet.API.entity.article article2 = new article();
            article2.Title = "关于我们团队";
            article2.Description = "关于我们团队";
            article2.PicUrl = string.Empty;
            article2.Url = "http://zy.234love.com";
            list.Add(article2);

            WeiNet.API.entity.article article3 = new article();
            article3.Title = "精彩案例";
            article3.Description = "精彩案例";
            article3.PicUrl = string.Empty;
            article3.Url = "http://zy.234love.com";
            list.Add(article3);

            WeiNet.API.entity.article article4 = new article();
            article4.Title = "服务内容";
            article4.Description = "服务内容";
            article4.PicUrl = string.Empty;
            article4.Url = "http://zy.234love.com";
            list.Add(article4);

            WeiNet.API.entity.article article5 = new article();
            article5.Title = "最新动态";
            article5.Description = "最新动态";
            article5.PicUrl = string.Empty;
            article5.Url = "http://zy.234love.com";
            list.Add(article5);


            WeiNet.API.message.Reply.WeiReply(e.message.FromUserName,
                                              e.message.ToUserName,
                                              list);
        }
    }
}

实体关系图


模拟微信服务器请求: