大佬请绕道!
最开始图方便,使用了PHP的http_build_query来将数组转为字符串,此处会将prepay_id=123456789的等号进行转换成%3D导致签名验证失败。
此处建议使用官方的例子,使用字符串将参数拼接,避免出错。
特别注意timestamp的s后端在签名的时候是大写S,而微信的js-sdk里面wx.chooseWXPay接口调用时是小写。
微信js-sdk文档里面还有一个坑。
wx.chooseWXPay({
timestamp: 0, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr: '', // 支付签名随机串,不长于 32 位
package: '', // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
signType: '', // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
paySign: '', // 支付签名
success: function (res) {
// 支付成功后的回调函数
}
});
调用这个接口居然没有用appId这个参数,不管你怎么调,最后都报支付验证签名失败。
最终在微信支付官方的文档里面看到调用接口有appId,果断加上试了一下。成功了。
你们这都不算什么,你们知道我被什么卡住了两天吗?
我之前对结果native支付,好像没有这么多事,挺顺利的,结果jsapi 卡住了,我是V2版的
//JS端 alert("payparams:" + JSON.stringify(payparams)); WeixinJSBridge.invoke("getBrandWCPayRequest", { "appId": payparams.appId, "nonceStr": payparams.nonceStr, "package": payparams.package, "paySign": payparams.paySign, "signType": payparams.signType, "timeStamp": payparams.timeStamp }, function(res) { if (res.err_msg == "get_brand_wcpay_request:ok") { alert("微信支付成功"); } else if (res.err_msg == 'get_brand_wcpay_request:cancel') { alert('用户取消支付'); } else { alert('支付失败'); } } //java 端 /** * 统一下单 jsapi 方式 * @param orderId 自身订单号 * @param amount 金额:分 * @param description 描述 * @return */ public ResponseMessage unifiedOrderByJsapi(String orderId,int amount,String description,String openid){ try{ Map<String,String> requestData = new HashMap<>(); //商品描述 requestData.put("body",description); requestData.put("openid",openid); requestData.put("appid",config.getAppID()); requestData.put("mch_id",config.getMchID()); requestData.put("nonce_str",WXPayUtil.generateNonceStr()); requestData.put("out_trade_no",orderId); requestData.put("total_fee",String.valueOf(amount)); ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = requestAttributes.getRequest(); String ip = StringUtil.getIp(request); requestData.put("spbill_create_ip",ip); requestData.put("notify_url",notify_url); requestData.put("trade_type","JSAPI"); requestData.put("sign_type", WXPayConstants.MD5); String oneSing = WXPayUtil.generateSignature(requestData,config.getKey(),WXPayConstants.SignType.MD5); requestData.put("sign", oneSing); Map<String,String> responseData = wxPay.unifiedOrder(requestData); if(responseData == null){ return ResponseMessage.error("调用jsapi统一下单失败"); } log.info("调用jsapi统一下单结果:return_code:"+responseData.get("return_code")); log.info("return_msg:"+responseData.get("return_msg")); log.info("result_code:"+responseData.get("result_code")); log.info("err_code:"+responseData.get("err_code")); log.info("err_code_des:"+responseData.get("err_code_des")); if(!"SUCCESS".equals(responseData.get("return_code"))){ return ResponseMessage.error(responseData.get("return_msg")); }else if(!"SUCCESS".equals(responseData.get("result_code"))) { return ResponseMessage.error("请求支付失败:" + responseData.get("err_code") + "-" + responseData.get("err_code_des")); }else{ String prepayId = responseData.get("prepay_id"); Map<String,String> payMap = new HashMap<String, String>(); payMap.put("appId",config.getAppID()); payMap.put("timeStamp", System.currentTimeMillis()/1000 + ""); payMap.put("nonceStr",WXPayUtil.generateNonceStr()); payMap.put("signType", WXPayConstants.MD5); payMap.put("package","prepay_id="+prepayId); String paySign = WXPayUtil.generateSignature(payMap,config.getKey(),WXPayConstants.SignType.MD5); payMap.put("paySign",paySign); return ResponseMessage.success(payMap); } }catch(Exception e){ return ResponseMessage.error("调用微信支付统一下单异常"); } }
参数什么的都没问题,包括签名我也用工具校验过了,最后实在想不明白,我就把签名方式从HMAC-SHA256 改为MD5(包括统一下单的也改了),他竟然成功了
我啥都不想说了(文档里说的清清楚楚,两种都支持)
微信这个jsapi就是个垃圾,,调了几天了,还是签名错误
我按照你说的加了后不行啊
前端timestamp,s一定要小写,文档里面的示例是大写,调了一晚上,感谢题主,微信的文档搞死人
遇到同样的问题,有两种可能,一种就是参数大小写的问题,另一种就是版本问题
遇到了同样的问题,解决过程是 前后端1个1个对比统一参数。小程序后端的加密字段和App的不一致特别注意这几个 appid和appId的区别 payMap.put("appId",); payMap.put("timeStamp",); payMap.put("nonceStr",); payMap.put("signType",); payMap.put("package","prepay_id="+prepayId);
牛啊牛啊,狗样的大小写
就是大小写s问题卡了一天
统一下单完成后,需要返回给前端的参数中的签名paySign ,一定要再次生成!!!!
网页端接口请求参数列表(参数需要重新进行签名计算,参与签名的参数为:appId、timeStamp、nonceStr、package、signType,参数区分大小写。)
详情参考手册
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6