#1010 增加微信分账相关接口

* 微信单次分账接口

* - 微信多次分账
- 微信完结分账
- 添加分账接受方
- 删除分账接受方
- 查询分账结果【未能完成单元测试,微信返回签名失败】
- 分账回退【未能完成单元测试,使用真实数据返回“参数不正确”,我对比官方文档除了缺少`sub_mch_id`和`sub_appid`之外其他相同,当我随便填了一个商户id的时候,提示“回退方没有开通分账回退功能”】
- 回退结果查询【未能完成单元测试,因分账回退无法进行,模拟数据返回”记录不存在“】
This commit is contained in:
王广鑫
2019-10-24 09:23:56 +08:00
committed by Binary Wang
parent 81df397536
commit d184ff8303
14 changed files with 977 additions and 16 deletions

View File

@@ -0,0 +1,70 @@
package com.github.binarywang.wxpay.bean.profitsharing;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.*;
import me.chanjar.weixin.common.annotation.Required;
/**
* @author Wang GuangXin 2019/10/23 14:02
* @version 1.0
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Builder(builderMethodName = "newBuilder")
@NoArgsConstructor
@AllArgsConstructor
@XStreamAlias("xml")
public class ProfitSharingFinishRequest extends BaseWxPayRequest {
private static final long serialVersionUID = -4265779954583596627L;
/**
* <pre>
* 字段名:微信订单号.
* 变量名transaction_id
* 是否必填:是
* String(32)
* 示例值4208450740201411110007820472
* 描述:微信支付订单号
* </pre>
*/
@XStreamAlias("transaction_id")
@Required
private String transactionId;
/**
* <pre>
* 字段名:商户分账单号.
* 变量名out_order_no
* 是否必填:是
* String(64)
* 示例值P20150806125346
* 描述商户系统内部的分账单号在商户系统内部唯一单次分账、多次分账、完结分账应使用不同的商户分账单号同一分账单号多次请求等同一次。只能是数字、大小写字母_-|*@
* </pre>
*/
@XStreamAlias("out_order_no")
@Required
private String outOrderNo;
/**
* <pre>
* 字段名:分账完结描述.
* 变量名out_order_no
* 是否必填:是
* String(80)
* 示例值:分账已完成
* 描述:分账完结的原因描述
* </pre>
*/
@XStreamAlias("description")
@Required
private String description;
@Override
protected void checkConstraints() throws WxPayException {
this.setSignType(WxPayConstants.SignType.HMAC_SHA256);
}
}

View File

@@ -0,0 +1,54 @@
package com.github.binarywang.wxpay.bean.profitsharing;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.*;
import me.chanjar.weixin.common.annotation.Required;
/**
* @author Wang GuangXin 2019/10/22 15:44
* @version 1.0
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Builder(builderMethodName = "newBuilder")
@NoArgsConstructor
@AllArgsConstructor
@XStreamAlias("xml")
public class ProfitSharingQueryRequest extends BaseWxPayRequest {
private static final long serialVersionUID = 3566332883053157102L;
/**
* <pre>
* 字段名:微信支付订单号.
* 变量名transaction_id
* 是否必填:是
* String(32)
* 示例值4208450740201411110007820472
* 描述:微信支付订单号
* </pre>
*/
@XStreamAlias("transaction_id")
@Required
private String transactionId;
/**
* <pre>
* 字段名:商户分账单号.
* 变量名out_order_no
* 是否必填:是
* String(64)
* 示例值P20150806125346
* 描述:查询分账结果,输入申请分账时的商户分账单号; 查询分账完结的执行结果,输入发起分账完结时的商户分账单号
* </pre>
*/
@XStreamAlias("out_order_no")
@Required
private String outOrderNo;
@Override
protected void checkConstraints() throws WxPayException {
this.setSignType(WxPayConstants.SignType.HMAC_SHA256);
}
}

View File

