diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/CombineTransactionsResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/CombineTransactionsResult.java index ad0dbe226..890df9acf 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/CombineTransactionsResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/CombineTransactionsResult.java @@ -69,7 +69,7 @@ public class CombineTransactionsResult implements Serializable { * */ @SerializedName(value = "scene_info") - private CombineTransactionsNotifyResult.SceneInfo sceneInfo; + private CombineTransactionsResult.SceneInfo sceneInfo; /** *
@@ -83,7 +83,7 @@ public class CombineTransactionsResult implements Serializable {
    * 
*/ @SerializedName(value = "sub_orders") - private List subOrders; + private List subOrders; /** *
@@ -95,7 +95,7 @@ public class CombineTransactionsResult implements Serializable {
    * 
*/ @SerializedName(value = "combine_payer_info") - private CombineTransactionsNotifyResult.CombinePayerInfo combinePayerInfo; + private CombineTransactionsResult.CombinePayerInfo combinePayerInfo; @Data @NoArgsConstructor @@ -248,7 +248,7 @@ public class CombineTransactionsResult implements Serializable { * */ @SerializedName(value = "amount") - private CombineTransactionsNotifyResult.Amount amount; + private CombineTransactionsResult.Amount amount; } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/EcommerceWithdrawRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/EcommerceWithdrawRequest.java new file mode 100644 index 000000000..8fdc31719 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/EcommerceWithdrawRequest.java @@ -0,0 +1,89 @@ +package com.github.binarywang.wxpay.bean.ecommerce; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 二级商户账户余额提现 + *
+ *   文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/combine/chapter3_3.shtml
+ * 
+ */ +@Data +@NoArgsConstructor +public class EcommerceWithdrawRequest implements Serializable { + + /** + *
+   * 字段名:二级商户号
+   * 变量名:sub_mchid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  电商平台二级商户号,由微信支付生成并下发。
+   * 示例值:1900000109
+   * 
+ */ + @SerializedName(value = "sub_mchid") + private String subMchid; + + /** + *
+   * 字段名:商户提现单号
+   * 变量名:out_request_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  必须是字母数字
+   * 示例值: 20190611222222222200000000012122
+   * 
+ */ + @SerializedName(value = "out_request_no") + private String outRequestNo; + + /** + *
+   * 字段名:提现金额
+   * 变量名:amount
+   * 是否必填:是
+   * 类型:int64
+   * 描述:
+   *  提现金额(单位:分)
+   * 示例值:100
+   * 
+ */ + @SerializedName(value = "amount") + private Integer amount; + + /** + *
+   * 字段名:备注
+   * 变量名:remark
+   * 是否必填:否
+   * 类型:string(56)
+   * 描述:
+   *  商户对提现单的备注
+   * 示例值:交易提现
+   * 
+ */ + @SerializedName(value = "remark") + private String remark; + + /** + *
+   * 字段名:银行附言
+   * 变量名:bank_memo
+   * 是否必填:否
+   * 类型:string(32)
+   * 描述:
+   *  展示在收款银行系统中的附言,数字、字母最长32个汉字(能否成功展示依赖银行系统支持)。
+   * 示例值:微信支付提现
+   * 
+ */ + @SerializedName(value = "bank_memo") + private String bankMemo; + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/EcommerceWithdrawResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/EcommerceWithdrawResult.java new file mode 100644 index 000000000..6d98b933a --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/EcommerceWithdrawResult.java @@ -0,0 +1,60 @@ +package com.github.binarywang.wxpay.bean.ecommerce; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 二级商户账户余额提现 结果 + *
+ *   文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_2.shtml
+ * 
+ */ +@Data +@NoArgsConstructor +public class EcommerceWithdrawResult implements Serializable { + + /** + *
+   * 字段名:二级商户号
+   * 变量名:sub_mchid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  电商平台二级商户号,由微信支付生成并下发。
+   * 示例值:1900000109
+   * 
+ */ + @SerializedName(value = "sub_mchid") + private String subMchid; + + /** + *
+   * 字段名:微信支付提现单号
+   * 变量名:withdraw_id
+   * 是否必填:是
+   * 类型:string(128)
+   * 描述:
+   *  电商平台提交二级商户提现申请后,由微信支付返回的申请单号,作为查询申请状态的唯一标识。
+   * 示例值: 12321937198237912739132791732912793127931279317929791239112123
+   * 
+ */ + @SerializedName(value = "withdraw_id") + private String withdrawId; + + /** + *
+   * 字段名:商户提现单号
+   * 变量名:out_request_no
+   * 是否必填:否
+   * 类型:string(32)
+   * 描述:
+   *  必须是字母数字
+   * 示例值: 20190611222222222200000000012122
+   * 
+ */ + @SerializedName(value = "out_request_no") + private String outRequestNo; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/MerchantWithdrawRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/MerchantWithdrawRequest.java new file mode 100644 index 000000000..14b10b497 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/MerchantWithdrawRequest.java @@ -0,0 +1,91 @@ +package com.github.binarywang.wxpay.bean.ecommerce; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 电商平台提现 + *
+ *   文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_5.shtml
+ * 
+ */ +@Data +@NoArgsConstructor +public class MerchantWithdrawRequest implements Serializable { + /** + *
+   * 字段名:商户提现单号
+   * 变量名:out_request_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户提现单号,由商户自定义生成。
+   * 示例值:20190611222222222200000000012122
+   * 
+ */ + @SerializedName(value = "out_request_no") + private String outRequestNo; + + /** + *
+   * 字段名:提现金额
+   * 变量名:amount
+   * 是否必填:是
+   * 类型:int64
+   * 描述:
+   *  提现金额,单位:分(RMB)
+   * 示例值:1
+   * 
+ */ + @SerializedName(value = "amount") + private Integer amount; + + /** + *
+   * 字段名:备注
+   * 变量名:remark
+   * 是否必填:否
+   * 类型:string(56)
+   * 描述:
+   *  商户对提现单的备注
+   * 示例值:交易提现
+   * 
+ */ + @SerializedName(value = "remark") + private String remark; + + /** + *
+   * 字段名:银行附言
+   * 变量名:bank_memo
+   * 是否必填:否
+   * 类型:string(32)
+   * 描述:
+   *  展示在收款银行系统中的附言,数字、字母最长32个汉字(能否成功展示依赖银行系统支持)。
+   * 示例值:xx平台提现
+   * 
+ */ + @SerializedName(value = "bank_memo") + private String bankMemo; + + /** + *
+   * 字段名:账户类型
+   * 变量名:account_type
+   * 是否必填:是
+   * 类型:string(16)
+   * 描述:
+   *  枚举值:
+   *    BASIC:基本账户
+   *    OPERATION:运营账户
+   *    FEES:手续费账户
+   * 示例值:BASIC
+   * 
+ */ + @SerializedName(value = "account_type") + private String accountType; + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/MerchantWithdrawResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/MerchantWithdrawResult.java new file mode 100644 index 000000000..8b6ac2e79 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/MerchantWithdrawResult.java @@ -0,0 +1,46 @@ +package com.github.binarywang.wxpay.bean.ecommerce; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 电商平台提现 结果 + *
+ *   文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_5.shtml
+ * 
+ */ +@Data +@NoArgsConstructor +public class MerchantWithdrawResult implements Serializable { + + /** + *
+   * 字段名:微信支付提现单号
+   * 变量名:withdraw_id
+   * 是否必填:否 (文档里面是【否】,理论上应该都有值)
+   * 类型:string(128)
+   * 描述:
+   *  微信支付系统生成的提现单号。
+   * 示例值:12321937198237912739132791732912793127931279317929791239112123
+   * 
+ */ + @SerializedName(value = "withdraw_id") + private String withdrawId; + + /** + *
+   * 字段名:商户提现单号
+   * 变量名:out_request_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  必须是字母数字
+   * 示例值: 20190611222222222200000000012122
+   * 
+ */ + @SerializedName(value = "out_request_no") + private String outRequestNo; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/PartnerTransactionsResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/PartnerTransactionsResult.java index 787de8b70..94848a09f 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/PartnerTransactionsResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/PartnerTransactionsResult.java @@ -203,7 +203,7 @@ public class PartnerTransactionsResult implements Serializable { * */ @SerializedName(value = "combine_payer_info") - private PartnerTransactionsNotifyResult.CombinePayerInfo combinePayerInfo; + private PartnerTransactionsResult.CombinePayerInfo combinePayerInfo; /** *
@@ -215,7 +215,7 @@ public class PartnerTransactionsResult implements Serializable {
    * 
*/ @SerializedName(value = "amount") - private PartnerTransactionsNotifyResult.Amount amount; + private PartnerTransactionsResult.Amount amount; /** *
@@ -227,7 +227,7 @@ public class PartnerTransactionsResult implements Serializable {
    * 
*/ @SerializedName(value = "scene_info") - private PartnerTransactionsNotifyResult.SceneInfo sceneInfo; + private PartnerTransactionsResult.SceneInfo sceneInfo; /** *
@@ -239,7 +239,7 @@ public class PartnerTransactionsResult implements Serializable {
    * 
*/ @SerializedName(value = "promotion_detail") - private List promotionDetails; + private List promotionDetails; @Data @NoArgsConstructor @@ -507,7 +507,7 @@ public class PartnerTransactionsResult implements Serializable { * */ @SerializedName(value = "goods_detail") - private List goodsDetails; + private List goodsDetails; } 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 47559e8d3..d0b941ca8 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 @@ -261,4 +261,27 @@ public interface EcommerceService { */ RefundsResult refunds(RefundsRequest request) throws WxPayException; + /** + *
+   * 二级商户账户余额提现API
+   * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_2.shtml
+   * 
+ * + * @param request 提现请求 + * @return 返回数据 return withdraw result + * @throws WxPayException the wx pay exception + */ + EcommerceWithdrawResult withdraw(EcommerceWithdrawRequest request) throws WxPayException; + + /** + *
+   * 电商平台提现API
+   * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_5.shtml
+   * 
+ * + * @param request 提现请求 + * @return 返回数据 return withdraw result + * @throws WxPayException the wx pay exception + */ + MerchantWithdrawResult withdraw(MerchantWithdrawRequest 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 d191fdf00..31af7c15f 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 @@ -20,6 +20,7 @@ import java.util.Objects; @RequiredArgsConstructor public class EcommerceServiceImpl implements EcommerceService { + private static final Gson GSON = new GsonBuilder().create(); private final WxPayService payService; @@ -201,6 +202,26 @@ public class EcommerceServiceImpl implements EcommerceService { return GSON.fromJson(response, RefundsResult.class); } + @Override + public EcommerceWithdrawResult withdraw(EcommerceWithdrawRequest request) throws WxPayException { + String url = String.format("%s/v3/ecommerce/fund/withdraw", this.payService.getPayBaseUrl()); + String response = this.payService.postV3(url, GSON.toJson(request)); + return GSON.fromJson(response, EcommerceWithdrawResult.class); + } + + @Override + public MerchantWithdrawResult withdraw(MerchantWithdrawRequest request) throws WxPayException { + String url = String.format("%s/v3/merchant/fund/withdraw", this.payService.getPayBaseUrl()); + String response = this.payService.postV3(url, GSON.toJson(request)); + return GSON.fromJson(response, MerchantWithdrawResult.class); + } + + /** + * 校验通知签名 + * @param header 通知头信息 + * @param data 通知数据 + * @return true:校验通过 false:校验不通过 + */ private boolean verifyNotifySign(SignatureHeader header, String data) { String beforeSign = String.format("%s\n%s\n%s\n", header.getTimeStamp(),