WeiXin组件Senpac(四)【消息处理流程】

本文详细介绍了微信公众号消息处理的接口和类库设计,包括请求消息基接口、响应消息基类、事件消息的继承结构以及MessageHandler的处理流程。重点讨论了消息的去重、加密和上下文管理,以及如何自定义处理不同类型的用户消息。同时,还展示了如何在控制器中使用MessageHandler进行响应处理。
摘要由CSDN通过智能技术生成

消息类型

最基的接口。

public interface IEntityBase{}

所有请求响应的基接口。

public interface IMessageBase : IEntityBase
{
    string ToUserName{get;set;}
    string FromUserName{get;set;}
    DateTime CreateTime{get;set;}
}

请求的基接口。

public interface IRequestMessageBase
{
    RequestMsgType MsgType{get;}
    string Encrypt{get;set;}
    long MsgId{get;set;}
}

请求的基类

public class RequestMessageBase : IRequestMessageBase
{
    public virutal RequestMsgType MsgType
    {
        get {return ReuqstMsgType.Text;}
    }
    public string Encrypt{get;}
    public RequestMessageBase(){}
    public long MsgId{get;set;}
}

文本类型的请求消息

public class RequestMessageText : RequestMessageBase, IRequestMessageBase,IRequestText
{
    public override ReqestMsgType MsgType
    {
        get {return RequestMsgType.Text;}
    }
    public string Content{get;set;}
}

图片请求消息

publci class RequestMessageImage : RequestMessageBase, IRequestMessageBase
{
    public override ReqestMsgType MsgType
    {
        get {return RequestMsgType.Image;}
    }
    public string MediaId{get;set;}
    public string PicUrl{get;set;}
}

其它请求消息

  • RequestMessageVoice
  • RequestMessageVideo
  • RequestMessageShortVideo
  • RequestMessageLocation
  • RequestMessageLink
  • RequestMessageEventBase

事件基接口。

public interface IReqestMessageEventBase : IRequestMessageBase
{
    Event Event{get;}
}

事件基类。

public class RequestMessageEventBase : RequestMessageBase, IRequestMessageEventBase
{
    public override ReqeustMsgType MsgType
    {
        get {return RequestMsgType.Event;}
    }
    public virtual Event Event
    {
        get {return Event.ENTER;}
    }
}

事件消息基类的子类还有其它共同属性,通过一个接口来实现。

public interface IRequestMessageEventKey
{
    string EventKey{get;set;}
}

事件订阅消息

public class RequestMessageEvent_Subscribe : RequestMessageEventBase, IRequestMessageEventBase, IRequestMessageEventKy
{
    public override Event Event
    {
        get {return Evnet.Subscribe;}
    }
    //场景中二维码带的参数
    public string EventKey{get;set;}
    //场景中二维码的ticket
    public string Ticket{get;set;}
}

取消订阅事件消息

public class RequestMessageEvent_Unsubscribe : RequestMessageEventBase, IRequestMessageEventBase
{
    public override Event Event
    {
        get {return Event.unsubscribe;}
    }
}
  • 进入回话事件消息:RequestMessageEvent_Enter
  • 公众号二维码扫描事件消息:RequestMessageEvent_Scan
  • 获取用户地理位置事件消息:RequestMessageEvent_Location
  • 点击菜单事件消息:RequestMessageEvent_Click
  • URL跳转事件消息:RequestMessageEvent_View
  • 扫码事件消息:RequestMessageEvent_Scancode_Push
  • 扫码事件弹出提示框:RequestMessageEvent_Scancode_Waitingmsg
  • 弹出拍照发图事件消息:RequestMessageEvent_Pic_Sysphoto
  • 弹出拍照或相册发图事件消息:RequestMessageEvent_Pic_Photo_Or_Album
  • 弹出微信相册发图事件消息:RequestMessageEvent_Locaiton_Select
  • 群发结果事件消息:RequestMessageEvent_MassSendJobFinish
  • 模板推送结束事件消息:RequestMessageEvent_TemplateSendJobFinish
  • 卡卷通过审核事件消息:RequestMessageEvent_Card_Pass_Check
  • 卡卷未通过审核事件消息:RequestMessageEvent_Card_Not_Pass_Check
  • 领取卡卷事件消息:RequestMessageEvent_User_Get_Card
  • 删除卡券事件消息:RequestMessageEvent_User_Del_Card
  • 客服接入会话事件消息:RequestMessageEvent_Kf_Create_Session
  • 客服关闭会话事件消息:RequestMessageEvent_Kf_Close_Session
  • 客服转接会话事件消息:RequestMessageEvent_Kf_Switch_Session
  • 门店审核结果通过事件消息:RequestMessageEvent_Poi_Check_Notify
  • wifi连网事件消息:RequestMessageEvent_WifiConnected
  • 卡券核销事件消息:RequestMessageEvent_User_Consume_Card
  • 从卡券进入公众号会话:RequestMessageEvent_User_Enter_Session_From_Card
  • 进入会员卡事件消息:RequestMessageEvent_User_View_Card
  • 微小店订单付款通知事件消息:RequestMessageEvent_Merchant_Order
  • 接收会员信息事件消息:RequestMessageEvent_Submit_Membercard_User_Info
  • 摇一摇事件通知消息:RequestMessageEvent_ShakearoundUserShake

