在本文中,你將了解如何使用 Java SDK 獲取交易和資金賬單。
# 準(zhǔn)備開始
在接入之前,你需要先做好以下準(zhǔn)備:
- 成為微信支付商戶 (opens new window)
- 商戶 API 私鑰 (opens new window):商戶申請商戶API證書時,會生成商戶私鑰,并保存在本地證書文件夾的文件
apiclient_key.pem
中 - 商戶 API 證書序列號 (opens new window)
- APIv3 密鑰
在準(zhǔn)備好商戶號和密鑰之后,你還需要:
- 安裝 SDK
- 閱讀關(guān)鍵概念,了解賬單的生成邏輯和賬單的內(nèi)容格式
# 下載交易賬單
由于待下載的賬單可能體積較大,為了平衡系統(tǒng)性能與簽名驗(yàn)證的實(shí)現(xiàn)成本,我們將賬單下載過程分為兩個步驟:
- 申請賬單下載地址:在此步驟中,你將獲得賬單的下載地址以及賬單摘要信息。
- 下載賬單并驗(yàn)證完整性:通過下載地址獲取賬單文件,并使用之前獲取的摘要信息來驗(yàn)證賬單的完整性。
為了降低開發(fā)者的理解和開發(fā)成本,Java SDK 將下載賬單的多個步驟封裝成了一個方法。你可指定以下參數(shù)調(diào)用 BillDownloadServiceExtension.getTradeBill()
獲得交易賬單的 DigestBillEntity
:
bill_date
:必填,賬單日期bill_type
:非必填,賬單類型:當(dāng)日所有ALL
、當(dāng)日支付成功SUCCESS
和當(dāng)日退款REFUND
。默認(rèn)為ALL
。tar_type
:非必填,壓縮格式,默認(rèn)為不壓縮,建議設(shè)置為GZIP
。
以下是示例代碼,說明如何下載2023年7月23日包含所有訂單信息的交易賬單,賬單以 GZIP 格式壓縮。
1// 使用RSAAutoCertificateConfig,構(gòu)造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);
# 保存文件
在接下來的步驟中,你需要將賬單文件保存到相應(yīng)的存儲設(shè)備中。針對較大的賬單文件,建議你采用流式方式讀取賬單數(shù)據(jù)并將其寫入存儲,以避免程序因內(nèi)存溢出而意外退出。
首先,通過調(diào)用 DigestBillEntity.getInputStream()
方法獲取賬單文件的輸入流,然后將其寫入到文件中。需要注意的是,如果你在發(fā)送請求時將 tar_type
參數(shù)設(shè)置為 GZIP
,那么 getInputStream()
方法返回的將是解壓縮后的原始數(shù)據(jù)流,無需你再進(jìn)行解壓縮操作。
1try (InputStream inputStream = bill.getInputStream()) {2 // 使用有緩存的 BufferedOutputStream3 try (BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFile))) {4 // 處理大文件時,常用的緩沖區(qū)大小為 8192 或 16384。5 // 不過,最佳緩沖區(qū)大小可能取決于具體的硬件和系統(tǒng)配置。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}
賬單文件下載完成后,你需要關(guān)閉相關(guān)的輸入和輸出流。在上述示例代碼中,我們使用了 try-with-resource 語句來自動關(guān)閉打開的流。當(dāng)然,你也可以選擇使用 try-finally 并調(diào)用 close()
方法來關(guān)閉流。
# 驗(yàn)證摘要
在存儲過程中,你應(yīng)計(jì)算賬單文件的摘要,并對比預(yù)期的摘要,確保賬單數(shù)據(jù)的準(zhǔn)確性和完整性。編程語言通常會提供一些流包裝器,例如 Java 的 DigestInputStream (opens new window) 和 Go 的 io.TeeReader (opens new window),以便在讀取數(shù)據(jù)流的同時計(jì)算數(shù)據(jù)的摘要。你應(yīng)優(yōu)先使用該類方法。
Java SDK 封裝了摘要的計(jì)算。從 DigestBillEntity.getInputStream()
的流讀取所有賬單數(shù)據(jù)后,你應(yīng)使用 DigestBillEntity.verifyHash()
方法驗(yàn)證賬單是否被篡改。
1// 驗(yàn)證數(shù)據(jù)流中已讀取數(shù)據(jù)的摘要2if (bill.verifyHash() == true) {3 // 賬單是完整準(zhǔn)確,可以開啟后續(xù)操作,例如完成每日對賬。4} else {5 // 賬單不完整或者被篡改,應(yīng)清理之前保存的文件6}
如果驗(yàn)證結(jié)果為真,說明賬單是完整、準(zhǔn)確、未經(jīng)篡改的;如果為假,說明賬單可能不完整或被篡改,此時應(yīng)刪除之前保存的文件。
# 下載資金賬單
如果你希望下載資金賬單,使用 Java SDK 指定以下參數(shù)調(diào)用 BillDownloadServiceExtension.getFundFlowBill()
獲取資金賬單的 DigestBillEntity
:
bill_date
:必填,賬單日期。account_type
:非必填,資金賬戶類型:基本賬戶BASIC
、運(yùn)營賬戶OPERATION
和手續(xù)費(fèi)賬戶FEES
。默認(rèn)為基本賬戶BASIC
。tar_type
:非必填,壓縮格式,默認(rèn)為不壓縮,建議設(shè)置為GZIP
。
以下是示例代碼,說明如何下載2023年7月23日基本賬戶的資金賬單,賬單以 GZIP 格式壓縮。
1// 使用構(gòu)建好的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
對象后,請參考保存文件并驗(yàn)證摘要,完成賬單的下載。
# 進(jìn)一步閱讀
- 閱讀資金賬單文件格式說明和交易賬單文件格式說明,了解如何解析賬單,以設(shè)計(jì)和實(shí)現(xiàn)你的程序化對賬。