瀏覽代碼

#503 微信支付增加资金账单下载接口

master
鱼丸Cwivan 6 年之前
committed by Binary Wang
父節點
當前提交
cc6dd65671
共有 7 個文件被更改,包括 430 次插入36 次删除
  1. +90
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayDownloadFundFlowRequest.java
  2. +71
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayFundFlowBaseResult.java
  3. +60
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayFundFlowResult.java
  4. +21
    -4
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java
  5. +43
    -32
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java
  6. +119
    -0
      weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java
  7. +26
    -0
      weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImplTest.java

+ 90
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayDownloadFundFlowRequest.java 查看文件

@@ -0,0 +1,90 @@
package com.github.binarywang.wxpay.bean.request;

import com.github.binarywang.wxpay.constant.WxPayConstants.AccountType;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.*;
import me.chanjar.weixin.common.annotation.Required;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.Arrays;

/**
* <pre>
* 微信支付下载资金账单请求参数类
* Created by cwivan on 2018-08-02.
* </pre>
*
* @author <a href="https://github.com/cwivan">cwivan</a>
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Builder(builderMethodName = "newBuilder")
@NoArgsConstructor
@AllArgsConstructor
@XStreamAlias("xml")
public class WxPayDownloadFundFlowRequest extends BaseWxPayRequest {
private static final String[] ACCOUNT_TYPES = new String[]{AccountType.BASIC, AccountType.OPERATION, AccountType.FEES};
private static final String SIGN_TYPE_HMAC_SHA256 = "HMAC-SHA256";
private static final String TAR_TYPE_GZIP = "GZIP";

/**
* <pre>
* 对账单日期
* bill_date
* 是
* String(8)
* 20140603
* 下载对账单的日期,格式:20140603
* </pre>
*/
@Required
@XStreamAlias("bill_date")
private String billDate;

/**
* <pre>
* 资金账户类型
* account_type
* 是
* Basic
* String(8)
* --Basic,基本账户
* --Operation,运营账户
* --Fees,手续费账户
* </pre>
*/
@Required
@XStreamAlias("account_type")
private String accountType;

/**
* <pre>
* 压缩账单
* tar_type
* 否
* String(8)
* GZIP
* 非必传参数,固定值:GZIP,返回格式为.gzip的压缩包账单。不传则默认为数据流形式。
* </pre>
*/
@XStreamAlias("tar_type")
private String tarType;

@Override
protected void checkConstraints() throws WxPayException {
if (StringUtils.isNotBlank(this.getTarType()) && !TAR_TYPE_GZIP.equals(this.getTarType())) {
throw new WxPayException("tar_type值如果存在,只能为GZIP");
}

if (!ArrayUtils.contains(ACCOUNT_TYPES, this.getAccountType())) {
throw new WxPayException(String.format("account_type必须为%s其中之一,实际值:%s",
Arrays.toString(ACCOUNT_TYPES), this.getAccountType()));
}
/**
* 目前仅支持HMAC-SHA256
*/
this.setSignType(SIGN_TYPE_HMAC_SHA256);
}
}

+ 71
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayFundFlowBaseResult.java 查看文件

@@ -0,0 +1,71 @@
package com.github.binarywang.wxpay.bean.result;

import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import java.io.Serializable;

/**
* 记账时间:2018-02-01 04:21:23 微信支付业务单号:50000305742018020103387128253 资金流水单号:1900009231201802015884652186 业务名称:退款
* 业务类型:退款 收支类型:支出 收支金额(元):0.02 账户结余(元):0.17 资金变更提交申请人:system 备注:缺货 业务凭证号:REF4200000068201801293084726067
*
* @author cwivan
*/
@Data
@NoArgsConstructor
public class WxPayFundFlowBaseResult implements Serializable {
private static final long serialVersionUID = 4474557532904682718L;

@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
}

/**
* 记账时间
*/
private String BillingTime;
/**
* 微信支付业务单号
*/
private String bizTransactionId;
/**
* 资金流水单号
*/
private String fundFlowId;
/**
* 业务名称
*/
private String bizName;
/**
* 业务类型
*/
private String bizType;
/**
* 收支类型
*/
private String financialType;
/**
* 收支金额(元)
*/
private String financialFee;
/**
* 账户结余(元)
*/
private String AccountBalance;
/**
* 资金变更提交申请人
*/
private String fundApplicant;
/**
* 备注
*/
private String memo;
/**
* 业务凭证号
*/
private String bizVoucherId;

}

