最近在做微信支付相关的业务,在调用微信的对账单接口时,遇到一个当时感觉很头大的问题,为什么说当时很头大呢?因为现在这个问题已经被我解决了!嘿嘿...
好吧,言归正传。我遇到的问题就是在调用微信的对账单接口时,微信会返回一个字符串给我,而这个字符串就包含了账单名称以及账单数据。喏,就是下面这个样子。
当时看了一脸懵逼,因为看不出任何可以进行解析的特征,因此不得不又认认真真的看了一遍接口的文档说明,结合着接口文档的说明和自己大胆的假设,最终将该字符串解析成自己想要的样子。接下来就来说说自己的解法吧。
按照文档说明剖析整体结构
从上面的文档说明中,我找出了最关键的三句话(用红框标记),从这个三句话中可以看出字符串的结构其实就是:
- 表头
- 数据记录
- 汇总表头
- 汇总数据
所以我就按照这种结构来解析整个字符串。 不过在解析之前需要说明,微信给的示例和调用接口返回的数据非常的具有迷惑性,它给的数据看不出任何的特别有用特征,但是当把接口返回字符串复制粘贴到你IDE编辑区后,你会发现每行数据后面都有一个换行符,但是在文档示例和IDE的Console区中的返回数据中是看不出这一点的。所以当这一点被发现后,其实问题就已经迎刃而解了。
解析对账单字符串
解析对账单的字符串,可以分为以下几个步骤:
- 解析表头
- 解析表头剩下的内容
- 解析交易记录
- 解析汇总表头和数据
解析表头
首先从表头的解析开始。由文档可知,从第二行开始,每行参数前都有这个符号:*** ***,因此在第一个 ***
*** 符号之前都是表头的内容。所以到这里就可以把表头的内容解析出来了。代码如下:
String bill = "\uFEFFTransaction time,Official account ID(appid),Vendor ID(mch_id),Sub vendor ID (sub_mch_id),Device ID(Device_info),Wechat order number(transaction_id),Vendor order number (out_transaction_id),User tag(openid),Transaction type(trade_type),Transaction status(trade_state),Payment bank(bank_type),Currency type(fee_type),Total amount(total_fee),Coupon amount,Wechat refund number (refund_id),Vendor refund number(out_refund_no),Refund amount(refund_fee),Coupon refund amount,Refund type,Refund status(refund_status_$n),Product name,Vendor's data package(attach),Fee,Rate,Payment Currency type(Cash_fee_type),Cash payment amount(Cash_fee),Settlement currency type,Settlement currency amount,Exchange rate,Refund exchange rate,Payer's Refund amount,Payer's Refund currency type,Refund currency type,Refund settlement currency type,Refund settlement amount\n" +
"`2018-08-06 11:57:04,`wxa7ca41f5ddb1d958,`1234567890,`224195623,`,`420000018620180806525649,`UW002807000000052018080600000014,`oRRUM1NqZxiBHzPtpk1iOd-oug0U,`NATIVE,`SUCCESS,`CMB_DEBIT,`NZD,`0.01,`0.00,`0,`0,`0.00,`0.00,`,`,`睡猫 支付-收款,`,`0.00000,`0.50%,`CNY,`0.04,`NZD,`0.01,`461620123,`0,`0,`,`,`,`0.00\n" +
"`2018-08-06 13:13:58,`wxa7ca41f5ddb1d958,`1234567890,`224195623,`,`420000016420180806864932,`UW002808030000022018080600000016,`oRRUM1JH3GFSPDDimcSO9T0pyKMI,`MICROPAY,`SUCCESS,`CFT,`NZD,`0.01,`0.00,`0,`0,`0.00,`0.00,`,`,`productDescribe,`,`0.00000,`0.50%,`CNY,`0.04,`NZD,`0.01,`460927123,`0,`0,`,`,`,`0.00\n" +
"Total transaction count,Total transaction amount,Total refund amount,Total coupon refund amount,Total commission amount\n" +
"`7,`0.07,`0.00,`0.00,`0.00000\n"
String tableHead = bill.substring(0, bill.indexOf("`"));
复制代码
解析剩余的内容
我们可以从Total
这个字符串入手,根据它来将剩余的内容一一解析成我们想要的内容,代码如下:
// 获取表头以外的其他内容:交易记录、汇总表头、汇总数据
String otherContent = bill.substring(bill.indexOf("`"));
System.out.println("otherContent" + otherContent);
//获取交易记录
String records = otherContent.substring(0, otherContent.indexOf("Total"));
String tradeRecords = records.replace("`", "");
System.out.println("records:" + tradeRecords);// 把 ` 全部去掉
// 获取汇总表头和汇总数据
String totalContent = otherContent.substring(otherContent.indexOf("Total"), otherContent.length());
String[] total = totalContent.split("\n");// 根据换行符分割
System.out.println("totalTableHead:" + total[0]);// 汇总表头
System.out.println("totalData:" + total[1]);// 汇总数据
复制代码
完整代码
public class AnalyseDownloadBill {
public static void main(String[] args) {
String bill = "Transaction time,Official account ID(appid),Vendor ID(mch_id),Sub vendor ID (sub_mch_id),Device ID(Device_info),Wechat order number(transaction_id),Vendor order number (out_transaction_id),User tag(openid),Transaction type(trade_type),Transaction status (trade_state),Payment bank(bank_type),Currency type(fee_type),Total amount(total_fee),Coupon amount,Wechat refund number(refund_id),Vendor refund number(out_refund_no),Refund amount (refund_fee),Coupon refund amount,Refund type,Refund status(refund_status_$n),Product name,Vendor'bill data package(attach),Fee,Rate,Payment Currency type(Cash_fee_type),Cash payment amount(Cash_fee),Settlement currency type,Settlement currency amount,Exchange rate,Refund exchange rate,Payer'bill Refund amount,Payer'bill Refund currency type,Refund currency type,Refund settlement currency type,Refund settlement amount\n`2018-07-13 13:58:59,`wxa7ca41f5ddb1d958,`1499826932,`224150459,`,`4200000111201807132458910571,`A20180713157 27,` oRRUM1OMLP5E071pqb0y48ugIDoY,`NATIVE,`SUCCESS,`CFT,`CNY,`0.05,`0.00,`0,`0,`0.00,`0.00,`,`,`测试扫 码支付 流程,`,`0.00000,`0.50%,`CNY,`0.05,`NZD,`0.01,`452930000,`0,`0,`,`,`,`0.00\n`2018-07-13 15:44:53,`wxa7ca41f5ddb1d958,`1499826932,`224150459,`,`4200000138201807136839391208,`A20180713344 47,` oRRUM1OMLP5E071pqb0y48ugIDoY,`MICROPAY,`SUCCESS,`CMB_DEBIT,`CNY,`0.05,`0.00,`0,`0,`0.00,`0.00,`,` ,`测 试刷卡接口,`,`0.00000,`0.50%,`CNY,`0.05,`NZD,`0.01,`452930000,`0,`0,`,`,`,`0.00\n`2018-07-13 16:06:52,`wxa7ca41f5ddb1d958,`1499826932,`224150459,`,`4200000138201807136839391208,`A20180713344 47,` oRRUM1OMLP5E071pqb0y48ugIDoY,`MICROPAY,`REFUND,`CMB_DEBIT,`CNY,`0.00,`0.00,`500000075220180713054 2334 1768,`A201807134645,`0.05,`0.00,`ORIGINAL,`SUCCESS,`测试刷卡接 口,`,`0.00000,`0.50%,`CNY,`0.00,`NZD,`0.00,`0,`452930000,`0.05,`CNY,`CNY,`NZD,`0.01\n`2018-07-13 16:05:34,`wxa7ca41f5ddb1d958,`1499826932,`224150459,`,`4200000111201807132458910571,`A20180713157 27,` oRRUM1OMLP5E071pqb0y48ugIDoY,`NATIVE,`REFUND,`CFT,`CNY,`0.00,`0.00,`50000307532018071305354138153 ,`A2 01807134527,`0.05,`0.00,`ORIGINAL,`SUCCESS,`测试扫码支付流 程,`,`0.00000,`0.50%,`CNY,`0.00,`NZD,`0.00,`0,`452930000,`0.05,`CNY,`CNY,`NZD,`0.01\nTotal transaction count,Total transaction amount,Total refund amount,Total coupon refund amount,Total commission amount\n`4,`0.10,`0.10,`0.00,`0.00000";
// 获取表头
String tableHead = bill.substring(0, bill.indexOf("`"));
System.out.println("tableHead:" + tableHead);
// 获取表头以外的其他内容:交易记录、汇总表头、汇总数据
String otherContent = bill.substring(bill.indexOf("`"));
System.out.println("otherContent" + otherContent);
//获取交易记录
String records = otherContent.substring(0, otherContent.indexOf("Total"));
String tradeRecords = records.replace("`", "");
System.out.println("records:" + tradeRecords);// 把 ` 全部去掉
// 获取汇总表头和汇总数据
String totalContent = otherContent.substring(otherContent.indexOf("Total"), otherContent.length());
String[] total = totalContent.split("\n");
System.out.println("totalTableHead:" + total[0]);// 汇总表头
System.out.println("totalData:" + total[1]);// 汇总数据
}
}
复制代码
总结
至此,我们的微信对账单返回值的解析就完成了。回头看其实这个解析一点都不难,只是我们没有认真阅读文档去了解它的结构,并且没有细心的发现它的一些特征,从而导致开始的茫然。所以在以后的开发中一定要认真阅读文档,最好能清晰的解读出文档中的关键内容,再加上一点点细心,那么肯定很多问题都能够迎刃而解的。