接入官方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", "");
    }

}
与自有支付系统对账
此处不做演示!
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