前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >支付宝账单下载读文件解析

支付宝账单下载读文件解析

作者头像
默存
发布2022-06-24 14:55:46
1.1K0
发布2022-06-24 14:55:46
举报
文章被收录于专栏:默存默存

支付宝开放平台API

1、查询对账单下载地址

https://opendocs.alipay.com/apis/api_15/alipay.data.dataservice.bill.downloadurl.query

2、对账说明 https://opendocs.alipay.com/open/204/106262

请求API下载账单解析

1、支付宝下载对账单,不保存文件、不解压直接解析。 2、实例实现的是(trade)支付宝交易收单的业务账单。

1、请求实体、响应实体

DownloadBillRequest.java

代码语言:javascript
复制
@Data
public class DownloadBillRequest implements Serializable {

    private static final long serialVersionUID = -9016422214082575601L;
    // 账单日期 (yyyy-MM-dd)
    private String billDate;
    // 账单类型(trade、signcustomer)
    private String billType;

}

DownloadBillResponse.java

代码语言:javascript
复制
@Data
public class DownloadBillResponse implements Serializable {

    private static final long serialVersionUID = 5344850998806040582L;

    // 返回状态码
    private String returnCode;
    // 返回信息
    private String returnMsg;
    // 错误代码
    private String errCode;
    // 账单明细
    List<BillInfo> billInfos;
}

