评论

JSAPI调起支付签名报错排查指引

JSAPI调起支付签名报错排查指引

V2版接口和V3版接口规则差异说明:

- 参数格式:V2接口为XML,V3接口为JSON

- 签名方式:V2接口为MD5或HMAC-SHA256,V3接口为非对称密钥SHA256-RSA

- 回调加密:V2接口无需加密,V3接口为AES-256-GCM加密


本文章主要协助开发者定位JSAPI调起支付返回签名验证失败报错的问题,大家可根据以下步骤逐步排查。

V2版本排查步骤:

步骤一、签名类型与下单时的签名类型不一致

检查调起支付的签名类型是否与下单一致,比如下单是HMAC-SHA256,而调起支付用的是MD5

步骤二、生成签名原串的参数和实际请求参数不一致

检查生成签名串的参数与实际发起请求的参数是否一致,例如生成签名时的时间戳、随机串与实际发起请求的不一致

步骤三、调起支付时的大小写不正确

检查客户端调用时的传参是否正确,注意参数是否区分大小写,参数大小写不正确将会导致签名错误

步骤四、使用的API版本不一致

检查下单和调起支付时使用的API版本是否一致,比如下单用的V2版本的API,而调起支付又参考的是V3的API来实现。

步骤五、使用的商户号信息不一致

检查下单和调起支付时使用的商户号是否一致,比如下单用的是A商户号,而调起支付又使用的是B商户号的信息生成签名

步骤六、使用的key不正确

需要用APIv2密钥生成签名, key设置路径:微信商户平台(pay.weixin.qq.com)-->账户中心-->账户设置-->API安全-->设置API密钥

步骤七、没有重新生成签名

调起支付的签名需要重新按照调起支付文档中规定的参数和要求生成,而不能直接使用统一下单接口的签名值(sign)


V3版本排查步骤:

步骤一、生成签名原串的参数和实际请求参数不一致

检查生成签名串的参数值与客户端实际发起请求的参数值是否一致

步骤二、调起支付时构造签名串的字段和格式不正确

检查调起支付时构造签名串格式是否正确,参与签名字段及格式应是:

步骤三、调起支付时的大小写不正确

检查客户端调用时的传参是否正确

步骤四、使用的API版本不一致

检查下单和调起支付时使用的API版本是否一致,比如调起支付参考的V3的API规则实现,而下单用的V2统一下单。

步骤五、使用的商户号信息不一致

检查下单和调起支付时使用的商户号是否一致,比如下单用的是A商户号,而调起支付又使用的是B商户号的信息生成签名

步骤六、没有重新生成sign

调起支付的签名paySign需要重新按照调起支付文档中规定的参数和要求生成,而不能直接使用下单接口的签名值signature


如通过以上步骤仍然无法解决你的问题,可以在帖子提供关键信息(比如签名工具中的截图和通过postman请求报错)并留言,记得对敏感信息打码,比如key,mch_id,appid等

附录:

1、SDK与相关API规则介绍

2、服务端签名报错排查指引

3、客户端签名报错排查指引



最后一次编辑于  2023-10-25  
点赞 0
收藏
评论

