微信下载对账单
最近接手了一个棘手的工作:微信下载对账单。
刚接手完全懵逼,怎么和微信对接啊。然后就是百度。。
终于找到了组织:
微信支付|开发文档 :点击跳转
通过文档我们可以看到,首先是:
1.下载对账单开放接口链接:
https://api.mch.weixin.qq.com/pay/downloadbill
关于应用场景:
商户可以通过该接口下载历史交易清单。比如掉单、系统错误等导致商户侧和微信侧数据不一致,通过对账单核对后可校正支付状态。注意:1、微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账单中,跟原支付单订单号一致;2、微信在次日9点启动生成前一天的对账单,建议商户10点后再获取;3、对账单中涉及金额的字段单位为“元”。4、对账单接口只能下载三个月以内的账单。
2.传入的参数:
接着我们看下传入参数:
其中,微信分配的appId 和 商户号 是自己的。
还有就是需要 去商户平台查自己商户号以及key。这个key主要用在生成签名中。
看一下查詢代码:
SortedMap<Object, Object> parameters = new TreeMap<Object, Object>(); parameters.put('appid', ConfigUtil.APPID); // APPid parameters.put('mch_id', ConfigUtil.MCH_ID); // 商户id // parameters.put('device_info', '');//微信支付分配的终端设备号,填写此字段,只下载该设备号 的对账单 parameters.put('nonce_str', PayCommonUtil.CreateNoncestr()); // 下载对账单的日期,格式:20140603,当前日期前一天。 String billDate = DateUtil.date2Str(DateUtil.addDay(new Date(), -1), 'yyyyMMdd'); parameters.put('bill_date', billDate);// // bill_type:ALL返回当日所有订单信息,默认值SUCCESS返回当日成功支付的订单。REFUND,返回当日退款订单 parameters.put('bill_type', 'ALL'); String sign = PayCommonUtil.createSign('utf-8', parameters); parameters.put('sign', sign); String reuqestXml = PayCommonUtil.getRequestXml(parameters); String result = CommonUtil.httpsRequest(ConfigUtil.DOWNLOAD_BILL_URL, 'POST', reuqestXml);
configUtil 工具类里面要配置APPID,MCH_ID,已及Key 。(注:所有的工具类我都放文章末尾链接里,自己下载即可。)我们需要在ConfigUtil工具类中配置一下:
public final static String APPID = '';//服务号的应用号 public final static String APP_SECRECT = '';//服务号的应用密码 public final static String TOKEN = 'weixinCourse';//服务号的配置token public final static String MCH_ID = '';//商户号 public final static String API_KEY = '';//API密钥 public final static String SIGN_TYPE = 'MD5';//签名加密方式 public final static String CERT_PATH = 'D:/apiclient_cert.p12';//微信支付证书存放路径地址
3.随机数:
我们看一下随机数的生成:
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;
}
4.关于签名:
关于签名,有三点需要注意:
①格式是:utf-8;
②签名类型:MD5以及HMAC-SHA256。默认为MD5,本例也是MD5。
③签名的生成:需要前面几个值(APPID等)以及Key:
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);
String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
return sign;
}
例如这样:
<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>
代码:
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)) { if ('attach'.equalsIgnoreCase(k)||'body'.equalsIgnoreCase(k)) { sb.append('<'+k+'>'+'<![CDATA['+v+']]></'+k+'>'); }else { sb.append('<'+k+'>'+v+'</'+k+'>'); } } sb.append('</xml>'); return sb.toString(); }
之后把xml传给微信对账单接口而后接口会返回值:
5.返回值解析:
关于返回值,这里我详解下:最重要一点是:成功和失败返回数据流类型不一样:成功返回文本格式,失败返回xml格式数据。
①返回失败的情况 :返回xml ,其中无数据也会返回xml 。并且格式是下图。
下面是错误码:
②成功:数据以文本方式返回。
拿微信给的成功返回数据举例:
交易时间,公众账号ID,商户号,子商户号,设备号,微信订单号,商户订单号,用户标识,交易类型,交易状态,付款银行,货币种类,总金额,代金券或立减优惠金额,微信退款单号,商户退款单号,退款金额,代金券或立减优惠退款金额,退款类型,退款状态,商品名称,商户数据包,手续费,费率`2014-11-1016:33:45,`wx2421b1c4370ec43b,`10000100,`0,`1000,`1001690740201411100005734289,`1415640626,`085e9858e3ba5186aafcbaed1,`MICROPAY,`SUCCESS,`CFT,`CNY,`0.01,`0.0,`0,`0,`0,`0,`,`,`被扫支付测试,`订单额外描述,`0,`0.60%`2014-11-1016:46:14,`wx2421b1c4370ec43b,`10000100,`0,`1000,`1002780740201411100005729794,`1415635270,`085e9858e90ca40c0b5aee463,`MICROPAY,`SUCCESS,`CFT,`CNY,`0.01,`0.0,`0,`0,`0,`0,`,`,`被扫支付测试,`订单额外描述,`0,`0.60%总交易单数,总交易额,总退款金额,总代金券或立减优惠退款金额,手续费总金额`2,`0.02,`0.0,`0.0,`0
我们对成功的数据进行处理:
①把第一行表头去掉
代码为:
String tradeMsg = result.substring(result.indexOf('`'));
数据为:
`2014-11-1016:33:45,`wx2421b1c4370ec43b,`10000100,`0,`1000,`1001690740201411100005734289,`1415640626,`085e9858e3ba5186aafcbaed1,`MICROPAY,`SUCCESS,`CFT,`CNY,`0.01,`0.0,`0,`0,`0,`0,`,`,`被扫支付测试,`订单额外描述,`0,`0.60%`2014-11-1016:46:14,`wx2421b1c4370ec43b,`10000100,`0,`1000,`1002780740201411100005729794,`1415635270,`085e9858e90ca40c0b5aee463,`MICROPAY,`SUCCESS,`CFT,`CNY,`0.01,`0.0,`0,`0,`0,`0,`,`,`被扫支付测试,`订单额外描述,`0,`0.60%总交易单数,总交易额,总退款金额,总代金券或立减优惠退款金额,手续费总金额`2,`0.02,`0.0,`0.0,`0
②去掉汇总数据,并且去掉'`'这个符号。
代码为:
String tradeInfo = tradeMsg.substring(0, tradeMsg.indexOf('总')).replace('`', '');// 去掉汇总数据,并且去掉'`'
数据为:
2014-11-1016:33:45,wx2421b1c4370ec43b,10000100,0,1000,1001690740201411100005734289,1415640626,085e9858e3ba5186aafcbaed1,MICROPAY,SUCCESS,CFT,CNY,0.01,0.0,0,0,0,0,,,被扫支付测试,订单额外描述,0,0.60%2014-11-1016:46:14,wx2421b1c4370ec43b,10000100,0,1000,1002780740201411100005729794,1415635270,085e9858e90ca40c0b5aee463,MICROPAY,SUCCESS,CFT,CNY,0.01,0.0,0,0,0,0,,,被扫支付测试,订单额外描述,0,0.60%
可以看到和我们想要的数据已经大致一样了。
③用spilt方法拿出每一天数据放进数组里。之后再用spilt方法把数据放进二维数组里。
String[] tradeArray = tradeInfo.split('%'); // 根据%来区分
for (String tradeDetailInfo : tradeArray) { String[] tradeDetailArray = tradeDetailInfo.split(','); }
④最后保存下来就可以了。
PtWxTradeDetail entity = null; entity = new PtWxTradeDetail(); entity.setId(null); // 自动生成id entity.setTransDate(DateUtil.str2Date(tradeDetailArray[0], format));// 交易时间 entity.setCommonId(tradeDetailArray[1]);// 公众账号ID entity.setBusinessNo(tradeDetailArray[2]);// 商户号 entity.setChildBusinessNo(tradeDetailArray[3]);// 子商户号 entity.setEquipmentNo(tradeDetailArray[4]);// 设备号 entity.setWxOrderNo(tradeDetailArray[5]);// 微信订单号 entity.setBusinessOrderNo(tradeDetailArray[6]);// 商户订单号 entity.setUserIdentity(tradeDetailArray[7]);// 用户标识 entity.setTransType(tradeDetailArray[8]);// 交易类型 entity.setTransStatus(tradeDetailArray[9]);// 交易状态 entity.setPaymentBank(tradeDetailArray[10]);// 付款银行 entity.setCurrency(tradeDetailArray[11]);// 货币种类 entity.setTotalAmount(tradeDetailArray[12]);// 总金额 entity.setRedEnvelopesAmount(tradeDetailArray[13]);// 企业红包金额 entity.setWxRefundNo(tradeDetailArray[14]);// 微信退款单号 entity.setBusinessRefundNo(tradeDetailArray[15]);// 商户退款单号 entity.setRefundAmount(tradeDetailArray[16]);// 退款金额 entity.setRedEnvelopesRefundAmount(tradeDetailArray[17]);// 企业红包退款金额 entity.setRefundType(tradeDetailArray[18]);// 退款类型 entity.setRefundStatus(tradeDetailArray[19]);// 退款状态 entity.setBusinessName(tradeDetailArray[20]);// 商品名称 entity.setBusinessData(tradeDetailArray[21]);// 商户数据包 entity.setFee(tradeDetailArray[22]);// 手续费 entity.setRate(tradeDetailArray[23] + '%');// 费率 entity.setCreateDate(new Date()); wxTradeDetailDao.insert(entity);
最后,微信支付工具类下载链接(百度网盘):点击下载
赞 (0)