+ 60
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayFundFlowResult.java 查看文件

@@ -0,0 +1,60 @@
package com.github.binarywang.wxpay.bean.result;

import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import java.io.Serializable;
import java.util.List;

/**
* <pre>
* 下载资金账单接口响应结果对象类
* Created by cwivan on 2018-08-02.
* </pre>
*
* @author cwivan
* @date 2018-08-02
*/
@Data
@NoArgsConstructor
public class WxPayFundFlowResult implements Serializable{
private static final long serialVersionUID = 8371500036495349207L;

@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
}

/**
* 资金流水返回对象
*/
private List<WxPayFundFlowBaseResult> wxPayFundFlowBaseResultList;

/**
* 资金流水总笔数
*/
private String totalRecord;

/**
* 收入笔数
*/
private String incomeRecord;

/**
* 收入金额
*/
private String incomeAmount;

/**
* 支出笔数
*/
private String expenditureRecord;

/**
* 支出金额
*/
private String expenditureAmount;

}

+ 21
- 4
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java 查看文件

@@ -1,11 +1,10 @@
package com.github.binarywang.wxpay.constant;

import java.text.Format;
import java.util.List;

import com.google.common.collect.Lists;
import org.apache.commons.lang3.time.FastDateFormat;

import com.google.common.collect.Lists;
import java.text.Format;
import java.util.List;

/**
* <pre>
@@ -106,6 +105,24 @@ public class WxPayConstants {
public static final String MICROPAY = "MICROPAY";
}

/**
* 账户类型
*/
public static class AccountType{
/**
* 基本账户
*/
public static final String BASIC = "Basic";
/**
* 运营账户
*/
public static final String OPERATION = "Operation";
/**
* Fees
*/
public static final String FEES = "Fees";
}

/**
* 签名类型.
*/


+ 43
- 32
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java 查看文件

@@ -1,44 +1,19 @@
package com.github.binarywang.wxpay.service;

import java.io.File;
import java.util.Date;
import java.util.Map;

import com.github.binarywang.wxpay.bean.WxPayApiData;
import com.github.binarywang.wxpay.bean.coupon.WxPayCouponInfoQueryRequest;
import com.github.binarywang.wxpay.bean.coupon.WxPayCouponInfoQueryResult;
import com.github.binarywang.wxpay.bean.coupon.WxPayCouponSendRequest;
import com.github.binarywang.wxpay.bean.coupon.WxPayCouponSendResult;
import com.github.binarywang.wxpay.bean.coupon.WxPayCouponStockQueryRequest;
import com.github.binarywang.wxpay.bean.coupon.WxPayCouponStockQueryResult;
import com.github.binarywang.wxpay.bean.coupon.*;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxScanPayNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayAuthcode2OpenidRequest;
import com.github.binarywang.wxpay.bean.request.WxPayDownloadBillRequest;
import com.github.binarywang.wxpay.bean.request.WxPayMicropayRequest;
import com.github.binarywang.wxpay.bean.request.WxPayOrderCloseRequest;
import com.github.binarywang.wxpay.bean.request.WxPayOrderQueryRequest;
import com.github.binarywang.wxpay.bean.request.WxPayOrderReverseRequest;
import com.github.binarywang.wxpay.bean.request.WxPayRefundQueryRequest;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayReportRequest;
import com.github.binarywang.wxpay.bean.request.WxPaySendRedpackRequest;
import com.github.binarywang.wxpay.bean.request.WxPayShorturlRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayBillResult;
import com.github.binarywang.wxpay.bean.result.WxPayMicropayResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderCloseResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderReverseResult;
import com.github.binarywang.wxpay.bean.result.WxPayRedpackQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.bean.result.WxPaySendRedpackResult;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.bean.request.*;
import com.github.binarywang.wxpay.bean.result.*;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;

import java.io.File;
import java.util.Date;
import java.util.Map;

/**
* <pre>
* 微信支付相关接口.
@@ -378,6 +353,42 @@ public interface WxPayService {
*/
WxPayBillResult downloadBill(WxPayDownloadBillRequest request) throws WxPayException;

