微信支付-加密、解密参数。验证签名方法。

时间:2024-03-03 13:48:16

微信并没有给ASP.net用户提供一个很好的实例,只好苦心研究,经过一个下午的努力和N次测试,终于知道如何解密和验签notify的数据了,以下是我实现的代码,好东西需分享给各位朋友:(以下的商户编号我已经修改过,所以没有返回true,请根据自己的实际数据测试)

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Drawing;

using System.Drawing.Imaging;

using System.IO;

using System.Drawing.Drawing2D;

using Ganxike.Bll;

using Ganxike.Entity;

using System.Text;

using System.Security.Cryptography;

  

namespace Ganxike.Front

{

    public partial class Test : System.Web.UI.Page

    {

        protected void Page_Load(object sender, EventArgs e)

        {

            //bank_billno:201407013021057579

            //bank_type:2011 //付款银行代号

            //discount:0 //折扣价格(如果有)

            //fee_type:1 //币种

            //input_charset:GBK //编码字符

            //notify_id:cEBCIhJpi4A6JrwjzYjarrY4-y04msE2T7Ixq0U19wcntbPlOXrtshGlKcEhGsN-uC78fnIcPi6mIFpl2UfDxW3R1yPv7yRQ //通知ID

            //out_trade_no:2033179023 //商户订单号

            //partner:1218656301 //商户号

            //product_fee:1 //物品费用(分)

            //sign:24897219B33E59DC7FA49FEC3CE0D1C3 //签名

            //sign_type:MD5 //签名方式

            //time_end:20140701145333 //支付完成时间

            //total_fee:1 //总金额(分)

            //trade_mode:1 //交易模式(1即时到帐)

            //trade_state:0 //交易状态(0成功)

            //transaction_id:1218656301201407013164175338 //订单号

            //transport_fee:0 //物流费用

  

            Dictionary<string, string> parameters = new Dictionary<string, string>();

            parameters.Add("bank_billno", "201407013021057579");

            parameters.Add("bank_type", "2011");

            parameters.Add("discount", "0");

            parameters.Add("fee_type", "1");

            parameters.Add("input_charset", "GBK");

            parameters.Add("notify_id", "cEBCIhJpi4A6JrwjzYjarrY4-y04msE2T7Ixq0U19wcntbPlOXrtshGlKcEhGsN-uC78fnIcPi6mIFpl2UfDxW3R1yPv7yRQ");

            parameters.Add("out_trade_no", "2033179023");

            parameters.Add("partner", "1218656301");

            parameters.Add("product_fee", "1");

            parameters.Add("sign_type", "MD5");

            parameters.Add("time_end", "20140701145333");

            parameters.Add("total_fee", "1");

            parameters.Add("trade_mode", "1");

            parameters.Add("trade_state", "0");

            parameters.Add("transaction_id", "1218656301201407013164175338");

            parameters.Add("transport_fee", "0");

  

            //将所有参数按Key字母排序

            string content = GetSignContent(parameters);

  

            Response.Write(VerifySignature(content, "24897219BABCDC7FA49DECE0D1C3", "20a01775b1234714920a47a6321cb292"));

        }

  

        /// <summary>

        /// 验证签名

        /// </summary>

        /// <param name="content">排序后的所有参数(不包括sign参数)</param>

        /// <param name="sign">合作商传过来的sign签名(对参数加密后的MD5)</param>

        /// <param name="ourKey">我们用于签名的密钥(用于解密的一串字符)</param>

        /// <returns></returns>

        public static bool VerifySignature(String content, String sign, String ourKey)

        {

            string signResult = WXPayMD5(content + "&key=" + ourKey).ToUpper();

            return (sign == signResult);

        }

  

  

        /// <summary>

        /// MD5加密

        /// </summary>

        /// <param name="s">需加密的字符</param>

        /// <returns></returns>

        public static String WXPayMD5(String s)

        {

            char[] hexDigits = { \'0\', \'1\', \'2\', \'3\', \'4\', \'5\', \'6\', \'7\', \'8\', \'9\',\'A\', \'B\', \'C\', \'D\', \'E\', \'F\' };

            try

            {

                byte[] btInput = System.Text.Encoding.Default.GetBytes(s);

                // 获得MD5摘要算法的 MessageDigest 对象

                MD5 mdInst = System.Security.Cryptography.MD5.Create();

                // 使用指定的字节更新摘要

                mdInst.ComputeHash(btInput);

                // 获得密文

                byte[] md = mdInst.Hash;

                // 把密文转换成十六进制的字符串形式

                int j = md.Length;

                char[] str = new char[j * 2];

                int k = 0;

                for (int i = 0; i < j; i++)

                {

                    byte byte0 = md[i];

                    str[k++] = hexDigits[(int)(((byte)byte0) >> 4) & 0xf];

                    str[k++] = hexDigits[byte0 & 0xf];

                }

                return new string(str);

            }

            catch (Exception e)

            {

                Console.Error.WriteLine(e.StackTrace);

                return null;

            }

        }

  

  

        /// <summary>

        /// 将字典所有值按Key字母顺序合并成字符串

        /// </summary>

        /// <param name="parameters">字典类</param>

        /// <returns>字符串</returns>

        public static string GetSignContent(IDictionary<string, string> parameters)

        {

            // 第一步:把字典按Key的字母顺序排序

            IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters);

            IEnumerator<KeyValuePair<string, string>> dem = sortedParams.GetEnumerator();

  

            // 第二步:把所有参数名和参数值串在一起

            StringBuilder query = new StringBuilder("");

            while (dem.MoveNext())

            {

                string key = dem.Current.Key;

                string value = dem.Current.Value;

                if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value))

                {

                    query.Append(key).Append("=").Append(value).Append("&");

                }

            }

            string content = query.ToString().Substring(0, query.Length - 1);

  

            return content;

        }

    }

}