开发指引(Java)
更新时间:2023.09.26在本文中,你将了解如何使用 Java SDK 获取交易和资金账单。
# 准备开始
在接入之前,你需要先做好以下准备:
- 成为微信支付商户 (opens new window)
- 商户 API 私钥 (opens new window):商户申请商户API证书时,会生成商户私钥,并保存在本地证书文件夹的文件
apiclient_key.pem
中 - 商户 API 证书序列号 (opens new window)
- APIv3 密钥
在准备好商户号和密钥之后,你还需要:
# 下载交易账单
由于待下载的账单可能体积较大,为了平衡系统性能与签名验证的实现成本,我们将账单下载过程分为两个步骤:
- 申请账单下载地址:在此步骤中,你将获得账单的下载地址以及账单摘要信息。
- 下载账单并验证完整性:通过下载地址获取账单文件,并使用之前获取的摘要信息来验证账单的完整性。
为了降低开发者的理解和开发成本,Java SDK 将下载账单的多个步骤封装成了一个方法。你可指定以下参数调用 BillDownloadServiceExtension.getTradeBill()
获得交易账单的 DigestBillEntity
:
bill_date
:必填,账单日期bill_type
:非必填,账单类型:当日所有ALL
、当日支付成功SUCCESS
和当日退款REFUND
。默认为ALL
。tar_type
:非必填,压缩格式,默认为不压缩,建议设置为GZIP
。
以下是示例代码,说明如何下载2023年7月23日包含所有订单信息的交易账单,账单以 GZIP 格式压缩。
1// 使用RSAAutoCertificateConfig,构造service 2BillDownloadServiceExtension service = new BillDownloadServiceExtension.Builder().config(config).build();3GetTradeBillRequest request = new GetTradeBillRequest();4request.setBillDate("2023-07-23");5request.setBillType(BillType.ALL);6request.setTarType(TarType.GZIP);78DigestBillEntity bill = service.getTradeBill(request);
# 保存文件
在接下来的步骤中,你需要将账单文件保存到相应的存储设备中。针对较大的账单文件,建议你采用流式方式读取账单数据并将其写入存储,以避免程序因内存溢出而意外退出。
首先,通过调用 DigestBillEntity.getInputStream()
方法获取账单文件的输入流,然后将其写入到文件中。需要注意的是,如果你在发送请求时将 tar_type
参数设置为 GZIP
,那么 getInputStream()
方法返回的将是解压缩后的原始数据流,无需你再进行解压缩操作。
1try (InputStream inputStream = bill.getInputStream()) {2 // 使用有缓存的 BufferedOutputStream3 try (BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFile))) {4 // 处理大文件时,常用的缓冲区大小为 8192 或 16384。5 // 不过,最佳缓冲区大小可能取决于具体的硬件和系统配置。6 byte[] buffer = new byte[16384];7 int bytesRead;8 while ((bytesRead = inputStream.read(buffer)) != -1) {9 outputStream.write(buffer, 0, bytesRead);10 }11 }12}
账单文件下载完成后,你需要关闭相关的输入和输出流。在上述示例代码中,我们使用了 try-with-resource 语句来自动关闭打开的流。当然,你也可以选择使用 try-finally 并调用 close()
方法来关闭流。
# 验证摘要
在存储过程中,你应计算账单文件的摘要,并对比预期的摘要,确保账单数据的准确性和完整性。编程语言通常会提供一些流包装器,例如 Java 的 DigestInputStream (opens new window) 和 Go 的 io.TeeReader (opens new window),以便在读取数据流的同时计算数据的摘要。你应优先使用该类方法。
Java SDK 封装了摘要的计算。从 DigestBillEntity.getInputStream()
的流读取所有账单数据后,你应使用 DigestBillEntity.verifyHash()
方法验证账单是否被篡改。
1// 验证数据流中已读取数据的摘要2if (bill.verifyHash() == true) {3 // 账单是完整准确,可以开启后续操作,例如完成每日对账。4} else {5 // 账单不完整或者被篡改,应清理之前保存的文件6}
如果验证结果为真,说明账单是完整、准确、未经篡改的;如果为假,说明账单可能不完整或被篡改,此时应删除之前保存的文件。
# 下载资金账单
如果你希望下载资金账单,使用 Java SDK 指定以下参数调用 BillDownloadServiceExtension.getFundFlowBill()
获取资金账单的 DigestBillEntity
:
bill_date
:必填,账单日期。account_type
:非必填,资金账户类型:基本账户BASIC
、运营账户OPERATION
和手续费账户FEES
。默认为基本账户BASIC
。tar_type
:非必填,压缩格式,默认为不压缩,建议设置为GZIP
。
以下是示例代码,说明如何下载2023年7月23日基本账户的资金账单,账单以 GZIP 格式压缩。
1// 使用构建好的config,初始化 2BillDownloadServiceExtension service = new BillDownloadServiceExtension.Builder().config(config).build();3GetFundFlowBillRequest request = new GetFundFlowBillRequest();4request.setBillDate("2023-07-23");5request.setAccountType(AccountType.BASIC);6request.setTarType(TarType.GZIP);78DigestBillEntity bill = service.getFundFlowBill(request);
获得 DigestBillEntity
对象后,请参考保存文件并验证摘要,完成账单的下载。
# 进一步阅读
- 阅读资金账单文件格式说明和交易账单文件格式说明,了解如何解析账单,以设计和实现你的程序化对账。