五个必填参数(timeStamp、nonceStr、package、signType、paySign)必须由后端调用微信统一下单接口获取prepay_id后,在服务端按微信签名规则生成并返回,前端不可自行拼接或签名。

uni.requestPayment 的五个必填参数从哪来
这五个参数——timeStamp、nonceStr、package、signType、paySign——**必须由后端生成并返回,前端不能自己拼或签名**。微信支付要求签名在服务端完成,否则 paySign 无效,调用 uni.requestPayment 会直接报错 errCode: -2(用户取消)或静默失败。
常见错误现象:
- 前端自己用 MD5 拼接字符串生成
paySign→ 微信校验不通过,支付弹窗不出现 - 后端返回的
package缺少prepay_id=前缀 →uni.requestPayment报 “invalid package” -
timeStamp传了毫秒时间戳(如Date.now())→ 应为**秒级时间戳**,微信会拒绝
正确做法是:后端调用微信统一下单接口(/pay/unifiedorder),拿到 prepay_id 后,按微信 V3 或 V2 签名规则生成完整参数对象,再返回给前端。
服务端生成 paySign 的关键逻辑(以 Node.js 为例)
签名不是简单哈希,而是对特定字段按字典序拼接 + 密钥后计算。V2 接口要求如下:
- 参与签名字段:
appId、nonceStr、package、signType、timeStamp、mchId(注意:V2 签名需含mchId,但前端uni.requestPayment不需要传它) - 拼接格式:
key1=value1&key2=value2&...&keyN=valueN&key=YOUR_API_KEY - 签名方式:
signType默认为MD5,输出大写 32 位 hex 字符串
示例(Node.js):
const crypto = require('crypto')
function genPaySign(params, apiKey) {
const keys = Object.keys(params).sort()
const str = keys.map(k => `${k}=${params[k]}`).join('&') + `&key=${apiKey}`
return crypto.createHash('md5').update(str, 'utf8').digest('hex').toUpperCase()
}
// 调用时传入 { appId, nonceStr, package, signType, timeStamp, mchId }
// 注意:mchId 是签名必需字段,但不在前端 requestPayment 参数里
uni.requestPayment 调用时容易漏掉的细节
即使后端参数全对,前端调用仍可能失败,原因常藏在以下几点:
-
provider必须写死为"wxpay",不是"weixin"或"wechat" -
package值必须是完整字符串"prepay_id=wx1234567890",开头不能有多余空格或换行 -
timeStamp必须是数字类型(不是字符串),且为**整数秒**,例如Math.floor(Date.now() / 1000) - 调试阶段若用自定义基座,需确认 manifest.json 中已勾选“微信支付”,且 AppID 填写正确(小程序用小程序 AppID,非公众号或开放平台)
典型调用片段:
uni.requestPayment({
provider: 'wxpay',
timeStamp: orderInfo.timeStamp, // number 类型
nonceStr: orderInfo.nonceStr,
package: orderInfo.package, // 必须含 prepay_id=
signType: orderInfo.signType || 'MD5',
paySign: orderInfo.paySign,
success(res) {
console.log('支付成功', res) // res.errMsg === 'requestPayment:ok'
},
fail(err) {
if (err.errMsg === 'requestPayment:fail cancel') {
console.log('用户取消')
} else {
console.error('支付异常', err)
}
}
})
回调地址 notify_url 为什么总收不到通知
微信支付成功后,会向你后端配置的 notify_url 发起 POST 请求,但开发者常遇到“收不到”或“收到空体”。根本原因不是代码没写,而是微信的硬性校验:
- 域名必须已备案,且在微信商户平台「产品中心 → 开发配置 → 支付授权目录」中添加(注意:是目录,不是单个 URL)
- 接口必须支持 HTTPS,且 SSL 证书有效(自签名证书不行)
- 微信回调 body 是 XML 格式,且**不带 Content-Type 头**,部分框架(如 Express)默认不解析无类型的 POST,需显式启用
app.use(express.raw({ type: '*/*' })) - 收到后必须返回
,且 HTTP 状态码为 200,多一个空格或换行都会被当失败重试SUCCESS OK
最易忽略的一点:微信回调是**异步且不可靠的**,不能只依赖它更新订单状态;必须配合后端主动查单(/pay/orderquery)或监听云函数触发事件做兜底。











