🆕 #2672 【微信支付】增加商家转账的更多接口

This commit is contained in:
Binary Wang 2022-06-21 16:49:54 +08:00
parent 541589be59
commit 1ccb94fd4e
17 changed files with 2018 additions and 75 deletions

View File

@ -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;
/**
* <pre>
* 字段名最大资源条数
* 变量名limit
* 是否必填
* 类型int
* 描述
* query该次请求可返回的最大资源转账明细单条数最小20条最大100条不传则默认20条不足20条按实际条数返回
* 示例值20
* </pre>
*/
@SerializedName("limit")
private Integer limit;
/**
* <pre>
* 字段名请求资源起始位置
* 变量名transfer_batch
* 是否必填
* 类型int
* 描述
* query该次请求资源转账明细单的起始位置从0开始转账明细单列表为空时不返回
* 示例值1
* </pre>
*/
@SerializedName("offset")
private Integer offset;
/**
* <pre>
* 字段名转账批次单
* 变量名transfer_batch
* 是否必填
* 类型object
* 描述
* 转账批次单基本信息
* </pre>
*/
@SerializedName("transfer_batch")
private TransferBatch transferBatch;
/**
* <pre>
* 字段名转账明细单列表
* 变量名transfer_detail_list
* 是否必填
* 类型array
* 描述
* body发起批量转账的明细列表最多三千笔
* </pre>
*/
@SerializedName("transfer_detail_list")
private List<TransferDetail> transferDetailList;
/**
* The type Transfer batch.
*/
@Data
@Accessors(chain = true)
public class TransferBatch implements Serializable {
/**
* <pre>
* 字段名商户号
* 变量名mchid
* 是否必填
* 类型string[1,32]
* 描述
* 微信支付分配的商户号
* 示例值1900001109
* </pre>
*/
@SerializedName("mchid")
private String mchid;
/**
* <pre>
* 字段名商家批次单号
* 变量名out_batch_no
* 是否必填
* 类型string[1,32]
* 描述
* 商户系统内部的商家批次单号在商户系统内部唯一
* 示例值plfk2020042013
* </pre>
*/
@SerializedName("out_batch_no")
private String outBatchNo;
/**
* <pre>
* 字段名微信批次单号
* 变量名batch_id
* 是否必填
* 类型string[1,32]
* 描述
* 微信批次单号微信商家转账系统返回的唯一标识
* 示例值1030000071100999991182020050700019480001
* </pre>
*/
@SerializedName("batch_id")
private String batchId;
/**
* <pre>
* 字段名直连商户的appid
* 变量名appid
* 是否必填
* 类型string[1,32]
* 描述
* 申请商户号的appid或商户号绑定的appid企业号corpid即为此appid
* 示例值wxf636efh567hg4356
* </pre>
*/
@SerializedName("appid")
private String appid;
/**
* <pre>
* 字段名批次状态
* 变量名batch_status
* 是否必填
* 类型string[1,32]
* 描述
* 枚举值
* WAIT_PAY待付款商户员工确认付款阶段
* ACCEPTED:已受理批次已受理成功若发起批量转账的30分钟后转账批次单仍处于该状态可能原因是商户账户余额不足等商户可查询账户资金流水若该笔转账批次单的扣款已经发生则表示批次已经进入转账中请再次查单确认
* PROCESSING:转账中已开始处理批次内的转账明细单
* FINISHED已完成批次内的所有转账明细单都已处理完成
* CLOSED已关闭可查询具体的批次关闭原因确认
* 示例值ACCEPTED
* </pre>
*/
@SerializedName("batch_status")
private String batchStatus;
/**
* <pre>
* 字段名批次类型
* 变量名batch_type
* 是否必填
* 类型string[1,32]
* 描述
* 枚举值
* APIAPI方式发起
* WEB页面方式发起
* 示例值API
* </pre>
*/
@SerializedName("batch_type")
private String batchType;
/**
* <pre>
* 字段名批次名称
* 变量名batch_name
* 是否必填
* 类型string[1,32]
* 描述
* 该笔批量转账的名称
* 示例值2019年1月深圳分部报销单
* </pre>
*/
@SerializedName("batch_name")
private String batchName;
/**
* <pre>
* 字段名批次备注
* 变量名batch_remark
* 是否必填
* 类型string[1,32]
* 描述
* 转账说明UTF8编码最多允许32个字符
* 示例值2019年1月深圳分部报销单
* </pre>
*/
@SerializedName("batch_remark")
private String batchRemark;
/**
* <pre>
* 字段名批次关闭原因
* 变量名close_reason
* 是否必填
* 类型string[1,64]
* 描述
* 如果批次单状态为CLOSED已关闭则有关闭原因
* MERCHANT_REVOCATION商户主动撤销
* OVERDUE_CLOSE系统超时关闭
* 示例值OVERDUE_CLOSE
* </pre>
*/
@SerializedName("close_reason")
private String closeReason;
/**
* <pre>
* 字段名转账总金额
* 变量名total_amount
* 是否必填
* 类型int
* 描述
* 转账金额单位为分
* 示例值4000000
* </pre>
*/
@SerializedName("total_amount")
private Integer totalAmount;
/**
* <pre>
* 字段名转账总笔数
* 变量名total_num
* 是否必填
* 类型int
* 描述
* 一个转账批次单最多发起三千笔转账
* 示例值200
* </pre>
*/
@SerializedName("total_num")
private Integer totalNum;
/**
* <pre>
* 字段名批次创建时间
* 变量名create_time
* 是否必填
* 类型string[1,32]
* 描述
* 批次受理成功时返回遵循rfc3339标准格式格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONEyyyy-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
* </pre>
*/
@SerializedName("create_time")
private String createTime;
/**
* <pre>
* 字段名批次更新时间
* 变量名update_time
* 是否必填
* 类型string[1,32]
* 描述
* 批次最近一次状态变更的时间遵循rfc3339标准格式格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONEyyyy-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
* </pre>
*/
@SerializedName("update_time")
private String updateTime;
/**
* <pre>
* 字段名转账成功金额
* 变量名success_amount
* 是否必填
* 类型int
* 描述
* 转账成功的金额单位为分当批次状态为PROCESSING转账中转账成功金额随时可能变化
* 示例值3900000
* </pre>
*/
@SerializedName("success_amount")
private Integer successAmount;
/**
* <pre>
* 字段名转账成功笔数
* 变量名success_num
* 是否必填
* 类型int
* 描述
* 转账成功的笔数当批次状态为PROCESSING转账中转账成功笔数随时可能变化
* 示例值199
* </pre>
*/
@SerializedName("success_num")
private Integer successNum;
/**
* <pre>
* 字段名转账失败金额
* 变量名fail_amount
* 是否必填
* 类型int
* 描述
* 转账失败的金额单位为分
* 示例值100000
* </pre>
*/
@SerializedName("fail_amount")
private Integer failAmount;
/**
* <pre>
* 字段名转账失败笔数
* 变量名fail_num
* 是否必填
* 类型int
* 描述
* 转账失败的笔数
* 示例值1
* </pre>
*/
@SerializedName("fail_num")
private Integer failNum;
}
/**
* The type Transfer detail.
*/
@Data
@Accessors(chain = true)
public class TransferDetail implements Serializable {
/**
* <pre>
* 字段名微信明细单号
* 变量名detail_id
* 是否必填
* 类型string[1,64]
* 描述
* 微信支付系统内部区分转账批次单下不同转账明细单的唯一标识
* 示例值1040000071100999991182020050700019500100
* </pre>
*/
@SerializedName("detail_id")
private String detailId;
/**
* <pre>
* 字段名商家明细单号
* 变量名out_detail_no
* 是否必填
* 类型string[1,32]
* 描述
* 商户系统内部区分转账批次单下不同转账明细单的唯一标识
* 示例值x23zy545Bd5436
* </pre>
*/
@SerializedName("out_detail_no")
private String outDetailNo;
/**
* <pre>
* 字段名明细状态
* 变量名detail_status
* 是否必填
* 类型string[1,32]
* 描述
* 枚举值
* PROCESSING转账中正在处理中转账结果尚未明确
* SUCCESS转账成功
* FAIL转账失败需要确认失败原因后再决定是否重新发起对该笔明细单的转账并非整个转账批次单
* 示例值SUCCESS
* </pre>
*/
@SerializedName("detail_status")
private String detailStatus;
}
}

