评论

微信公众号服务器配置,有关签名验证踩坑

微信公众号服务器配置,有关签名验证踩坑

验证签名,腾讯官方提供的文档居然有写“密文”,如下图,切记要去掉。。。。

C# WebApi配置服务器代码分享:
public static readonly ILog BaseLogger = LogManager.GetLogger(“CheckTokenController”);
//公众平台上开发者设置的token, appID, EncodingAESKey
public static string sToken = “微信配置”;
public static string sAppID = “你的公众号ID”;
public static string sEncodingAESKey = “可随机可自定义,切记与微信配置一致”;
//用于消息去重
public static Dictionary<string, DateTime> _msgId = new Dictionary<string, DateTime>();

    Tencent.WXBizMsgCrypt wxcpt = new Tencent.WXBizMsgCrypt(sToken, sEncodingAESKey, sAppID);
    /// <summary>
    /// 用于微信验证
    /// </summary>
    /// <param name="signature"></param>
    /// <param name="timestamp"></param>
    /// <param name="nonce"></param>
    /// <param name="echoStr"></param>
    /// <returns></returns>
    [HttpGet]
    public HttpResponseMessage Get(string signature, string timestamp, string nonce, string echoStr)
    {
        StreamReader sr = new StreamReader(System.Web.HttpContext.Current.Request.InputStream, Encoding.UTF8);
        BaseLogger.Info(sr);
        var sMsgSignature = "";
        var ret = wxcpt.GenarateSinature(sToken, timestamp, nonce, ref sMsgSignature);
        if (ret != 0)
        {
            return new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent("")
            };
        }
        if (sMsgSignature == signature)
        {
            return new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent(echoStr)
            };
        }
        return new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = new StringContent("")
        };
    }

    /// <summary>
    /// 接收微信推送的消息及事件
    /// </summary>
    /// <param name="signature"></param>
    /// <param name="timestamp"></param>
    /// <param name="nonce"></param>
    /// <returns></returns>
    [HttpPost]
    public HttpResponseMessage Get([FromUri]string signature,[FromUri]string timestamp,[FromUri]string nonce)
    {
        try
        {
            var requestContent = Request.Content.ReadAsStringAsync().Result;
            
            var msg = "";
            var ret = wxcpt.DecryptMsg(signature, timestamp, nonce, requestContent, ref msg);

            if (ret != 0)
            {
                BaseLogger.Error("解密失败,返回码:"+ret);
            }

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(msg);
            
            WxMessage wxMessage = new WxMessage();
            wxMessage.MsgType = xmlDoc.SelectSingleNode("xml/MsgType").InnerText;//消息类型
            wxMessage.FromUserName = xmlDoc.SelectSingleNode("xml/FromUserName").InnerText;//发送人
            wxMessage.ToUserName = xmlDoc.SelectSingleNode("xml/ToUserName").InnerText;//接受人
            wxMessage.CreateTime = xmlDoc.SelectSingleNode("xml/CreateTime").InnerText;//时间戳
            string MsgId = wxMessage.MsgType == "event" ? "" : xmlDoc.SelectSingleNode("xml/MsgId").InnerText;//消息ID,事件中没有

            //验证消息是否重复
            if (Removal(wxMessage.MsgType, MsgId, wxMessage.FromUserName, wxMessage.CreateTime))
            {
                return null;
            }
            switch (wxMessage.MsgType)
            {
                case "event":
                    //接收关注/取消关注事件
                    wxMessage.EventName = xmlDoc.SelectSingleNode("xml").SelectSingleNode("Event").InnerText;
                    //关注回复消息
                    if (!string.IsNullOrEmpty(wxMessage.EventName) && wxMessage.EventName == "subscribe")
                    {
                        string content = "您好,欢迎访问****公众平台";
                        content = SendTextMessage(wxMessage, content);
                        return new HttpResponseMessage(HttpStatusCode.OK)
                        {
                            Content = new StringContent(content)
                        };
                    }
                    break;
            }

            if (wxMessage.MsgType == "event")
            {
                
            }
            return new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent("")
            };
        }catch(Exception ex)
        {
            BaseLogger.Error(ex);
            return new HttpResponseMessage(HttpStatusCode.InternalServerError)
            {
                Content = new StringContent(ex.Message)
            };
        }
    }
    
    
    private string SendTextMessage(WxMessage wxmessage, string content)
    {
        string result = string.Format(Message, wxmessage.FromUserName, wxmessage.ToUserName, DateTime.Now.Ticks, content);
        return result;
    }

    /// <summary>

/// 验证消息是否重复如果重复 返回true
        /// </summary>
        /// <param name=“msgTypeStr”>消息类型</param>
        /// <param name=“MsgId”>消息编号</param>
        /// <param name=“userName”>发送人Id</param>
        /// <param name=“createTime”>时间戳</param>
        /// <returns></returns>
        private static bool Removal(string msgTypeStr, string MsgId, string userName, string createTime)
{
if (string.IsNullOrWhiteSpace(MsgId))
{
MsgId = userName + createTime;
}
            //删除3分钟之前的消息
            foreach (var item in _msgId)
{
if (item.Value < DateTime.Now.AddMinutes(-3))
{
_msgId.Remove(item.Key);
}
}
            //验证消息是否存在
            if (_msgId.Keys.Contains(MsgId))
{
return true;
}
else
{
_msgId[MsgId] = DateTime.Now;
}
return false;
}

    public string Message
    {
        get
        {
            return @"<xml>
       <ToUserName><![CDATA[{0}]]></ToUserName>
       <FromUserName><![CDATA[{1}]]></FromUserName>
       <CreateTime>{2}</CreateTime>
       <MsgType><![CDATA[text]]></MsgType>
       <Content><![CDATA[{3}]]></Content>
     </xml>";
        }
    }
最后一次编辑于  09-19  
点赞 1
收藏
评论

1 个评论

  • 月光
    月光
    11-17

    真的感谢。百思不得其解。弄了两天才看到你这篇帖子才找到问题所在,一直以为是自己的代码出了问题,没想到真的是微信团队的坑

    11-17
    赞同 1
    回复