这几天在集成微信JSSDK支付,由于文档模糊,调试报错信息少,折腾了好久才终于搞定了,下面是js代码
//下面这些代码块是在ajax回调函数中,data是服务端返回的数据,wxSign含有签名信息
if (!data.success) {
alert("pay failed");
}
var wxSign = data.wxSign;
//微信js支付方式1
wx.chooseWXPay({
timestamp: wxSign.timestamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr: wxSign.nonceStr, // 支付签名随机串,不长于 32 位
package: wxSign.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
signType: wxSign.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
paySign: wxSign.paySign, // 支付签名
success: function (res) {
// 支付成功后的回调函数
alert("success pay:" + JSON.stringify(res));
}
});
//微信js支付方式2
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId": "wx12345678", //公众号名称,由商户传入
"timeStamp": wxSign.timestamp, //时间戳,自1970年以来的秒数
"nonceStr": wxSign.nonceStr, //随机串
"package": wxSign.package,
"signType": wxSign.signType, //微信签名方式:
"paySign": wxSign.paySign //微信签名
},
function(res) {
alert("pay result:"+JSON.stringify(res));
if (res.err_msg == "get_brand_wcpay_request:ok") {
} // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。
}
);
官方推荐是用方式1,经过测试方式2也可以用。调试过程中方式1给出的错误信息非常少,基本没用处,我是用方式2来调试的,信息较为详细。
其中方式1的文档上关于签名是这么描述的
“prepay_id 通过微信支付统一下单接口拿到,paySign 采用统一的微信支付 Sign 签名生成方法,注意这里 appId 也要参与签名,appId 与 config 中传入的 appId 一致,即最后参与签名的参数有appId, timeStamp, nonceStr, package, signType。“
可按照上面的做确总是报错,后面才知道要加上 &key="+key 再MD5签名才是ok的,这里key是微信商户号申请时的key。另外要注意后端的sign生成过程中,变量名是驼峰式的,而前端是全部小写,以下附上java代码
/**
* @param appId
* @param prepayId 微信统一下单接口返回的prepay_id
* @return
*/
public static WXJsPaySignInfo sign(String appId, String prepayId){
long timeStamp = System.currentTimeMillis() / 1000;
String packages = "prepay_id="+prepayId;
String nonceStr = RandomStringUtils.randomAlphanumeric(30);
String signType = "MD5";
String msg = List.of("appId="+appId, "timeStamp="+timeStamp, "nonceStr="+nonceStr, "package="+packages, "signType="+signType)
.sorted().mkString("&")+"&key="+PayConfig.getInstance().getWeixin().getKey();
String sign = DigestUtils.md5Hex(BytesUtil.getUtf8Bytes(msg)).toUpperCase();
WXJsPaySignInfo info = new WXJsPaySignInfo();
info.set_package(packages);
info.setNonceStr(nonceStr);
info.setPaySign(sign);
info.setSignType(signType);
info.setTimestamp(timeStamp);
return info;
}
另外,关于支付目录,也需要注意
比如你设置的支付目录为 http://mysite.com/order/
则weixin jssdk的代码必须在以下1,2页面里,3不行
1. http://mysite.com/order
2. http://mysite.com/order/?id=1
3. http://mysite.com/order?id=1 #注意这个地址,微信sdk支付会失败,这也是个深坑
以下是方式1和方式2的文档,感觉很混乱,没一个统一的文档说明,第三方根本不知道该用哪个。
附:
方式1文档:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
方式2文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6