View File

@ -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;
/**
* <pre>
* 字段名受理类型
* 变量名accept_type
* 是否必填
* 类型string[1,32]
* 描述
* query电子回单受理类型
* BATCH_TRANSFER批量转账明细电子回单
* TRANSFER_TO_POCKET企业付款至零钱电子回单
* TRANSFER_TO_BANK企业付款至银行卡电子回单
* 示例值BATCH_TRANSFER
* </pre>
*/
@SerializedName("accept_type")
private String acceptType;
/**
* <pre>
* 字段名商家转账批次单号
* 变量名out_batch_no
* 是否必填
* 类型string[5,32]
* 描述
* query需要电子回单的批量转账明细单所在的转账批次单号该单号为商户申请转账时生成的商户单号受理类型为BATCH_TRANSFER时该单号必填否则该单号留空
* 示例值GD2021011610162610BBdkkIwcu3
* </pre>
*/
@SerializedName("out_batch_no")
private String outBatchNo;
/**
* <pre>
* 字段名商家转账明细单号
* 变量名out_detail_no
* 是否必填
* 类型string[5,32]
* 描述
* query该单号为商户申请转账时生成的商家转账明细单号
* 1.受理类型为BATCH_TRANSFER时填写商家批量转账明细单号
* 2. 受理类型为TRANSFER_TO_POCKET或TRANSFER_TO_BANK时填写商家转账单号
* 示例值mx0911231610162610v4CNkO4HAf
* </pre>
*/
@SerializedName("out_detail_no")
private String outDetailNo;
}

