• 00
  • :
  • 00
  • :
  • 00

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

通过认真查看微信提供的加密类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/

 

日志列表:

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

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

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

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

 

posted @ 2014-10-22 14:20  Garson_Zhang  阅读(1098)  评论(0编辑  收藏  举报