diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/FundBillRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/FundBillRequest.java new file mode 100644 index 0000000000..9f12bc3781 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/FundBillRequest.java @@ -0,0 +1,79 @@ +package com.github.binarywang.wxpay.bean.ecommerce; + +import com.google.gson.annotations.SerializedName; +import lombok.*; + +/** + * 资金账单请求 + * @author: f00lish + * @date: 2020/09/28 + */ +@Data +@Builder +@ToString +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class FundBillRequest { + + /** + *
+   * 字段名:账单日期
+   * 变量名:bill_date
+   * 是否必填:是
+   * 类型:string(10)
+   * 描述:
+   *  格式YYYY-MM-DD
+   *  仅支持三个月内的账单下载申请。
+   *  示例值:2019-06-11
+   * 
+ */ + @SerializedName(value = "bill_date") + private String billDate; + + + /** + *
+   * 字段名:资金账户类型
+   * 变量名:account_type
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  枚举值:
+   *  ALL:所有账户
+   *  示例值:ALL
+   * 
+ */ + @SerializedName(value = "account_type") + private String accountType; + + /** + *
+   * 字段名:压缩类型
+   * 变量名:tar_type
+   * 是否必填:否
+   * 类型:string(32)
+   * 描述:
+   *  不填则以不压缩的方式返回数据流
+   *  枚举值:
+   *  GZIP:返回格式为.gzip的压缩包账单
+   *  示例值:GZIP
+   * 
+ */ + @SerializedName(value = "tar_type") + private String tarType; + + /** + *
+   * 字段名:加密算法
+   * 变量名:algorithm
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  枚举值:
+   *  AEAD_AES_256_GCM:AEAD_AES_256_GCM加密算法
+   *  示例值:AEAD_AES_256_GCM
+   * 
+ */ + @SerializedName(value = "algorithm") + private String algorithm; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/FundBillResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/FundBillResult.java new file mode 100644 index 0000000000..de0dcdb890 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/FundBillResult.java @@ -0,0 +1,139 @@ +package com.github.binarywang.wxpay.bean.ecommerce; + +import com.google.gson.annotations.SerializedName; +import lombok.*; + +/** + * 资金账单结果 + * @author: f00lish + * @date: 2020/09/28 + */ +@Data +@Builder +@ToString +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class FundBillResult { + + /** + *
+   * 字段名:下载信息总数
+   * 变量名:download_bill_count
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  下载信息总数
+   *  示例值:1
+   * 
+ */ + @SerializedName(value = "download_bill_count") + private int downloadBillCount; + + + + /** + *
+   * 字段名:下载信息明细
+   * 变量名:download_bill_list
+   * 是否必填:否
+   * 类型:array
+   * 描述:
+   *  下载信息明细
+   * 
+ */ + @SerializedName(value = "download_bill_list") + private FundBill[] downloadBillList; + + @Data + public static class FundBill { + + /** + *
+     * 字段名:账单文件序号
+     * 变量名:bill_sequence
+     * 是否必填:是
+     * 类型:int
+     * 描述:
+     *  商户将多个文件按账单文件序号的顺序合并为完整的资金账单文件,起始值为1
+     *  示例值:1
+     * 
+ */ + @SerializedName(value = "bill_sequence") + private String billSequence; + + /** + *
+     * 字段名:哈希类型
+     * 变量名:hash_type
+     * 是否必填:是
+     * 类型:string(32)
+     * 描述:
+     *  枚举值:
+     *  SHA1:SHA1值
+     *  示例值:SHA1
+     * 
+ */ + @SerializedName(value = "hash_type") + private String hashType; + + /** + *
+     * 字段名:哈希值
+     * 变量名:hash_value
+     * 是否必填:是
+     * 类型:string(1024)
+     * 描述:
+     *  原始账单(gzip需要解压缩)的摘要值,用于校验文件的完整性。
+     *  示例值:79bb0f45fc4c42234a918000b2668d689e2bde04
+     * 
+ */ + @SerializedName(value = "hash_value") + private String hashValue; + + /** + *
+     * 字段名:账单下载地址
+     * 变量名:download_url
+     * 是否必填:是
+     * 类型:string(2048)
+     * 描述:
+     *  供下一步请求账单文件的下载地址,该地址30s内有效。
+     *  示例值:https://api.mch.weixin.qq.com/v3/billdownload/file?token=xxx
+     * 
+ */ + @SerializedName(value = "download_url") + private String downloadUrl; + + + /** + *
+     * 字段名:加密密钥
+     * 变量名:encrypt_key
+     * 是否必填:是
+     * 类型:string(512)
+     * 描述:
+     *  加密账单文件使用的加密密钥。密钥用商户证书的公钥进行加密,然后进行Base64编码
+     *  示例值:YpkbxSne+mDwyXq//xYPmtr9eQ5LsH7zLMZSs+GSEcY4wjhlsfioS4n9X6q1ZBL0wM1v5qd7KhWuj0rFJ4N1FidP7Q8KDy25QDTt46wiKnsPKSCAXWRFNw1D2JmJBqZsc9y5g0DupONWKYB2GfRigRDEBVszj67uOIILPdxOKX1w3N4jvu0U9IFanJa7ldm70KVvYrMWVgQFDPbgjh1gVDbuTAjmPN88AobLdkiegnBUS2woDZW+PfhPo13kweOiR3h1gXIKRlnKnN3Jkkwpna/AFFijXrFphO3voSuiV0CfptfzTtcae4X3DYG3RSroKqmpa+5tuy2aU2VJUSIuFQ==
+     * 
+ */ + @SerializedName(value = "encrypt_key") + private String encryptKey; + + /** + *
+     * 字段名:随机字符串
+     * 变量名:nonce
+     * 是否必填:是
+     * 类型:string(16)
+     * 描述:
+     *  加密账单文件使用的随机字符串
+     *  示例值:a8607ef79034c49c
+     * 
+ */ + @SerializedName(value = "nonce") + private String nonce; + + + } + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/BillRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/TradeBillRequest.java similarity index 97% rename from weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/BillRequest.java rename to weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/TradeBillRequest.java index 247b2a7d01..ad623edf56 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/BillRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/TradeBillRequest.java @@ -4,7 +4,7 @@ import lombok.*; /** - * 账单请求 + * 交易账单请求 * @author: f00lish * @date: 2020/09/28 */ @@ -13,7 +13,7 @@ @ToString @NoArgsConstructor(access = AccessLevel.PRIVATE) @AllArgsConstructor(access = AccessLevel.PRIVATE) -public class BillRequest { +public class TradeBillRequest { /** *
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/BillResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/TradeBillResult.java
similarity index 96%
rename from weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/BillResult.java
rename to weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/TradeBillResult.java
index 4a5bdb9524..2fb7b60564 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/BillResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/TradeBillResult.java
@@ -4,7 +4,7 @@
 import lombok.*;
 
 /**
- * 账单结果
+ * 交易账单结果
  * @author: f00lish
  * @date: 2020/09/28
  */
@@ -13,7 +13,7 @@
 @ToString
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
 @AllArgsConstructor(access = AccessLevel.PRIVATE)
-public class BillResult {
+public class TradeBillResult {
 
   /**
    * 
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/enums/BillTypeEnum.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/enums/FundBillTypeEnum.java
similarity index 64%
rename from weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/enums/BillTypeEnum.java
rename to weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/enums/FundBillTypeEnum.java
index 598ee4be4b..72aff3a02b 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/enums/BillTypeEnum.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/enums/FundBillTypeEnum.java
@@ -10,17 +10,16 @@
  */
 @Getter
 @AllArgsConstructor
-public enum BillTypeEnum {
+public enum FundBillTypeEnum {
 
   /**
-   * 交易账单
+   * 资金账单
    */
-  TRADE_BILL("%s/v3/bill/tradebill?%s"),
+  FUND_FLOW_BILL("%s/v3/bill/fundflowbill?%s"),
   /**
-   * 资金账单
+   * 二级商户资金账单
    */
-  FUND_FLOW_BILL("%s/v3/bill/fundflowbill?%s");
-
+  SUB_FUND_FLOW_BILL("%s/v3/ecommerce/bill/fundflowbill?%s");
 
   /**
    * url
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EcommerceService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EcommerceService.java
index 367f2e8e1e..91c58e7ac3 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EcommerceService.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EcommerceService.java
@@ -1,7 +1,7 @@
 package com.github.binarywang.wxpay.service;
 
 import com.github.binarywang.wxpay.bean.ecommerce.*;
-import com.github.binarywang.wxpay.bean.ecommerce.enums.BillTypeEnum;
+import com.github.binarywang.wxpay.bean.ecommerce.enums.FundBillTypeEnum;
 import com.github.binarywang.wxpay.bean.ecommerce.enums.SpAccountTypeEnum;
 import com.github.binarywang.wxpay.bean.ecommerce.enums.TradeTypeEnum;
 import com.github.binarywang.wxpay.exception.WxPayException;
@@ -394,12 +394,24 @@ public interface EcommerceService {
    * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/bill.shtml
    * 
* + * @param request 请求信息。 + * @return 返回数据 return trade bill result + * @throws WxPayException the wx pay exception + */ + TradeBillResult applyBill(TradeBillRequest request) throws WxPayException; + + /** + *
+   * 申请资金账单API
+   * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/bill/chapter3_2.shtml
+   * 
+ * * @param billType 账单类型。 - * @param request 二级商户号。 - * @return 返回数据 return bill result + * @param request 请求信息。 + * @return 返回数据 return fund bill result * @throws WxPayException the wx pay exception */ - BillResult applyBill(BillTypeEnum billType, BillRequest request) throws WxPayException; + FundBillResult applyFundBill(FundBillTypeEnum billType, FundBillRequest request) throws WxPayException; /** *
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EcommerceServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EcommerceServiceImpl.java
index 67976caf31..58a02d8ff8 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EcommerceServiceImpl.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EcommerceServiceImpl.java
@@ -1,7 +1,7 @@
 package com.github.binarywang.wxpay.service.impl;
 
 import com.github.binarywang.wxpay.bean.ecommerce.*;
-import com.github.binarywang.wxpay.bean.ecommerce.enums.BillTypeEnum;
+import com.github.binarywang.wxpay.bean.ecommerce.enums.FundBillTypeEnum;
 import com.github.binarywang.wxpay.bean.ecommerce.enums.SpAccountTypeEnum;
 import com.github.binarywang.wxpay.bean.ecommerce.enums.TradeTypeEnum;
 import com.github.binarywang.wxpay.exception.WxPayException;
@@ -295,10 +295,17 @@ public SettlementResult querySettlement(String subMchid) throws WxPayException {
   }
 
   @Override
-  public BillResult applyBill(BillTypeEnum billType, BillRequest request) throws WxPayException {
+  public TradeBillResult applyBill(TradeBillRequest request) throws WxPayException {
+    String url = String.format("%s/v3/bill/tradebill?%s", this.payService.getPayBaseUrl(), this.parseURLPair(request));
+    String response = this.payService.getV3(URI.create(url));
+    return GSON.fromJson(response, TradeBillResult.class);
+  }
+
+  @Override
+  public FundBillResult applyFundBill(FundBillTypeEnum billType, FundBillRequest request) throws WxPayException {
     String url = String.format(billType.getUrl(), this.payService.getPayBaseUrl(), this.parseURLPair(request));
     String response = this.payService.getV3(URI.create(url));
-    return GSON.fromJson(response, BillResult.class);
+    return GSON.fromJson(response, FundBillResult.class);
   }
 
   @Override
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/util/AesUtils.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/util/AesUtils.java
index 4030965ebe..2c8c40252f 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/util/AesUtils.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/util/AesUtils.java
@@ -4,6 +4,11 @@
 import com.google.common.io.BaseEncoding;
 import org.apache.commons.lang3.StringUtils;
 
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
 import java.io.IOException;
 import java.security.GeneralSecurityException;
 import java.security.InvalidAlgorithmParameterException;
@@ -13,11 +18,6 @@
 import java.util.Map;
 import java.util.SortedMap;
 import java.util.TreeMap;
-import javax.crypto.Cipher;
-import javax.crypto.Mac;
-import javax.crypto.NoSuchPaddingException;
-import javax.crypto.spec.GCMParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
 
 public class AesUtils {
 
@@ -32,6 +32,31 @@ public AesUtils(byte[] key) {
     this.aesKey = key;
   }
 
+  public static byte[] decryptToByte(byte[] nonce, byte[] cipherData, byte[] key)
+    throws GeneralSecurityException {
+    return decryptToByte(null, nonce, cipherData, key);
+  }
+
+  public static byte[] decryptToByte(byte[] associatedData, byte[] nonce, byte[] cipherData, byte[] key)
+    throws GeneralSecurityException {
+    try {
+      Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+
+      SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
+      GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);
+
+      cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, spec);
+      if (associatedData != null) {
+        cipher.updateAAD(associatedData);
+      }
+      return cipher.doFinal(cipherData);
+    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+      throw new IllegalStateException(e);
+    } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
+      throw new IllegalArgumentException(e);
+    }
+  }
+
   public String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext)
       throws GeneralSecurityException, IOException {
     try {
diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayBillResultTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayTradeFundBillResultTest.java
similarity index 100%
rename from weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayBillResultTest.java
rename to weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayTradeFundBillResultTest.java