微信对账单接口的使用以及对接口数据的解析方式

来源:互联网 发布:python rectangle 编辑:程序博客网 时间:2024/04/29 01:25

最近公司在做对账单的功能,从来没做过三方接口的我荣幸承包此活大哭,千辛万苦找到https://api.mch.weixin.qq.com/pay/downloadbill这个接口,于是陷入漫长的研究与实验阶段,从网上找了很多的文章,但是并没有帮助解决问题一直显示说我的数据格式错误,我怀疑是拼接参数的时候有问题,为了方便后面有跟我遇到相同问题的同志们,我将我的经验写下来,一来帮助大家使用这个接口,而来帮助自己进行总结,一举两得。。。

第一步:自己找到接口的说明根据说明进行一步步操作,如果期间遇到问题可以查询解决。

1:

接口链接

https://api.mch.weixin.qq.com/pay/downloadbill

2:参数列表,自己找到匹配的数据进行设置。字段名变量名必填类型示例值描述公众账号IDappid是String(32)wx8888888888888888微信分配的公众账号ID(企业号corpid即为此appId)商户号mch_id是String(32)1900000109微信支付分配的商户号设备号device_info否String(32)013467007045764微信支付分配的终端设备号随机字符串nonce_str是String(32)5K8264ILTKCH16CQ2502SI8ZNMTM67VS随机字符串,不长于32位。推荐随机数生成算法签名sign是String(32)C380BEC2BFD727A4B6845133519F3AD6签名,详见签名生成算法对账单日期bill_date是String(8)20140603下载对账单的日期,格式:20140603账单类型bill_type否String(8)ALL

ALL,返回当日所有订单信息,默认值

SUCCESS,返回当日成功支付的订单

REFUND,返回当日退款订单 


3:这个是文档给的参数格式,我就是在这个地方花费不少时间(这个格式需要修改一下)

<xml>
<appid>wx2421b1c4370ec43b</appid>
<bill_date>20141110</bill_date>
<bill_type>ALL</bill_type>
<mch_id>10000100</mch_id>
<nonce_str>21df7dc9cd8616b56919f20d9f679233</nonce_str>
<sign>332F17B766FC787203EBE9D6E40457A1</sign>
</xml> 

第二步:这里我直接贴连接代码,根据代码我细讲

               SortedMap<Object, Object> parameters = new TreeMap <Object, Object>();//用来放置各个所需要的参数,自己对应寻找填写。parameters.put("appid", appid);//appidparameters.put("bill_date", today);//下载对账单的日期,格式:20140603// bill_type:ALL返回当日所有订单信息,默认值SUCCESS返回当日成功支付的订单。REFUND,返回当日退款订单parameters.put("bill_type", "ALL");parameters.put("mch_id", partner);parameters.put("nonce_str", PayCommonUtil.CreateNoncestr());//生成的随机数<span style="font-size:24px;"></span><pre name="code" class="java">这个方法PayCommonUtil.CreateNoncestr()后面贴出。
String sign = PayCommonUtil.createSign("utf-8", parameters);//签名方式parameters.put("sign", sign);String reuqestXml = PayCommonUtil.getRequestXml(parameters);//这个就是将参数拼接成xml格式,具体在代码中展示String result = CommonUtil.httpsRequest(ConfigUtil.DOWNLOAD_BILL_URL, "POST", reuqestXml);//请求方式if (result.startsWith("<xml>")) {// 查询日期为当天时,错误信息提示日期无效System.out.println("无订单");} else {String tradeInfo = tradeMsg.substring(0, tradeMsg.indexOf("总"));//这个参数是把具体的返回值给取出来,去掉了参数名和最后的统计参数和数据,方便后面解析数据使用

tradeInfo = tradeInfo.replaceAll("%", "%,");

<span style="font-size:32px;"><strong>PayCommonUtil.CreateNoncestr()方法展示:</strong></span>
<pre name="code" class="java">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;}
<span style="font-size:32px;">PayCommonUtil.createSign("utf-8", parameters)</span><span style="font-size: 32px; font-family: Arial, Helvetica, sans-serif;">方法展示:</span>
public static String createSign(String characterEncoding, SortedMap<Object, Object> parameters) {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=" + ConfigUtil.API_KEY);//此处的key值自己查找帐号String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();return sign;}

PayCommonUtil.getRequestXml(parameters)方法展示:
<pre name="code" class="java">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)) {<span style="color:#ff0000;">sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");//这个位置就是我说的格式,加上这块后就好用了,感谢这个方法的提供者李欣桦。</span>} else {sb.append("<" + k + ">" + v + "</" + k + ">");}}sb.append("</xml>");return sb.toString();}


第三步:返回数据的格式解析

我自己是想将返回的数据保存到数据库中的,就想将这些数据进行解析,我先寻找规律,发现在费率那个位置的%后面没有逗号,而这个位置正好是一条数据的结尾,于是我将%换成%,问题就是这样解决,代码如下:

tradeInfo = tradeInfo.replaceAll("%", "%,");//这个参数上面讲到过,是处理后的。

public void saveWeiXinRecord(String Str) {String[] stringbuf = null;stringbuf = Str.split(",");for (int i = 0; i < stringbuf.length; i++) {System.out.println(stringbuf[i]);}int num = stringbuf.length / 24;for (int i = 1; i <= num; i++) {for (int j = i * 24 - 24; j < i * 24; j++) {wxMXRecord wxmxRecord = new wxMXRecord();wxmxRecord.setPayTime(stringbuf[j]);j++;wxmxRecord.setPublicId(stringbuf[j]);j++;wxmxRecord.setBussinessno(stringbuf[j]);j++;wxmxRecord.setBussinessnox(stringbuf[j]);j++;wxmxRecord.setMachineno(stringbuf[j]);j++;wxmxRecord.setWxorderId(stringbuf[j]);j++;wxmxRecord.setShorderId(stringbuf[j]);j++;wxmxRecord.setUsertype(stringbuf[j]);j++;wxmxRecord.setTradetype(stringbuf[j]);j++;wxmxRecord.setTradestatus(stringbuf[j]);j++;wxmxRecord.setBank(stringbuf[j]);j++;wxmxRecord.setMoneytype(stringbuf[j]);j++;wxmxRecord.setTotalmoney(stringbuf[j]);j++;wxmxRecord.setRedboxnum(stringbuf[j]);j++;wxmxRecord.setBackorderno(stringbuf[j]);j++;wxmxRecord.setBusbackorderno(stringbuf[j]);j++;wxmxRecord.setBackmoneynum(stringbuf[j]);j++;wxmxRecord.setBackredboxnum(stringbuf[j]);j++;wxmxRecord.setBacktype(stringbuf[j]);j++;wxmxRecord.setBackstatus(stringbuf[j]);j++;wxmxRecord.setProductname(stringbuf[j]);j++;wxmxRecord.setDatebag(stringbuf[j]);j++;wxmxRecord.setShouxufei(stringbuf[j]);j++;wxmxRecord.setFeilv(stringbuf[j]);wxmxRecord.setType("微信");weiXinMXDao.saveOrUpdate(wxmxRecord);}}}
这个就是将这些个参数数据根据逗号分开,存入到数组中,然后循环设置到一个实体对象中,然后执行对象保存即可。


以上有的代码是参考网上的,我的具体思路就是这些,第一次写,有点乱,有不足之处欢迎大家提出,有一些工具代码可以从这下载。点击下载


0 0
原创粉丝点击