`

2、获取zip下载地址

代码语言:javascript
复制
public DownloadBillResponse downloadBill(DownloadBillRequest downloadBillRequest) {
        DownloadBillResponse response = new DownloadBillResponse();
        try {
            AlipayDataDataserviceBillDownloadurlQueryRequest request = new AlipayDataDataserviceBillDownloadurlQueryRequest();
            if (Objects.isNull(downloadBillRequest.getBillType())) {
                downloadBillRequest.setBillType("trade");
            }
            Map param = HumpConversionUtils.transform(downloadBillRequest);
            request.setBizContent(JSON.toJSONString(param));
            AlipayDataDataserviceBillDownloadurlQueryResponse result = new DefaultAlipayClient(
                    "https://openapi.alipay.com/gateway.do",
                   "你的AppId",
                   "你的应用私钥",
                    "json",
                    "utf-8",
                   "你的支付公钥",
                   "RSA2"
            ).execute(request);

            if (Objects.equals(PayStatus.ALI_SUCCESS, result.getCode())) {
                List<BillInfo> billInfos = downloadBill(result.getBillDownloadUrl())
                response.setReturnCode(result.getCode());
                response.setBillInfos(billInfos);
                return response;
            }
            response.setReturnCode(result.getCode());
        } catch (AlipayApiException e) 
            e.printStackTrace();
        }
        return response;
    }

3、解析文件获取数据(重点)

1、这里只解析明细数据,没有做汇总数据的解析。 2、文件不做保存、不做解压直接解析获取数据。

代码语言:javascript
复制
public List<BillInfo> downloadBill(String downloadUrl) {
        List<BillInfo> aliBillInfos = new ArrayList<>();
        HttpURLConnection conn = null;
        ZipInputStream in = null;
        BufferedReader br = null;
        try {
            URL url = new URL(downloadUrl);
            conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5 * 1000);
            conn.setRequestMethod("GET");
            conn.connect();

            // 不解压直接读取,加上GBK解决乱码问题
            in = new ZipInputStream(conn.getInputStream(), Charset.forName("GBK"));
            br = new BufferedReader(new InputStreamReader(in, "GBK"));
            ZipEntry zipFile;

            // 循环读取zip中的cvs文件,无法使用jdk自带,因为文件名中有中文
            while ((zipFile = in.getNextEntry()) != null) {
                if (zipFile.isDirectory()) {
                    // 目录不处理
                }
                // 获得cvs名字,检测文件是否存在
                String fileName = zipFile.getName();
                log.info("对账单解析,输出文件名称:{}", fileName);
                if (!Objects.isNull(fileName) && fileName.indexOf(".") != -1 && !fileName.contains("汇总")) {
                    String line;
                    int i = 0;
                    // 按行读取数据
                    while ((line = br.readLine()) != null) {
                        if (!line.startsWith("#")) {
                            log.info("解析数据:{}", line);
                            if (i > 0) {
                                String[] lines = line.split(",",-1);
                                BillInfo aliBillInfo = BillInfo.builder()
                                        .tradeNo(lines[0].trim())
                                        .outTradeNo(lines[1].trim())
                                        .businessType(lines[2].trim())
                                        .tradeName(lines[3].trim())
                                        .createTime(lines[4].trim())
                                        .finishTime(lines[5].trim())
                                        .storeNumber(lines[6].trim())
                                        .storeName(lines[7].trim())
                                        .operator(lines[8].trim())
                                        .terminalNumber(lines[9].trim())
                                        .clientAccount(lines[10].trim())
                                        .orderAmount(lines[11].trim())
                                        .realAmount(lines[12].trim())
                                        .redPaperAmount(lines[13].trim())
                                        .jifenbaoAmount(lines[14].trim())
                                        .zfbDiscountAmount(lines[15].trim())
                                        .merchantOffersAmount(lines[16].trim())
                                        .CouponWriteOffAmount(lines[17].trim())
                                        .couponName(lines[18].trim())
                                        .merchantRedAmount(lines[19].trim())
                                        .cardAmount(lines[20].trim())
                                        .refundNo(lines[21].trim())
                                        .serviceFee(lines[22].trim())
                                        .fenrun(lines[23].trim())
                                        .build();
                                aliBillInfos.add(aliBillInfo);
                            }
                            i++;
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (br != null) br.close();
                if (in != null) in.close();
                if (conn != null) conn.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return aliBillInfos;
    }

4、账单实体

代码语言:javascript
复制
@Data
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
public class BillInfo implements Serializable {

    private static final long serialVersionUID = -3947062662460225647L;

    /**
     * 支付宝交易号
     */
    private String tradeNo;
    /**
     * 商户订单号
     */
    private String outTradeNo;
    /**
     * 业务类型
     */
    private String businessType;
    /**
     * 商品名称
     */
    private String tradeName;
    /**
     * 创建时间
     */
    private String createTime;
    /**
     * 完成时间
     */
    private String finishTime;
    /**
     * 门店编号
     */
    private String storeNumber;
    /**
     * 门店名称
     */
    private String storeName;
    /**
     * 操作员
     */
    private String operator;
    /**
     * 终端号
     */
    private String terminalNumber;
    /**
     * 对方账户
     */
    private String clientAccount;
    /**
     * 订单金额(元)
     */
    private String orderAmount;
    /**
     * 商家实收(元)
     */
    private String realAmount;
    /**
     * 支付宝红包(元)
     */
    private String redPaperAmount;
    /**
     * 集分宝(元)
     */
    private String jifenbaoAmount;
    /**
     * 支付宝优惠(元)
     */
    private String zfbDiscountAmount;
    /**
     * 商家优惠(元)
     */
    private String merchantOffersAmount;
    /**
     * 券核销金额(元)
     */
    private String CouponWriteOffAmount;
    /**
     * 券名称
     */
    private String couponName;
    /**
     * 商家红包消费金额(元)
     */
    private String merchantRedAmount;
    /**
     * 卡消费金额(元)
     */
    private String cardAmount;
    /**
     * 退款批次号/请求号
     */
    private String refundNo;
    /**
     * 服务费(元)
     */
    private String serviceFee;
    /**
     * 分润(元)
     */
    private String fenrun;
    /**
     * 备注
     */
    private String remark;
}

5、驼峰规范属性转下划线工具类

代码语言:javascript
复制
/**
 * 驼峰规范属性转下划线 (Bean 》 Map)
 * 支持递归转换,如属性为JavaBean时
 */
public class HumpConversionUtils {

    private static String compile = "[A-Z]";

    private HumpConversionUtils() {
    }

    /**
     * @methodName:transform
     * @description:驼峰转下划线(对象
     */
    public static <T> Map transform(T object) {
        if (object == null) {
            return null;
        }
        Map<String, Object> map = new HashMap<>();
        Field[] fields = object.getClass().getDeclaredFields();
        try {
            for (int i = 0; i < fields.length; i++) {
                String fieldName = fields[i].getName();
                if ("serialVersionUID".equalsIgnoreCase(fieldName)) {
                    continue;
                }
                // 转换驼峰形式属性名称成下划线风格,获取map的key 例:fieldName 》 field_name
                String transformFieldName = HumpConversionUtils.getTransformFieldName(fieldName);
                Object FieldValue = null;
                String name = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
                String type = fields[i].getGenericType().toString();
                Method m = object.getClass().getMethod("get" + name);
                switch (type) {
                    // 如果有需要,可以仿照下面继续进行扩充,再增加对其它类型的判断
                    case "class java.lang.String":
                    case "class java.lang.Boolean":
                    case "class java.util.Date":
                    case "class java.lang.Integer":
                    case "class java.lang.Long":
                        // 调用getter方法获取属性值
                        FieldValue = m.invoke(object);
                        break;
                    default:
                        // 属性类型为bean,则递归
                        Object obj = m.invoke(object);
                        FieldValue = HumpConversionUtils.transform(obj);
                }
                map.put(transformFieldName, FieldValue);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * @methodName:getTransformFieldName
     * @description:驼峰转下划线(字符串
     */
    private static String getTransformFieldName(String fieldName) {
        Pattern humpPattern = Pattern.compile(compile);
        Matcher matcher = humpPattern.matcher(fieldName);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }
}

7、业务明细账单模板

了解更多的技术博文: https://gitee.com/typ1805[gitee] https://blog.csdn.net/typ1805[csdn]

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-07-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 全栈客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 请求API下载账单解析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档