转载

「掘金者说」 java后台实现对账功能复盘笔记

对账管理是一个模块功能点,对账不清楚,那就:扯不清,道不明。人工排查那就无比痛苦,借助软件智能分析辅助。

关于csv文件解析

心中有数,对对账单。目前,我们工作中都会用到对账业务,通过XXL-JOB调度采集数据。每一次新项目业务都需要对接第三方缴费接口,那么对账就是一个棘手事情,调用写法各式各样,每次都要重复造轮子,那可否封装一个依赖包提供研发使用呢?然后,写 pig-go-pay-sdk 。为了完成任务紧急且重要,通过封装好的老板sdk文件 pig-java-pay-sdk 依赖进行配置发送接口报文请求,响应一个json下载地址链接。下载文件之后是一个zip文件里面一个csv文件。csv文件可以用excel打开或用notepad打开。csv文件内容,如下:

#明细查询
#商号:[641787296]
#账期:[20200316]
#--------------------------业务明细列表--------------------------------
订单号,流水号,金额(分),币种,类型,日期,时间
5A605CB39D1C420E9FE6B04C91D923E1,PIG2020031502163665,60,01,TRADE,20200316,185936
688H660BC69B45B3ADC39D3D435411E8,PIG2020031500193460,50,01,TRADE,20200316,221847
#--------------------------业务明细列表结束--------------------------------
#交易合计:0笔,商家交易共:0分
#退款合计:0笔,商家退款共:0分
#生成时间:[2020-03-20 16:50:37]
复制代码

小伙伴说:正常读取行数,解析就完事情了。不过。我可要学习开源opencsv和hutool。我采用opencsv5.1读取CSV文件和Hutool5.3.2工具进行使用。

代码思路

仅供参考,CodeReview

依赖导入

<dependency>
    <groupId>cn.pig4cloud</groupId>
    <artifactId>pig-java-pay-sdk</artifactId>
    <version>2.6.5</version>
</dependency>

<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.2.3</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.opencsv/opencsv -->
<dependency>
    <groupId>com.opencsv</groupId>
    <artifactId>opencsv</artifactId>
    <version>5.1</version>
</dependency>

复制代码

表结构设计

设计两张表, amt_payamt_pay_detail 。表结构,这里忽略跳过。

单元测试

TestSettleRequest

/**
 * 对账管理单用测试
 *
 * @author Lucky
 * @date 2020-03-17 11:13:33
 */
@SpringBootTest(classes = {PigPayApplication.class})
@RunWith(SpringRunner.class)
public class TestSettleRequest {
        @Test
	public void testSettle() throws IOException, CsvException {
            //1 请求缴费接口 获取jsonStr (忽略)
    
            //2 验证解析json 验证参数是否正常 (忽略)
    
    	    //3 解析csv文件头尾内容 (分享)
            analysisCsvToHeadAndTail(csvFilePath);
        
             //4 解析csv文件详情内容 (分享)
            analysisCsvToBody(csvFilePath);
	
	}

	/**
	 * 3 解析csv文件头尾内容 hutool
	 *
	 * @param csvFileStr 文件全路径 "/app/641787296_20200316.csv"
	 */
	private AmtPayVo analysisCsvToHeadAndTail(String csvFileStr) {
		//String csvFile = "D://app//641787296_20200316.csv";
		CsvReader reader = CsvUtil.getReader();
		//从文件中读取CSV数据
		CsvData data = reader.read(FileUtil.file(csvFileStr));
		List<CsvRow> rows = data.getRows();
		if (rows.size() <= 0) {
			return null;
		}
		// 遍历行
		AmtPayVo amtPayVo = new AmtPayVo();
		for (CsvRow csvRow : rows) {
			//注意是采用非“!”来获取
			String rowStr = csvRow.getRawList().toString();
			if (!rowStr.contains("#") || rowStr.contains("#-") || rowStr.contains("#明细查询")
			) {
				continue;
			}
			//getRawList返回一个List列表,列表的每一项为CSV中的一个单元格(既逗号分隔部分)
			Console.log(csvRow.getRawList());
			amtPayVo.setRemark("对账明细查询");
			buildAmtPayVo(amtPayVo, csvRow.getRawList());
		}
		Console.log(amtPayVo.toString());
		return amtPayVo;
	}

	/**
	 * 4 解析csv文件详情内容 opencsv
	 *
	 * @param csvFileStr 文件全路径 "/app/641787296_20200316.csv"
	 * @throws IOException
	 * @throws CsvException
	 */
	private List<AmtPayDetail> analysisCsvToBody(String csvFileStr) throws IOException, CsvException {
		// Create castobaen and csvreader object
		MyCSVReader csvReader = null;
		try {
			csvReader = new MyCSVReader(new FileReader(csvFileStr));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		//The default line to start reading.
		csvReader.skip(4);

		List<AmtPayDetail> amtPayDetailList = new CsvToBeanBuilder(csvReader)
				//.withFilter(new MyCsvToBeanFilter()) //增加过滤器,将#过滤掉
				.withType(AmtPayDetail.class)
				.withIgnoreQuotations(true)
				.withThrowExceptions(false) //1
				//.withSkipLines(4)
				.withIgnoreLeadingWhiteSpace(true)
				.build()
				.parse();

		if (amtPayDetailList.size() <= 0) {
			Console.log("解析csv文件详情内容:当天无对账单详情数据");
			return null;
		}
		// print details of Bean object
		for (AmtPayDetail amtPayDetail : amtPayDetailList) {
			Console.log(amtPayDetail);
		}
		return amtPayDetailList;
	}
}
复制代码

AmtPayDetail

/**
 * 对账明细详情
 *
 * @author Lucky
 * @date 2020-03-17 11:13:33
 */
@Data
public class AmtPayDetail {
	private static final long serialVersionUID = 1L;


	/**
	 * 商户号,由平台提供
	 */
	@CsvBindByName(column = "商户号")
	private String merchantOrderNo;

	/**
	 * 流水号
	 */
	@CsvBindByName(column = "流水号")
	private String payOrderNo;

	/**
	 * 金额(分) 单位为分
	 */
	@CsvBindByName(column = "金额(分)")
	private String tranAmt;

	/**
	 * 交易币种
	 */
	@CsvBindByName(column = "交易币种")
	private String currencyCode;

	/**
	 * 交易类型
	 */
	@CsvBindByName(column = "交易类型")
	private String type;

	/**
	 * 日期,格式为:yyyyMMdd
	 */
	@CsvBindByName(column = "日期")
	private String orderDate;

	/**
	 * 时间,格式为:HHmmss
	 */
	@CsvBindByName(column = "时间")
	private String orderTime;
}
复制代码
原文  https://juejin.im/post/5e74e0ff6fb9a07cae138543
正文到此结束
Loading...