JSAPI/小程序支付:后端下单成功但 wx.requestPayment 拉起失败,按这几处排查
JSAPI/小程序支付里,“后端下单成功、返回了 prepay_id,但前端 wx.requestPayment 报 fail / 只闪一下 / 白屏没反应”是最常见的一类问题。它不像回调丢失那么玄,多数是参数单位、appid 归属、签名算法版本这几处对不上。下面按链路拆,给出可直接对照排查的点。
下单成功 ≠ 能拉起收银台
/v3/pay/transactions/jsapi 返回 200 只说明订单创建成功,拿到的 prepay_id 是给前端拉起支付用的凭据。之后能不能弹出微信收银台,取决于三点:
- 下单时几个“身份/金额/订单号”对不对得上;
- 拿到 prepay_id 后,给 wx.requestPayment 的五个参数拼得对不对;
- paySign 用的是不是 v3 的 RSA 算法(别把 v2 的 MD5 习惯带过来)。
任何一个错,前端表现都是 requestPayment:fail,但报错文案未必直白。
先排下单这头的三组“对不上”
如果下单本身就在报 4xx,先把下面三类对清楚:后端就能拦下,不用等前端。
金额单位:分,不是元
amount.total 单位是分,整型、必须大于 0。传 0 或带小数点直接报:
{"code":"PARAM_ERROR","message":"输入源 \"/body/amount/total\" 映射到数值字段\"总金额\"规则校验失败,值低于最小值 1"}
1 元填 100,不是 1.00,字符串也别传。注意接口金额单位是分,但对账单里是元,做对账脚本别再按“都是分”处理。
appid / mchid / openid 归属一致
- appid 必须和 mchid 有绑定,否则报
APPID_MCHID_NOT_MATCH(错误码 268445527)。 - JSAPI/小程序下单必须传
payer.openid,否则报268501013。 - 下单 openid 必须是在同一个 appid 下获取的,跨 appid 会报
OPENID_MISMATCH或268445527。不同 appid 下同一用户的 openid 不同。 - 公众号获取 openid 的网页授权域名要在公众平台配置,否则报
10003 redirect_url 域名与后台配置不一致、10005 此公众号没有这些 scope 权限。
out_trade_no:幂等是“单号”幂等,参数不能变
- 6-32 字符,只能由数字/大小写字母/
_/-/|/*组成,商户号下唯一。 - 第一次下单没支付,第二次用同一单号重试可以,但所有参数(appid、mchid、金额、商品描述)必须和首次完全一致。
- 任何一处不一致,报
OUT_TRADE_NO_USED(403,错误码 268498688“请求重入时参数与首次不一致”)。 - 同一单号不允许换到别的下单接口重复提交。
拿到 prepay_id 后:拉起前核对这四个值和一个签名
wx.requestPayment 的 timeStamp、package、signType、paySign、appid 这几项重点核对:
timeStamp:秒级 10 位字符串,不是毫秒。package:必须是prepay_id=前缀 + 下单返回值。signType:v3 固定RSA;MD5/HMAC-SHA256是 v2 才用。paySign:用 appid、timeStamp、nonceStr、package 四个字段拼待签名串,SHA256 with RSA 结果 Base64;signType不参与签名但必须传。- 签名 appid 要用实际调起支付那个 appid,且与下单一致(服务商对应 sp_appid/sub_appid 之一)。
时效与前端回调不可靠
- prepay_id 有效期 2 小时,超时要拿原参数重新下单换新。
- 下单不传
time_expire,订单默认有效 7 天,超时自动关闭;传了time_expire,用户只能在结束时间前支付,超时需要关单。 wx.requestPayment的 success/fail 只代表拉起过程结果,不能作为支付成功依据,要以你后端查单 + 支付成功回调通知为准。页面展示也走查单,别信前端requestPayment:ok就发权益。
常见 errMsg 对照
requestPayment:fail cancel:用户取消。errno102:小程序支付权限被限制。JSAPI缺少参数appId(JS-SDK):wx.config 注入未成功。- 闪一下没反应:timeStamp 用了毫秒 / signType 用了 MD5 / paySign 的 appid 与下单不一致。
- 下单 4xx:金额单位超范围、归属不一致、out_trade_no 重复。
JSAPI(公众号网页)走 WeixinJSBridge.invoke('getBrandWCPayRequest'),只在内置浏览器有效。
参考文档
未实测部分(具体商户号权限、服务商 sub_appid 绑定)请在商户/公众平台核对。