收藏
回答

JSAPI第二次签名到底什么机制?

JSAPI 二次签名的机制到底是什么样的,我已经按照官网与网上的踩坑文章一一排查了,还是报支付验证签名失败,目前可以确认正确的点如下:

  1. appid,mch_id,api_key 是正确的,因为统一下单接口调用成功了。

  2. 二次签名的算法正确,首先因为是直接调用 sdk 里面的 generateSignature 方法,另外也把对应的 5 个参数值通过官网检测网址检验过,得到的值是一样的。

接下来是二次签名的实现方法

    try {
        System.out.println("开始");
        Map<String, String> resp = wxpay.unifiedOrder(data);
        System.out.println("resp; "+resp);
        System.out.println("结束");
 
        Map<String, String> dataSign = new HashMap<String, String>();
        String timeStr=(new Date().getTime()/1000)+"";
        dataSign.put("appId",config.getAppID());
        dataSign.put("timeStamp",WXPayUtil.getCurrentTimestamp()+"");
        dataSign.put("nonceStr", resp.get("nonce_str"));
        dataSign.put("package","prepay_id="+resp.get("prepay_id"));
        dataSign.put("signType","MD5");
        String signStr=WXPayUtil.generateSignature(dataSign, config.getKey(),SignType.MD5);
 
        dataSign.put("paySign",signStr);
        System.out.println("paySign:"+dataSign);
        return dataSign;
    } catch (Exception e) {
        System.out.println("异常");
        e.printStackTrace();
    }
}catch (Exception e){
    e.printStackTrace();
}

二次签名前台程序:

onBridgeReady = (data) => {
  WeixinJSBridge.invoke(
    // 'getBrandWCPayRequest', data,
    'getBrandWCPayRequest', {
      appId: data.appId,
      timeStamp: data.timeStamp,
      nonceStr: data.nonceStr,
      package: data.package,
      signType: 'MD5',
      paySign: data.paySign
    },
    (res) => {
      alert(JSON.stringify(res));
      if (res.err_msg == 'get_brand_wcpay_request:ok') {
        // 使用以上方式判断前端返回,微信团队郑重提示:
        //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
      }
    });
};


请帮忙看看我是不是哪儿遗漏了重要信息?

最后一次编辑于  12-02
回答关注问题邀请回答
收藏

4 个回答

  • 微信支付技术助手1
    微信支付技术助手1
    12-02

    按照以下几点来检查,

    1)你签名中的key,也就是你的API密钥key,这个参数要你们自己到商户平台设置的,设置的规则是32位数字与字母大小写的组合的随机数,不能设置成签名串和参数appsecret,你们有正确设置吗???

    2)检查开放平台对应的包名与签名是否有正确设置。

    https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5 这里有详细的设置说明。

    3)调用支付使用的noncestr这个参数必须和商家服务器调用统一下单接口返回的那个noncestr一致

    4)从预支付订单返回的数据 ,没有重新签名,也会引起这个问题。

    5)重新安装微信后试试。

    =======注意,二次签名也需要加上key


    12-02
    赞同
    回复 1
    • Hanks
      Hanks
      12-02
      你这个第三条,我这第二次签名一直用的新nonceStr,一直也没报错
      12-02
      回复
  • Apr
    Apr
    12-04

    主要问题就是SignType的问题,建议重新封装下WXPay这个类,构造加上SignType参数

    12-04
    赞同 1
    回复
  • Meedx
    Meedx
    12-02

    我记得有一个挺坑的地方,文档上说是用MD5的sign-type,然后实际好像是HMAC-SHA256,要不试试?

    12-02
    赞同 1
    回复 8
    • 斌斌
      斌斌
      12-02
      我改一下试试
      12-02
      回复
    • Meedx
      Meedx
      12-02回复斌斌
      你要看看你下单的时候是否设置了signType
      12-02
      回复
    • 斌斌
      斌斌
      12-02回复Meedx
      我统一下单的时候没有单独设置 signType,稍等一下,我看看能不能把默认的 signType 打印出来看一下
      12-02
      回复
    • 斌斌
      斌斌
      12-02
      刚才打印了一下,默认确实用的是 SHA256,刚才把用到的几处 signtype 都打出来了,已经确认都用了 sha256,不过还是说验证失败
      12-02
      回复
    • Meedx
      Meedx
      12-02回复斌斌
      前端的signType改了吗?

      MPWXPay wxpay = new MPWXPay(mpconfig);
         Map result = wxpay.unifiedOrder(requestData);
         Map resMap = new HashMap<>();

         resMap.put("package", "prepay_id=" + result.get("prepay_id"));
         resMap.put("signType", "HMAC-SHA256");
         resMap.put("nonceStr", result.get("nonce_str"));
         resMap.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
         resMap.put("appId", mpconfig.getAppID());

         String signs = WXPayUtil.generateSignature(resMap, mpconfig.getKey(), SignType.HMACSHA256);
         resMap.put("paySign", signs);
         resMap.remove("appId");
         return resMap;
      这个是我的
      12-02
      1
      回复
    查看更多(3)
  • Hanks
    Hanks
    12-02

    看了好久,好像没有什么问题呀。。。

    https://developers.weixin.qq.com/community/develop/article/doc/000242e804c6186fb679e6c7652813

    12-02
    赞同
    回复 11
    • Hanks
      Hanks
      12-02
      你看下这一行,你重新生成一下,不要用旧的
      12-02
      回复
    • 斌斌
      斌斌
      12-02回复Hanks
      这个不行,最开始我用的是自己生成的,是因为看到下面这个图片的第 3 条才改的,不过效果都是一样的
      12-02
      回复
    • Hanks
      Hanks
      12-02回复斌斌
      都console出来看看吧,前端也console出来,然后再看看服务器那边是否缓存了
      12-02
      回复
    • 斌斌
      斌斌
      12-02
      我把 nonce_str 改成了 sdk 生成,然后也打了一下日志,暂时看不出毛病来,前端也能获取到,另外还按照上面 Meedx 的建议修改了 signtype,也没好使
      12-02
      回复
    • Hanks
      Hanks
      12-02回复斌斌
      Map dataSign =new HashMap();


      你存储对象的地方,用的map,key你用string可以,value试试改成Object ,不要用String
      12-02
      回复
    查看更多(6)
问题标签