收藏
回答

小程序支付验证签名失败

问题模块
API和组件



已成功通过统一支付接口获取到prepay_id,使用和统一下单同样的小程序appId和对应的商户API key对appId,nonceStr,package,signType,timeStamp这几个参数进行md5加密,参数传到小程序后调起支付时报支付验证签名失败


相关代码:

public Map getPayInfo(Map data)throws Exception {
   Map unifiedOrder = unifiedOrder(data);
   Map signData = Maps.newHashMap();
   signData.put("appId", this.config.getAppID());
   signData.put("timeStamp", String.valueOf(WXPayUtil.getCurrentTimestamp()));
   signData.put("nonceStr", WXPayUtil.generateNonceStr());
   signData.put("package", "prepay_id=" + unifiedOrder.get("prepay_id"));
   signData.put("signType", WXPayConstants.MD5);
   Map returnData = Maps.newHashMap();
   returnData.put("timeStamp", signData.get("timeStamp"));
   returnData.put("nonceStr", signData.get("nonceStr"));
   returnData.put("package", signData.get("package"));
   returnData.put("signType", signData.get("signType"));
   returnData.put("paySign", WXPayUtil.generateSignature(signData, this.config.getKey()));
   return returnData;
}


md5加密前的串是这样的:

appId=****&nonceStr=2f3c978b0e91435dab8b0f0045665158&package=prepay_id=wx201707141513256189b0503e0006016925&signType=MD5&timeStamp=1500016405&key=****


签名前有加key,签名时的appId和key和统一下单的appId和key是相同的。


md5加密算法没有问题,用微信签名校验工具也核对过了,参数名称检查了很多遍和文档上是一样的。


小程序代码:

var timeStamp = res.payInfo.timeStamp;
var nonceStr = res.payInfo.nonceStr;
var packageInfo = res.payInfo.package;
var signType = res.payInfo.signType;
var paySign = res.payInfo.paySign;
wx.requestPayment({
 'timeStamp': timeStamp,
 'nonceStr': nonceStr,
 'package': packageInfo,
 'signType': signType,
 'paySign': paySign,
 'success': function (res) {
   console.log(res);
 },
 'fail': function (res) {
   console.log(res);
 }
})


到底哪里有问题啊,求助!!!

最后一次编辑于  2017-07-14  (未经腾讯允许,不得转载)
邀请回答
复制链接收藏关注问题回答

13 个回答

  • pz
    pz
    2017-09-02

    我也被坑了n久,完全一样的问题。weixin支付SDK真心不如支付宝支付SDK好用

    2017-09-02
    赞同 11
    回复
  • Tooko
    Tooko
    2017-07-14

    timeStamp生成签名的时候不要转string。发起requestPayment入参的时候前台自己timestamp.toString()。

    2017-07-14
    赞同
    回复
  • 杨木
    杨木
    2017-07-14

    加密还需要增加一个商户key才能验证签名的

    2017-07-14
    赞同
    回复
  • 未那酱
    未那酱
    2017-07-14

    @Tooko

    timeStamp生成签名时不是字符串形式的,可以看我签名前打出来的串中

    appId=****&nonceStr=2f3c978b0e91435dab8b0f0045665158&package=prepay_id=wx201707141513256189b0503e0006016925&signType=MD5&timeStamp=1500016405&key=****

    timeStamp是10位数字形式的。

    我刚刚也尝试了你说的方法但还是签名验证失败。


    @杨木

    md5加密时是有添加key的,在最后

    appId=****&nonceStr=2f3c978b0e91435dab8b0f0045665158&package=prepay_id=wx201707141513256189b0503e0006016925&signType=MD5&timeStamp=1500016405&key=****

    2017-07-14
    赞同
    回复
  • 杨木
    杨木
    2017-07-14

    直接在前端JS试一下看能不能调起支付

    2017-07-14
    赞同
    回复
  • 未那酱
    未那酱
    2017-07-14

    @杨木

    小程序端是能直接调起支付的,但是会弹出支付验证签名失败的提示。

    2017-07-14
    赞同
    回复
  • 杨木
    杨木
    2017-07-14

    是不是一定要转成大写

    2017-07-14
    赞同
    回复
  • Tooko
    Tooko
    2017-07-14

    我以前自己试接口的时候前台的生成签名。你用这个和你自己的签名的对比一下哪不一样吧。肯定哪个熟悉不匹配才验证不通过的

    function paySign(appid, nonceStr, prepay_id, timestamp, key) {
        var sign = ''
        //签名顺序按照ASCII字典序排序
        var signA = "appId=" + appid + "&nonceStr=" + nonceStr + "&package=prepay_id=" + prepay_id + "&signType=MD5&timeStamp=" + timestamp
        var signB = signA + "&key=" + key
        // console.log(signB)
        sign = MD5Util.MD5(signB).toUpperCase()
        return sign
    }

    function getTimestamp() {
        var timestamp = Date.parse(new Date()) / 1000
        return timestamp
    }

    function getNonceStr(len) {
        len = len || 32
        var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678' 
        var maxPos = $chars.length
        var str = ''
        for (var i = 0; i < len; i++) {
            str += $chars.charAt(Math.floor(Math.random() * maxPos))
        }
        return str
    }

    function requestPayment(prepay_id) {
        var timestamp = getTimestamp()
        var nonceStr = getNonceStr(32)
        var paysign = paySign(app.globalData.appId, nonceStr, prepay_id, timestamp, app.globalData.api_key)
        // console.log(paysign)
        wx.requestPayment({
            'timeStamp': timestamp.toString(),
            'nonceStr': nonceStr,
            'package': 'prepay_id=' + prepay_id,
            'signType': 'MD5',
            'paySign': paysign,
            'success': function (res) {
                wx.showToast({ title: '支付成功' })
            },
            'fail': function (res) {
            }
        })
    }

    2017-07-14
    赞同
    回复
  • 未那酱
    未那酱
    2017-07-14

    @杨木

    md5加密完是有转大写的


    @Tooko

    刚刚直接用你的代码试了下在前端签名,但调起支付同样是弹的支付验证签名失败 ,我用同样的参数在后台md5签名结果与前台签名相同,说明签名方法应该没问题,签名参数在前台签名时都是直接用的你的说明签名参数应该也没问题。

    按理说我能用小程序的appId和对应商户的API key调成功统一下单接口,那appId和key应该没有问题啊,为什么用相同的appId和key进行二次签名会出现签名失败呢,我真的不知道该怎么办了。。。。

    2017-07-14
    赞同
    回复 1
    • 管思旭
      管思旭
      2018-09-17

      我也是统一下单成功,可是小程序端调用的时候返回签名错误,你解决了吗?

      2018-09-17
      赞同 11
      回复
  • sven
    sven
    2017-07-25

    java SKD 中的坑, 就是这个问题. NND的. 网页支付的时候就被这个问题坑了, 不过当时我是把 wxpay.isPayResultNotifySignatureValid 的校验默认修改成了HMAC-SHA256 加密算法了. 想不到再接入小程序微信支付的时候, 统一下单能成功, 但是扫描二维码后一直提示签名验证失败!!  你说这bug我找谁理论去. 还好今天一早查了下社区. 发现原来不只我入坑~ 兄台早就踩过了. 哈哈哈.  现在按照你的解决方案, 把统一下单也修改成MD5, 校验也修改成MD5了 就好了.

    2017-07-25
    赞同
    回复