View File

@ -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;
/**
* <pre>
* 字段名受理类型
* 变量名accept_type
* 是否必填
* 类型string[1,32]
* 描述
* 电子回单受理类型
* BATCH_TRANSFER批量转账明细电子回单
* TRANSFER_TO_POCKET企业付款至零钱电子回单
* TRANSFER_TO_BANK企业付款至银行卡电子回单
* 示例值BATCH_TRANSFER
* </pre>
*/
@SerializedName("accept_type")
private String acceptType;
/**
* <pre>
* 字段名商家转账批次单号
* 变量名out_batch_no
* 是否必填
* 类型string[5,32]
* 描述
* 需要电子回单的批量转账明细单所在的转账批次单号该单号为商户申请转账时生成的商户单号受理类型为BATCH_TRANSFER时该单号必填否则该单号留空
* 示例值GD2021011610162610BBdkkIwcu3
* </pre>
*/
@SerializedName("out_batch_no")
private String outBatchNo;
/**
* <pre>
* 字段名商家转账明细单号
* 变量名out_detail_no
* 是否必填
* 类型string[5,32]
* 描述
* 该单号为商户申请转账时生成的商家转账明细单号
* 1.受理类型为BATCH_TRANSFER时填写商家批量转账明细单号
* 2. 受理类型为TRANSFER_TO_POCKET或TRANSFER_TO_BANK时填写商家转账单号
* 示例值mx0911231610162610v4CNkO4HAf
* </pre>
*/
@SerializedName("out_detail_no")
private String outDetailNo;
/**
* <pre>
* 字段名电子回单受理单号
* 变量名signature_no
* 是否必填
* 类型string[3,256]
* 描述
* 电子回单受理单号受理单据的唯一标识
* 示例值1050000010509999485212020110200058820001
* </pre>
*/
@SerializedName("signature_no")
private String signatureNo;
/**
* <pre>
* 字段名电子回单状态
* 变量名signature_status
* 是否必填
* 类型string[1,10]
* 描述
* 枚举值
* ACCEPTED:已受理电子签章已受理成功
* FINISHED:已完成电子签章已处理完成
* 示例值ACCEPTED
* </pre>
*/
@SerializedName("signature_status")
private String signatureStatus;
/**
* <pre>
* 字段名电子回单文件的hash方法
* 变量名hash_type
* 是否必填
* 类型string[1,20]
* 描述
* 电子回单文件的hash方法回单状态为FINISHED时返回
* 示例值SHA256
* </pre>
*/
@SerializedName("hash_type")
private String hashType;
/**
* <pre>
* 字段名电子回单文件的hash值
* 变量名hash_value
* 是否必填
* 类型string[3,1000]
* 描述
* 电子回单文件的hash值用于下载之后验证文件的完整正确性回单状态为FINISHED时返回
* 示例值DE731F35146A0BEFADE5DB9D1E468D96C01CA8898119C674FEE9F11F4DBE5529
* </pre>
*/
@SerializedName("hash_value")
private String hashValue;
/**
* <pre>
* 字段名电子回单文件的下载地址
* 变量名download_url
* 是否必填
* 类型string[10,3000]
* 描述
* 电子回单文件的下载地址回单状态为FINISHED时返回URL有效时长为10分钟10分钟后需要重新去获取下载地址但不需要走受理
* 示例值https://api.mch.weixin.qq.com/v3/billdownload/file?token=xxx
* </pre>
*/
@SerializedName("download_url")
private String downloadUrl;
}

View File

