最近接触了一些比较新奇的东西,记录一下php
先贴出微信官方的API地址,感觉一下微信的魅力。。。html
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6java
了解完微信下载帐单的一些注意事项以后,我们正式开始数据库
下面是具体实现:apache
先贴出主方法,其余工具类会有具体说明:json
public static void main(String[] args) throws Exception { // downloadBill(); } public static void downloadBill() throws Exception { //这里的MyConfig工具类是本身封装的一些配置,为了方便本身使用,你们能够跳过这一步 MyConfig myConfig = new MyConfig(); SortedMap<Object,Object> parameters =new TreeMap<Object,Object>(); //这里面的value值,你们本身根据本身的微信商户参数配置一下 parameters.put("appid", myConfig.getAppID());//appid parameters.put("mch_id", myConfig.getMchID());//商户号 parameters.put("nonce_str", CreateNoncestr());//随机字符串 parameters.put("bill_date", "20180125");//对帐单日期 parameters.put("bill_type", "ALL");//对帐单类型 //这里调用方法生成微信须要的签名(这里是一个坑点,当时在作微信退款的时候由于签名不符合规范被卡一天时间) String sign = createSign("utf-8", parameters);//签名 parameters.put("sign", sign); //这里的getRequestXml方法是转xml的工具方法,下面我会贴出来 String reuqestXml = getRequestXml(parameters); /** * 这里的CommonUtil是一个https通用工具类,我也会在下面贴出来 * download_bill_url是微信官方提供的对帐单下载地址 * download_bill_url = “https://api.mch.weixin.qq.com/pay/downloadbill“ */ String result=CommonUtil.httpsRequest(myConfig.download_bill_url, "POST", reuqestXml); //微信对帐单生成时间是第二天的9点以后,因此查询日期为当天时,错误信息提示日期无效 if(result.startsWith("<xml>")){ System.out.println(result); System.out.println("无订单"); }else { String tradeMsg = result.substring(result.indexOf("`")); String tradeInfo = tradeMsg.substring(0, tradeMsg.indexOf("总")).replace("`", "");// 去掉汇总数据,而且去掉'`' String tradeInfo = tradeMsg.substring(0,tradeMsg.indexOf("总")); String tradeTotalMsg =tradeMsg.substring(tradeMsg.indexOf("总")); String tradeTotalInfo =tradeTotalMsg.substring(tradeTotalMsg.indexOf("`")); System.out.println("result----->"+result); System.out.println("tradeMsg----->"+tradeMsg); System.out.println("tradeInfo----->"+tradeInfo); System.out.println("tradeTotalMsg----->"+tradeTotalMsg); System.out.println("tradeTotalInfo----->"+tradeTotalInfo); //最后一栏是费率,里面以%结尾,以此做为切割目标,方便操做存数据库 String[] tradeArray = tradeInfo.split("%"); List<Map<String, Object>> resultList = new ArrayList<>(); for(int i = 0;i < tradeArray.length;i++) { String[] tradeDetailArray = tradeArray[i].split(","); Map<String, Object> map = new HashMap<>(); /** * 这里我取了几个对我来讲用处较大的几个字段 * 详细字段的话,你们能够参考一下这里,或本身看控制台打印结果 * https://www.cnblogs.com/mgqy/articles/7657483.html */ map.put("readeTime", tradeDetailArray[0]);//交易时间 map.put("appid", tradeDetailArray[1]);//公众号ID map.put("mchId", tradeDetailArray[2]);//商户号 map.put("transactionId", tradeDetailArray[5]);//微信订单号 map.put("outTradeNo", tradeDetailArray[6]);//商户订单号 map.put("openid", tradeDetailArray[7]);//用户标识(openid) map.put("tradeState", tradeDetailArray[9]);// 交易状态 map.put("tradeBank", tradeDetailArray[10]);// 付款银行 map.put("totalFee", tradeDetailArray[12]);//总金额 map.put("refundFee", tradeDetailArray[16]);//退款金额 map.put("tradeName", tradeDetailArray[20]);// 商品名称 map.put("poundage", tradeDetailArray[22]);//手续费 resultList.add(map); } System.out.println("resultList--->"+resultList); } }
下面是一些用到的工具类和方法:api
一、随机字符串生成方法微信
/** * 随机字符串 * @return */ public static String CreateNoncestr() { String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; String res = ""; for (int i = 0; i < 16; i++) { Random rd = new Random(); res += chars.charAt(rd.nextInt(chars.length() - 1)); } return res; }
二、编写签名方法app
/** * 编写签名 * @param charSet * @param parameters * @return * @throws Exception */ public static String createSign(String charSet,SortedMap<Object,Object> parameters) throws Exception{ MyConfig myconfig = new MyConfig(); StringBuffer sb = new StringBuffer(); Set es = parameters.entrySet(); Iterator it = es.iterator(); while(it.hasNext()) { 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=" + myconfig.getKey()); // String sign = MD5Util.MD5Encode(sb.toString(), charSet).toUpperCase(); String sign = MD5Util.MD5Encode(sb.toString(), charSet).toUpperCase(); // String sign = MD5.MD5Encode(sb.toString(), charSet).toUpperCase(); return sign; }
三、转xml格式方法dom
/** * 转为xml格式 * @param parameters * @return */ public static String getRequestXml(SortedMap<Object,Object> parameters){ StringBuffer sb = new StringBuffer(); sb.append("<xml>"); Set es = parameters.entrySet(); Iterator it = es.iterator(); while(it.hasNext()) { Map.Entry entry = (Map.Entry)it.next(); String k = (String)entry.getKey(); String v = (String)entry.getValue(); if ("attach".equalsIgnoreCase(k)||"body".equalsIgnoreCase(k)||"sign".equalsIgnoreCase(k)) { sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">"); }else { sb.append("<"+k+">"+v+"</"+k+">"); } } sb.append("</xml>"); return sb.toString(); }
四、https通用工具类
import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.ConnectException; import java.net.URL; import javax.net.ssl.HttpsURLConnection; import org.apache.log4j.Logger; import net.sf.json.JSONObject; /** * https通用工具类 */ public class CommonUtil { private static Logger log = Logger.getLogger(CommonUtil.class); public static JSONObject httpsRequestToJsonObject(String requestUrl, String requestMethod, String outputStr) { JSONObject jsonObject = null; try { String buffer = httpsRequest(requestUrl, requestMethod, outputStr); jsonObject = JSONObject.fromObject(buffer.toString()); } catch (Exception e) { log.error("https请求异常:"+e.getMessage()); } return jsonObject; } public static String httpsRequest(String requestUrl, String requestMethod, String outputStr){ try { URL url = new URL(requestUrl); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); // 设置请求方式(GET/POST) conn.setRequestMethod(requestMethod); conn.setRequestProperty("content-type", "application/x-www-form-urlencoded"); // 当outputStr不为null时向输出流写数据 if (null != outputStr) { OutputStream outputStream = conn.getOutputStream(); // 注意编码格式 outputStream.write(outputStr.getBytes("UTF-8")); outputStream.close(); } // 从输入流读取返回内容 InputStream inputStream = conn.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str = null; StringBuffer buffer = new StringBuffer(); while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } // 释放资源 bufferedReader.close(); inputStreamReader.close(); inputStream.close(); inputStream = null; conn.disconnect(); return buffer.toString(); } catch (ConnectException ce) { System.out.println("链接超时:{}"); } catch (Exception e) { System.out.println("https请求异常:{}"); } return null; } }
到此,微信下载对帐单功能就实现了
代码写的很差之处,请你们多多包涵并提出宝贵意见 937017870@qq.com