小程序支付调起失败,统一下单返回的prepay_id用不了?

UX乐萱 阅读 25

我在做微信小程序支付,后端已经成功调用了统一下单接口,也拿到了prepay_id,但前端调wx.requestPayment时一直报“支付验证签名失败”。我确认了时间戳、nonceStr这些参数都按文档传了,但还是不行。

这是我的前端调用代码:

wx.requestPayment({
  timeStamp: res.timeStamp, // 后端返回的时间戳字符串
  nonceStr: res.nonceStr,
  package: 'prepay_id=' + res.prepayId,
  signType: 'RSA',
  paySign: res.paySign,
  success(res) {
    console.log('支付成功', res)
  },
  fail(err) {
    console.error('支付失败', err)
  }
})

是不是signType写错了?还是package格式不对?真的搞不懂哪里漏了。

我来解答 赞 4 收藏
二维码
手机扫码查看
1 条解答
极客柯福
这个问题我之前踩过坑,问题大概率出在paySign的生成上。

前端调起支付时的paySign需要单独计算,不能直接用统一下单接口返回的签名。你得在后端重新生成一个签名给前端用。

V3版本的签名串拼接规则是这样的:

appId + "n" + timeStamp + "n" + nonceStr + "n" + "prepay_id=" + prepay_id + "n"

注意最后有个换行符,别漏了。然后用商户私钥做SHA256withRSA签名,再base64编码。

给你一段后端生成的示例代码(假设用的是PHP):

$appId = '你的小程序appid';
$timeStamp = (string)time();
$nonceStr = '随机字符串';
$prepayId = '统一下单返回的prepay_id';

// 拼接签名串,注意每行后面都有换行符
$signStr = $appId . "n" . $timeStamp . "n" . $nonceStr . "n" . "prepay_id=" . $prepayId . "n";

// 用商户私钥签名
openssl_sign($signStr, $signature, $privateKey, OPENSSL_ALGO_SHA256);
$paySign = base64_encode($signature);

// 返回给前端
return [
'timeStamp' => $timeStamp,
'nonceStr' => $nonceStr,
'prepayId' => $prepayId,
'paySign' => $paySign,
];


还有几个容易踩坑的地方提醒一下:

timeStamp必须是字符串类型,而且要和签名时用的值完全一致。我见过有人前端又重新取了时间戳,导致签名验证失败。

signType用RSA是对的,说明你用的是V3接口,配套的签名方式没问题。

另外说个安全相关的,商户私钥文件一定要保管好,不要提交到git仓库,最好放环境变量或者配置中心,防止泄露。还有nonceStr要用加密安全的随机数生成,别用简单的rand()函数,防止被猜出来。

如果还是不行,把后端签名串的内容打印出来核对一下格式,看看换行符是不是真的换行了。
点赞
2026-02-28 15:07