uni.requestPayment需后端统一下单返回prepay_id及完整签名参数,前端仅透传;provider必须为"wxpay",timeStamp为字符串,package须含"prepay_id="前缀,paySign由后端生成,真机调试需检查体验者权限、商户号绑定及运行环境。

uni-app里调用uni.requestPayment前必须先获取prepay_id
微信小程序支付不是前端直接发起,而是必须由后端统一下单返回prepay_id,前端再拿这个字段调起支付。很多开发者卡在第一步——直接在前端拼接参数调uni.requestPayment,结果报错requestPayment:fail invalid sign或invalid appid。
关键点在于:uni.requestPayment只负责“唤起微信支付界面”,它不参与签名、不生成订单,所有签名逻辑(包括timeStamp、nonceStr、package、signType、paySign)都得由后端完成并返回,前端原样透传。
- 后端必须使用微信官方
unifiedorder接口下单,返回的result.sign才是有效的paySign -
package字段值形如prepay_id=wx1234567890,不能漏掉prepay_id=前缀 - 前端收到的
timeStamp必须是字符串类型(微信校验严格),后端别用数字类型返回 - 测试时务必用真实微信开放平台绑定的
appid,开发环境用AppID而非AppSecret
小程序端uni.requestPayment参数必须严格对齐微信文档
uni-app封装了各平台支付API,但微信小程序版仍要求字段名、类型、顺序与微信原生一致,否则静默失败或提示fail jsapi error。
常见填错项:
-
provider必须写死为"wxpay"(不是"weixin"或"wechat") -
timeStamp是字符串,不是数字;nonceStr必须是随机32位以内字符串(推荐用Math.random().toString(36).substr(2, 15)生成) -
package字段值必须是"prepay_id=xxx"完整字符串,不能带空格或换行 -
paySign是后端用appId+timeStamp+nonceStr+package+signType+key拼接签名后的结果,前端不能二次计算
示例调用:
uni.requestPayment({
provider: 'wxpay',
timeStamp: res.timeStamp,
nonceStr: res.nonceStr,
package: res.package,
signType: res.signType,
paySign: res.paySign,
success: (res) => {
console.log('支付成功', res)
},
fail: (err) => {
console.error('支付失败', err)
}
})
真机调试时requestPayment无反应或报fail: permission denied
这个错误几乎全是配置问题,和代码关系不大。重点检查三处:
- 小程序后台「开发管理 → 开发者工具」是否已添加当前调试手机号为体验者(未添加则无法调起支付)
- 「微信支付 → 商户号」是否已在小程序后台正确绑定,且状态为“已开通”
- 调用
uni.requestPayment的页面路径是否在app.json或pages.json中声明,且未被tabBar或条件编译屏蔽 - 确保是通过微信客户端打开(扫码或搜索进入),开发者工具里点击“预览”不支持支付
另外,iOS真机偶尔因系统弹窗拦截导致无响应,可加uni.showLoading过渡,避免用户误点多次。
uni-app多端兼容下微信支付不能写死provider
如果项目同时发布到App、H5、小程序,uni.requestPayment的provider值会随平台变化:app用"alipay"或"wxpay"(需配置支付SDK),h5走跳转,只有mp-weixin才真正调微信JSAPI。
建议用条件编译隔离:
// #ifdef MP-WEIXIN
uni.requestPayment({ provider: 'wxpay', ... })
// #endif
// #ifdef APP-PLUS
uni.pay({ provider: 'wxpay', ... })
// #endif
注意:uni.requestPayment在App端实际调用的是uni.pay,行为不一致;H5端必须走后端重定向到https://wx.tenpay.com/...,不能用该API。
最易忽略的是:微信小程序支付回调不经过前端,所有业务状态(如支付成功后跳转、更新订单)必须依赖后端通知(notify_url)或主动轮询订单状态,前端success回调仅表示“用户点了确认”,不代表钱已到账。



















