众所周知,腾讯的文档是给内部人员看的,官方Demo不够完全,以致新手入门困难,这里通过调用第三方封装接口,将部分流程进行简化
第三方封装官网:https://javen205.gitee.io/ijpay/
微信官方文档:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_8.shtml
此项目的GitHub地址: https://github.com/qingyiyezhou/WechatPayDemo/tree/master
一、Maven引入
<dependency>
<groupId>com.github.javen205</groupId>
<artifactId>IJPay-All</artifactId>
<version>2.7.4</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.25</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
功能:下载交易账单
1.申请交易账单核心方法
/**
* 申请交易账单
*
* @param billDate 账单日期(仅支持三个月内的账单下载申请)
* @return 交易账单返参
*/
public WechatTradeBillDownloadResp tradeBill(String billDate) {
try {
if (CharSequenceUtil.isEmpty(billDate)) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.DATE, -1);
billDate = DateUtil.format(calendar.getTime(), "YYYY-MM-dd");
}
Map<String, String> params = new HashMap<>(12);
params.put("bill_date", billDate);
params.put("bill_type", "ALL");
// 返回格式为.gzip的压缩包账单,不设置默认为数据流
//params.put("tar_type", "GZIP");
IJPayHttpResponse result = WxPayApi.v3(
RequestMethod.GET,
WxDomain.CHINA.getType(),
WxApiType.TRADE_BILL.toString(),
wechatConfig.getMchId(),
wechatConfig.getSerialNo(),
null,
getPrivateKey(),
params
);
// 根据证书序列号查询对应的证书来验证签名结果
checkedSignature(result);
if (result.getStatus() != 200) {
throw new RuntimeException("申请交易账单失败," + result.getBody());
}
return JSON.parseObject(result.getBody(), WechatTradeBillDownloadResp.class);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
2.下载交易账单核心方法
/**
* 下载交易账单
*
* @param token token
* @return 交易账单数据
*/
public HttpResponse billDownload(String token) throws Exception {
long timestamp = System.currentTimeMillis() / 1000;
String authType = "WECHATPAY2-SHA256-RSA2048";
// 生成随机字符串
String nonceStr = WxPayKit.generateStr();
String urlSuffix = WxApiType.BILL_DOWNLOAD.toString().concat("?").concat("token=" + token);
// 拼接url
String url = WxDomain.CHINA.getType() + urlSuffix;
// 构建签名
String authorization = WxPayKit.buildAuthorization(RequestMethod.GET, urlSuffix,
wechatConfig.getMchId(), wechatConfig.getSerialNo(),
getPrivateKey(), "", nonceStr, timestamp, authType);
Map<String, String> headers = WxPayApi.getHeaders(authorization, wechatConfig.getSerialNo());
return HttpRequest.get(url).addHeaders(headers).execute();
}
3.Service调用
public TradeBillDataResp downloadTradeBill(String date) {
WechatPayV3 wechatPayV3 = new WechatPayV3(wechatConfig);
// 申请交易账单
WechatTradeBillDownloadResp wechatTradeBillDownloadResp = wechatPayV3.tradeBill(date);
// 解析交易账单下载地址,获取token
String downloadUrl = wechatTradeBillDownloadResp.getDownloadUrl();
UrlBuilder urlBuilder = UrlBuilder.ofHttp(downloadUrl, CharsetUtil.CHARSET_UTF_8);
String token = urlBuilder.getQuery().get("token").toString();
try (
// 获取交易账单数据流
HttpResponse httpResponse = wechatPayV3.billDownload(token);
) {
if (httpResponse.getStatus() != 200){
return null;
}
// 异步备份交易账单文件(建议使用线程池,此处简略操作)
new Thread(() -> {
File folder = new File(WECHAT_TEMP_PATH);
if (!folder.exists() && !folder.isDirectory()) {
boolean mkdirs = folder.mkdirs();
Assert.isTrue(mkdirs, "创建微信交易账单文件夹失败");
}
// 文件名
String targetPath = WECHAT_TEMP_PATH.concat(wechatConfig.getMchId())
.concat("All")
.concat(date)
.concat(".csv");
IOUtil.backUpFile(httpResponse.bodyStream(), targetPath);
});
// 解析数据流
return parseBody(httpResponse.body());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@GetMapping("/downloadTradeBill")
TradeBillDataResp downloadTradeBill(@RequestParam String date) {
return wechatBillService.downloadTradeBill(date);
}
4.测试
最后吐槽一下,微信支付的文档真的烂