zoukankan      html  css  js  c++  java
  • 《微信企业号开发日志》本地调试程序三

    通过认真查看微信提供的加密类WXBizMsgCrypt.cs,终于找到生成msg_signature的方法,并提取出来,用于模拟微信接口的时候自动生成msg_signature,提取结果如下:

          /// <summary>
            /// 计算出msg_Signature
            /// </summary>
            /// <param name="sToken"></param>
            /// <param name="sTimeStamp"></param>
            /// <param name="sNonce"></param>
            /// <param name="sMsgEncrypt"></param>
            /// <returns></returns>
            public static string GetSignature(string sToken, string sTimeStamp, string sNonce, string sMsgEncrypt)
            {
                ArrayList AL = new ArrayList();
                AL.Add(sToken);
                AL.Add(sTimeStamp);
                AL.Add(sNonce);
                AL.Add(sMsgEncrypt);
                AL.Sort(new DictionarySort());
                string raw = "";
                for (int i = 0; i < AL.Count; ++i)
                {
                    raw += AL[i];
                }
    
                SHA1 sha;
                ASCIIEncoding enc;
                string hash = "";
    
                sha = new SHA1CryptoServiceProvider();
                enc = new ASCIIEncoding();
                byte[] dataToHash = enc.GetBytes(raw);
                byte[] dataHashed = sha.ComputeHash(dataToHash);
                hash = BitConverter.ToString(dataHashed).Replace("-", "");
                hash = hash.ToLower();
                return hash;
            }
    
            public class DictionarySort : System.Collections.IComparer
            {
                public int Compare(object oLeft, object oRight)
                {
                    string sLeft = oLeft as string;
                    string sRight = oRight as string;
                    int iLeftLength = sLeft.Length;
                    int iRightLength = sRight.Length;
                    int index = 0;
                    while (index < iLeftLength && index < iRightLength)
                    {
                        if (sLeft[index] < sRight[index])
                            return -1;
                        else if (sLeft[index] > sRight[index])
                            return 1;
                        else
                            index++;
                    }
                    return iLeftLength - iRightLength;
    
                }
            }
    
    
            /// <summary>
            /// 获得消息创建时间
            /// </summary>
            /// <returns></returns>
            public static string GetCreateTime()
            {
                int v =Convert.ToInt32( DateTime.Now.Subtract(new DateTime(1970, 1, 1, 8, 0, 0)).TotalSeconds);
                return v.ToString();
            }
            /// <summary>
            /// 获得随机数Nonce
            /// </summary>
            /// <returns></returns>
            public static string GetNonce()
            {
                Random rd = new Random(Guid.NewGuid().GetHashCode());
    
                int Length = rd.Next(5, 10);//随机长度
    
                string Nonce = String.Empty;
                
                //生成第一位随机数,第一位不能是0,
                Nonce += rd.Next(1, 9).ToString();
    
                for (int i = 1; i < Length; i++)
                {
                    Nonce += rd.Next(0, 9).ToString();
                }
    
                return Nonce;
            }

    有了这个方法我们就可以真正的做出模拟了,(之前模拟回调要从微信回调把参数取出来手动填写,现在不需要了,全部自动生成)

    修改界面如下:

    第一部分一样需要自己填写,2,3,4修改为只读属性,不必用户在自己填写,系统自动生成,

    如果4中的随机字符串等于回调结果的字符串,则表示回调认证成功!

    按钮1.生成回调参数的方法如下:

    WXBizMsgCryptAPI类继承自微信的加密类库WXBizMsgCrypt,代码如下:

       public class URLParam
        {
    
            public string timestamp { get; set; }
            public string nonce { get; set; }
            public string msg_signature { get; set; }
        }
    
        public class WXBizMsgCryptAPI : WXBizMsgCrypt
        {
           
         
    
            URLParam CurrentURLParam;
            public WXBizMsgCryptAPI(string sCorpToken, string sEncodingAESKey, string sCorpID)
                : base(sCorpToken, sEncodingAESKey, sCorpID)
            {
                CurrentURLParam = new URLParam();
            }
    
            #region 生成回调各参数及其XML
    
            /// <summary>
            /// 解密获取的结果
            /// </summary>
            /// <param name="Result"></param>
            /// <returns></returns>
            public string APIResultHandler(string Result)
            {
                XmlDocument CBdoc = new XmlDocument();
                XmlNode CBroot;
    
                CBdoc.LoadXml(Result);
                CBroot = CBdoc.FirstChild;
                string CBsEncryptMsg = CBroot["Encrypt"].InnerText;
                string CBMsgSignature = CBroot["MsgSignature"].InnerText;
                string CBTimeStamp = CBroot["TimeStamp"].InnerText;
                string CBNonce = CBroot["Nonce"].InnerText;
    
                string DecResult = "";
                int i = DecryptMsg(CBMsgSignature, CBTimeStamp, CBNonce, Result, ref DecResult);
                if (i == 0)
                {
                    return DecResult;
                }
                else
                {
                    return i.ToString();
                }
            }
    
            /// <summary>
            /// 微信发送消息参数准备,返回timestamp,nonce,msg_singature
            /// </summary>
            /// <param name="msg">需要发送的消息</param>
            /// <param name="Data">加密后的消息</param>
            public URLParam APIEncryptMsg(string msg, ref string Data)
            {
    
                //刷新一组随机数
                CurrentURLParam.timestamp = CommonTools.GetCreateTime();
                CurrentURLParam.nonce = CommonTools.GetNonce();
    
    
                string sData = "";
                string msg_Signature = "";
                //加密消息并返回新的msg_signature
                APIEncryptMsg(msg, CurrentURLParam.timestamp, CurrentURLParam.nonce, ref sData, ref msg_Signature);//加密并获得Sign
    
                //记录新的msg_Signature
                CurrentURLParam.msg_signature = msg_Signature;
    
                Data = sData;
    
                return CurrentURLParam;
            }
    
            /// <summary>
            /// 加密消息并返回新的msg_signature
            /// </summary>
            /// <param name="msg">需要发送(加密)的数据,微信规定,发送数据前先进行加密处理</param>
            /// <param name="Data">返回加密后的XML</param>
            /// <param name="msg_Signature">返回新的msg_Signature</param>
            /// <returns></returns>
           private  int APIEncryptMsg(string msg, string timestamp, string Nonce, ref string Data, ref string msg_Signature)
            {
                int i = EncryptMsg(msg, timestamp, Nonce, ref Data);
                XmlDocument doc = new XmlDocument();
                XmlNode root;
                string sEncryptMsg;
    
                if (i == 0)//刷新signature
                {
    
                    doc.LoadXml(Data);
                    root = doc.FirstChild;
                    sEncryptMsg = root["Encrypt"].InnerText;
    
                    msg_Signature = CommonTools.GetSignature(m_sToken, timestamp, Nonce, sEncryptMsg);
                }
                return i;
            }
    
            /// <summary>
            /// 获得Encrypt节点
            /// </summary>
            /// <param name="EncryXMLData">通过加密后的XML格式数据</param>
            /// <returns></returns>
            public string APIGetEncrypt(string EncryXMLData)
            {
                XmlDocument doc = new XmlDocument();
                XmlNode root;
                string sEncryptMsg;
    
    
                doc.LoadXml(EncryXMLData);
                root = doc.FirstChild;
                sEncryptMsg = root["Encrypt"].InnerText;
                return sEncryptMsg;
            }
    
            #endregion
        }

    GetEncryptXML()方法代码:

      void GetEncryptXML(string msg, ref string sMsg_EncryptMsg)
            {
                var v = GenerateData.APIEncryptMsg(msg, ref sMsg_EncryptMsg);
    
                //记录生成的URL参数
                txt_msg_signature.Text = v.msg_signature;
                txt_timestamp.Text = v.timestamp;
                txt_nonce.Text = v.nonce;
            }

    按钮事件:

     //获取参数按钮事件
            private void btn_msg_signature_Click(object sender, EventArgs e)
            {
                //先随机生成一个字符串用于回调验证
                string msg = Guid.NewGuid().ToString().Replace("-", "");
                txt_Msg.Text = msg;
    
    
                string Msg_EncryptMsg = "";//加密后的数据
                GetEncryptXML(msg, ref Msg_EncryptMsg);
    
                string Encrypt = GenerateData.APIGetEncrypt(Msg_EncryptMsg);
                //获取到加密后XML的Encrypt节点,URL编码后以Get方式提交
                txt_echostr.Text = System.Web.HttpUtility.UrlEncode(Encrypt);
            }

     GenerateDataWXBizMsgCryptAPI的一个实例

    按钮2,(2.本地回调,请在本地断点调试)的事件代码如下

       //微信首次回调验证按钮事件
            private void btn_CallBackValidate_Click(object sender, EventArgs e)
            {
                string URL = GenerateValidationURL();
                txt_ValidURL.Text = URL;
    
                if (String.IsNullOrEmpty(URL)) return;
    
                txt_ValidBackData.Text = CommonTools.GetWebData(URL);
            }

    本节完成!

    开源项目地址:https://github.com/GarsonZhang/QYWXLocalDebug/

    日志列表:

    《微信企业号开发日志》本地调试程序一

    《微信企业号开发日志》本地调试程序二

    《微信企业号开发日志》本地调试程序三

    《微信企业号开发日志》本地调试程序四

    慎于行,敏于思!GGGGGG
  • 相关阅读:
    星空Password
    股票交易
    【1】博客目录
    事务
    C#基础索引
    C# String
    MSIL
    Evaluation Stack
    Spring源码编译以及导入Intellij IDEA的操作步骤
    WebFlux响应式编程简单示例
  • 原文地址:https://www.cnblogs.com/GarsonZhang/p/4043031.html
Copyright © 2011-2022 走看看