@ -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;
/**
* <pre>
* 字段名商户号
* 变量名mchid
* 是否必填
* 类型string[1,32]
* 描述
* 微信支付分配的商户号
* 示例值1900001109
* </pre>
*/
@SerializedName("mchid")
private String mchid;
/**
* <pre>
* 字段名商家批次单号
* 变量名out_batch_no
* 是否必填
* 类型string[1,32]
* 描述
* 商户系统内部的商家批次单号在商户系统内部唯一
* 示例值plfk2020042013
* </pre>
*/
@SerializedName("out_batch_no")
private String outBatchNo;
/**
* <pre>
* 字段名微信批次单号
* 变量名batch_id
* 是否必填
* 类型string[1,64]
* 描述
* 微信批次单号微信商家转账系统返回的唯一标识
* 示例值1030000071100999991182020050700019480001
* </pre>
*/
@SerializedName("batch_id")
private String batchId;
/**
* <pre>
* 字段名直连商户的appid
* 变量名appid
* 是否必填
* 类型string[1,32]
* 描述
* 申请商户号的appid或商户号绑定的appid企业号corpid即为此appid
* 示例值wxf636efh567hg4356
* </pre>
*/
@SerializedName("appid")
private String appid;
/**
* <pre>
* 字段名商家明细单号
* 变量名out_detail_no
* 是否必填
* 类型string[1,32]
* 描述
* 商户系统内部区分转账批次单下不同转账明细单的唯一标识
* 示例值x23zy545Bd5436
* </pre>
*/
@SerializedName("out_detail_no")
private String outDetailNo;
/**
* <pre>
* 字段名微信明细单号
* 变量名detail_id
* 是否必填
* 类型string[1,64]
* 描述
* 微信支付系统内部区分转账批次单下不同转账明细单的唯一标识
* 示例值1040000071100999991182020050700019500100
* </pre>
*/
@SerializedName("detail_id")
private String detailId;
/**
* <pre>
* 字段名明细状态
* 变量名detail_status
* 是否必填
* 类型string[1,32]
* 描述
* 枚举值
* PROCESSING:转账中正在处理中转账结果尚未明确
* SUCCESS:转账成功
* FAIL:转账失败需要确认失败原因后再决定是否重新发起对该笔明细单的转账并非整个转账批次单
* 示例值SUCCESS
* </pre>
*/
@SerializedName("detail_status")
private String detailStatus;
/**
* <pre>
* 字段名转账金额
* 变量名transfer_amount
* 是否必填
* 类型int
* 描述
* 转账金额单位为分
* 示例值200000
* </pre>
*/
@SerializedName("transfer_amount")
private Integer transferAmount;
/**
* <pre>
* 字段名转账备注
* 变量名transfer_remark
* 是否必填
* 类型string[1,32]
* 描述
* 单条转账备注微信用户会收到该备注UTF8编码最多允许32个字符
* 示例值2020年4月报销
* </pre>
*/
@SerializedName("transfer_remark")
private String transferRemark;
/**
* <pre>
* 字段名明细失败原因
* 变量名fail_reason
* 是否必填
* 类型string[1,64]
* 描述
* 如果转账失败则有失败原因
* ACCOUNT_FROZEN账户冻结
* REAL_NAME_CHECK_FAIL用户未实名
* NAME_NOT_CORRECT用户姓名校验失败
* OPENID_INVALIDOpenid校验失败
* 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
* </pre>
*/
@SerializedName("fail_reason")
private String failReason;
/**
* <pre>
* 字段名用户在直连商户应用下的用户标示
* 变量名openid
* 是否必填
* 类型string[1,128]
* 描述
* 用户在直连商户appid下的唯一标识
* 示例值o-MYE42l80oelYMDE34nYD456Xoy
* </pre>
*/
@SerializedName("openid")
private String openid;
/**
* <pre>
* 字段名收款用户姓名
* 变量名user_name
* 是否必填
* 类型string[1,1024]
* 描述
* 1商户转账时传入了收款用户姓名查询时会返回收款用户姓名
* 2收款方姓名采用标准RSA算法公钥由微信侧提供
* 3 该字段需进行加密处理加密方法详见敏感信息加密说明(提醒必须在HTTP头中上送Wechatpay-Serial)
* 示例值757b340b45ebef5467rter35gf464344v3542sdf4t6re4tb4f54ty45t4yyry45
* </pre>
*/
@SerializedName("user_name")
private String userName;
/**
* <pre>
* 字段名转账发起时间
* 变量名initiate_time
* 是否必填
* 类型string[1,32]
* 描述
* 转账发起的时间遵循rfc3339标准格式格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONEyyyy-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
* </pre>
*/
@SerializedName("initiate_time")
private String initiateTime;
/**
* <pre>
* 字段名明细更新时间
* 变量名update_time
* 是否必填
* 类型string[1,32]
* 描述
* 明细最后一次状态变更的时间遵循rfc3339标准格式格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONEyyyy-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
* </pre>
*/
@SerializedName("update_time")
private String updateTime;
}