@@ -0,0 +1,114 @@
package com.github.binarywang.wxpay.bean.profitsharing;
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* @author Wang GuangXin 2019/10/22 15:51
* @version 1.0
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@XStreamAlias("xml")
public class ProfitSharingQueryResult extends BaseWxPayResult {
private static final long serialVersionUID = 2548673608075775067L;
/**
* 微信订单号
*/
@XStreamAlias("transaction_id")
private String transactionId;
/**
* 商户分账单号
*/
@XStreamAlias("out_order_no")
private String outOrderNo;
/**
* 微信分账单号
*/
@XStreamAlias("orderId")
private String orderId;
/**
* 分账单状态
*/
@XStreamAlias("status")
private String status;
/**
* 关单原因
*/
@XStreamAlias("close_reason")
private String closeReason;
/**
* 分账接收方列表
*/
@XStreamAlias("receivers")
private String receivers;
/**
* 分账金额
*/
@XStreamAlias("amount")
private Integer amount;
/**
* 分账描述
*/
@XStreamAlias("description")
private String description;
public ProfitSharingQueryResult.Receivers formatReceivers() {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
Gson gson = gsonBuilder.create();
return gson.fromJson(receivers, Receivers.class);
}
@Data
public class Receivers {
/**
* 分账接收方类型
*/
private String type;
/**
* 分账接收方帐号
*/
private String account;
/**
* 分账金额
*/
private Integer amount;
/**
* 分账描述
*/
private String description;
/**
* 分账结果
*/
private String result;
/**
* 分账完成时间
*/
private String finishTime;
/**
* 分账失败原因
*/
private String failReason;
@Override
public String toString() {
return "Receivers{" +
"type='" + type + '\'' +
", account='" + account + '\'' +
", amount=" + amount +
", description='" + description + '\'' +
", result='" + result + '\'' +
", finishTime='" + finishTime + '\'' +
", failReason='" + failReason + '\'' +
'}';
}
}
}

View File

@@ -0,0 +1,47 @@
package com.github.binarywang.wxpay.bean.profitsharing;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.*;
import me.chanjar.weixin.common.annotation.Required;
/**
* 添加/删除分账接受方请求对象
*
* @author Wang GuangXin 2019/10/22 13:41
* @version 1.0
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Builder(builderMethodName = "newBuilder")
@NoArgsConstructor
@AllArgsConstructor
@XStreamAlias("xml")
public class ProfitSharingReceiverRequest extends BaseWxPayRequest {
private static final long serialVersionUID = 2628263563539120323L;
/**
* <pre>
* 字段名:分账接收方.
* 变量名receiver
* 是否必填:是
* String(2048)
* 示例值:{
* "type": "MERCHANT_ID",
* "account": "190001001",
* "name": "示例商户全称",
* "relation_type": "STORE_OWNER"
* }
* 描述分账接收方对象json格式
* </pre>
*/
@XStreamAlias("receiver")
@Required
private String receiver;
@Override
protected void checkConstraints() throws WxPayException {
this.setSignType(WxPayConstants.SignType.HMAC_SHA256);
}
}

View File

@@ -0,0 +1,25 @@
package com.github.binarywang.wxpay.bean.profitsharing;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* @author Wang GuangXin 2019/10/22 14:54
* @version 1.0
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@XStreamAlias("xml")
public class ProfitSharingReceiverResult extends BaseWxPayResult {
private static final long serialVersionUID = 876204163877798066L;
/**
* 分账接收方.
*/
@XStreamAlias("receiver")
private String receiver;
}

View File

