美文网首页
偶发性微信支付签名失败问题

偶发性微信支付签名失败问题

作者: 昵称被占用最扎心 | 来源:发表于2022-08-30 21:53 被阅读0次

线上环境小程序商城突然出现一部分用户拉不起支付的情况,查询日志发现有大量"签名失败"。

微信统一支付请求返回: 
<xml><return_code><![CDATA[FAIL]]></return_code>
<return_msg><![CDATA[签名错误,请检查后再试]]></return_msg>
</xml>

微信签名是根据支付字符串md5生成的,所以这种偶发性的错误,应该不是md5签名方法的问题。

private String encodeMd5(String inStr) {
        StringBuffer hexValue = new StringBuffer();
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");

            byte[] byteArray = inStr.getBytes("UTF-8");
            byte[] md5Bytes = md5.digest(byteArray);

            for (int i = 0; i < md5Bytes.length; i++) {
                int val = ((int) md5Bytes[i]) & 0xff;
                if (val < 16) {
                    hexValue.append("0");
                }
                hexValue.append(Integer.toHexString(val));
            }
        } catch (Exception e) {
            System.out.println(e.toString());
            e.printStackTrace();
            return "";
        }
        return hexValue.toString();
    }

md5 = MessageDigest.getInstance("MD5") 虽然是创建了一个新的实例,但是仍然有线程安全问题,官方给的是通过md5.digest避免或者换apache有线程安全的md5工具类。本项目中的md5加密是没有线程安全问题的,单独测试过,没有问题。
接着查代码,在生成sign后,最后需要将sign和其他要素组成为一个xml,在这块,用了一个对象转xml方法,核心代码如下:

     public String toXML(Object request) {
        XStream xstreamReq = new XStream(new XppDriver());
        xstreamReq.alias("xml", request.getClass());
        String requestXML = xstreamReq.toXML(request).replace("\n", "").replace("__", "_");
        return requestXML;
    }

在这个方法中,生成的xml的字符串做了两次替换,一次是将换行符去掉,第二次是将两个下划线替换成一个下换线。第一个替换可以理解,第二个替换不知道什么作用,所以去掉后测试下。发现,这样写的目的是简单粗暴的解决对象属性中存在"_"时,转换后的xml文件的标签变成了"__"两个下划线。例如有一个对象的其中一个属性为xx_xxx,xstreamReq.toXML(request) 生成的xml中这个属性的标签成了<xx__xxx></xx__xxx>,而通过.replace("__", "_")可以简单粗暴的将这个问题解决掉。
但是这样写只解决了标签的问题,同时引入了新的bug。微信openID是存在包含“__”两个下划线的情况的,这种情况下,微信的openID被替换成了错误的,而签名是正确的,最终导致签名和xml数据不一致,签名失败。其效果相当于将微信用户openId包含两个下划线的用户拉入了支付黑名单,永远拉不起支付。在网上搜索了下,很多文章都在用上面方法生成最终请求xml做拉起支付请求。

问题找到就好办了,解决xml生成时,因对象属性存在"_",防止生成的xml标签将这类对象属性标签转成“__”两个下划线,解决方案如下:

    public String toXMLNotreplace(Object request) {
        XStream xstreamReq = new XStream(new Xpp3Driver(new NoNameCoder()));
        xstreamReq.alias("xml", request.getClass());
        String requestXML = xstreamReq.toXML(request).replace("\n", "");
        return requestXML;
    }

相关文章

  • 偶发性微信支付签名失败问题

    线上环境小程序商城突然出现一部分用户拉不起支付的情况,查询日志发现有大量"签名失败"。 微信签名是根据支付字符串m...

  • httpclient请求报错

    今天做的线上微信支付出了问题,微信公众号支付--(统一下单失败) 查看原因,在做验证签名的时候报错: java.l...

  • 微信支付,签名失败

    微信支付可能有毒,毒害很多开发的小伙伴,这里做下整理。 1.首先配置支付授权目录(https://pay.weix...

  • iOS 开发-微信支付 支付验证签名失败

    iOS 开发-微信支付 支付验证签名失败 原因:时间戳提交错误 要求 UInt32 in t类型

  • 支付宝和微信支付报错

    支付宝 : 微信: 微信支付验证签名失败可能的原因有两个:一、传给微信sdk的参数中时间戳的格式错误。iOS中时间...

  • 2019-12-26 ios 微信支付签名验证失败

    语言oc 微信支付签名失败,第一先确认商户号,商户秘钥,应用id是否有误. 主要出问题的位置是第二步:sign签名...

  • 微信支付: 签名验证失败

    自己检查签名正确性:https://pay.weixin.qq.com/wiki/doc/api/jsapi.ph...

  • 微信支付-验证签名失败

    1.统一下单接口返回的数据,除去sign字段,其他字段按ASCII码排序,使用MD5再一次签名 2.保证WXPay...

  • 微信支付-支付验证签名失败(iOS)

    在项目中添加微信支付,iOS端的所有东西都已经按照文档搞好了,可就是跳转到微信的时候显示“支付验证签名失败”,可是...

  • iOS-微信支付SDK

    微信支付流程:客户端发起支付请求--->后台和微信SDK交互之后返回带签名的客户端支付信息(之前带签名的支付信息是...

网友评论

      本文标题:偶发性微信支付签名失败问题

      本文链接:https://www.haomeiwen.com/subject/ylhknrtx.html