微信支付签名遇到的坑
来源:互联网 发布:数据库系统的二级映射 编辑:程序博客网 时间:2024/05/16 14:14
这两天做了下微信支付,其中也遇到不少问题,记录下,以免下次重复踩坑。
结合我们项目使用场景,我选择了扫码支付 模式二 (具体开发步骤见 官方文档 扫码支付模式二)
微信下单方法:
SortedMap<Object,Object> param = new TreeMap<Object,Object>();//公众号IDparam.put("appid", appid);//订单主题param.put("body", body);//商户号param.put("mch_id", mch_id);//随机字符串param.put("nonce_str", randomStr);//回调地址param.put("notify_url", NOTIFY_URL);//商户订单号param.put("out_trade_no",out_trade_no);//客户端IPparam.put("spbill_create_ip",ip);//金额param.put("total_fee",changeY2F(ppd.getPartyFee().toString()));//订单类型param.put("trade_type", "NATIVE");String sign = createSign(param, apiKey);//签名param.put("sign", sign);System.out.println("========== sign: " + sign);String xml = getRequestXML(param); System.out.println("========== xml: " + xml);String content = HttpClinetUtil.sendPost(UNIFORMORDER, new String(xml.getBytes(),"ISO8859-1"));System.out.println("==========content: " + content);JSONObject result_xml = JSONObject.parseObject(xml2JSON(content)) ;System.out.println("================return_msg: " +result_xml.get("return_msg"));String return_code = result_xml.getString("return_code");String result_code = result_xml.getString("result_code");
由于微信total_fee 参数要求是具体到多少分 (整数),这里我们需要将金额进行转换 changeY2F 具体实现如下 (直接引用了网上的 不需要重复造轮子)
public String changeY2F(String amount) { String currency = amount.replaceAll("\\$|\\¥|\\,", ""); // 处理包含, ¥ // 或者$的金额 int index = currency.indexOf("."); int length = currency.length(); Long amLong = 0l; if (index == -1) { amLong = Long.valueOf(currency + "00"); } else if (length - index >= 3) { amLong = Long.valueOf((currency.substring(0, index + 3)).replace(".", "")); } else if (length - index == 2) { amLong = Long.valueOf((currency.substring(0, index + 2)).replace(".", "") + 0); } else { amLong = Long.valueOf((currency.substring(0, index + 1)).replace(".", "") + "00"); } return amLong.toString(); }
随机字符串的生成方法:
// 随机字符串生成 public static String getRandomString(int length) { // length表示生成字符串的长度 String base = "abcdefghijklmnopqrstuvwxyz0123456789"; Random random = new Random(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < length; i++) { int number = random.nextInt(base.length()); sb.append(base.charAt(number)); } return sb.toString(); }
生成签名方法:
//创建md5 数字签证 public String createSign(SortedMap<Object, Object> parame,String apiKey) throws Exception{ StringBuffer buffer = new StringBuffer(); Set set = parame.entrySet(); Iterator iterator = set.iterator(); while(iterator.hasNext()){ Map.Entry entry = (Map.Entry) iterator.next(); String key = (String)entry.getKey(); Object value = (String)entry.getValue(); if(null != value && !"".equals(value) && !"sign".equals(key) && !"key".equals(key)){ buffer.append(key+"="+value+"&"); } } buffer.append("key="+apiKey); System.out.println("============ " + buffer.toString()); String sign = MD5(buffer.toString()).toUpperCase(); System.out.println("签名参数:"+sign); return sign; }
MD5 我直接引用了官方sdk的方法:
public String MD5(String data) throws Exception { java.security.MessageDigest md = MessageDigest.getInstance("MD5"); byte[] array = md.digest(data.getBytes("UTF-8")); StringBuilder sb = new StringBuilder(); for (byte item : array) { sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3)); } return sb.toString().toUpperCase(); }
生成xml请求参数方法:
public static String getRequestXML(SortedMap<Object, Object> parame){ StringBuffer buffer = new StringBuffer(); buffer.append("<xml>"); Set set = parame.entrySet(); Iterator iterator = set.iterator(); while(iterator.hasNext()){ Map.Entry entry = (Map.Entry) iterator.next(); String key = (String)entry.getKey(); String value = (String)entry.getValue(); //过滤相关字段sign if("sign".equalsIgnoreCase(key)){ buffer.append("<"+key+">"+"<![CDATA["+value+"]]>"+"</"+key+">"); }else{ buffer.append("<"+key+">"+value+"</"+key+">"); } } buffer.append("</xml>"); return buffer.toString(); }这里需要注意的是 参数排序需要安装ascii码升序排列 即 a b c 这个顺序
这里一个遇到一个大坑,一直签名错误,同样的参数在官网签名验证可以通过,但是调用接口就返回乱码,经过各种尝试 还是不行 (参数包含中文时候) 后来发现这里需要
转码为 ISO8859-1
最后就是对返回xml数据的解析了
public static String xml2JSON(String xml) { JSONObject obj = new JSONObject(); try { InputStream is = new ByteArrayInputStream(xml.getBytes("utf-8")); // 读取输入流 SAXReader reader = new SAXReader(); Document document = reader.read(is); // 得到xml根元素 Element root = document.getRootElement(); // 得到根元素的所有子节点 List<Element> elementList = root.elements(); for (Element e : elementList) obj.put(e.getName(), e.getText()); return obj.toString(); } catch (Exception e) { e.printStackTrace(); return null; } }
核心代码就这么多了,具体过程官方文档给的很详细,这里就不多做累述了
关键点就是签名算法 以及最后对请求参数的转码和金额的单位(分)
阅读全文
0 0
- 微信支付签名遇到的坑
- 微信支付遇到签名失败怎么办?
- Android微信支付遇到的坑
- 微信支付遇到过的坑
- Android微信支付遇到的坑
- 微信支付遇到的坑们
- 微信支付遇到的坑
- 微信支付遇到的坑
- 微信支付遇到的坑
- 微信支付遇到的坑
- 微信支付---签名
- 微信支付签名
- 微信支付遇到的坑(移动支付)
- 微信支付—关于sgin签名的坑
- 微信支付签名算法的一些坑……
- 支付宝和微信的签名
- 微信支付签名错误
- 微信支付签名方法
- CString类常用方法----Left(),Mid(),Right()……
- PAT 1079 Total Sales of Supply Chain(树遍历+BFS)
- PHP将Excel导入数据库及数据库数据导出至Excel的方法 亲测
- 单例模式 (二) 延迟加载/"懒汉模式" —— 使用DCL双检查锁机制
- Teamcenter11.2.3.1 安装时遇到的TreeCache无法创建的问题
- 微信支付签名遇到的坑
- Unity 脚本之间的消息传递,事件管理
- JavaScript(3)
- ios10.1上 交叉编译 boost1_64_0
- 第一个annotation版的HelloWorld
- 237. Delete Node in a Linked List(C语言版本)
- 相对路径面试题
- php 发送邮件教程 发送邮件附带附件 利用PHPMailer发送邮件教程
- Qt自定义加载控件Spinner