@@ -17,7 +17,7 @@ import me.chanjar.weixin.common.annotation.Required;
@NoArgsConstructor
@AllArgsConstructor
@XStreamAlias("xml")
public class ProfitsharingRequest extends BaseWxPayRequest {
public class ProfitSharingRequest extends BaseWxPayRequest {
private static final long serialVersionUID = 212049937430575842L;
/**

View File

@@ -0,0 +1,72 @@
package com.github.binarywang.wxpay.bean.profitsharing;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.*;
import me.chanjar.weixin.common.annotation.Required;
import org.apache.commons.lang3.StringUtils;
/**
* @author Wang GuangXin 2019/10/23 15:32
* @version 1.0
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Builder(builderMethodName = "newBuilder")
@NoArgsConstructor
@AllArgsConstructor
@XStreamAlias("xml")
public class ProfitSharingReturnQueryRequest extends BaseWxPayRequest {
private static final long serialVersionUID = -8838464614726086009L;
/**
* <pre>
* 字段名:微信分账单号.
* 变量名order_id
* 是否必填:二选一
* string(64)
* 示例值3008450740201411110007820472
* 描述:原发起分账请求时,微信返回的微信分账单号,与商户分账单号一一对应。
* 微信分账单号与商户分账单号二选一填写
* </pre>
*/
@XStreamAlias("order_id")
private String orderId;
/**
* <pre>
* 字段名:商户分账单号.
* 变量名out_order_no
* 是否必填:二选一
* Sstring(64)
* 示例值P20180806125346
* 描述:原发起分账请求时使用的商户后台系统的分账单号。
* 微信分账单号与商户分账单号二选一填写
* </pre>
*/
@XStreamAlias("out_order_no")
private String outOrderNo;
/**
* <pre>
* 字段名:商户回退单号.
* 变量名out_return_no
* 是否必填:是
* string(64)
* 示例值R20190516001
* 描述:调用回退接口提供的商户系统内部的回退单号
* </pre>
*/
@Required
@XStreamAlias("out_return_no")
private String outReturnNo;
@Override
protected void checkConstraints() throws WxPayException {
if (StringUtils.isBlank(orderId) && StringUtils.isBlank(outOrderNo)) {
throw new WxPayException("order_id 和 outOrderNo 必须有一个存在");
}
this.setSignType(WxPayConstants.SignType.HMAC_SHA256);
}
}

View File

@@ -0,0 +1,133 @@
package com.github.binarywang.wxpay.bean.profitsharing;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.*;
import me.chanjar.weixin.common.annotation.Required;
import org.apache.commons.lang3.StringUtils;
/**
* @author Wang GuangXin 2019/10/23 14:27
* @version 1.0
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Builder(builderMethodName = "newBuilder")
@NoArgsConstructor
@AllArgsConstructor
@XStreamAlias("xml")
public class ProfitSharingReturnRequest extends BaseWxPayRequest {
private static final long serialVersionUID = 5926280401474809744L;
/**
* <pre>
* 字段名:微信分账单号.
* 变量名order_id
* 是否必填:二选一
* string(64)
* 示例值3008450740201411110007820472
* 描述:原发起分账请求时,微信返回的微信分账单号,与商户分账单号一一对应。
* 微信分账单号与商户分账单号二选一填写
* </pre>
*/
@XStreamAlias("order_id")
private String orderId;
/**
* <pre>
* 字段名:商户分账单号.
* 变量名out_order_no
* 是否必填:二选一
* Sstring(64)
* 示例值P20180806125346
* 描述:原发起分账请求时使用的商户后台系统的分账单号。
* 微信分账单号与商户分账单号二选一填写
* </pre>
*/
@XStreamAlias("out_order_no")
private String outOrderNo;
/**
* <pre>
* 字段名:商户回退单号.
* 变量名out_return_no
* 是否必填:是
* string(64)
* 示例值R20190516001
* 描述:此回退单号是商户在自己后台生成的一个新的回退单号,在商户后台唯一
* 只能是数字、大小写字母_-|*@ ,同一回退单号多次请求等同一次。
* </pre>
*/
@Required
@XStreamAlias("out_return_no")
private String outReturnNo;
/**
* <pre>
* 字段名:回退方类型.
* 变量名return_account_type
* 是否必填:是
* String(32)
* 示例值MERCHANT_ID
* 描述:枚举值:
* MERCHANT_ID商户ID
* 暂时只支持从商户接收方回退分账金额
* </pre>
*/
@Required
@XStreamAlias("return_account_type")
private String returnAccountType;
/**
* <pre>
* 字段名:回退方账号.
* 变量名return_account
* 是否必填:是
* String(64)
* 示例值86693852
* 描述回退方类型是MERCHANT_ID时填写商户ID
* 只能对原分账请求中成功分给商户接收方进行回退
* </pre>
*/
@Required
@XStreamAlias("return_account")
private String returnAccount;
/**
* <pre>
* 字段名:回退金额.
* 变量名return_amount
* 是否必填:是
* int
* 示例值888
* 描述:需要从分账接收方回退的金额,单位为分,只能为整数,不能超过原始分账单分出给该接收方的金额
* </pre>
*/
@Required
@XStreamAlias("return_amount")
private Integer returnAmount;
/**
* <pre>
* 字段名:回退描述.
* 变量名description
* 是否必填:是
* String(80)
* 示例值:用户退款
* 描述:分账回退的原因描述
* </pre>
*/
@Required
@XStreamAlias("description")
private String description;
@Override
protected void checkConstraints() throws WxPayException {
if (StringUtils.isBlank(orderId) && StringUtils.isBlank(outOrderNo)) {
throw new WxPayException("order_id 和 outOrderNo 必须有一个存在");
}
this.setSignType(WxPayConstants.SignType.HMAC_SHA256);
}
}

View File

@@ -0,0 +1,74 @@
package com.github.binarywang.wxpay.bean.profitsharing;
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* @author Wang GuangXin 2019/10/23 14:41
* @version 1.0
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@XStreamAlias("xml")
public class ProfitSharingReturnResult extends BaseWxPayResult {
private static final long serialVersionUID = 718554909816994568L;
/**
* 微信分账单号
*/
@XStreamAlias("order_id")
private String orderId;
/**
* 商户分账单号
*/
@XStreamAlias("out_order_no")
private String outOrderNo;
/**
* 商户回退单号
*/
@XStreamAlias("out_return_no")
private String outReturnNo;
/**
* 微信回退单号
*/
@XStreamAlias("return_no")
private String returnNo;
/**
* 回退方类型
*/
@XStreamAlias("return_account_type")
private String returnAccountType;
/**
* 回退方账号
*/
@XStreamAlias("return_account")
private String returnAccount;
/**
* 回退金额
*/
@XStreamAlias("return_amount")
private Integer returnAmount;
/**
* 回退描述
*/
@XStreamAlias("description")
private String description;
/**
* 回退结果
*/
@XStreamAlias("result")
private String result;
/**
* 失败原因
*/
@XStreamAlias("fail_reason")
private String failReason;
/**
* 完成时间
*/
@XStreamAlias("finish_time")
private String finishTime;
}

