P.S:这边先吐槽一下微信,泥特么的API版本赶写得再好一点么?
回归正题。
之前我们进行了预支付。预支付这边的话我大概再讲一下流程。这个也是我这边demo实现的流程。
1、打开一个页面,这个页面里面要包含一个openId,这边的话,可以用微信的snsapi_base的形式,直接跳转页面然后获取到openId后再跳转到支付页面,这样支付页面上就包含了openId了。
2、然后我们可以在跳转到支付页面的时候,对应的把所有的参数以及签名都计算好了,先都传到页面上的隐藏域里。
注意下这边比较坑爹的一点,就是签名。签名和预支付的签名方式是一样的,排序完了之后,还要加上商户的key,再进行MD5加密,这样才算是正确的,下载下来的PDF的API里面只有讲到参数加密,而且如果你没有加上key然后就加密的话,在js的config的时候,也会确认通过,但是最后要调用支付的时候,就会提示商户密匙错误之类的。
3、在支付的时候。用ajax先把隐藏域的参数传到预支付,然后获取prepay_id之后,在后台先将需要的参数都计算好,包含这边的支付接口的paySign的计算(记得加上key再MD5加密!),然后在ajax的success里面调用支付接口即可。(再P.S:注意下这边的计量单位是分,API里面说这边是要整数,但是整数的意思是分。)
JS例子:
$(function(){
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: $("#appId").val(), // 必填,公众号的唯一标识
timestamp: $("#timestamp").val(), // 必填,生成签名的时间戳
nonceStr: $("#nonceStr").val(), // 必填,生成签名的随机串
signature: $("#signature").val(),// 必填,签名,见附录1
jsApiList: ['chooseWXPay'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
$("#submitBut").click(function(){
if (typeof('WeixinJSBridge') == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', callPay, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', callPay);
document.attachEvent('onWeixinJSBridgeReady', callPay);
}
}else{
callPay();
}
});
});
function callPay(){
$.ajax({
type:'POST',
url:'/ui/prePayment.do',
data:{rmbNumber: $("#rmbNumber").val(), openId: $("#openId").val()},
success:function(result){
var json = jQuery.parseJSON(result);
wx.chooseWXPay({
timestamp: json.timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr: json.nonceStr, // 支付签名随机串,不长于 32 位
package: "prepay_id=" + json.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
signType: json.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
paySign: json.paySign, // 支付签名
success: function (res) {
// 支付成功后的回调函数
alert("支付成功!");
}
});
}
});
}
预支付里面,要传给chooseWXPay的paySign的加密片段:
List<String> payList = new ArrayList<String>();
payList.add("appId="+ resultJson.getString("appId"));
payList.add("timeStamp=" + resultJson.getString("timeStamp"));
payList.add("nonceStr=" + resultJson.getString("nonceStr"));
payList.add("package=prepay_id=" + resultJson.getString("package"));
payList.add("signType=" + resultJson.getString("signType"));
//进行排序,字ascii码从小到大
Collections.sort(payList, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
if (o1.compareTo(o2) < 0)
return -1;
if (o1.compareTo(o2) > 0)
return 1;
return 0;
}
});
payList.add("key=7fce91e9d6ca156c8d7105**********");//这边是商户支付密匙
resultJson.put("paySign", MD5Utils.toMD5Code(StringUtils.join(payList, "&")));
问题总结:
1、提示商户密匙错误,要看看对应的密匙在生成sign的时候有没有加入进去。
2、invalid signatrue的错误除了参照API的修改意外,还要注意微信对参数大小写限制得非常严格,可能在他让你输入的参数的地方使用了驼峰法,但是加密的时候却是全小写的形式,还有注意就是有一个地方要获取当前的url来进行加密,记得不要带有端口,也不要包含#后面的所有东西。最后还需要在公众平台的微信支付中开发配置里面进行支付地址的配置。商户平台里面对应的JS调用也要进行JS调用页面的路径配置。
3、吐槽吐槽,再吐槽。自从使用了微信支付,就掉进去了一个连环坑,这个坑爬起来之后,然后还没走两步又噗通一声掉下去另外一个坑,周而复始!