4 个评论

  • 陆Hope丶
    陆Hope丶
    09-20

    我是v3,我的原因是小程序发起支付的签名也用了后端支付接口的签名了,原来微信小程序发起支付填写的签名还需要另外生成,大家注意这个点。

    09-20
    赞同
    回复
  • 严某某
    严某某
    04-07

    您好 微信支付V3调用JSAPi支付 使用官方验签工具提示这个错误 查看明文格式,大小写,密钥格式都验证无误。还是提示这个问题,期待回复

    04-07
    赞同
    回复
  • Jason
    Jason
    02-22

    下单成功,返回 prepay_id 正常。小程序用JSAPI调起支付时扫码,返回“验证签名失败”。使用签名验收工具,在本地验证签名,是验证通过的。 微信只返回"requestPayment:fail cancel",一头雾水>_<。。。"request

    PrivateKey privateKey = wechatPayConfig.getPrivateKey(wechatPayConfig.getKeyPemPath());
    
    // 实例化签名对象
    Signature signature = Signature.getInstance("SHA256withRSA");
    signature.initSign(privateKey);
    signature.update(signStr.getBytes("utf-8"));
    // 生成签名
    byte[] signed = signature.sign();
    
    // 将签名转换为Base64编码的字符串
    String sign = Base64.getEncoder().encodeToString(signed);
    

    Payment:fail cancel"

    02-22
    赞同
    回复 3
    • Jason
      Jason
      02-22
      参数核对了,大小写和商户号也没有问题。
      02-22
      回复
    • 张文建
      张文建
      04-09回复Jason
      解决了吗
      04-09
      回复
    • এ᭄草莓冰激凌ꦿృ༊
      এ᭄草莓冰激凌ꦿృ༊
      07-08
      解决了吗
      07-08
      回复
  • 🍃哎呀
    🍃哎呀
    2023-08-15
    生成和调用的值完全一样:
    timeStamp前-----1692074529
    randoNumber前-----808804b5d1ee4b3695ffb2a2a78d3be9
    timeStamp后-----1692074529
    nonceStr后-----808804b5d1ee4b3695ffb2a2a78d3be9
    后端获取sign代码:
    String sign(byte[] message) throws Exception {
        WxPayConfig config = wxPayService.getConfig();
        //签名方式
        Signature sign = Signature.getInstance("SHA256withRSA");
        //私钥,通过MyPrivateKey来获取,这是个静态类可以接调用方法 ,需要的是_key.pem文件的绝对路径配上文件名
        sign.initSign(config.getPrivateKey());
        sign.update(message);
        System.out.println("sign-----------"+sign.sign());
        return Base64.getEncoder().encodeToString(sign.sign());
    }
    String buildMessage(String appId, String timeStamp,String nonceStr,String prepay_id) {
        System.out.println("timeStamp后-----"+timeStamp);
        System.out.println("nonceStr后-----"+nonceStr);
        return appId + "\n"
                + timeStamp + "\n"
                + nonceStr + "\n"
                + prepay_id + "\n";
    }
    前端调用的大小写也对:
      appId: data.appId, //公众号ID,由商户传入
      timeStamp: data.timeStamp, //时间戳,自1970年以来的秒数
      nonceStr: data.nonceStr, //随机串
      package: data.package,
      signType: data.signType, //微信签名方式:
      paySign: data.paySign, //微信签名
    还是报下面这个错是为什么???
    

    
    
    2023-08-15
    赞同
    回复 1
    • H、
      H、
      2023-08-21
      你这个是js-sdk这一块的签名错误,和拉起微信收银台报错是不一样的。
      invalid signature签名错误。建议按如下顺序检查:
      确认签名算法正确,可用http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 页面工具进行校验。
      确认config中nonceStr(js中驼峰标准大写S), timestamp与用以签名中的对应noncestr, timestamp一致。
      确认url是页面完整的url(请在当前页面alert(location.href.split('#')[0])确认),包括'http(s)://'部分,以及'?'后面的GET参数部分,但不包括'#'hash后面的部分。
      确认 config 中的 appid 与用来获取 jsapi_ticket 的 appid 一致。
      确保一定缓存access_token和jsapi_ticket。
      确保你获取用来签名的url是动态获取的,动态页面可参见实例代码中php的实现方式。如果是html的静态页面在前端通过ajax将url传到后台签名,前端需要用js获取当前页面除去'#'hash部分的链接(可用location.href.split('#')[0]获取,而且需要encodeURIComponent),因为页面一旦分享,微信客户端会在你的链接末尾加入其它参数,如果不是动态获取当前链接,将导致分享后的页面签名失败。
      更加具体的可参考文档:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html
      2023-08-21
      回复
登录 后发表内容