View File

@ -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;
/**
* <pre>
* 字段名商家批次单号
* 变量名out_batch_no
* 是否必填
* 类型string[5,32]
* 描述
* body商户系统内部的商家批次单号在商户系统内部唯一需要电子回单的批次单号
* 示例值plfk2020042013
* </pre>
*/
@SerializedName("out_batch_no")
private String outBatchNo;
}

View File

@ -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;
/**
* <pre>
* 字段名商家批次单号
* 变量名out_batch_no
* 是否必填
* 类型string[5,32]
* 描述
* body商户系统内部的商家批次单号在商户系统内部唯一需要电子回单的批次单号
* 示例值plfk2020042013
* </pre>
*/
@SerializedName("out_batch_no")
private String outBatchNo;
/**
* <pre>
* 字段名电子回单申请单号
* 变量名signature_no
* 是否必填
* 类型string[3,45]
* 描述
* 电子回单申请单号申请单据的唯一标识
* 示例值1050000010509999485212020110200058820001
* </pre>
*/
@SerializedName("signature_no")
private String signatureNo;
/**
* <pre>
* 字段名电子回单状态
* 变量名signature_status
* 是否必填
* 类型string[1,10]
* 描述
* 枚举值
* ACCEPTED:已受理电子签章已受理成功
* FINISHED:已完成电子签章已处理完成
* 示例值ACCEPTED
* </pre>
*/
@SerializedName("signature_status")
private String signatureStatus;
/**
* <pre>
* 字段名电子回单文件的hash方法
* 变量名hash_type
* 是否必填
* 类型string[1,20]
* 描述
* 电子回单文件的hash方法回单状态为FINISHED时返回
* 示例值SHA256
* </pre>
*/
@SerializedName("hash_type")
private String hashType;
/**
* <pre>
* 字段名电子回单文件的hash值
* 变量名hash_value
* 是否必填
* 类型string[3,1000]
* 描述
* 电子回单文件的hash值用于下载之后验证文件的完整正确性回单状态为FINISHED时返回
* 示例值DE731F35146A0BEFADE5DB9D1E468D96C01CA8898119C674FEE9F11F4DBE5529
* </pre>
*/
@SerializedName("hash_value")
private String hashValue;
/**
* <pre>
* 字段名电子回单文件的下载地址
* 变量名download_url
* 是否必填
* 类型string[10,3000]
* 描述
* 电子回单文件的下载地址回单状态为FINISHED时返回URL有效时长为10分钟10分钟后需要重新去获取下载地址但不需要走受理
* 示例值https://api.mch.weixin.qq.com/v3/billdownload/file?token=xxx
* </pre>
*/
@SerializedName("download_url")
private String downloadUrl;
/**
* <pre>
* 字段名创建时间
* 变量名create_time
* 是否必填
* 类型string[1,32]
* 描述
* 电子签章单创建时间遵循rfc3339标准格式格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONEyyyy-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
* </pre>
*/
@SerializedName("create_time")
private String createTime;
/**
* <pre>
* 字段名更新时间
* 变量名update_time
* 是否必填
* 类型string[1,32]
* 描述
* 电子签章单最近一次状态变更的时间遵循rfc3339标准格式格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONEyyyy-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
* </pre>
*/
@SerializedName("update_time")
private String updateTime;
}

View File

@ -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;
/**
* <pre>
* 字段名商家批次单号
* 变量名out_batch_no
* 是否必填
* 类型string[1,32]
* 描述
* path商户系统内部的商家批次单号要求此参数只能由数字大小写字母组成在商户系统内部唯一
* 示例值plfk2020042013
* </pre>
*/
@SerializedName("out_batch_no")
private String outBatchNo;
/**
* <pre>
* 字段名是否查询转账明细单
* 变量名need_query_detail
* 是否必填
* 类型boolean
* 描述
* query枚举值
* true
* false默认否
* 商户可选择是否查询指定状态的转账明细单当转账批次单状态为FINISHED已完成才会返回满足条件的转账明细单
* 示例值true
* </pre>
*/
@SerializedName("need_query_detail")
private Boolean needQueryDetail;
/**
* <pre>
* 字段名请求资源起始位置
* 变量名offset
* 是否必填
* 类型int
* 描述
* query该次请求资源的起始位置从0开始默认值为0
* </pre>
*/
@SerializedName("offset")
private Integer offset;
/**
* <pre>
* 字段名最大资源条数
* 变量名limit
* 是否必填
* 类型int
* 描述
* query该次请求可返回的最大明细条数最小20条最大100条不传则默认20条不足20条按实际条数返回
* 示例值20
* </pre>
*/
@SerializedName("limit")
private Integer limit;
/**
* <pre>
* 字段名明细状态
* 变量名detail_status
* 是否必填
* 类型string[1,32]
* 描述
* query查询指定状态的转账明细单当need_query_detail为true时该字段必填
* ALL:全部需要同时查询转账成功和转账失败的明细单
* SUCCESS:转账成功只查询转账成功的明细单
* FAIL:转账失败只查询转账失败的明细单
* 示例值FAIL
* </pre>
*/
@SerializedName("detail_status")
private String detailStatus;
}

