业务示例代码

更新时间:2025.12.03

1. 目标

通过本教程的学习,你应该可以:

2. 业务处理流程

2.1. 申请交易账单并下载账单

微信支付在每日10点后生成昨日交易账单文件,商户可通过接口获取账单下载链接。账单包含交易金额、时间及营销信息,利于订单核对、退款审查及银行到账确认。详细介绍参考:下载账单-产品介绍

1package com.java.downloadbilldemo.partner;
2
3import com.java.demo.DownloadBill; // 下载账单 https://pay.weixin.qq.com/doc/v3/partner/4013080597
4import com.java.demo.GetTradeBill; // 申请所有/单个特约商户交易账单 https://pay.weixin.qq.com/doc/v3/partner/4013080595
5import com.java.utils.WXPayUtility; // 引用微信支付工具库,参考:https://pay.weixin.qq.com/doc/v3/partner/4014985777
6
7import static com.java.demo.DownloadBill.*; // 下载账单 https://pay.weixin.qq.com/doc/v3/partner/4013080597
8import static com.java.demo.GetTradeBill.*; // 申请所有/单个特约商户交易账单 https://pay.weixin.qq.com/doc/v3/partner/4013080595
9
10public class DownloadTradeBillDemo {
11    public static void main(String[] args) {
12        GetTradeBill getTradeBill = new GetTradeBill(
13                "19xxxxxxxx", // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/partner/4013080340
14                "1DDE55AD98Exxxxxxxxxx", // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4012081992
15                "/path/to/apiclient_key.pem", // 商户API证书私钥文件路径,本地文件路径
16                "PUB_KEY_ID_xxxxxxxxxxxxx", // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013038589
17                "/path/to/wxp_pub.pem" // 微信支付公钥文件路径,本地文件路径
18        );
19
20        DownloadBill downloadBill = new DownloadBill(
21                "19xxxxxxxx", // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/partner/4013080340
22                "1DDE55AD98Exxxxxxxxxx", // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4012081992
23                "/path/to/apiclient_key.pem", // 商户API证书私钥文件路径,本地文件路径
24                "PUB_KEY_ID_xxxxxxxxxxxxx", // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013038589
25                "/path/to/wxp_pub.pem" // 微信支付公钥文件路径,本地文件路径
26        );
27        try {
28            GetTradeBillRequest getTradeBillRequest = new GetTradeBillRequest();
29            getTradeBillRequest.billDate = "2025-08-11"; // 期望申请下载的账单日期
30            getTradeBillRequest.billType = BillType.ALL; // 期望申请下载的账单类型
31            getTradeBillRequest.tarType = GetTradeBill.TarType.GZIP; // 期望申请下载的账单类型
32
33            QueryBillEntity response = getTradeBill.run(getTradeBillRequest);
34
35            System.out.println("Download URL: " + response.downloadUrl);
36
37            DownloadBillRequest downloadBillRequest = new DownloadBillRequest();
38            downloadBillRequest.downloadUrl = response.downloadUrl;
39            downloadBillRequest.localFilePath = "test.csv"; // 期望下载的账单文件路径
40            downloadBillRequest.tarType = DownloadBill.TarType.valueOf(getTradeBillRequest.tarType.name());
41            downloadBillRequest.expectedHashType = DownloadBill.HashType.valueOf(response.hashType.name());
42            downloadBillRequest.expectedHashValue = response.hashValue;
43
44            downloadBill.run(downloadBillRequest);
45
46            System.out.println("File downloaded successfully! Local file path: " + downloadBillRequest.localFilePath);
47            // TODO: 请求成功,继续业务逻辑
48        } catch (WXPayUtility.ApiException e) {
49            // TODO: 请求失败,根据状态码执行不同的逻辑
50            String errorCode = e.getErrorCode();
51            if (errorCode != null && errorCode.equals("NO_STATEMENT_EXIST")) {
52                // 错误:账单不存在
53                // 解决方式:请检查当前商户号在指定日期内是否有成功的交易或退款
54                // 描述:说明指定日期无账单文件生成。若无交易,则无需重试
55            } else if (errorCode != null && errorCode.equals("STATEMENT_CREATING")) {
56                // 错误:账单正在生成中
57                // 解决方式:请检查当前商户号在指定日期内是否有成功的交易或退款
58                // 描述:说明指定日期账单正在生成中。若无交易,则无需重试;若有交易,则在T+1日上午10点后再重新下载
59            } else if (errorCode != null && errorCode.equals("SYSTEM_ERROR")) {
60                // 错误:系统错误
61                // 解决方式:稍后重试
62                // 描述:微信支付系统失败,系统失败直接立即重试大概率还会是系统失败,建议等1分钟后再重试
63            } else if (errorCode != null && errorCode.equals("FREQUENCY_LIMITED")) {
64                // 错误:限频报错
65                // 解决方式:稍后重试
66                // 描述: 接口频率限制,直接立即重试大概率还会是系统失败,建议等1分钟后再重试
67            } else if (errorCode != null && errorCode.equals("SIGN_ERROR")) {
68                // 错误:签名错误
69                // 解决方式:检查平台商户证书序列号,证书私钥文件,公钥ID,公钥文件,同时确认下签名过程是不是按照微信支付的签名方式
70                // 描述:签名报错,需要确认签名材料和签名流程是否正确
71            } else if (errorCode != null && errorCode.equals("PARAM_ERROR")) {
72                // 错误:参数错误
73                // 解决方式:按照报错返回的message,重新输入请求参数
74                // 描述:参数的类型,长度,或者必填选项没有填写等
75            } else if (errorCode != null && errorCode.equals("INVALID_REQUEST")) {
76                // 错误:请求非法,请求参数正确,但是不符合下载账单业务规则
77                // 解决方式:根据具体message查看具体哪里不符合业务规则,如果可以修改参数达到符合业务规则的修改请求符合业务规则之后再重试
78                // 描述:不符合业务规则的场景如:
79                // - 账单时间超过三个月,不允许申请下载账单
80            } else {
81                // 其他类型错误:稍等一会后重试
82            }
83        }
84    }
85}
86

 