/**
* <pre>
* 下载资金账单.
* 商户可以通过该接口下载自2017年6月1日起 的历史资金流水账单。
* 注意:
* 1、资金账单中的数据反映的是商户微信账户资金变动情况;
* 2、当日账单在次日上午9点开始生成,建议商户在上午10点以后获取;
* 3、资金账单中涉及金额的字段单位为“元”。
* 接口链接:https://api.mch.weixin.qq.com/pay/downloadfundflow
* 详情请见: <a href="https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_18">下载对账单</a>
* </pre>
*
* @param billDate 资金账单日期 bill_date 下载对账单的日期,格式:20140603
* @param accountType 资金账户类型 account_type Basic,基本账户,Operation,运营账户,Fees,手续费账户
* @param tarType 压缩账单 tar_type 非必传参数,固定值:GZIP,返回格式为.gzip的压缩包账单。不传则默认为数据流形式。
* @return WxPayFundFlowResult对象
*/
WxPayFundFlowResult downloadFundFlow(String billDate, String accountType, String tarType) throws WxPayException;

/**
* <pre>
* 下载资金账单.
* 商户可以通过该接口下载自2017年6月1日起 的历史资金流水账单。
* 注意:
* 1、资金账单中的数据反映的是商户微信账户资金变动情况;
* 2、当日账单在次日上午9点开始生成,建议商户在上午10点以后获取;
* 3、资金账单中涉及金额的字段单位为“元”。
* 接口链接:https://api.mch.weixin.qq.com/pay/downloadfundflow
* 详情请见: <a href="https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_18">下载对账单</a>
* </pre>
*
* @param request 下载资金流水请求
* @return WxPayFundFlowResult对象
*/
WxPayFundFlowResult downloadFundFlow(WxPayDownloadFundFlowRequest request) throws WxPayException;

/**
* <pre>
* 提交刷卡支付.


+ 119
- 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java 查看文件

@@ -581,6 +581,125 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
return wxPayBillResult;
}

@Override
public WxPayFundFlowResult downloadFundFlow(String billDate, String accountType, String tarType) throws WxPayException {

WxPayDownloadFundFlowRequest request = new WxPayDownloadFundFlowRequest();
request.setBillDate(billDate);
request.setAccountType(accountType);
request.setTarType(tarType);

return this.downloadFundFlow(request);
}

@Override
public WxPayFundFlowResult downloadFundFlow(WxPayDownloadFundFlowRequest request) throws WxPayException {
request.checkAndSign(this.getConfig());

String url = this.getPayBaseUrl() + "/pay/downloadfundflow";

String responseContent;
if (TarType.GZIP.equals(request.getTarType())) {
responseContent = this.handleGzipFundFlow(url, request.toXML());
} else {
responseContent = this.post(url, request.toXML(), true);
if (responseContent.startsWith("<")) {
throw WxPayException.from(BaseWxPayResult.fromXML(responseContent, WxPayCommonResult.class));
}
}

return this.handleFundFlow(responseContent);
}

private String handleGzipFundFlow(String url, String requestStr) throws WxPayException {
try {
byte[] responseBytes = this.postForBytes(url, requestStr, true);
Path tempDirectory = Files.createTempDirectory("fundFlow");
Path path = Paths.get(tempDirectory.toString(), System.currentTimeMillis() + ".gzip");
Files.write(path, responseBytes);

try {
List<String> allLines = Files.readAllLines(ZipUtil.ungzip(path.toFile()).toPath(), StandardCharsets.UTF_8);
return Joiner.on("\n").join(allLines);
} catch (ZipException e) {
if (e.getMessage().contains("Not in GZIP format")) {
throw WxPayException.from(BaseWxPayResult.fromXML(new String(responseBytes, StandardCharsets.UTF_8),
WxPayCommonResult.class));
} else {
this.log.error("解压zip文件出错", e);
throw new WxPayException("解压zip文件出错");
}
}
} catch (WxPayException wxPayException) {
throw wxPayException;
} catch (Exception e){
this.log.error("解析对账单文件时出错", e);
throw new WxPayException("解压zip文件出错");
}
}

private WxPayFundFlowResult handleFundFlow(String responseContent) {
WxPayFundFlowResult wxPayFundFlowResult = new WxPayFundFlowResult();

String listStr = "";
String objStr = "";

if (StringUtils.isNotBlank(responseContent) && responseContent.contains("资金流水总笔数")) {
listStr = responseContent.substring(0, responseContent.indexOf("资金流水总笔数"));
objStr = responseContent.substring(responseContent.indexOf("资金流水总笔数"));
}
/*
* 记账时间:2018-02-01 04:21:23 微信支付业务单号:50000305742018020103387128253 资金流水单号:1900009231201802015884652186 业务名称:退款
* 业务类型:退款 收支类型:支出 收支金额(元):0.02 账户结余(元):0.17 资金变更提交申请人:system 备注:缺货 业务凭证号:REF4200000068201801293084726067
* 参考以上格式进行取值
*/
List<WxPayFundFlowBaseResult> wxPayFundFlowBaseResultList = new LinkedList<>();
// 去空格
String newStr = listStr.replaceAll(",", " ");
// 数据分组
String[] tempStr = newStr.split("`");
// 分组标题
String[] t = tempStr[0].split(" ");
// 计算循环次数
int j = tempStr.length / t.length;
// 纪录数组下标
int k = 1;
for (int i = 0; i < j; i++) {
WxPayFundFlowBaseResult wxPayFundFlowBaseResult = new WxPayFundFlowBaseResult();

wxPayFundFlowBaseResult.setBillingTime(tempStr[k].trim());
wxPayFundFlowBaseResult.setBizTransactionId(tempStr[k + 1].trim());
wxPayFundFlowBaseResult.setFundFlowId(tempStr[k + 2].trim());
wxPayFundFlowBaseResult.setBizName(tempStr[k + 3].trim());
wxPayFundFlowBaseResult.setBizType(tempStr[k + 4].trim());
wxPayFundFlowBaseResult.setFinancialType(tempStr[k + 5].trim());
wxPayFundFlowBaseResult.setFinancialFee(tempStr[k + 6].trim());
wxPayFundFlowBaseResult.setAccountBalance(tempStr[k + 7].trim());
wxPayFundFlowBaseResult.setFundApplicant(tempStr[k + 8].trim());
wxPayFundFlowBaseResult.setMemo(tempStr[k + 9].trim());
wxPayFundFlowBaseResult.setBizVoucherId(tempStr[k + 10].trim());

wxPayFundFlowBaseResultList.add(wxPayFundFlowBaseResult);
k += t.length;
}
wxPayFundFlowResult.setWxPayFundFlowBaseResultList(wxPayFundFlowBaseResultList);