View File

@ -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;
/**
* <pre>
* 字段名商家明细单号
* 变量名out_detail_no
* 是否必填
* 类型string[1,32]
* 描述
* path商户系统内部区分转账批次单下不同转账明细单的唯一标识要求此参数只能由数字大小写字母组成
* 示例值x23zy545Bd5436
* </pre>
*/
@SerializedName("out_detail_no")
private String outDetailNo;
/**
* <pre>
* 字段名商家批次单号
* 变量名out_batch_no
* 是否必填
* 类型string[1,32]
* 描述
* path商户系统内部的商家批次单号要求此参数只能由数字大小写字母组成在商户系统内部唯一
* 示例值plfk2020042013
* </pre>
*/
@SerializedName("out_batch_no")
private String outBatchNo;
}

View File

@ -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;
/**
* <pre>
* 字段名直连商户的appid
* 变量名appid
* 是否必填
* 类型string[1,32]
* 描述
* 申请商户号的appid或商户号绑定的appid企业号corpid即为此appid
* 示例值wxf636efh567hg4356
* </pre>
*/
@SerializedName("appid")
private String appid;
/**
* <pre>
* 字段名商家批次单号
* 变量名out_batch_no
* 是否必填
* 类型string[1,32]
* 描述
* path商户系统内部的商家批次单号要求此参数只能由数字大小写字母组成在商户系统内部唯一
* 示例值plfk2020042013
* </pre>
*/
@SerializedName("out_batch_no")
private String outBatchNo;
/**
* <pre>
* 字段名批次名称
* 变量名batch_name
* 是否必填
* 类型string[1,32]
* 描述
* 该笔批量转账的名称
* 示例值2019年1月深圳分部报销单
* </pre>
*/
@SerializedName("batch_name")
private String batchName;
/**
* <pre>
* 字段名批次备注
* 变量名batch_remark
* 是否必填
* 类型string[1,32]
* 描述
* 转账说明UTF8编码最多允许32个字符
* 示例值2019年1月深圳分部报销单
* </pre>
*/
@SerializedName("batch_remark")
private String batchRemark;
/**
* <pre>
* 字段名转账总金额
* 变量名total_amount
* 是否必填
* 类型int
* 描述
* 转账金额单位为分
* 示例值4000000
* </pre>
*/
@SerializedName("total_amount")
private Integer totalAmount;
/**
* <pre>
* 字段名转账总笔数
* 变量名total_num
* 是否必填
* 类型int
* 描述
* 一个转账批次单最多发起三千笔转账
* 示例值200
* </pre>
*/
@SerializedName("total_num")
private Integer totalNum;
/**
* <pre>
* 字段名转账明细单列表
* 变量名transfer_detail_list
* 是否必填
* 类型array
* 描述
* body发起批量转账的明细列表最多三千笔
* </pre>
*/
@SerializedName("transfer_detail_list")
@SpecEncrypt
private List<TransferDetailList> transferDetailList;
/**
* The type Transfer detail list.
*/
@Data
@Accessors(chain = true)
public static class TransferDetailList implements Serializable {
/**
* <pre>
* 字段名商家明细单号
* 变量名out_detail_no
* 是否必填
* 类型string[1,32]
* 描述
* 商户系统内部区分转账批次单下不同转账明细单的唯一标识
* 示例值x23zy545Bd5436
* </pre>
*/
@SerializedName("out_detail_no")
private String outDetailNo;
/**
* <pre>
* 字段名转账金额
* 变量名transfer_amount
* 是否必填
* 类型int
* 描述
* 转账金额单位为分
* 示例值200000
* </pre>
*/
@SerializedName("transfer_amount")
private Integer transferAmount;
/**
* <pre>
* 字段名转账备注
* 变量名transfer_remark
* 是否必填
* 类型string[1,32]
* 描述
* 单条转账备注微信用户会收到该备注UTF8编码最多允许32个字符
* 示例值2020年4月报销
* </pre>
*/
@SerializedName("transfer_remark")
private String transferRemark;
/**
* <pre>
* 字段名用户在直连商户应用下的用户标示
* 变量名openid
* 是否必填
* 类型string[1,128]
* 描述
* 用户在直连商户appid下的唯一标识
* 示例值o-MYE42l80oelYMDE34nYD456Xoy
* </pre>
*/
@SerializedName("openid")
private String openid;
/**
* <pre>
* 字段名收款用户姓名
* 变量名user_name
* 是否必填
* 类型string[1,1024]
* 描述
* 1商户转账时传入了收款用户姓名查询时会返回收款用户姓名
* 2收款方姓名采用标准RSA算法公钥由微信侧提供
* 3 该字段需进行加密处理加密方法详见敏感信息加密说明(提醒必须在HTTP头中上送Wechatpay-Serial)
* 示例值757b340b45ebef5467rter35gf464344v3542sdf4t6re4tb4f54ty45t4yyry45
* </pre>
*/
@SerializedName("user_name")
@SpecEncrypt
private String userName;
}
}

