本文作者:小黑黑

[微信]了解MessageHandler

小黑黑 1年前 ( 2019-03-23 ) 1059 抢沙发
[微信]了解MessageHandler摘要:        前面我们已经简单使用了MessageHandler来处理微信消息,那么MessageHandler是怎么运作的呢,我们将深入了...

       前面我们已经简单使用了MessageHandler来处理微信消息,那么MessageHandler是怎么运作的呢,我们将深入了解下。

       在WeiXinController中我们写了一个Post方法,并且ActionName和Get方法的名称一致,微信在收到用户客户端消息时,会将消息转发到和Get方法同名的Post方法中,PostModel这个实体包含了微信公众号服务器发送过来的加密参数集合,我们可以在这里面获取一些加密参数信息。

var messageHandler = new CustomMessageHandler(Request.GetRequestMemoryStream(), postModel, 10);

       紧接着我们床加了MessageHandler的实例,并将Stream流和postModel以及maxRecordCount传入到构造方法中。其中maxRecordCount为单个用户上下文消息列表存储的最大长度,比如我们传入10条,那么当用户发送第11条数据后,发送的第一条数据将会被清除。

       当我们执行CustomMessageHandler时会首先执行父类中的Init()方法,首先会判断我们是否采用了加密,如果采用了加密,那么将会先对数据进行解密:

XDocument decryptDoc = postDataDocument;

if (_postModel != null && !_postModel.Token.IsNullOrWhiteSpace()
    && postDataDocument.Root.Element("Encrypt") != null && !string.IsNullOrEmpty(postDataDocument.Root.Element("Encrypt").Value))
{
    //使用了加密
    UsingEcryptMessage = true;
    EcryptRequestDocument = postDataDocument;

    WXBizMsgCrypt msgCrype = new WXBizMsgCrypt(_postModel.Token, _postModel.EncodingAESKey, _postModel.AppId);
    string msgXml = null;
    var result = msgCrype.DecryptMsg(_postModel.Msg_Signature, _postModel.Timestamp, _postModel.Nonce, postDataStr, ref msgXml);

    //判断result类型
    if (result != 0)
    {
        //验证没有通过,取消执行
        CancelExcute = true;
        return null;
    }

    if (postDataDocument.Root.Element("FromUserName") != null && !string.IsNullOrEmpty(postDataDocument.Root.Element("FromUserName").Value))
    {
        //TODO:使用了兼容模式,进行验证即可
        UsingCompatibilityModelEcryptMessage = true;
    }

    decryptDoc = XDocument.Parse(msgXml);//完成解密
}

这样我们就拿到了解密后数据,紧接着就会将XDocument转换为RequestMessageBase实体。

RequestMessage = RequestMessageFactory.GetRequestEntity(decryptDoc);

在GetRequestMessageBase()方法中,会根据消息的类型来生成响应的实体类。

msgType = MsgTypeHelper.GetRequestMsgType(doc);
switch (msgType)
{
    case RequestMsgType.Text:
        requestMessage = new RequestMessageText();
        break;
    case RequestMsgType.Location:
        requestMessage = new RequestMessageLocation();
        break;
    case RequestMsgType.Image:
        requestMessage = new RequestMessageImage();
        break;
    .........
}
得到相对应的实体信息后,将会把XML内容填充到实体中,然后返回实体。
Senparc.NeuChar.Helpers.EntityHelper.FillEntityWithXml(requestMessage, doc);

执行messageHandler.Execute();方法时,会执行BuildResponseMessage()方法,这样就会执行到我们自己的CustomMessageHandler的相对应的方法或事件中去。

/// <summary>
/// 执行微信请求
/// </summary>
public override void BuildResponseMessage()
{
    var weixinAppId = this._postModel == null ? "" : this._postModel.AppId;
    switch (RequestMessage.MsgType)
    {
        case RequestMsgType.Text:
            {
                var requestMessage = RequestMessage as RequestMessageText;

                ResponseMessage = CurrentMessageHandlerNode.Execute(requestMessage, this, weixinAppId) ??
                                    (OnTextOrEventRequest(requestMessage) ?? OnTextRequest(requestMessage));
            }
            break;
        case RequestMsgType.Location:
            ResponseMessage = OnLocationRequest(RequestMessage as RequestMessageLocation);
            break;
        case RequestMsgType.Image:
            ResponseMessage = CurrentMessageHandlerNode.Execute(RequestMessage, this, weixinAppId) ??
                                OnImageRequest(RequestMessage as RequestMessageImage);
            break;
        ..........
    }
}

       当我们的服务器处理完之后,通过return new FixWeixinBugWeixinResult(messageHandler);来将消息发送给微信服务器,通过请求源码我们应该可以猜想到,应用服务器将消息发送给微信服务器之前所做的工作,对数据加密,将数据组装成xml格式数据。到这,这个流程也就结束了。

    


分享到: 网站分享代码

发表评论

快捷回复:

评论列表 (暂无评论,1059人围观)参与讨论

还没有评论,来说两句吧...