微信支付签名失败与回调无响应的坑

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xxdddail/article/details/88524571

一、按微信官方的c#部分demo的代码,付款或退款时签名失败,总结了一下,大致以下几种可能。

1.参数没有按官方的接口传输。

2.参数正常,但转换成xml传输时,字符串放到CDATA内,没有放到XML节点中,实际上字符串放到CDATA和XML节点中都是可行的。官方的demo是放到CDATA中,而官方文档是放到XML节点中。所以严格来说,这个不算是坑。

3.按官方demo的代码,在生成签名时makeSign方法,用的是x2,注意x是小写,导致转换出的签名是小写的,实际上是用大写的X,转换出的签名才是大写的,这是一个巨坑。

4.使用了cert证书来发起https请求,但请求总是失败,可能是iis站点的应用程序池使用的是ApplicationPoolIdentity,导致读取cert证书时出错,在应用程序池上右键->高级设置->标识中切抱为LocalSystem.

5.cert的证书没有安装,直接双击从微信公众号后台下载的证书安装即可,安装时建议选择【本地计算机】,而不是【当前用户】。证书密码默认是商户号。

6.参数中传的ip是服务器的ip,但调试时却在本地,导致签名失败。建议可以放到服务器中试跑一下,然后输出日志来查看情况。

7.使用的支付密码不对,建议重新生成一个。

8.cert证书的密码不对,默认是商户号。

9.支付的额度太小,官方说明是要大于0.1元,建议使用1元。要注意1元传的是100(单位是分)

10.数据中含有中文,签名出错。只要将签名算法的编码改成UTF-8即可。官方代码MD5用了UTF-8,但是CalcHMACSHA256Hash却用的是Encoding.Default,这是个巨坑。

二、按微信官方的c#部分demo的代码,付款、退款、查询都没有问题,就是付款完了之后没有回调,总结了一下,大致以下几种可能。

1.微信公众号的管理后台需要设置授权的目录,必须是http或https开始的完整站点目录位置,比如https://www.xxx.com/WeiXin。回调的页面WXPayNotify.aspx就放到WeiXin目录下,在传参数notify_url时传的是https://www.xxx.com/WeiXin/WXPayNotify.aspx。

2.使用了https站点。windows下的站点,如果使用了https,特别是多个https证书的时候,需要对sni进行相应的设置,否则回调会失败。要确认这个问题,可以将站点先换成http(换的时候记得在微信公众号的管理后台将授权目录也改成https的),然后测试一下。我在项目中碰到的就是这个问题。原先用http站点没有问题的,后来因为升级改成了https,结果导致回调失败了。可以参考该文章https://blog.csdn.net/u010067685/article/details/86481497

3.签名失败导致。

4.退款回调的req_info必须解码才能得到数据,其中payKey是微信后台生成的key(默认是支付商户号),需要md5并转换成小写后才能用AES解密数据,代码如下

       /// <summary>
        /// 解密req_info
        /// </summary>
        /// <param name="payKey">支付key</param>
        /// <returns></returns>
        public string DecryptReqInfo(string payKey)
        {
            if (string.IsNullOrEmpty(req_info) || string.IsNullOrEmpty(payKey))
            {
                return null;
            }
            var keyMd5 = MD5(payKey).ToLower();//必须转换成小写
            var xml = Decrypt256ECB(req_info, keyMd5);
            return xml
        }

        public static string MD5(string source)
        {
            //获取要加密的字段,并转化为Byte[]数组  
            byte[] source= Encoding.UTF8.GetBytes(source);
            //获取加密服务  
            var md5CSP = new MD5CryptoServiceProvider();

            //加密Byte[]数组  
            byte[] resultEncrypt = md5CSP.ComputeHash(source);

            //将加密后的数组转化为字段(普通加密)  
            //string dest =Encoding.ASCII.GetString(resultEncrypt);
            string dest = "";
            foreach (var item in resultEncrypt)
            {
                dest += (item.ToString("X2"));
            }

            return dest;
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="encryptStrOfBase64">加密后的base64字符串</param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string Decrypt256ECB(string encryptStrOfBase64, string key)
        {
            byte[] keyArray = Encoding.UTF8.GetBytes(key);
            byte[] toEncryptArray = Convert.FromBase64String(encryptStrOfBase64);
            RijndaelManaged rDel = new RijndaelManaged();
            rDel.Key = keyArray;
            rDel.Mode = CipherMode.ECB;
            rDel.Padding = PaddingMode.PKCS7;
            ICryptoTransform cTransform = rDel.CreateDecryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
            var str=Encoding.UTF8.GetString(resultArray);
            return str;
        }

5.一笔订单分多次退款,提示余额不足,可先充入一些钱进去,比如1元。原因是发生一笔单拆成多笔来退时,会计算手续费,当所有钱都退完后,手续费才会完全返还到支付商户号的后台。比如1元分两笔0.5元退,第一笔退0.5元后,会计算0.01元的手术费,这样后台其实只剩下0.49元,当第二次再发起0.5元退款时就会提示余额不足。当充了1元,则余额足了,第二笔0.5元退款成功,同时余额会恢复到1元。

猜你喜欢

转载自blog.csdn.net/xxdddail/article/details/88524571
今日推荐