响应消息

响应也有基接口和基类。

public class ResponseMessageBase : IResponseMessageBase
{
    //注意,在响应的基类中没有MsgId,这意味着,应用程序回复微信服务器的消息必须一次成功,如果不成功,客户端收到的信息是:公众号暂时无法提供服务,请稍后再试。例如,微信服务器连续发了3条MsgId一样的消息到应用服务器,如果应用服务器没有对消息去重,会分别响应三次请求,客户端只会收到最后一次发送的信息
    public virutal ResponseMsgType MsgType
    {
        get {return ResponseMsgType.Text;}
    }
    //从请求消息返回响应类型实例
    public static T CreateFromRequestMessage<T>(IRequestMessageBase requestMessage) where T : ResponseMessageBase
    {
        try{
            var tType = typeof(T);
            var responseName = tType.Name.Replace("ResponseMessage","");
            ResponseMsgType msgType = (ResponseMsgType)Enum.Parse(typeof(ReesponseMsgType), responseName);
            return CreateFromRequestMessage(requestMessage, msgType) as T;
        }
        catch(Exception ex)
        {
            throw new WeixinException();
        }
    }
}

图文的响应消息

public class ResponseMssageNews : ResponseMessageBase, IResponseMessageBase
{
    new public virutal ResponseMsgType MsgType
    {
        get {return ResponseMsgType.News;}
    }
    public int ArticalCount
    {
        get {
            return Articles = null ? 0 : ArTICALS.Count;
        }
        set{
        }
    }
    public List<Article> Articles{get;set;}
    public ResponseMessageNews()
    {
        Articles = new List<Article>();
    }
}

最多10条图文。

使用MessageHandler

public class CustomMessageHandler : MessageHandler<CustomMessageContext>
{
    public CustomMessageHandler(Stream inputStream, PostModel postModel) : base(intpuStream, postModel)
    {
    }
    //必须重写的方法
    //如果所有的方法不生效,用这个兜底
    public override IResponseMessageBae DefaultResponseMessage(IRequestMessageBase requestMessage)
    {
        var responseMessage = base.CreateResponseMessage<ResponseMessageText>();
        responseMessage.Content = "";
        return responseMessage;
    }
    public override IResponseMessageBase OnTextRequest(RequestMessageText requestMessage)
    {
    }
}

MessageHandler中有很多方法,虚方法可以重写。

public class MessageHandler
{
    //抽象方法必须被重写
    //抽象方法是没有方法体的
    public abstract IResponseMessageBase DefaultReposneMessage(IRequestMessageBase requestMessage);
    //虚方法不一定需要被重写
    //在OnTextRequest或OnEventRequest之前被触发
    //如果返回null,继续执行OnTextRequest或OnEventRequest
    //如果返回不是Null,终止执行OnTextRequest或OnEventRequest
    //如果客户端传来的是事件消息,会将RequestmessageEvent自动转换成RequestMessageText类型,其中RequestMessageText.Content就是RequestMessageEvent.EventKey
    public virutal IResponseMessageBase OnTextOrEventRequest(RequestMessageText requestMessage)
    {
    }
    ...
    public virutal IResponseMessageBase OnEvent_LocaltionRequest(RequestMessageEvent_Location requestMessage){};
}

在控制器中的使用

[HttpPost]
[Actionname("Index")]
public ActionResult Post(PostModel postModel)
{
    if(!CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, Token))
    {
        return Content();
    }
    postModel.Token = "";
    postModel.EncodingAESKey = "";
    postMode.AppId = AppId;
    var messageHandle = new CustomMessageHandler(Request.InputStream, postModel);
    messageHandler.Execute();
    return new FixWeixinBugWeixinResult(messageHandler);
}

MessageHandlerOnExecutingOnEecuted方法