/*
* 资金流水总笔数,收入笔数,收入金额,支出笔数,支出金额 `20.0,`17.0,`0.35,`3.0,`0.18
* 参考以上格式进行取值
*/
String totalStr = objStr.replaceAll(",", " ");
String[] totalTempStr = totalStr.split("`");
wxPayFundFlowResult.setTotalRecord(totalTempStr[1]);
wxPayFundFlowResult.setIncomeRecord(totalTempStr[2]);
wxPayFundFlowResult.setIncomeAmount(totalTempStr[3]);
wxPayFundFlowResult.setExpenditureRecord(totalTempStr[4]);
wxPayFundFlowResult.setExpenditureAmount(totalTempStr[5]);

return wxPayFundFlowResult;

}

@Override
public WxPayMicropayResult micropay(WxPayMicropayRequest request) throws WxPayException {
request.checkAndSign(this.getConfig());


+ 26
- 0
weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImplTest.java 查看文件

@@ -11,6 +11,7 @@ import com.github.binarywang.wxpay.bean.result.*;
import com.github.binarywang.wxpay.constant.WxPayConstants.BillType;
import com.github.binarywang.wxpay.constant.WxPayConstants.SignType;
import com.github.binarywang.wxpay.constant.WxPayConstants.TradeType;
import com.github.binarywang.wxpay.constant.WxPayConstants.AccountType;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.testbase.ApiTestModule;
@@ -165,6 +166,31 @@ public class BaseWxPayServiceImplTest {
this.payService.downloadBill("", "", "", null);
}

@DataProvider
public Object[][] fundFlowData() {
return new Object[][]{
{"20180819", AccountType.BASIC, TarType.GZIP},
{"20180819", AccountType.OPERATION, TarType.GZIP},
{"20180819", AccountType.FEES, TarType.GZIP},
{"20180819", AccountType.BASIC, null},
{"20180819", AccountType.OPERATION, null},
{"20180819", AccountType.FEES, null}
};
}

@Test(dataProvider = "fundFlowData")
public void testDownloadFundFlow(String billDate, String accountType, String tarType) throws Exception {
WxPayFundFlowResult fundFlowResult = this.payService.downloadFundFlow(billDate, accountType, tarType);
assertThat(fundFlowResult).isNotNull();
this.logger.info(fundFlowResult.toString());
}

@Test(expectedExceptions = WxPayException.class)
public void testDownloadFundFlow_withNoParams() throws Exception {
//必填字段为空时,抛出异常
this.payService.downloadFundFlow("", "", null);
}

@Test
public void testReport() throws Exception {
WxPayReportRequest request = new WxPayReportRequest();


Loading…
取消
儲存