2.2. 申请服务商资金账单并下载账单

微信支付按天提供服务商各账户的资金流水账单文件,服务商可以通过该接口获取账单文件的下载地址。账单文件详细记录了服务商账户资金操作的相关信息,包括业务单号、收支金额及记账时间等,以便服务商进行核对与确认。详细介绍参考: 产品介绍 

1package com.java.downloadbilldemo.partner;
2
3import com.java.demo.DownloadBill; // 下载账单 https://pay.weixin.qq.com/doc/v3/partner/4013080597
4import com.java.demo.DownloadBill.DownloadBillRequest;
5import com.java.demo.GetFundFlowBill; // 申请服务商资金账单 https://pay.weixin.qq.com/doc/v3/partner/4013080596
6import com.java.demo.GetFundFlowBill.FundFlowBillAccountType;
7import com.java.demo.GetFundFlowBill.GetFundFlowBillRequest;
8import com.java.demo.GetFundFlowBill.QueryBillEntity;
9import com.java.utils.WXPayUtility; // 引用微信支付工具库,参考:https://pay.weixin.qq.com/doc/v3/partner/4014985777
10
11public class DownloadFundFlowBillDemo {
12
13    public static void main(String[] args) {
14        String mchCode = "19xxxxxxxx"; // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/partner/4012081992
15        String mchSerialNo = "1DDE55AD98Exxxxxxxxxx"; // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4012081992
16        String mchPrivateKeyPath = "/path/to/apiclient_key.pem"; // 商户API证书私钥文件路径,本地文件路径
17        String mchPublicKeyId = "PUB_KEY_ID_xxxxxxxxxxxxx"; // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013038589
18        String mchPublicKeyPath = "/path/to/wxp_pub.pem"; // 微信支付公钥文件路径,本地文件路径
19
20        GetFundFlowBill getFundFlowBill = new GetFundFlowBill(
21                mchCode,
22                mchSerialNo,
23                mchPrivateKeyPath,
24                mchPublicKeyId,
25                mchPublicKeyPath
26        );
27
28        DownloadBill downloadBill = new DownloadBill(
29                mchCode,
30                mchSerialNo,
31                mchPrivateKeyPath,
32                mchPublicKeyId,
33                mchPublicKeyPath
34        );
35
36        try {
37            GetFundFlowBillRequest getFundFlowBillRequest = new GetFundFlowBillRequest();
38            getFundFlowBillRequest.billDate = "2025-11-25"; // 期望申请下载的账单日期
39            getFundFlowBillRequest.accountType = FundFlowBillAccountType.BASIC; // 期望申请下载的账单类型
40            getFundFlowBillRequest.tarType = GetFundFlowBill.TarType.GZIP; // 期望申请下载的账单压缩类型
41
42            QueryBillEntity response = getFundFlowBill.run(getFundFlowBillRequest);
43
44            System.out.println("Download URL: " + response.downloadUrl);
45
46            DownloadBillRequest downloadBillRequest = new DownloadBillRequest();
47            downloadBillRequest.downloadUrl = response.downloadUrl;
48            // 期望下载的账单文件路径(当前目录下 mchCode+accountType+bill_date.csv)
49            downloadBillRequest.localFilePath = mchCode + "_" + getFundFlowBillRequest.accountType.name() + "_" + getFundFlowBillRequest.billDate + ".csv";
50            downloadBillRequest.tarType = DownloadBill.TarType.valueOf(getFundFlowBillRequest.tarType.name());
51            downloadBillRequest.expectedHashType = DownloadBill.HashType.valueOf(response.hashType.name());
52            downloadBillRequest.expectedHashValue = response.hashValue;
53
54            downloadBill.run(downloadBillRequest);
55
56            System.out.println("File downloaded successfully! Local file path: " + downloadBillRequest.localFilePath);
57
58        } catch (WXPayUtility.ApiException e) {
59            // TODO: 请求失败,根据状态码执行不同的逻辑
60            String errorCode = e.getErrorCode();
61            if (errorCode != null && errorCode.equals("NO_STATEMENT_EXIST")) {
62                // 错误:账单不存在
63                // 解决方式:请检查当前商户号在指定日期内是否有资金变动
64                // 描述:说明指定日期无账单文件生成。若无资金变动,则无需重试
65            } else if (errorCode != null && errorCode.equals("STATEMENT_CREATING")) {
66                // 错误:账单正在生成中
67                // 解决方式:请检查当前商户号在指定日期内是否有资金变动
68                // 描述:说明指定日期账单正在生成中。若无资金变动,则无需重试;若有资金变动,则在T+1日上午10点后再重新下载
69            } else if (errorCode != null && errorCode.equals("SYSTEM_ERROR")) {
70                // 错误:系统错误
71                // 解决方式:稍后重试
72                // 描述:微信支付系统失败,系统失败直接立即重试大概率还会是系统失败,建议等1分钟后再重试
73            } else if (errorCode != null && errorCode.equals("FREQUENCY_LIMITED")) {
74                // 错误:限频报错
75                // 解决方式:稍后重试
76                // 描述:接口频率限制,直接立即重试大概率还会是系统失败,建议等1分钟后再重试
77            } else if (errorCode != null && errorCode.equals("SIGN_ERROR")) {
78                // 错误:签名错误
79                // 解决方式:检查平台商户证书序列号,证书私钥文件,公钥ID,公钥文件,同时确认下签名过程是不是按照微信支付的签名方式
80                // 描述:签名报错,需要确认签名材料和签名流程是否正确
81            } else if (errorCode != null && errorCode.equals("PARAM_ERROR")) {
82                // 错误:参数错误
83                // 解决方式:按照报错返回的message,重新输入请求参数
84                // 描述:参数的类型,长度,或者必填选项没有填写等
85            } else if (errorCode != null && errorCode.equals("INVALID_REQUEST")) {
86                // 错误:请求非法,请求参数正确,但是不符合下载账单业务规则
87                // 解决方式:根据具体message查看具体哪里不符合业务规则,如果可以修改参数达到符合业务规则的修改请求符合业务规则之后再重试
88                // 描述:不符合业务规则的场景如:
89                // - 账单时间超过三个月,不允许申请下载账单
90            } else {
91                // 其他类型错误:稍等一会后重试
92            }
93        }
94    }
95}
96