public class CustomMessageHandler
{
    public override void OnExecuting()
    {
    }
    public override void OnExecuted()
    {
    }
}

用户上下文

客户端的信息如何保存下来呢?放到一个集合类里,对数量做规定。

public class MessageContainer<T> : List<T>
{
}

所有的消息会进入消息队列。

public class MessageQueue<TM, TRequest, TResponse> : List<TM>
    where TM : class, IMessageContext<TRequest, TResponse>,new()
    where TRequest : IRequestmessageBase
    where TResponse : IResponseMessageBase
{
}

单个用户的信息放在了MessageContext中,从接口开始。

public interface IMessageContext<TRequest, TResponse> 
    where TRequest : IRequestMessageBase
    where TResponse : IResponseMessageBase
    {
        string UserName
        DateTime LastAcitveTime
        MessageContianer<TRequest> RequestMessages
        MessageContainer<TResponse> ResponseMessages
        int MaxRecordCount
        object StorageData//存储用户状态
        Double? ExpireMinutes;
        AppStoreState AppStoreState;
        //上下文移除时触发
        event EventHandler<WeixinContextRemovedEventArgs<TRequest, TResponse>> MessageContextRemoved;
        void OnRemoved();//消息删除时触发
    }

上下文的实现类。

public class MessageContext<TRequest, TResponse> : IMessageContext<TRequest, TResponse>
    where TRequest : IRequestMessageBae
    where TResponse : IResponseMessageBase
    {
        private int _maxRecourdCount;
        public string UserName{get;set;}
        public DateTime LastActiveTime{get;set;}
        public MessageContainer<TRequest> RequestMessages{get;set;}
        public MessageContainer<TResponse> ResponseMessages{get;set;}
        public int MaxRecourdCount
        {
            get
            {
                return _maxRecourdCount;
            }
            set
            {
                RequestMessages.MaxRecordCount= value;
                ResponseMessages.MaxRecourdCOunt = value;
                _maxRecourdCount = value;
            }
        }
        public object StorageData{get;set;}
        public Double? ExpireMinutes{get;set;}
        publci AppStoreState AppStoreState{get;set;}
        public virutal event EventHandler<WeixinContextRemovedEventArgs<TRequest, TResponse>> MessageCOntextRemoved = null;
        public messageContext()
        {
            RequestMessages = new MessageContainer<TRequest>(MaxRecountCount);
            ResponseMessages = new MessageContainer<TResponse>(MaxRecourdCount);
            LastActiveTime = DateTime.Now;
        }
        private void OnMessageContextRemoved(WeixinContextRemovedEventArgs<TRequest, TResponse> e)
        {
            EventHadnler<WeixinContextRemovedEventArgs<TReqeust, TRespone>> temp = MessageContextRemoved;
            if(temp!=null)
            {
                temp(this,e);
            }
        }
        public virutal void OnRemoved()
        {
            var onRemoveArg = new WeixinContextRemovedEventArgs<TRequest, TResponse>(this);
            OnMssageContextRemoved(onRemovedArg);
        }
    }

自定义一个上下文

publci class CustomMessageContext : MessageContext<IRequestMessageBase, IResponseMessageBase>
{
    public CustomMessageContext()
    {
        base.MessageContextRemoved += CustmMessageContext_MessageContextRemoved;
    }
    void CustomMessageContext_MessageContextRemovied(object sender, WeixinContextRemovedEventArs<IRequestMessageBase, IResponsMessageBase> e)
    {
        var messageContex = e.MessageContext as CustomMessageContext;
        if(messageContext ==null) return;
        //TODO:
    }
}

全局上下文

WeixinContext

- 所有单个用户的上下文
- 不是静态类,在同一个应用中创建多个全局上下文
- MessageHandler中有一个静态的WeiXinContext,所有任何MessageHandler的子类中都可以获取到WeixinContext,它是全局的、唯一的
- Dictionary<string, TM> MessageCollection,所有单个用户MessageContext的集合,不能操作
- MessageQueue<TM, TRequest, TResponse>,所有单个用户MessageContext的队列

消息去重

去重设置一

messageHandler.OmitRepeatedMessage = false;

去重设置二

public CustomMessageHandler(Stream inputStream, PostModel postModelk, int maxRecourdCOunt = 0) : base(inputStream, postModel, maxRecourdCount)
{
    base.OmitRepeatedMessageFunc = requestMessage => {
        var textRequestMessage = requestMessage as RquestMessageText;
        if(textRequuestMessage != null && textRequestMessage.Content == "")
        {
            return false;
        }
    }
}

消息加密

MessageHandler考虑了加密情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值