View File

@ -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;
/**
* <pre>
* 字段名商家批次单号
* 变量名out_batch_no
* 是否必填
* 类型string[1,32]
* 描述
* 商户系统内部的商家批次单号在商户系统内部唯一
* 示例值plfk2020042013
* </pre>
*/
@SerializedName("out_batch_no")
private String outBatchNo;
/**
* <pre>
* 字段名微信批次单号
* 变量名batch_id
* 是否必填
* 类型string[1,32]
* 描述
* 微信批次单号微信商家转账系统返回的唯一标识
* 示例值1030000071100999991182020050700019480001
* </pre>
*/
@SerializedName("batch_id")
private String batchId;
/**
* <pre>
* 字段名批次创建时间
* 变量名create_time
* 是否必填
* 类型string[1,32]
* 描述
* 批次受理成功时返回遵循rfc3339标准格式格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONEyyyy-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
* </pre>
*/
@SerializedName("create_time")
private String createTime;
}

View File

@ -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;
/**
* <pre>
* 字段名微信批次单号
* 变量名batch_id
* 是否必填
* 类型string[1,64]
* 描述
* path微信批次单号微信商家转账系统返回的唯一标识
* 示例值1030000071100999991182020050700019480001
* </pre>
*/
@SerializedName("batch_id")
private String batchId;
/**
* <pre>
* 字段名是否查询转账明细单
* 变量名need_query_detail
* 是否必填
* 类型boolean
* 描述
* query枚举值
* true
* false默认否
* 商户可选择是否查询指定状态的转账明细单当转账批次单状态为FINISHED已完成才会返回满足条件的转账明细单
* 示例值true
* </pre>
*/
@SerializedName("need_query_detail")
private Boolean needQueryDetail;
/**
* <pre>
* 字段名请求资源起始位置
* 变量名offset
* 是否必填
* 类型int
* 描述
* query该次请求资源的起始位置从0开始默认值为0
* </pre>
*/
@SerializedName("offset")
private Integer offset;
/**
* <pre>
* 字段名最大资源条数
* 变量名limit
* 是否必填
* 类型int
* 描述
* query该次请求可返回的最大明细条数最小20条最大100条不传则默认20条不足20条按实际条数返回
* 示例值20
* </pre>
*/
@SerializedName("limit")
private Integer limit;
/**
* <pre>
* 字段名明细状态
* 变量名detail_status
* 是否必填
* 类型string[1,32]
* 描述
* query查询指定状态的转账明细单当need_query_detail为true时该字段必填
* ALL:全部需要同时查询转账成功和转账失败的明细单
* SUCCESS:转账成功只查询转账成功的明细单
* FAIL:转账失败只查询转账失败的明细单
* 示例值FAIL
* </pre>
*/
@SerializedName("detail_status")
private String detailStatus;
}

View File

@ -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;
/**
* <pre>
* 字段名微信批次单号
* 变量名batch_id
* 是否必填
* 类型string[1,64]
* 描述
* path微信批次单号微信商家转账系统返回的唯一标识
* 示例值1030000071100999991182020050700019480001
* </pre>
*/
@SerializedName("batch_id")
private String batchId;
/**
* <pre>
* 字段名微信明细单号
* 变量名detail_id
* 是否必填
* 类型string[1,64]
* 描述
* path微信支付系统内部区分转账批次单下不同转账明细单的唯一标识
* 示例值1040000071100999991182020050700019500100
* </pre>
*/
@SerializedName("detail_id")
private String detailId;
}

