From ec97c77c8e00cc9a5741cf4ef44226948240f352 Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Tue, 21 Jun 2022 16:49:54 +0800 Subject: [PATCH] =?UTF-8?q?:new:=20#2672=20=E3=80=90=E5=BE=AE=E4=BF=A1?= =?UTF-8?q?=E6=94=AF=E4=BB=98=E3=80=91=E5=A2=9E=E5=8A=A0=E5=95=86=E5=AE=B6?= =?UTF-8?q?=E8=BD=AC=E8=B4=A6=E7=9A=84=E6=9B=B4=E5=A4=9A=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../merchanttransfer/BatchesQueryResult.java | 384 ++++++++++++++++++ .../DetailElectronicBillRequest.java | 71 ++++ .../DetailElectronicBillResult.java | 143 +++++++ .../merchanttransfer/DetailsQueryResult.java | 242 +++++++++++ .../ElectronicBillApplyRequest.java | 38 ++ .../ElectronicBillResult.java | 138 +++++++ .../MerchantBatchesQueryRequest.java | 99 +++++ .../MerchantDetailsQueryRequest.java | 52 +++ .../TransferCreateRequest.java | 208 ++++++++++ .../TransferCreateResult.java | 66 +++ .../WxBatchesQueryRequest.java | 99 +++++ .../WxDetailsQueryRequest.java | 53 +++ .../service/MerchantTransferService.java | 150 +++++++ .../wxpay/service/WxPayService.java | 7 + .../service/impl/BaseWxPayServiceImpl.java | 115 ++---- .../impl/MerchantTransferServiceImpl.java | 118 ++++++ .../impl/MerchantTransferServiceImplTest.java | 110 +++++ 17 files changed, 2018 insertions(+), 75 deletions(-) create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/BatchesQueryResult.java create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailElectronicBillRequest.java create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailElectronicBillResult.java create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailsQueryResult.java create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/ElectronicBillApplyRequest.java create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/ElectronicBillResult.java create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/MerchantBatchesQueryRequest.java create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/MerchantDetailsQueryRequest.java create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/TransferCreateRequest.java create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/TransferCreateResult.java create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/WxBatchesQueryRequest.java create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/WxDetailsQueryRequest.java create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MerchantTransferService.java create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MerchantTransferServiceImpl.java create mode 100644 weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/MerchantTransferServiceImplTest.java diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/BatchesQueryResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/BatchesQueryResult.java new file mode 100644 index 0000000000..d547471b8f --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/BatchesQueryResult.java @@ -0,0 +1,384 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + +/** + * The type Batches query result. + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class BatchesQueryResult implements Serializable { + private static final long serialVersionUID = -4160610913430904527L; + /** + *
+   * 字段名:最大资源条数
+   * 变量名:limit
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  query该次请求可返回的最大资源(转账明细单)条数,最小20条,最大100条,不传则默认20条。不足20条按实际条数返回
+   * 示例值:20
+   * 
+ */ + @SerializedName("limit") + private Integer limit; + + /** + *
+   * 字段名:请求资源起始位置
+   * 变量名:transfer_batch
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  query该次请求资源(转账明细单)的起始位置,从0开始,转账明细单列表为空时不返回
+   * 示例值:1
+   * 
+ */ + @SerializedName("offset") + private Integer offset; + /** + *
+   * 字段名:转账批次单
+   * 变量名:transfer_batch
+   * 是否必填:是
+   * 类型:object
+   * 描述:
+   *  转账批次单基本信息
+   * 
+ */ + @SerializedName("transfer_batch") + private TransferBatch transferBatch; + + /** + *
+   * 字段名:转账明细单列表
+   * 变量名:transfer_detail_list
+   * 是否必填:否
+   * 类型:array
+   * 描述:
+   *  body发起批量转账的明细列表,最多三千笔
+   * 
+ */ + @SerializedName("transfer_detail_list") + private List transferDetailList; + + /** + * The type Transfer batch. + */ + @Data + @Accessors(chain = true) + public class TransferBatch implements Serializable { + /** + *
+     * 字段名:商户号
+     * 变量名:mchid
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  微信支付分配的商户号
+     * 示例值:1900001109
+     * 
+ */ + @SerializedName("mchid") + private String mchid; + + /** + *
+     * 字段名:商家批次单号
+     * 变量名:out_batch_no
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  商户系统内部的商家批次单号,在商户系统内部唯一
+     * 示例值:plfk2020042013
+     * 
+ */ + @SerializedName("out_batch_no") + private String outBatchNo; + + /** + *
+     * 字段名:微信批次单号
+     * 变量名:batch_id
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  微信批次单号,微信商家转账系统返回的唯一标识
+     * 示例值:1030000071100999991182020050700019480001
+     * 
+ */ + @SerializedName("batch_id") + private String batchId; + + /** + *
+     * 字段名:直连商户的appid
+     * 变量名:appid
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  申请商户号的appid或商户号绑定的appid(企业号corpid即为此appid)
+     * 示例值:wxf636efh567hg4356
+     * 
+ */ + @SerializedName("appid") + private String appid; + + /** + *
+     * 字段名:批次状态
+     * 变量名:batch_status
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  枚举值:
+     * WAIT_PAY:待付款,商户员工确认付款阶段
+     * ACCEPTED:已受理。批次已受理成功,若发起批量转账的30分钟后,转账批次单仍处于该状态,可能原因是商户账户余额不足等。商户可查询账户资金流水,若该笔转账批次单的扣款已经发生,则表示批次已经进入转账中,请再次查单确认
+     * PROCESSING:转账中。已开始处理批次内的转账明细单
+     * FINISHED:已完成。批次内的所有转账明细单都已处理完成
+     * CLOSED:已关闭。可查询具体的批次关闭原因确认
+     * 示例值:ACCEPTED
+     * 
+ */ + @SerializedName("batch_status") + private String batchStatus; + + /** + *
+     * 字段名:批次类型
+     * 变量名:batch_type
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  枚举值:
+     * API:API方式发起
+     * WEB:页面方式发起
+     * 示例值:API
+     * 
+ */ + @SerializedName("batch_type") + private String batchType; + + /** + *
+     * 字段名:批次名称
+     * 变量名:batch_name
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  该笔批量转账的名称
+     * 示例值:2019年1月深圳分部报销单
+     * 
+ */ + @SerializedName("batch_name") + private String batchName; + + /** + *
+     * 字段名:批次备注
+     * 变量名:batch_remark
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  转账说明,UTF8编码,最多允许32个字符
+     * 示例值:2019年1月深圳分部报销单
+     * 
+ */ + @SerializedName("batch_remark") + private String batchRemark; + + /** + *
+     * 字段名:批次关闭原因
+     * 变量名:close_reason
+     * 是否必填:否
+     * 类型:string[1,64]
+     * 描述:
+     *  如果批次单状态为“CLOSED”(已关闭),则有关闭原因
+     * MERCHANT_REVOCATION:商户主动撤销
+     * OVERDUE_CLOSE:系统超时关闭
+     * 示例值:OVERDUE_CLOSE
+     * 
+ */ + @SerializedName("close_reason") + private String closeReason; + + /** + *
+     * 字段名:转账总金额
+     * 变量名:total_amount
+     * 是否必填:是
+     * 类型:int
+     * 描述:
+     *  转账金额单位为分
+     * 示例值:4000000
+     * 
+ */ + @SerializedName("total_amount") + private Integer totalAmount; + + /** + *
+     * 字段名:转账总笔数
+     * 变量名:total_num
+     * 是否必填:是
+     * 类型:int
+     * 描述:
+     *  一个转账批次单最多发起三千笔转账
+     * 示例值:200
+     * 
+ */ + @SerializedName("total_num") + private Integer totalNum; + + /** + *
+     * 字段名:批次创建时间
+     * 变量名:create_time
+     * 是否必填:否
+     * 类型:string[1,32]
+     * 描述:
+     *  批次受理成功时返回,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示北京时间2015年05月20日13点29分35秒
+     * 示例值:2015-05-20T13:29:35.120+08:00
+     * 
+ */ + @SerializedName("create_time") + private String createTime; + + /** + *
+     * 字段名:批次更新时间
+     * 变量名:update_time
+     * 是否必填:否
+     * 类型:string[1,32]
+     * 描述:
+     *  批次最近一次状态变更的时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示北京时间2015年05月20日13点29分35秒
+     * 示例值:2015-05-20T13:29:35.120+08:00
+     * 
+ */ + @SerializedName("update_time") + private String updateTime; + + /** + *
+     * 字段名:转账成功金额
+     * 变量名:success_amount
+     * 是否必填:否
+     * 类型:int
+     * 描述:
+     *  转账成功的金额,单位为分。当批次状态为“PROCESSING”(转账中)时,转账成功金额随时可能变化
+     * 示例值:3900000
+     * 
+ */ + @SerializedName("success_amount") + private Integer successAmount; + + /** + *
+     * 字段名:转账成功笔数
+     * 变量名:success_num
+     * 是否必填:否
+     * 类型:int
+     * 描述:
+     *  转账成功的笔数。当批次状态为“PROCESSING”(转账中)时,转账成功笔数随时可能变化
+     * 示例值:199
+     * 
+ */ + @SerializedName("success_num") + private Integer successNum; + + /** + *
+     * 字段名:转账失败金额
+     * 变量名:fail_amount
+     * 是否必填:否
+     * 类型:int
+     * 描述:
+     *  转账失败的金额,单位为分
+     * 示例值:100000
+     * 
+ */ + @SerializedName("fail_amount") + private Integer failAmount; + + /** + *
+     * 字段名:转账失败笔数
+     * 变量名:fail_num
+     * 是否必填:否
+     * 类型:int
+     * 描述:
+     *  转账失败的笔数
+     * 示例值:1
+     * 
+ */ + @SerializedName("fail_num") + private Integer failNum; + } + + /** + * The type Transfer detail. + */ + @Data + @Accessors(chain = true) + public class TransferDetail implements Serializable { + /** + *
+     * 字段名:微信明细单号
+     * 变量名:detail_id
+     * 是否必填:是
+     * 类型:string[1,64]
+     * 描述:
+     *  微信支付系统内部区分转账批次单下不同转账明细单的唯一标识
+     * 示例值:1040000071100999991182020050700019500100
+     * 
+ */ + @SerializedName("detail_id") + private String detailId; + + /** + *
+     * 字段名:商家明细单号
+     * 变量名:out_detail_no
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  商户系统内部区分转账批次单下不同转账明细单的唯一标识
+     * 示例值:x23zy545Bd5436
+     * 
+ */ + @SerializedName("out_detail_no") + private String outDetailNo; + + /** + *
+     * 字段名:明细状态
+     * 变量名:detail_status
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  枚举值:
+     * PROCESSING:转账中。正在处理中,转账结果尚未明确
+     * SUCCESS:转账成功
+     * FAIL:转账失败。需要确认失败原因后,再决定是否重新发起对该笔明细单的转账(并非整个转账批次单)
+     * 示例值:SUCCESS
+     * 
+ */ + @SerializedName("detail_status") + private String detailStatus; + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailElectronicBillRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailElectronicBillRequest.java new file mode 100644 index 0000000000..adfc8585fc --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailElectronicBillRequest.java @@ -0,0 +1,71 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * The type Detail electronic bill request. + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class DetailElectronicBillRequest implements Serializable { + private static final long serialVersionUID = 716155129313310192L; + /** + *
+   * 字段名:受理类型
+   * 变量名:accept_type
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   * query电子回单受理类型:
+   * BATCH_TRANSFER:批量转账明细电子回单
+   * TRANSFER_TO_POCKET:企业付款至零钱电子回单
+   * TRANSFER_TO_BANK:企业付款至银行卡电子回单
+   * 示例值:BATCH_TRANSFER
+   * 
+ */ + @SerializedName("accept_type") + private String acceptType; + + /** + *
+   * 字段名:商家转账批次单号
+   * 变量名:out_batch_no
+   * 是否必填:否
+   * 类型:string[5,32]
+   * 描述:
+   * query需要电子回单的批量转账明细单所在的转账批次单号,该单号为商户申请转账时生成的商户单号。受理类型为BATCH_TRANSFER时该单号必填,否则该单号留空。
+   * 示例值:GD2021011610162610BBdkkIwcu3
+   * 
+ */ + @SerializedName("out_batch_no") + private String outBatchNo; + + /** + *
+   * 字段名:商家转账明细单号
+   * 变量名:out_detail_no
+   * 是否必填:是
+   * 类型:string[5,32]
+   * 描述:
+   * query该单号为商户申请转账时生成的商家转账明细单号。
+   * 1.受理类型为BATCH_TRANSFER时填写商家批量转账明细单号。
+   * 2. 受理类型为TRANSFER_TO_POCKET或TRANSFER_TO_BANK时填写商家转账单号。
+   * 示例值:mx0911231610162610v4CNkO4HAf
+   * 
+ */ + @SerializedName("out_detail_no") + private String outDetailNo; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailElectronicBillResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailElectronicBillResult.java new file mode 100644 index 0000000000..3199a3ed06 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailElectronicBillResult.java @@ -0,0 +1,143 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * 查询转账明细电子回单受理结果响应实体 + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class DetailElectronicBillResult implements Serializable { + private static final long serialVersionUID = -6544648835213399159L; + /** + *
+   * 字段名:受理类型
+   * 变量名:accept_type
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  电子回单受理类型:
+   * BATCH_TRANSFER:批量转账明细电子回单
+   * TRANSFER_TO_POCKET:企业付款至零钱电子回单
+   * TRANSFER_TO_BANK:企业付款至银行卡电子回单
+   * 示例值:BATCH_TRANSFER
+   * 
+ */ + @SerializedName("accept_type") + private String acceptType; + + /** + *
+   * 字段名:商家转账批次单号
+   * 变量名:out_batch_no
+   * 是否必填:否
+   * 类型:string[5,32]
+   * 描述:
+   *  需要电子回单的批量转账明细单所在的转账批次单号,该单号为商户申请转账时生成的商户单号。受理类型为BATCH_TRANSFER时该单号必填,否则该单号留空。
+   * 示例值:GD2021011610162610BBdkkIwcu3
+   * 
+ */ + @SerializedName("out_batch_no") + private String outBatchNo; + + /** + *
+   * 字段名:商家转账明细单号
+   * 变量名:out_detail_no
+   * 是否必填:是
+   * 类型:string[5,32]
+   * 描述:
+   *  该单号为商户申请转账时生成的商家转账明细单号。
+   * 1.受理类型为BATCH_TRANSFER时填写商家批量转账明细单号。
+   * 2. 受理类型为TRANSFER_TO_POCKET或TRANSFER_TO_BANK时填写商家转账单号。
+   * 示例值:mx0911231610162610v4CNkO4HAf
+   * 
+ */ + @SerializedName("out_detail_no") + private String outDetailNo; + + /** + *
+   * 字段名:电子回单受理单号
+   * 变量名:signature_no
+   * 是否必填:是
+   * 类型:string[3,256]
+   * 描述:
+   *  电子回单受理单号,受理单据的唯一标识
+   * 示例值:1050000010509999485212020110200058820001
+   * 
+ */ + @SerializedName("signature_no") + private String signatureNo; + + /** + *
+   * 字段名:电子回单状态
+   * 变量名:signature_status
+   * 是否必填:否
+   * 类型:string[1,10]
+   * 描述:
+   *  枚举值:
+   * ACCEPTED:已受理,电子签章已受理成功
+   * FINISHED:已完成。电子签章已处理完成
+   * 示例值:ACCEPTED
+   * 
+ */ + @SerializedName("signature_status") + private String signatureStatus; + + /** + *
+   * 字段名:电子回单文件的hash方法
+   * 变量名:hash_type
+   * 是否必填:否
+   * 类型:string[1,20]
+   * 描述:
+   *  电子回单文件的hash方法,回单状态为:FINISHED时返回
+   * 示例值:SHA256
+   * 
+ */ + @SerializedName("hash_type") + private String hashType; + + /** + *
+   * 字段名:电子回单文件的hash值
+   * 变量名:hash_value
+   * 是否必填:否
+   * 类型:string[3,1000]
+   * 描述:
+   *  电子回单文件的hash值,用于下载之后验证文件的完整、正确性,回单状态为:FINISHED时返回
+   * 示例值:DE731F35146A0BEFADE5DB9D1E468D96C01CA8898119C674FEE9F11F4DBE5529
+   * 
+ */ + @SerializedName("hash_value") + private String hashValue; + + /** + *
+   * 字段名:电子回单文件的下载地址
+   * 变量名:download_url
+   * 是否必填:否
+   * 类型:string[10,3000]
+   * 描述:
+   *  电子回单文件的下载地址,回单状态为:FINISHED时返回。URL有效时长为10分钟,10分钟后需要重新去获取下载地址(但不需要走受理)
+   * 示例值:https://api.mch.weixin.qq.com/v3/billdownload/file?token=xxx
+   * 
+ */ + @SerializedName("download_url") + private String downloadUrl; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailsQueryResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailsQueryResult.java new file mode 100644 index 0000000000..b7bca954cf --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/DetailsQueryResult.java @@ -0,0 +1,242 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * 微信明细单号查询明细单 响应实体、 + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class DetailsQueryResult implements Serializable { + private static final long serialVersionUID = -6900642921137234815L; + /** + *
+   * 字段名:商户号
+   * 变量名:mchid
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  微信支付分配的商户号
+   * 示例值:1900001109
+   * 
+ */ + @SerializedName("mchid") + private String mchid; + + /** + *
+   * 字段名:商家批次单号
+   * 变量名:out_batch_no
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  商户系统内部的商家批次单号,在商户系统内部唯一
+   * 示例值:plfk2020042013
+   * 
+ */ + @SerializedName("out_batch_no") + private String outBatchNo; + + /** + *
+   * 字段名:微信批次单号
+   * 变量名:batch_id
+   * 是否必填:是
+   * 类型:string[1,64]
+   * 描述:
+   *  微信批次单号,微信商家转账系统返回的唯一标识
+   * 示例值:1030000071100999991182020050700019480001
+   * 
+ */ + @SerializedName("batch_id") + private String batchId; + + /** + *
+   * 字段名:直连商户的appid
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  申请商户号的appid或商户号绑定的appid(企业号corpid即为此appid)
+   * 示例值:wxf636efh567hg4356
+   * 
+ */ + @SerializedName("appid") + private String appid; + + /** + *
+   * 字段名:商家明细单号
+   * 变量名:out_detail_no
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  商户系统内部区分转账批次单下不同转账明细单的唯一标识
+   * 示例值:x23zy545Bd5436
+   * 
+ */ + @SerializedName("out_detail_no") + private String outDetailNo; + + /** + *
+   * 字段名:微信明细单号
+   * 变量名:detail_id
+   * 是否必填:是
+   * 类型:string[1,64]
+   * 描述:
+   *  微信支付系统内部区分转账批次单下不同转账明细单的唯一标识
+   * 示例值:1040000071100999991182020050700019500100
+   * 
+ */ + @SerializedName("detail_id") + private String detailId; + + /** + *
+   * 字段名:明细状态
+   * 变量名:detail_status
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  枚举值:
+   * PROCESSING:转账中。正在处理中,转账结果尚未明确
+   * SUCCESS:转账成功
+   * FAIL:转账失败。需要确认失败原因后,再决定是否重新发起对该笔明细单的转账(并非整个转账批次单)
+   * 示例值:SUCCESS
+   * 
+ */ + @SerializedName("detail_status") + private String detailStatus; + + /** + *
+   * 字段名:转账金额
+   * 变量名:transfer_amount
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  转账金额单位为分
+   * 示例值:200000
+   * 
+ */ + @SerializedName("transfer_amount") + private Integer transferAmount; + + /** + *
+   * 字段名:转账备注
+   * 变量名:transfer_remark
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  单条转账备注(微信用户会收到该备注),UTF8编码,最多允许32个字符
+   * 示例值:2020年4月报销
+   * 
+ */ + @SerializedName("transfer_remark") + private String transferRemark; + + /** + *
+   * 字段名:明细失败原因
+   * 变量名:fail_reason
+   * 是否必填:否
+   * 类型:string[1,64]
+   * 描述:
+   *  如果转账失败则有失败原因
+   * ACCOUNT_FROZEN:账户冻结
+   * REAL_NAME_CHECK_FAIL:用户未实名
+   * NAME_NOT_CORRECT:用户姓名校验失败
+   * OPENID_INVALID:Openid校验失败
+   * TRANSFER_QUOTA_EXCEED:超过用户单笔收款额度
+   * DAY_RECEIVED_QUOTA_EXCEED:超过用户单日收款额度
+   * MONTH_RECEIVED_QUOTA_EXCEED:超过用户单月收款额度
+   * DAY_RECEIVED_COUNT_EXCEED:超过用户单日收款次数
+   * PRODUCT_AUTH_CHECK_FAIL:产品权限校验失败
+   * OVERDUE_CLOSE:转账关闭
+   * ID_CARD_NOT_CORRECT:用户身份证校验失败
+   * ACCOUNT_NOT_EXIST:用户账户不存在
+   * TRANSFER_RISK:转账存在风险
+   * REALNAME_ACCOUNT_RECEIVED_QUOTA_EXCEED:用户账户收款受限,请引导用户在微信支付查看详情
+   * RECEIVE_ACCOUNT_NOT_PERMMIT:未配置该用户为转账收款人
+   * PAYER_ACCOUNT_ABNORMAL:商户账户付款受限,可前往商户平台-违约记录获取解除功能限制指引
+   * PAYEE_ACCOUNT_ABNORMAL:用户账户收款异常,请引导用户完善其在微信支付的身份信息以继续收款
+   * 示例值:ACCOUNT_FROZEN
+   * 
+ */ + @SerializedName("fail_reason") + private String failReason; + + /** + *
+   * 字段名:用户在直连商户应用下的用户标示
+   * 变量名:openid
+   * 是否必填:是
+   * 类型:string[1,128]
+   * 描述:
+   *  用户在直连商户appid下的唯一标识
+   * 示例值:o-MYE42l80oelYMDE34nYD456Xoy
+   * 
+ */ + @SerializedName("openid") + private String openid; + + /** + *
+   * 字段名:收款用户姓名
+   * 变量名:user_name
+   * 是否必填:否
+   * 类型:string[1,1024]
+   * 描述:
+   *  1、商户转账时传入了收款用户姓名、查询时会返回收款用户姓名;
+   * 2、收款方姓名采用标准RSA算法,公钥由微信侧提供
+   * 3、 该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
+   * 示例值:757b340b45ebef5467rter35gf464344v3542sdf4t6re4tb4f54ty45t4yyry45
+   * 
+ */ + @SerializedName("user_name") + private String userName; + + /** + *
+   * 字段名:转账发起时间
+   * 变量名:initiate_time
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  转账发起的时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示北京时间2015年05月20日13点29分35秒
+   * 示例值:2015-05-20T13:29:35.120+08:00
+   * 
+ */ + @SerializedName("initiate_time") + private String initiateTime; + + /** + *
+   * 字段名:明细更新时间
+   * 变量名:update_time
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  明细最后一次状态变更的时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示北京时间2015年05月20日13点29分35秒
+   * 示例值:2015-05-20T13:29:35.120+08:00
+   * 
+ */ + @SerializedName("update_time") + private String updateTime; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/ElectronicBillApplyRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/ElectronicBillApplyRequest.java new file mode 100644 index 0000000000..66ca59e4bc --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/ElectronicBillApplyRequest.java @@ -0,0 +1,38 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * The type Electronic bill apply request. + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class ElectronicBillApplyRequest implements Serializable { + private static final long serialVersionUID = -2121536206019844928L; + /** + *
+   * 字段名:商家批次单号
+   * 变量名:out_batch_no
+   * 是否必填:是
+   * 类型:string[5,32]
+   * 描述:
+   *  body商户系统内部的商家批次单号,在商户系统内部唯一。需要电子回单的批次单号
+   * 示例值:plfk2020042013
+   * 
+ */ + @SerializedName("out_batch_no") + private String outBatchNo; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/ElectronicBillResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/ElectronicBillResult.java new file mode 100644 index 0000000000..699f66c3c7 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/ElectronicBillResult.java @@ -0,0 +1,138 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * The type Electronic bill result. + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class ElectronicBillResult implements Serializable { + private static final long serialVersionUID = 7528245102572829190L; + /** + *
+   * 字段名:商家批次单号
+   * 变量名:out_batch_no
+   * 是否必填:是
+   * 类型:string[5,32]
+   * 描述:
+   *  body商户系统内部的商家批次单号,在商户系统内部唯一。需要电子回单的批次单号
+   * 示例值:plfk2020042013
+   * 
+ */ + @SerializedName("out_batch_no") + private String outBatchNo; + + /** + *
+   * 字段名:电子回单申请单号
+   * 变量名:signature_no
+   * 是否必填:是
+   * 类型:string[3,45]
+   * 描述:
+   *  电子回单申请单号,申请单据的唯一标识
+   * 示例值:1050000010509999485212020110200058820001
+   * 
+ */ + @SerializedName("signature_no") + private String signatureNo; + + /** + *
+   * 字段名:电子回单状态
+   * 变量名:signature_status
+   * 是否必填:否
+   * 类型:string[1,10]
+   * 描述:
+   *  枚举值:
+   * ACCEPTED:已受理,电子签章已受理成功
+   * FINISHED:已完成。电子签章已处理完成
+   * 示例值:ACCEPTED
+   * 
+ */ + @SerializedName("signature_status") + private String signatureStatus; + + /** + *
+   * 字段名:电子回单文件的hash方法
+   * 变量名:hash_type
+   * 是否必填:否
+   * 类型:string[1,20]
+   * 描述:
+   *  电子回单文件的hash方法,回单状态为:FINISHED时返回。
+   * 示例值:SHA256
+   * 
+ */ + @SerializedName("hash_type") + private String hashType; + + /** + *
+   * 字段名:电子回单文件的hash值
+   * 变量名:hash_value
+   * 是否必填:否
+   * 类型:string[3,1000]
+   * 描述:
+   *  电子回单文件的hash值,用于下载之后验证文件的完整、正确性,回单状态为:FINISHED时返回。
+   * 示例值:DE731F35146A0BEFADE5DB9D1E468D96C01CA8898119C674FEE9F11F4DBE5529
+   * 
+ */ + @SerializedName("hash_value") + private String hashValue; + + /** + *
+   * 字段名:电子回单文件的下载地址
+   * 变量名:download_url
+   * 是否必填:否
+   * 类型:string[10,3000]
+   * 描述:
+   *  电子回单文件的下载地址,回单状态为:FINISHED时返回。URL有效时长为10分钟,10分钟后需要重新去获取下载地址(但不需要走受理)
+   * 示例值:https://api.mch.weixin.qq.com/v3/billdownload/file?token=xxx
+   * 
+ */ + @SerializedName("download_url") + private String downloadUrl; + + /** + *
+   * 字段名:创建时间
+   * 变量名:create_time
+   * 是否必填:否
+   * 类型:string[1,32]
+   * 描述:
+   *  电子签章单创建时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示北京时间2015年05月20日13点29分35秒
+   * 示例值:2020-05-20T13:29:35.120+08:00
+   * 
+ */ + @SerializedName("create_time") + private String createTime; + + /** + *
+   * 字段名:更新时间
+   * 变量名:update_time
+   * 是否必填:否
+   * 类型:string[1,32]
+   * 描述:
+   *  电子签章单最近一次状态变更的时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示北京时间2015年05月20日13点29分35秒
+   * 示例值:2020-05-21T13:29:35.120+08:00
+   * 
+ */ + @SerializedName("update_time") + private String updateTime; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/MerchantBatchesQueryRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/MerchantBatchesQueryRequest.java new file mode 100644 index 0000000000..a123db2305 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/MerchantBatchesQueryRequest.java @@ -0,0 +1,99 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * The type Merchant batches query request. + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class MerchantBatchesQueryRequest implements Serializable { + private static final long serialVersionUID = 7074459219428697275L; + /** + *
+   * 字段名:商家批次单号
+   * 变量名:out_batch_no
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  path商户系统内部的商家批次单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一
+   * 示例值:plfk2020042013
+   * 
+ */ + @SerializedName("out_batch_no") + private String outBatchNo; + + /** + *
+   * 字段名:是否查询转账明细单
+   * 变量名:need_query_detail
+   * 是否必填:是
+   * 类型:boolean
+   * 描述:
+   *  query枚举值:
+   * true:是;
+   * false:否,默认否。
+   * 商户可选择是否查询指定状态的转账明细单,当转账批次单状态为“FINISHED”(已完成)时,才会返回满足条件的转账明细单
+   * 示例值:true
+   * 
+ */ + @SerializedName("need_query_detail") + private Boolean needQueryDetail; + + /** + *
+   * 字段名:请求资源起始位置
+   * 变量名:offset
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  query该次请求资源的起始位置,从0开始,默认值为0
+   * 
+ */ + @SerializedName("offset") + private Integer offset; + + /** + *
+   * 字段名:最大资源条数
+   * 变量名:limit
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  query该次请求可返回的最大明细条数,最小20条,最大100条,不传则默认20条。不足20条按实际条数返回
+   * 示例值:20
+   * 
+ */ + @SerializedName("limit") + private Integer limit; + + /** + *
+   * 字段名:明细状态
+   * 变量名:detail_status
+   * 是否必填:否
+   * 类型:string[1,32]
+   * 描述:
+   *  query查询指定状态的转账明细单,当need_query_detail为true时,该字段必填
+   * ALL:全部。需要同时查询转账成功和转账失败的明细单
+   * SUCCESS:转账成功。只查询转账成功的明细单
+   * FAIL:转账失败。只查询转账失败的明细单
+   * 示例值:FAIL
+   * 
+ */ + @SerializedName("detail_status") + private String detailStatus; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/MerchantDetailsQueryRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/MerchantDetailsQueryRequest.java new file mode 100644 index 0000000000..d9ae599c33 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/MerchantDetailsQueryRequest.java @@ -0,0 +1,52 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * The type Merchant details query request. + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class MerchantDetailsQueryRequest implements Serializable { + private static final long serialVersionUID = 3167548999175561804L; + /** + *
+   * 字段名:商家明细单号
+   * 变量名:out_detail_no
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   * path商户系统内部区分转账批次单下不同转账明细单的唯一标识,要求此参数只能由数字、大小写字母组成
+   * 示例值:x23zy545Bd5436
+   * 
+ */ + @SerializedName("out_detail_no") + private String outDetailNo; + + /** + *
+   * 字段名:商家批次单号
+   * 变量名:out_batch_no
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  path商户系统内部的商家批次单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一
+   * 示例值:plfk2020042013
+   * 
+ */ + @SerializedName("out_batch_no") + private String outBatchNo; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/TransferCreateRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/TransferCreateRequest.java new file mode 100644 index 0000000000..946f0d67df --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/TransferCreateRequest.java @@ -0,0 +1,208 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.github.binarywang.wxpay.v3.SpecEncrypt; +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + +/** + * The type Transfer create request. + * + * @author glz + * @date 2022-5-26 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class TransferCreateRequest implements Serializable { + private static final long serialVersionUID = -6865437704112740902L; + /** + *
+   * 字段名:直连商户的appid
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  申请商户号的appid或商户号绑定的appid(企业号corpid即为此appid)
+   * 示例值:wxf636efh567hg4356
+   * 
+ */ + @SerializedName("appid") + private String appid; + + /** + *
+   * 字段名:商家批次单号
+   * 变量名:out_batch_no
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  path商户系统内部的商家批次单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一
+   * 示例值:plfk2020042013
+   * 
+ */ + @SerializedName("out_batch_no") + private String outBatchNo; + + /** + *
+   * 字段名:批次名称
+   * 变量名:batch_name
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  该笔批量转账的名称
+   * 示例值:2019年1月深圳分部报销单
+   * 
+ */ + @SerializedName("batch_name") + private String batchName; + + /** + *
+   * 字段名:批次备注
+   * 变量名:batch_remark
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  转账说明,UTF8编码,最多允许32个字符
+   * 示例值:2019年1月深圳分部报销单
+   * 
+ */ + @SerializedName("batch_remark") + private String batchRemark; + + /** + *
+   * 字段名:转账总金额
+   * 变量名:total_amount
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  转账金额单位为分
+   * 示例值:4000000
+   * 
+ */ + @SerializedName("total_amount") + private Integer totalAmount; + + /** + *
+   * 字段名:转账总笔数
+   * 变量名:total_num
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  一个转账批次单最多发起三千笔转账
+   * 示例值:200
+   * 
+ */ + @SerializedName("total_num") + private Integer totalNum; + + /** + *
+   * 字段名:转账明细单列表
+   * 变量名:transfer_detail_list
+   * 是否必填:否
+   * 类型:array
+   * 描述:
+   *  body发起批量转账的明细列表,最多三千笔
+   * 
+ */ + @SerializedName("transfer_detail_list") + @SpecEncrypt + private List transferDetailList; + + + /** + * The type Transfer detail list. + */ + @Data + @Accessors(chain = true) + public static class TransferDetailList implements Serializable { + + /** + *
+     * 字段名:商家明细单号
+     * 变量名:out_detail_no
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  商户系统内部区分转账批次单下不同转账明细单的唯一标识
+     * 示例值:x23zy545Bd5436
+     * 
+ */ + @SerializedName("out_detail_no") + private String outDetailNo; + + /** + *
+     * 字段名:转账金额
+     * 变量名:transfer_amount
+     * 是否必填:是
+     * 类型:int
+     * 描述:
+     *  转账金额单位为分
+     * 示例值:200000
+     * 
+ */ + @SerializedName("transfer_amount") + private Integer transferAmount; + + /** + *
+     * 字段名:转账备注
+     * 变量名:transfer_remark
+     * 是否必填:是
+     * 类型:string[1,32]
+     * 描述:
+     *  单条转账备注(微信用户会收到该备注),UTF8编码,最多允许32个字符
+     * 示例值:2020年4月报销
+     * 
+ */ + @SerializedName("transfer_remark") + private String transferRemark; + + /** + *
+     * 字段名:用户在直连商户应用下的用户标示
+     * 变量名:openid
+     * 是否必填:是
+     * 类型:string[1,128]
+     * 描述:
+     *  用户在直连商户appid下的唯一标识
+     * 示例值:o-MYE42l80oelYMDE34nYD456Xoy
+     * 
+ */ + @SerializedName("openid") + private String openid; + + /** + *
+     * 字段名:收款用户姓名
+     * 变量名:user_name
+     * 是否必填:否
+     * 类型:string[1,1024]
+     * 描述:
+     *  1、商户转账时传入了收款用户姓名、查询时会返回收款用户姓名;
+     * 2、收款方姓名采用标准RSA算法,公钥由微信侧提供
+     * 3、 该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
+     * 示例值:757b340b45ebef5467rter35gf464344v3542sdf4t6re4tb4f54ty45t4yyry45
+     * 
+ */ + @SerializedName("user_name") + @SpecEncrypt + private String userName; + } +} + + diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/TransferCreateResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/TransferCreateResult.java new file mode 100644 index 0000000000..e5b057a797 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/TransferCreateResult.java @@ -0,0 +1,66 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * The type Transfer create result. + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class TransferCreateResult implements Serializable { + private static final long serialVersionUID = 586974090302358983L; + /** + *
+   * 字段名:商家批次单号
+   * 变量名:out_batch_no
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  商户系统内部的商家批次单号,在商户系统内部唯一
+   * 示例值:plfk2020042013
+   * 
+ */ + @SerializedName("out_batch_no") + private String outBatchNo; + + /** + *
+   * 字段名:微信批次单号
+   * 变量名:batch_id
+   * 是否必填:是
+   * 类型:string[1,32]
+   * 描述:
+   *  微信批次单号,微信商家转账系统返回的唯一标识
+   * 示例值:1030000071100999991182020050700019480001
+   * 
+ */ + @SerializedName("batch_id") + private String batchId; + + /** + *
+   * 字段名:批次创建时间
+   * 变量名:create_time
+   * 是否必填:否
+   * 类型:string[1,32]
+   * 描述:
+   *  批次受理成功时返回,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示北京时间2015年05月20日13点29分35秒
+   * 示例值:2015-05-20T13:29:35.120+08:00
+   * 
+ */ + @SerializedName("create_time") + private String createTime; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/WxBatchesQueryRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/WxBatchesQueryRequest.java new file mode 100644 index 0000000000..1cf4697f47 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/WxBatchesQueryRequest.java @@ -0,0 +1,99 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * The type Wx batches query request. + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxBatchesQueryRequest implements Serializable { + private static final long serialVersionUID = 1030840820271586649L; + /** + *
+   * 字段名:微信批次单号
+   * 变量名:batch_id
+   * 是否必填:是
+   * 类型:string[1,64]
+   * 描述:
+   *  path微信批次单号,微信商家转账系统返回的唯一标识
+   * 示例值:1030000071100999991182020050700019480001
+   * 
+ */ + @SerializedName("batch_id") + private String batchId; + + /** + *
+   * 字段名:是否查询转账明细单
+   * 变量名:need_query_detail
+   * 是否必填:是
+   * 类型:boolean
+   * 描述:
+   *  query枚举值:
+   * true:是;
+   * false:否,默认否。
+   * 商户可选择是否查询指定状态的转账明细单,当转账批次单状态为“FINISHED”(已完成)时,才会返回满足条件的转账明细单
+   * 示例值:true
+   * 
+ */ + @SerializedName("need_query_detail") + private Boolean needQueryDetail; + + /** + *
+   * 字段名:请求资源起始位置
+   * 变量名:offset
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  query该次请求资源的起始位置,从0开始,默认值为0
+   * 
+ */ + @SerializedName("offset") + private Integer offset; + + /** + *
+   * 字段名:最大资源条数
+   * 变量名:limit
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  query该次请求可返回的最大明细条数,最小20条,最大100条,不传则默认20条。不足20条按实际条数返回
+   * 示例值:20
+   * 
+ */ + @SerializedName("limit") + private Integer limit; + + /** + *
+   * 字段名:明细状态
+   * 变量名:detail_status
+   * 是否必填:否
+   * 类型:string[1,32]
+   * 描述:
+   *  query查询指定状态的转账明细单,当need_query_detail为true时,该字段必填
+   * ALL:全部。需要同时查询转账成功和转账失败的明细单
+   * SUCCESS:转账成功。只查询转账成功的明细单
+   * FAIL:转账失败。只查询转账失败的明细单
+   * 示例值:FAIL
+   * 
+ */ + @SerializedName("detail_status") + private String detailStatus; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/WxDetailsQueryRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/WxDetailsQueryRequest.java new file mode 100644 index 0000000000..6216bed53e --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/merchanttransfer/WxDetailsQueryRequest.java @@ -0,0 +1,53 @@ +package com.github.binarywang.wxpay.bean.merchanttransfer; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * The type Wx details query request. + * + * @author glz + * @date 2022-6-11 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class WxDetailsQueryRequest implements Serializable { + private static final long serialVersionUID = 4869511970509348272L; + + /** + *
+   * 字段名:微信批次单号
+   * 变量名:batch_id
+   * 是否必填:是
+   * 类型:string[1,64]
+   * 描述:
+   *  path微信批次单号,微信商家转账系统返回的唯一标识
+   * 示例值:1030000071100999991182020050700019480001
+   * 
+ */ + @SerializedName("batch_id") + private String batchId; + + /** + *
+   * 字段名:微信明细单号
+   * 变量名:detail_id
+   * 是否必填:是
+   * 类型:string[1,64]
+   * 描述:
+   *  path微信支付系统内部区分转账批次单下不同转账明细单的唯一标识
+   * 示例值:1040000071100999991182020050700019500100
+   * 
+ */ + @SerializedName("detail_id") + private String detailId; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MerchantTransferService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MerchantTransferService.java new file mode 100644 index 0000000000..049253acac --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MerchantTransferService.java @@ -0,0 +1,150 @@ +package com.github.binarywang.wxpay.service; + +import com.github.binarywang.wxpay.bean.merchanttransfer.*; +import com.github.binarywang.wxpay.exception.WxPayException; + +/** + * 商家转账到零钱(直联商户) + * + * @author glz + * @date 2022-6-11 + */ +public interface MerchantTransferService { + + /** + * 发起商家转账API + *

+ * 适用对象:直连商户 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_1.shtml + * 请求URL:https://api.mch.weixin.qq.com/v3/transfer/batches + * 请求方式:POST + * 接口限频: 单个商户 50QPS,如果超过频率限制,会报错FREQUENCY_LIMITED,请降低频率请求。 + * 是否需要证书:是 + * + * @param request the request + * @return transfer create result + * @throws WxPayException the wx pay exception + */ + TransferCreateResult createTransfer(TransferCreateRequest request) throws WxPayException; + + /** + * 微信批次单号查询批次单API + *

+ * 适用对象:直连商户 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_2.shtml + * 请求URL:https://api.mch.weixin.qq.com/v3/transfer/batches/batch-id/{batch_id} + * 请求方式:GET + * 接口限频: 单个商户 50QPS,如果超过频率限制,会报错FREQUENCY_LIMITED,请降低频率请求。 + * + * @param request the request + * @return batches query result + * @throws WxPayException the wx pay exception + */ + BatchesQueryResult queryWxBatches(WxBatchesQueryRequest request) throws WxPayException; + + /** + * 微信明细单号查询明细单API + *

+ * 适用对象:直连商户 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_3.shtml + * 请求URL:https://api.mch.weixin.qq.com/v3/transfer/batches/batch-id/{batch_id}/details/detail-id/{detail_id} + * 请求方式:GET + * 接口限频: 单个商户 50QPS,如果超过频率限制,会报错FREQUENCY_LIMITED,请降低频率请求。 + * + * @param request the request + * @return details query result + * @throws WxPayException the wx pay exception + */ + DetailsQueryResult queryWxDetails(WxDetailsQueryRequest request) throws WxPayException; + + /** + * 商家批次单号查询批次单API + *

+ * 适用对象:直连商户 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_5.shtml + * 请求URL:https://api.mch.weixin.qq.com/v3/transfer/batches/out-batch-no/{out_batch_no} + * 请求方式:GET + * 接口限频: 单个商户 50QPS,如果超过频率限制,会报错FREQUENCY_LIMITED,请降低频率请求。 + * + * @param request the request + * @return batches query result + * @throws WxPayException the wx pay exception + */ + BatchesQueryResult queryMerchantBatches(MerchantBatchesQueryRequest request) throws WxPayException; + + /** + * 商家明细单号查询明细单API + *

+ * 适用对象:直连商户 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_6.shtml + * 请求URL:https://api.mch.weixin.qq.com/v3/transfer/batches/out-batch-no/{out_batch_no}/details/out-detail-no/{out_detail_no} + * 请求方式:GET + * 接口限频: 单个商户 50QPS,如果超过频率限制,会报错FREQUENCY_LIMITED,请降低频率请求。 + * + * @param request the request + * @return details query result + * @throws WxPayException the wx pay exception + */ + DetailsQueryResult queryMerchantDetails(MerchantDetailsQueryRequest request) throws WxPayException; + + /** + * 转账电子回单申请受理API + *

+ * 适用对象:直连商户 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_7.shtml + * 请求URL:https://api.mch.weixin.qq.com/v3/transfer/bill-receipt + * 请求方式:POST + * 接口限频: 单个商户 20QPS,如果超过频率限制,会报错FREQUENCY_LIMITED,请降低频率请求。 + * + * @param request the request + * @return electronic bill result + * @throws WxPayException the wx pay exception + */ + ElectronicBillResult applyElectronicBill(ElectronicBillApplyRequest request) throws WxPayException; + + /** + * 查询转账电子回单API + *

+ * 适用对象:直连商户 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_8.shtml + * 请求URL:https://api.mch.weixin.qq.com/v3/transfer/bill-receipt/{out_batch_no} + * 请求方式:GET + * + * @param outBatchNo the out batch no + * @return electronic bill result + * @throws WxPayException the wx pay exception + */ + ElectronicBillResult queryElectronicBill(String outBatchNo) throws WxPayException; + + /** + * 转账明细电子回单受理API + *

+ * 适用对象:直连商户 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_9.shtml + * 请求URL:https://api.mch.weixin.qq.com/v3/transfer-detail/electronic-receipts + * 请求方式:POST + * 接口限频: 单个商户 20QPS,如果超过频率限制,会报错FREQUENCY_LIMITED,请降低频率请求。 + * 前置条件:只支持受理最近30天内的转账明细单 + * + * @param request the request + * @return detail electronic bill result + * @throws WxPayException the wx pay exception + */ + DetailElectronicBillResult applyDetailElectronicBill(DetailElectronicBillRequest request) throws WxPayException; + + + /** + * 查询转账明细电子回单受理结果API + *

+ * 适用对象:直连商户 + * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_10.shtml + * 请求URL:https://api.mch.weixin.qq.com/v3/transfer-detail/electronic-receipts + * 请求方式:GET + * 前置条件:只支持查询最近90天内的转账明细单 + * + * @param request the request + * @return detail electronic bill result + * @throws WxPayException the wx pay exception + */ + DetailElectronicBillResult queryDetailElectronicBill(DetailElectronicBillRequest request) throws WxPayException; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java index 29735a00c4..bf95d5593b 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java @@ -304,6 +304,13 @@ public interface WxPayService { */ MarketingBusiFavorService getMarketingBusiFavorService(); + /** + * 获取商家转账到零钱服务类 + * + * @return the merchant transfer service + */ + MerchantTransferService getMerchantTransferService(); + /** * 设置企业付款服务类,允许开发者自定义实现类. * diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java index 6753f6d1f6..f88165c721 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java @@ -27,6 +27,8 @@ import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import lombok.Getter; +import lombok.Setter; import me.chanjar.weixin.common.error.WxRuntimeException; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -63,100 +65,63 @@ public abstract class BaseWxPayServiceImpl implements WxPayService { static ThreadLocal wxApiData = new ThreadLocal<>(); + + @Setter + @Getter private EntPayService entPayService = new EntPayServiceImpl(this); + + @Getter private final ProfitSharingService profitSharingService = new ProfitSharingServiceImpl(this); + + @Getter private final ProfitSharingV3Service profitSharingV3Service = new ProfitSharingV3ServiceImpl(this); - private final RedpackService redpackService = new RedpackServiceImpl(this); - private final PayScoreService payScoreService = new PayScoreServiceImpl(this); - private final EcommerceService ecommerceService = new EcommerceServiceImpl(this); - private final BusinessCircleService businessCircleService = new BusinessCircleServiceImpl(this); - private final MerchantMediaService merchantMediaService = new MerchantMediaServiceImpl(this); - private final MarketingMediaService marketingMediaService = new MarketingMediaServiceImpl(this); - private final MarketingFavorService marketingFavorService = new MarketingFavorServiceImpl(this); - private final MarketingBusiFavorService marketingBusiFavorService = new MarketingBusiFavorServiceImpl(this); - private final WxEntrustPapService wxEntrustPapService = new WxEntrustPapServiceImpl(this); - private final PartnerTransferService partnerTransferService = new PartnerTransferServiceImpl(this); - private final PayrollService payrollService = new PayrollServiceImpl(this); - private final ComplaintService complaintsService = new ComplaintServiceImpl(this); - private final BankService bankService = new BankServiceImpl(this); - private final TransferService transferService = new TransferServiceImpl(this); - protected Map configMap; + @Getter + private final RedpackService redpackService = new RedpackServiceImpl(this); - @Override - public EntPayService getEntPayService() { - return entPayService; - } + @Getter + private final PayScoreService payScoreService = new PayScoreServiceImpl(this); - @Override - public ProfitSharingService getProfitSharingService() { - return profitSharingService; - } + @Getter + private final EcommerceService ecommerceService = new EcommerceServiceImpl(this); - @Override - public ProfitSharingV3Service getProfitSharingV3Service() { - return profitSharingV3Service; - } + @Getter + private final BusinessCircleService businessCircleService = new BusinessCircleServiceImpl(this); - @Override - public PayScoreService getPayScoreService() { - return payScoreService; - } + @Getter + private final MerchantMediaService merchantMediaService = new MerchantMediaServiceImpl(this); - @Override - public RedpackService getRedpackService() { - return this.redpackService; - } + @Getter + private final MarketingMediaService marketingMediaService = new MarketingMediaServiceImpl(this); - @Override - public EcommerceService getEcommerceService() { - return ecommerceService; - } + @Getter + private final MarketingFavorService marketingFavorService = new MarketingFavorServiceImpl(this); - @Override - public BusinessCircleService getBusinessCircleService() { - return this.businessCircleService; - } + @Getter + private final MarketingBusiFavorService marketingBusiFavorService = new MarketingBusiFavorServiceImpl(this); - @Override - public MerchantMediaService getMerchantMediaService() { - return this.merchantMediaService; - } + @Getter + private final WxEntrustPapService wxEntrustPapService = new WxEntrustPapServiceImpl(this); - @Override - public MarketingMediaService getMarketingMediaService() { - return this.marketingMediaService; - } + @Getter + private final PartnerTransferService partnerTransferService = new PartnerTransferServiceImpl(this); - @Override - public MarketingFavorService getMarketingFavorService() { - return this.marketingFavorService; - } + @Getter + private final PayrollService payrollService = new PayrollServiceImpl(this); - @Override - public MarketingBusiFavorService getMarketingBusiFavorService() { - return this.marketingBusiFavorService; - } + @Getter + private final ComplaintService complaintsService = new ComplaintServiceImpl(this); - @Override - public void setEntPayService(EntPayService entPayService) { - this.entPayService = entPayService; - } + @Getter + private final BankService bankService = new BankServiceImpl(this); - @Override - public WxEntrustPapService getWxEntrustPapService() { - return wxEntrustPapService; - } + @Getter + private final TransferService transferService = new TransferServiceImpl(this); - @Override - public PartnerTransferService getPartnerTransferService() { - return partnerTransferService; - } + @Getter + private final MerchantTransferService merchantTransferService = new MerchantTransferServiceImpl(this); - @Override - public PayrollService getPayrollService() { - return payrollService; - } + protected Map configMap; @Override public WxPayConfig getConfig() { diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MerchantTransferServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MerchantTransferServiceImpl.java new file mode 100644 index 0000000000..0a6317e3a3 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MerchantTransferServiceImpl.java @@ -0,0 +1,118 @@ +package com.github.binarywang.wxpay.service.impl; + +import com.github.binarywang.wxpay.bean.merchanttransfer.*; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.service.MerchantTransferService; +import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * @author glz + * @date 2022/6/11 + */ +@Slf4j +@RequiredArgsConstructor +public class MerchantTransferServiceImpl implements MerchantTransferService { + private static final Gson GSON = (new GsonBuilder()).create(); + + private final WxPayService wxPayService; + + + @Override + public TransferCreateResult createTransfer(TransferCreateRequest request) throws WxPayException { + request.setAppid(this.wxPayService.getConfig().getAppId()); + String url = String.format("%s/v3/transfer/batches", this.wxPayService.getPayBaseUrl()); + RsaCryptoUtil.encryptFields(request, this.wxPayService.getConfig().getVerifier().getValidCertificate()); + + String response = wxPayService.postV3WithWechatpaySerial(url,GSON.toJson(request)); + return GSON.fromJson(response, TransferCreateResult.class); + } + + @Override + public BatchesQueryResult queryWxBatches(WxBatchesQueryRequest request) throws WxPayException { + String url = String.format("%s/v3/transfer/batches/batch-id/%s?need_query_detail=%b", this.wxPayService.getPayBaseUrl(), request.getBatchId(), request.getNeedQueryDetail()); + + if(request.getOffset()!=null){ + url = String.format("%s&offset=%d",url,request.getOffset()); + } + if(request.getLimit()!=null){ + url = String.format("%s&limit=%d",url,request.getLimit()); + } + if(request.getDetailStatus()!=null && request.getDetailStatus().length()!=0){ + url = String.format("%s&detail_status=%s",url,request.getDetailStatus()); + } + + String response = wxPayService.getV3(url); + return GSON.fromJson(response, BatchesQueryResult.class); + } + + @Override + public DetailsQueryResult queryWxDetails(WxDetailsQueryRequest request) throws WxPayException { + String url = String.format("%s/v3/transfer/batches/batch-id/%s/details/detail-id/%s",this.wxPayService.getPayBaseUrl(),request.getBatchId(),request.getDetailId()); + String response = wxPayService.getV3(url); + return GSON.fromJson(response, DetailsQueryResult.class); + } + + @Override + public BatchesQueryResult queryMerchantBatches(MerchantBatchesQueryRequest request) throws WxPayException { + String url = String.format("%s/v3/transfer/batches/out-batch-no/%s?need_query_detail=%b", this.wxPayService.getPayBaseUrl(), request.getOutBatchNo(),request.getNeedQueryDetail()); + + if(request.getOffset()!=null){ + url = String.format("%s&offset=%d",url,request.getOffset()); + } + if(request.getLimit()!=null){ + url = String.format("%s&limit=%d",url,request.getLimit()); + } + if(request.getDetailStatus()!=null && request.getDetailStatus().length()!=0){ + url = String.format("%s&detail_status=%s",url,request.getDetailStatus()); + } + + String response = wxPayService.getV3(url); + return GSON.fromJson(response, BatchesQueryResult.class); + } + + @Override + public DetailsQueryResult queryMerchantDetails(MerchantDetailsQueryRequest request) throws WxPayException { + String url = String.format("%s/v3/transfer/batches/out-batch-no/%s/details/out-detail-no/%s",this.wxPayService.getPayBaseUrl(),request.getOutBatchNo(),request.getOutDetailNo()); + String response = wxPayService.getV3(url); + return GSON.fromJson(response, DetailsQueryResult.class); + } + + @Override + public ElectronicBillResult applyElectronicBill(ElectronicBillApplyRequest request) throws WxPayException { + String url = String.format("%s/v3/transfer/bill-receipt",this.wxPayService.getPayBaseUrl()); + String response = wxPayService.postV3(url,GSON.toJson(request)); + return GSON.fromJson(response, ElectronicBillResult.class); + } + + @Override + public ElectronicBillResult queryElectronicBill(String outBatchNo) throws WxPayException { + String url = String.format("%s/v3/transfer/bill-receipt/%s",this.wxPayService.getPayBaseUrl(),outBatchNo); + String response = wxPayService.getV3(url); + return GSON.fromJson(response, ElectronicBillResult.class); + } + + @Override + public DetailElectronicBillResult applyDetailElectronicBill(DetailElectronicBillRequest request) throws WxPayException { + String url = String.format("%s/v3/transfer-detail/electronic-receipts",this.wxPayService.getPayBaseUrl()); + String response = wxPayService.postV3(url,GSON.toJson(request)); + return GSON.fromJson(response, DetailElectronicBillResult.class); + } + + @Override + public DetailElectronicBillResult queryDetailElectronicBill(DetailElectronicBillRequest request) throws WxPayException { + String url = String.format("%s/v3/transfer-detail/electronic-receipts?accept_type=%s&out_detail_no=%s", this.wxPayService.getPayBaseUrl(), request.getAcceptType(),request.getOutDetailNo()); + + if(request.getOutBatchNo()!=null && request.getOutBatchNo().length()!=0){ + url = String.format("%s&out_batch_no=%s",url,request.getOutBatchNo()); + } + + String response = wxPayService.getV3(url); + return GSON.fromJson(response, DetailElectronicBillResult.class); + } + +} diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/MerchantTransferServiceImplTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/MerchantTransferServiceImplTest.java new file mode 100644 index 0000000000..fd7eb66c95 --- /dev/null +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/MerchantTransferServiceImplTest.java @@ -0,0 +1,110 @@ +package com.github.binarywang.wxpay.service.impl; + +import com.github.binarywang.wxpay.bean.merchanttransfer.*; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.testbase.ApiTestModule; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.inject.Inject; +import lombok.extern.slf4j.Slf4j; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +/** + * 商家转账到零钱(直连商户) + * @author glz + * @date 2022/6/11 + */ +@Slf4j +@Test +@Guice(modules = ApiTestModule.class) +public class MerchantTransferServiceImplTest { + + @Inject + private WxPayService wxPayService; + + private static final Gson GSON = new GsonBuilder().create(); + + @Test + public void createTransfer() throws WxPayException { + String requestParamStr = "{\"out_batch_no\":\"p11lfk2020042013\",\"batch_name\":\"xxx\",\"batch_remark\":\"xxx\",\"total_amount\":30,\"total_num\":1,\"transfer_detail_list\":[{\"out_detail_no\":\"x23zy545Bd5436\",\"transfer_amount\":30,\"transfer_remark\":\"5586提款\",\"openid\":\"or1b65DLMUir7F-_vLwKlutmm3qw\",\"user_name\":\"xxx\"}]}"; + + TransferCreateRequest request = GSON.fromJson(requestParamStr, TransferCreateRequest.class); + TransferCreateResult result = wxPayService.getMerchantTransferService().createTransfer(request); + log.info(result.toString()); + } + + @Test + public void queryWxBatches() throws WxPayException { + String requestParamStr = "{\"batch_id\":\"xxx\",\"need_query_detail\":true,\"offset\":0,\"limit\":20,\"detail_status\":\"ALL\"}"; + + WxBatchesQueryRequest request = GSON.fromJson(requestParamStr, WxBatchesQueryRequest.class); + log.info("request:{}",request); + BatchesQueryResult result = wxPayService.getMerchantTransferService().queryWxBatches(request); + log.info(result.toString()); + } + + @Test + public void queryWxDetails() throws WxPayException { + String requestParamStr = "{\"batch_id\":\"xxx\",\"detail_id\":\"xxx\"}"; + + WxDetailsQueryRequest request = GSON.fromJson(requestParamStr, WxDetailsQueryRequest.class); + DetailsQueryResult result = wxPayService.getMerchantTransferService().queryWxDetails(request); + log.info(result.toString()); + } + + @Test + public void queryMerchantBatches() throws WxPayException { + String requestParamStr = "{\"out_batch_no\":\"p11lfk2020042013\",\"need_query_detail\":true,\"offset\":0,\"limit\":20,\"detail_status\":\"ALL\"}"; + + MerchantBatchesQueryRequest request = GSON.fromJson(requestParamStr, MerchantBatchesQueryRequest.class); + BatchesQueryResult result = wxPayService.getMerchantTransferService().queryMerchantBatches(request); + log.info(result.toString()); + } + + @Test + public void queryMerchantDetails() throws WxPayException { + String requestParamStr = "{\"out_detail_no\":\"x23zy545Bd5436\",\"out_batch_no\":\"p11lfk2020042013\"}"; + + MerchantDetailsQueryRequest request = GSON.fromJson(requestParamStr, MerchantDetailsQueryRequest.class); + DetailsQueryResult result = wxPayService.getMerchantTransferService().queryMerchantDetails(request); + log.info(result.toString()); + } + + @Test + public void applyElectronicBill() throws WxPayException { + String requestParamStr = "{\"out_batch_no\":\"p11lfk2020042013\"}"; + + ElectronicBillApplyRequest request = GSON.fromJson(requestParamStr, ElectronicBillApplyRequest.class); + ElectronicBillResult result = wxPayService.getMerchantTransferService().applyElectronicBill(request); + log.info(result.toString()); + } + + @Test + public void queryElectronicBill() throws WxPayException { + String outBatchNo = "p11lfk2020042013"; + + ElectronicBillResult result = wxPayService.getMerchantTransferService().queryElectronicBill(outBatchNo); + log.info(result.toString()); + } + + @Test + public void applyDetailElectronicBill() throws WxPayException { + String requestParamStr = "{\"accept_type\":\"BATCH_TRANSFER\",\"out_batch_no\":\"p11lfk2020042013\",\"out_detail_no\":\"x23zy545Bd5436\"}"; + + DetailElectronicBillRequest request = GSON.fromJson(requestParamStr, DetailElectronicBillRequest.class); + DetailElectronicBillResult result = wxPayService.getMerchantTransferService().applyDetailElectronicBill(request); + log.info(result.toString()); + } + + @Test + public void queryDetailElectronicBill() throws WxPayException { + String requestParamStr = "{\"accept_type\":\"BATCH_TRANSFER\",\"out_batch_no\":\"p11lfk2020042013\",\"out_detail_no\":\"x23zy545Bd5436\"}"; + + DetailElectronicBillRequest request = GSON.fromJson(requestParamStr, DetailElectronicBillRequest.class); + DetailElectronicBillResult result = wxPayService.getMerchantTransferService().queryDetailElectronicBill(request); + log.info(result.toString()); + } + +}