注:本博客为处女作,不到之处望海涵。
很多集成了微信支付的程序猿宝宝们最失望的是,发起支付,支付界面不出来,直接回调了-1.而且还是各种不知名的原因,本文现在填个微信支付的坑,希望遇到问题的宝宝可以解决相对应的问题。
注册api和在manifest中注册相应的类此处省略,网上大把的代码。
支付前提条件,服务端已经成功发起预付单并且返回给了APP,发起预付单是服务端做的,详情在https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
在得到服务端返回的预付信息里,拿到对应的信息发起支付,特别是会话ID:prepayId 和时间戳:timeStamp 不可以手动生成,否则是调不起支付的。
PayReq payReq = new PayReq(); payReq.appId = jsonObject.getString("appid"); payReq.partnerId = jsonObject.getString("mch_id"); payReq.prepayId = jsonObject.getString("prepay_id"); payReq.packageValue = "Sign=WXPay"; payReq.nonceStr = jsonObject.getString("nonce_str"); payReq.timeStamp = jsonObject.getString("timestamp");
这些都有了之后接下来就是我要填的坑了~
payReq.sign
在服务端成功发起预付订单后,本身就带了sign签名,但是,这个sign签名字段我们不能直接拿来使用!!!我们需要自己二次签名,服务端签名的没有包含prepayId 字段,在我们发起支付的时候我们必须包含prepayId 字段进行二次签名,这样才能使得支付订单信息完整。接下来上代码了。
SortedMap<Object, Object> parameters = new TreeMap<Object, Object>(); parameters.put("appid", payReq.appId); parameters.put("noncestr", payReq.nonceStr); parameters.put("package", payReq.packageValue); parameters.put("partnerid", payReq.partnerId); parameters.put("prepayid", payReq.prepayId); parameters.put("timestamp", payReq.timeStamp); String characterEncoding = "UTF-8"; String mySign = createSign(characterEncoding, parameters);
把我们需要签名的字段和值加进集合,注意需要按照字母排序。
createSign方法:
public static String createSign(String characterEncoding, SortedMap<Object, Object> parameters) { StringBuffer sb = new StringBuffer(); Set es = parameters.entrySet();// 所有参与传参的参数按照accsii排序(升序) Iterator it = es.iterator(); while (it.hasNext()) { @SuppressWarnings("rawtypes") Map.Entry entry = (Map.Entry) it.next(); String k = (String) entry.getKey(); Object v = entry.getValue(); if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { sb.append(k + "=" + v + "&"); } } sb.append("key="+ your key); //KEY是商户秘钥 String sign = stringToMD5(sb.toString()).toUpperCase(); return sign; }
stringToMD5方法:
public static String stringToMD5(String string) { byte[] hash; try { hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8")); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } catch (UnsupportedEncodingException e) { e.printStackTrace(); return null; } StringBuilder hex = new StringBuilder(hash.length * 2); for (byte b : hash) { if ((b & 0xFF) < 0x10) hex.append("0"); hex.append(Integer.toHexString(b & 0xFF)); } return hex.toString().toUpperCase(); }
最后得到的sign字段再填入支付订单中:
payReq.sign = mySign;
然后可以发起支付了~~
总结:本次填的坑为:预付订单成功生成,APP端成功拿到会话id,但是死活就是调不起支付。希望有的宝宝遇到和我一样的问题从而顺利解决。