View File

@ -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
* <p>
* 适用对象直连商户
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_1.shtml
* 请求URLhttps://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
* <p>
* 适用对象直连商户
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_2.shtml
* 请求URLhttps://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
* <p>
* 适用对象直连商户
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_3.shtml
* 请求URLhttps://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
* <p>
* 适用对象直连商户
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_5.shtml
* 请求URLhttps://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
* <p>
* 适用对象直连商户
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_6.shtml
* 请求URLhttps://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
* <p>
* 适用对象直连商户
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_7.shtml
* 请求URLhttps://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
* <p>
* 适用对象直连商户
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_8.shtml
* 请求URLhttps://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
* <p>
* 适用对象直连商户
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_9.shtml
* 请求URLhttps://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
* <p>
* 适用对象直连商户
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_10.shtml
* 请求URLhttps://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;
}

View File

@ -304,6 +304,13 @@ public interface WxPayService {
*/
MarketingBusiFavorService getMarketingBusiFavorService();
/**
* 获取商家转账到零钱服务类
*
* @return the merchant transfer service
*/
MerchantTransferService getMerchantTransferService();
/**
* 设置企业付款服务类允许开发者自定义实现类.
*

View File

@ -27,6 +27,8 @@ import com.google.common.collect.ImmutableMap;
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,101 +65,64 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
static ThreadLocal<WxPayApiData> 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);
@Getter
private final RedpackService redpackService = new RedpackServiceImpl(this);
@Getter
private final PayScoreService payScoreService = new PayScoreServiceImpl(this);
@Getter
private final EcommerceService ecommerceService = new EcommerceServiceImpl(this);
@Getter
private final BusinessCircleService businessCircleService = new BusinessCircleServiceImpl(this);
@Getter
private final MerchantMediaService merchantMediaService = new MerchantMediaServiceImpl(this);
@Getter
private final MarketingMediaService marketingMediaService = new MarketingMediaServiceImpl(this);
@Getter
private final MarketingFavorService marketingFavorService = new MarketingFavorServiceImpl(this);
@Getter
private final MarketingBusiFavorService marketingBusiFavorService = new MarketingBusiFavorServiceImpl(this);
@Getter
private final WxEntrustPapService wxEntrustPapService = new WxEntrustPapServiceImpl(this);
@Getter
private final PartnerTransferService partnerTransferService = new PartnerTransferServiceImpl(this);
@Getter
private final PayrollService payrollService = new PayrollServiceImpl(this);
@Getter
private final ComplaintService complaintsService = new ComplaintServiceImpl(this);
@Getter
private final BankService bankService = new BankServiceImpl(this);
@Getter
private final TransferService transferService = new TransferServiceImpl(this);
@Getter
private final MerchantTransferService merchantTransferService = new MerchantTransferServiceImpl(this);
protected Map<String, WxPayConfig> configMap;
@Override
public EntPayService getEntPayService() {
return entPayService;
}
@Override
public ProfitSharingService getProfitSharingService() {
return profitSharingService;
}
@Override
public ProfitSharingV3Service getProfitSharingV3Service() {
return profitSharingV3Service;
}
@Override
public PayScoreService getPayScoreService() {
return payScoreService;
}
@Override
public RedpackService getRedpackService() {
return this.redpackService;
}
@Override
public EcommerceService getEcommerceService() {
return ecommerceService;
}
@Override
public BusinessCircleService getBusinessCircleService() {
return this.businessCircleService;
}
@Override
public MerchantMediaService getMerchantMediaService() {
return this.merchantMediaService;
}
@Override
public MarketingMediaService getMarketingMediaService() {
return this.marketingMediaService;
}
@Override
public MarketingFavorService getMarketingFavorService() {
return this.marketingFavorService;
}
@Override
public MarketingBusiFavorService getMarketingBusiFavorService() {
return this.marketingBusiFavorService;
}
@Override
public void setEntPayService(EntPayService entPayService) {
this.entPayService = entPayService;
}
@Override
public WxEntrustPapService getWxEntrustPapService() {
return wxEntrustPapService;
}
@Override
public PartnerTransferService getPartnerTransferService() {
return partnerTransferService;
}
@Override
public PayrollService getPayrollService() {
return payrollService;
}
@Override
public WxPayConfig getConfig() {
if (this.configMap.size() == 1) {

View File

@ -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);
}
}

View File

@ -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());
}
}