支付宝系统与自有业务系统对账实现
文章目录账单下载数据解析数据解析方法实现账单下载参考官网API数据解析数据解析方法实现待同步!!!
·
接入官方SDK
官方文档:https://opendocs.alipay.com/open/54/103419
完整处理方法总览
/**
* 支付宝交易账单获取
*
* @author zhengshangjin
* created on 2020-09-08
*/
@Override
public void aliPayBill() {
MultipleFactory factory = getMultipleFactory("");
try {
AlipayDataDataserviceBillDownloadurlQueryResponse resp = factory.Common().downloadBill("trade", "2020-09-07");
System.out.println("请求响应结果:" + JsonUtils.toJson(resp));
String homePath = System.getProperties().getProperty("user.home");
System.out.println("系统用户主目录: " + homePath);
String fileName = FileUtils.downloadNet(resp.getBillDownloadUrl(), homePath);
System.out.println("已下载文件名(含后缀): " + fileName);
List<String> filePaths = ZipUtils.unZipFiles(homePath + "/" + fileName, "");
System.out.println("解压完成文件路径: " + JsonUtils.toJson(filePaths));
String billPath = filePaths.stream().filter(o -> o.lastIndexOf("_业务明细.csv") != -1)
.limit(1).collect(Collectors.joining());
System.out.println("账单的完整路径为: " + billPath);
List<AliPayBill> payBills = aliBillAnalysis(billPath);
System.out.println("解析结果账单列表: " + JsonUtils.toJson(payBills));
} catch (Exception e) {
e.printStackTrace();
}
}
获取账单链接
AlipayDataDataserviceBillDownloadurlQueryResponse resp = factory.Common().downloadBill("trade", "2020-09-07");
System.out.println("请求响应结果:" + JsonUtils.toJson(resp));
下载账单压缩包
/**
* 下载网络文件
*
* @param urlPath 下载地址 URL
* @param targetDir 保存文件路径
* @return 下载的文件名
* @author zhengshangjin
* created on 2020-09-09
*/
public static String downloadNet(String urlPath, String targetDir) throws Exception {
URL url = new URL(urlPath);
HttpURLConnection http = (HttpURLConnection) url.openConnection();
http.setConnectTimeout(3000);
http.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");
String fileName = getFileName(http, urlPath);
InputStream inputStream = http.getInputStream();
OutputStream out = new FileOutputStream(new File(targetDir, fileName));
int len;
byte[] buff = new byte[1024 * 10];
while ((len = inputStream.read(buff)) != -1) {
out.write(buff, 0, len);
out.flush();
}
out.close();
inputStream.close();
http.disconnect();
return fileName;
}
/**
* 解析链接中文件名
*
* @param http http连接
* @param urlPath 网络地址
* @return 文件名
* @author zhengshangjin
* created on 2020-09-09
*/
private static String getFileName(HttpURLConnection http, String urlPath) throws UnsupportedEncodingException {
String headerField = http.getHeaderField("Content-Disposition");
String fileName = null;
if (headerField != null) {
String decode = URLDecoder.decode(headerField, "UTF-8");
fileName = decode.split(";")[1].split("=")[1].replaceAll("\"", "");
}
// 尝试从url中获取文件名
if (fileName == null) {
String[] arr = urlPath.split("/");
fileName = arr[arr.length - 1];
}
return fileName;
}
解压账单压缩包
/**
* 解压ZIP文件
* 解压目录为空则为解压到当前文件目录下
*
* @param zipPath 文件目录 例: (/Users/zhengshangjin/Downloads/20200907.zip)
* @param targetDir 解压目录 例: (/Users/zhengshangjin/Downloads) 解压目录为空则为解压到当前文件目录下
* @author zhengshangjin
* created on 2020-09-09
*/
public static List<String> unZipFiles(String zipPath, String targetDir) {
try {
return unZipFiles(new File(zipPath), targetDir);
} catch (IOException e) {
e.printStackTrace();
return Collections.emptyList();
}
}
private static final String SLASH = "/";
/**
* 解压ZIP文件
*
* @param zipFile 原始文件
* @param targetDir 解压目录 例: (/Users/zhengshangjin/Downloads) 解压目录为空则为解压到当前文件目录下
* @return 文件地址列表
* @author zhengshangjin
* created on 2020-09-09
*/
public static List<String> unZipFiles(File zipFile, String targetDir) throws IOException {
// 解决中文文件夹乱码
ZipFile zip = new ZipFile(zipFile, Charset.forName("GBK"));
// 获取压缩包文件名(此处Linux/Unix与Windows的目录具备差异 '/' or '\\')
String zipName = zip.getName().substring(zip.getName().lastIndexOf(SLASH) + 1, zip.getName().lastIndexOf('.'));
String zipPath = zip.getName().substring(0, zip.getName().lastIndexOf(SLASH));
// 处理解压后文件最终保存路径
targetDir = StringUtils.isEmpty(targetDir) ? zipPath + SLASH + zipName : targetDir + SLASH + zipName;
// 列表第一位始终为解压根目录
List<String> pathList = new ArrayList<>();
pathList.add(targetDir);
for (Enumeration<? extends ZipEntry> entries = zip.entries(); entries.hasMoreElements(); ) {
ZipEntry entry = entries.nextElement();
String zipEntryName = entry.getName();
InputStream in = zip.getInputStream(entry);
String outPath = (targetDir + SLASH + zipEntryName).replaceAll("\\*", SLASH);
pathList.add(outPath);
// 判断路径是否存在,不存在则创建文件路径
File file = new File(outPath.substring(0, outPath.lastIndexOf(SLASH)));
if (!file.exists()) {
if (!file.mkdirs()) {
throw new RuntimeException("文件夹创建失败");
}
}
// 判断文件全路径是否为文件夹,如果是上面已经上传,不需要解压 防止重复生成
if (new File(outPath).isDirectory()) {
continue;
}
// 输出文件路径信息
FileOutputStream out = new FileOutputStream(outPath);
byte[] buf1 = new byte[1024];
int len;
while ((len = in.read(buf1)) > 0) {
out.write(buf1, 0, len);
}
in.close();
out.close();
}
return pathList;
}
读取并解析数据
解析方法
/**
* 解析账单csv数据
*
* @param billPath 账单csv地址
* @return list
* @author zhengshangjin
* created on 2020-09-09
*/
private List<AliPayBill> aliBillAnalysis(String billPath) throws IOException {
String billTail = "#-----------------------------------------业务明细列表结束------------------------------------";
File file = new File(billPath);
FileInputStream fileInputStream = new FileInputStream(file);
DataInputStream dataInputStream = new DataInputStream(fileInputStream);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(dataInputStream, "GBK"));
// 去除标头
for (int i = 0; i < 5; i++) {
String title = bufferedReader.readLine();
}
String rowRecord;
List<AliPayBill> aliPayBills = new ArrayList<>();
while ((rowRecord = bufferedReader.readLine()) != null) {
// 去除标尾
if (billTail.equals(rowRecord)) {
bufferedReader.close();
return aliPayBills;
}
String[] rowArray = rowRecord.split(",");
aliPayBills.add(new AliPayBill().attach(rowArray));
}
return aliPayBills;
}
数据对象
/**
* <p>
* 支付宝交易账单
* </p>
*
* @author zhengshangjin
* @version 1.0.0
* @since 1.0.0
* created on 2021-09-08
*/
@Data
public class AliPayBill implements Serializable {
private static final long serialVersionUID = 1L;
/**
* [0] 支付宝交易号
*/
private String aliOrderNo;
/**
* [1] 商户订单号
*/
private String mchOrderNo;
/**
* [2] 业务类型
*/
private String businessType;
/**
* [3] 商品名称
*/
private String goodsName;
/**
* [4] 创建时间
*/
private LocalDateTime createTime;
/**
* [5] 完成时间
*/
private LocalDateTime finishTime;
/**
* [6] 门店编号
*/
private String storeId;
/**
* [7] 门店名称
*/
private String storeName;
/**
* [8] 操作员
*/
private String operatorId;
/**
* [9] 终端号
*/
private String terminalId;
/**
* [10] 对方账户
*/
private String transNo;
/**
* [11] 订单金额(元)
*/
private BigDecimal orderAmount;
/**
* [12] 商家实收(元)
*/
private BigDecimal amount;
/**
* [13] 支付宝红包(元)
*/
private BigDecimal aliRedAmount;
/**
* [14] 集分宝(元)
*/
private BigDecimal pointAmount;
/**
* [15] 支付宝优惠(元)
*/
private BigDecimal aliDiscountsAmount;
/**
* [16] 商家优惠(元)
*/
private BigDecimal outDiscountsAmount;
/**
* [17] 券核销金额(元)
*/
private BigDecimal couponAmount;
/**
* [18] 券名称
*/
private String couponName;
/**
* [19] 商家红包消费(元)
*/
private BigDecimal outRedAmount;
/**
* [20] 卡消费金额(元)
*/
private BigDecimal cardAmount;
/**
* [21] 退款批次号/请求号
*/
private String refundNo;
/**
* [22] 服务费(元)
*/
private BigDecimal coverChargeAmount;
/**
* [23] 分润(元)
*/
private BigDecimal shareBenefitAmount;
/**
* [24] 备注
*/
private String remark;
/**
* 数据转换提取
*
* @param order 订单数组
* @return bill
* @author zhengshangjin
* created on 2021-09-08
*/
public AliPayBill attach(String[] order) {
if (order == null || order.length < 1) {
return null;
}
AliPayBill bill = new AliPayBill();
bill.setAliOrderNo(replace(order[0]));
bill.setMchOrderNo(replace(order[1]));
bill.setBusinessType(replace(order[2]));
bill.setGoodsName(replace(order[3]));
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
if (StringUtils.isNotEmpty(order[4])) {
bill.setCreateTime(LocalDateTime.parse(replace(order[4]), formatter));
}
if (StringUtils.isNotEmpty(order[5])) {
bill.setFinishTime(LocalDateTime.parse(replace(order[5]), formatter));
}
bill.setStoreId(replace(order[6]));
bill.setStoreName(replace(order[7]));
bill.setOperatorId(replace(order[8]));
bill.setTerminalId(replace(order[9]));
bill.setTransNo(replace(order[10]));
if (StringUtils.isNotEmpty(order[11])) {
bill.setOrderAmount(new BigDecimal(replace(order[11])));
}
if (StringUtils.isNotEmpty(order[12])) {
bill.setAmount(new BigDecimal(replace(order[12])));
}
if (StringUtils.isNotEmpty(order[13])) {
bill.setAliRedAmount(new BigDecimal(replace(order[13])));
}
if (StringUtils.isNotEmpty(order[14])) {
bill.setPointAmount(new BigDecimal(replace(order[14])));
}
if (StringUtils.isNotEmpty(order[15])) {
bill.setAliDiscountsAmount(new BigDecimal(replace(order[15])));
}
if (StringUtils.isNotEmpty(order[16])) {
bill.setOutDiscountsAmount(new BigDecimal(replace(order[16])));
}
if (StringUtils.isNotEmpty(order[17])) {
bill.setCouponAmount(new BigDecimal(replace(order[17])));
}
bill.setCouponName(replace(order[18]));
if (StringUtils.isNotEmpty(order[19])) {
bill.setOutRedAmount(new BigDecimal(replace(order[19])));
}
if (StringUtils.isNotEmpty(order[20])) {
bill.setCardAmount(new BigDecimal(replace(order[20])));
}
bill.setRefundNo(replace(order[21]));
if (StringUtils.isNotEmpty(order[22])) {
bill.setCoverChargeAmount(new BigDecimal(replace(order[22])));
}
if (StringUtils.isNotEmpty(order[23])) {
bill.setShareBenefitAmount(new BigDecimal(replace(order[23])));
}
// bill.setRemark(replace(order[24]));
return bill;
}
/**
* 处理特殊符号
*/
private String replace(String content) {
if (StringUtils.isEmpty(content)) {
return "";
}
return content.replaceAll("\t", "");
}
}
与自有支付系统对账
此处不做演示!
更多推荐
已为社区贡献2条内容
所有评论(0)