前言
接着昨天的写。微信公众号支付开发的第三步,也是最后一步,通过预下单的ID发起支付请求。
通过预下单的ID发起支付请求
获取signature 这里采用SHA-1 加密方法(必为无论新版旧版)
String timestamp = myDate.getTime() / 1000 + "";
String nonce_str = CommonUtil.create_nonce_str();
String string1;
String signature = "";
String jsapi_ticket = WeixinUtil.getjsapi_ticket();
// 注意这里参数名必须全部小写,且必须有序
//jsapi_ticket 每7200秒 更新一次 建议写入进程 自动获取
string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str
+ "×tamp=" + timestamp + "&url=" + url;
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(string1.getBytes("UTF-8"));
signature = CommonUtil.byteToStr(crypt.digest());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
Map<String, String> map = new HashMap<String, String>();
map.put("noncestr", nonce_str);
map.put("timestamp", timestamp);
map.put("signature", signature);
public static String byteToStr(byte[] byteArray) {
String strDigest = "";
for (int i = 0; i < byteArray.length; i++) {
strDigest += byteToHexStr(byteArray[i]);
}
return strDigest;
}
public static String byteToHexStr(byte bytes) {
char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
'B', 'C', 'D', 'E', 'F' };
char[] tempArr = new char[2];
tempArr[0] = Digit[(bytes >>> 4) & 0X0F];
tempArr[1] = Digit[bytes & 0X0F];
String s = new String(tempArr);
return s;
}
注入微信config,这里的参数为上面生成signature的参数值
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: 'wx7c1af8e43fa7304d', // 必填,公众号的唯一标识
timestamp: timestamp, // 必填,生成签名的时间戳
nonceStr: nonceStr, // 必填,生成签名的随机串
signature: signature,// 必填,签名,见附录1
jsApiList: ['chooseWXPay'] // 必填,需要使用的JS接口列表,这里只写支付的
});
再算签名
String nonce = CommonUtil.create_nonce_str().replace("-", "");
Date myDate = new Date();
String timestamp = myDate.getTime() / 1000 + "";
// 再算签名
String newPrepay_id = "prepay_id=" + prepay_id;
String args =
"appId=wx7c1af8e43fa7304d"
+ "&nonceStr=" + nonce
+ "&package=" + newPrepay_id
+ "&signType=MD5"
+ "&timeStamp="+ timestamp //此处timeStamp 为大写 S 。绝对注意
+ "&key=cqutcqutcqutcqutcqutcqutcqutcqut";
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.reset();
md5.update(args.getBytes("UTF-8"));
String paySign = CommonUtil.byteToStr(md5.digest()).toUpperCase();
Map<String, String> map = new HashMap<String, String>();
map.put("noncestr", nonce);
map.put("timestamp", timestamp);
map.put("prepay_id", newPrepay_id);
map.put("paySign", paySign);
调用js 发起微信支付请求,这次数据第二次获取签名的数据值
wx.chooseWXPay({
timestamp : back.timestamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但 最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr : back.noncestr, // 支付签名随机串,不长于 32 位
package : back.prepay_id, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
signType : "MD5", // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
paySign : back.paySign,
success : function(res) {
}
})
遇到的坑
- 获取第一次签名是采用的加密方式是 SHA-1 也不用转换成大写
- 注入weixin.config 时间戳timestamp 中的s为小写 第一次签名是也为小写
- 第二次算签名package的值应该为 “prepay_id=” + prepay_id 前面加上
- 第二次算签名时时间戳timeStamp的S为大写,大写,大写。重要的事情说三遍
- 发起支付请求时各参数为获取第二次签名时的参数值