View File

@@ -1,5 +1,9 @@
package com.github.binarywang.wxpay.bean.profitsharing;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.Serializable;
/**
@@ -11,8 +15,13 @@ public class Receiver implements Serializable {
private String account;
private Integer amount;
private String description;
private String name;
private String relationType;
private String customRelation;
/**
* 此构造函数用于单次分账
*
* @param type MERCHANT_ID商户ID
* PERSONAL_WECHATID个人微信号PERSONAL_OPENID个人openid由父商户APPID转换得到PERSONAL_SUB_OPENID: 个人sub_openid由子商户APPID转换得到
* @param account 类型是MERCHANT_ID时是商户ID
@@ -29,6 +38,66 @@ public class Receiver implements Serializable {
this.description = description;
}
/**
* 此构造用于添加分账方
*
* @param type MERCHANT_ID商户ID
* PERSONAL_WECHATID个人微信号PERSONAL_OPENID个人openid由父商户APPID转换得到PERSONAL_SUB_OPENID: 个人sub_openid由子商户APPID转换得到
* @param account 类型是MERCHANT_ID时是商户ID
* 类型是PERSONAL_WECHATID时是个人微信号
* 类型是PERSONAL_OPENID时是个人openid
* 类型是PERSONAL_SUB_OPENID时是个人sub_openid
* @param name 分账接收方类型是MERCHANT_ID时是商户全称必传
* 分账接收方类型是PERSONAL_NAME 时,是个人姓名(必传)
* 分账接收方类型是PERSONAL_OPENID时是个人姓名选传传则校验
* 分账接收方类型是PERSONAL_SUB_OPENID时是个人姓名选传传则校验
* @param relationType 子商户与接收方的关系。
* 本字段值为枚举:
* SERVICE_PROVIDER服务商
* STORE门店
* STAFF员工
* STORE_OWNER店主
* PARTNER合作伙伴
* HEADQUARTER总部
* BRAND品牌方
* DISTRIBUTOR分销商
* USER用户
* SUPPLIER供应商
* CUSTOM自定义
* @param customRelation 子商户与接收方具体的关系本字段最多10个字。
* 当字段relation_type的值为CUSTOM时本字段必填
* 当字段relation_type的值不为CUSTOM时本字段无需填写
*/
public Receiver(String type, String account, String name, String relationType, String customRelation) {
this.type = type;
this.account = account;
this.name = name;
this.relationType = relationType;
this.customRelation = customRelation;
}
/**
* 用于删除分账接受方
*
* @param type MERCHANT_ID商户ID
* PERSONAL_WECHATID个人微信号PERSONAL_OPENID个人openid由父商户APPID转换得到PERSONAL_SUB_OPENID: 个人sub_openid由子商户APPID转换得到
* @param account 类型是MERCHANT_ID时是商户ID
* 类型是PERSONAL_WECHATID时是个人微信号
* 类型是PERSONAL_OPENID时是个人openid
* 类型是PERSONAL_SUB_OPENID时是个人sub_openid
*/
public Receiver(String type, String account) {
this.type = type;
this.account = account;
}
public String toJSONString() {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
Gson gson = gsonBuilder.create();
return gson.toJson(this);
}
public String getType() {
return type;
}
@@ -44,4 +113,16 @@ public class Receiver implements Serializable {
public String getDescription() {
return description;
}
public String getName() {
return name;
}
public String getRelationType() {
return relationType;
}
public String getCustomRelation() {
return customRelation;
}
}

View File

@@ -346,6 +346,17 @@ public class WxPayUnifiedOrderRequest extends BaseWxPayRequest {
*/
@XStreamAlias("fingerprint")
private String fingerprint;
/**
* <pre>
* 字段名:是否指定服务商分账.
* 变量名profit_sharing
* 是否必填:否
* 详情Y-是,需要分账 N-否,不分账,字母要求大写,不传默认不分账
* 详细参考 https://pay.weixin.qq.com/wiki/doc/api/allocation_sl.php?chapter=24_3&index=3
* </pre>
*/
@XStreamAlias("profit_sharing")
private String profitSharing;
/**
* 如果配置中已经设置,可以不设置值.