#1010 微信支付模块增加单次分账接口

This commit is contained in:
王广鑫 2019-10-22 13:45:55 +08:00 committed by Binary Wang
parent 70ce3a2ff9
commit 81df397536
10 changed files with 351 additions and 5 deletions

View File

@ -0,0 +1,33 @@
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/22 10:06
* @version 1.0
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@XStreamAlias("xml")
public class ProfitSharingResult extends BaseWxPayResult {
/**
* 微信订单号.
*/
@XStreamAlias("transaction_id")
private String transactionId;
/**
* 商户分账单号.
*/
@XStreamAlias("out_order_no")
private String outOrderNo;
/**
* 微信分账单号.
*/
@XStreamAlias("order_id")
private String orderId;
}

View File

@ -0,0 +1,86 @@
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/21 17:57
* @version 1.0
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Builder(builderMethodName = "newBuilder")
@NoArgsConstructor
@AllArgsConstructor
@XStreamAlias("xml")
public class ProfitsharingRequest extends BaseWxPayRequest {
private static final long serialVersionUID = 212049937430575842L;
/**
* <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>
* 字段名分账接收方列表.
* 变量名receivers
* 是否必填
* String(10240)
* 示例值[
* {
* "type": "MERCHANT_ID",
* "account":"190001001",
* "amount":100,
* "description": "分到商户"
* },
* {
* "type": "PERSONAL_WECHATID",
* "account":"86693952",
* "amount":888,
* "description": "分到个人"
* }
* ]
* 描述分账接收方列表不超过50个json对象不能设置分账方作为分账接受方使用Json格式
* </pre>
*/
@XStreamAlias("receivers")
@Required
private String receivers;
@Override
protected void checkConstraints() throws WxPayException {
/**
* 目前仅支持HMAC-SHA256
*/
this.setSignType(WxPayConstants.SignType.HMAC_SHA256);
}
}

View File

@ -0,0 +1,47 @@
package com.github.binarywang.wxpay.bean.profitsharing;
import java.io.Serializable;
/**
* @author Wang GuangXin 2019/10/22 11:07
* @version 1.0
*/
public class Receiver implements Serializable {
private String type;
private String account;
private Integer amount;
private String 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 amount 分账金额单位为分只能为整数不能超过原订单支付金额及最大分账比例金额
* @param description 分账的原因描述分账账单中需要体现
*/
public Receiver(String type, String account, Integer amount, String description) {
this.type = type;
this.account = account;
this.amount = amount;
this.description = description;
}
public String getType() {
return type;
}
public String getAccount() {
return account;
}
public Integer getAmount() {
return amount;
}
public String getDescription() {
return description;
}
}

View File

@ -0,0 +1,51 @@
package com.github.binarywang.wxpay.bean.profitsharing;
import com.google.gson.Gson;
import java.io.Serializable;
import java.util.ArrayList;
/**
* @author Wang GuangXin 2019/10/22 11:01
* @version 1.0
*/
public class ReceiverList implements Serializable {
private static final long serialVersionUID = -1316860887694489921L;
ArrayList list;
private ReceiverList() {
}
/**
* 获取一个实例
* @return
*/
public static ReceiverList getInstance() {
ReceiverList receiverList = new ReceiverList();
receiverList.list = new ArrayList();
return receiverList;
}
/**
* 添加一个分账条目
* 注意微信上限为50个
* @param receiver
* @return
*/
public ReceiverList add(Receiver receiver) {
this.list.add(receiver);
return this;
}
/**
* 转为JSON格式
* @return
*/
public String toJSONString() {
Gson gson = new Gson();
return gson.toJson(this.list);
}
}

View File

@ -1,12 +1,11 @@
package com.github.binarywang.wxpay.constant;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.time.FastDateFormat;
import java.text.Format;
import java.util.List;
import org.apache.commons.lang3.time.FastDateFormat;
import com.google.common.collect.Lists;
/**
* <pre>
* 微信支付常量类
@ -273,4 +272,23 @@ public class WxPayConstants {
*/
public static final String CHANGE = "CHANGE";
}
public static class ReceiverType {
/**
* 商户id
*/
public static final String MERCHANT_ID = "MERCHANT_ID";
/**
* 个人微信号
*/
public static final String PERSONAL_WECHATID = "PERSONAL_WECHATID";
/**
* 个人openid
*/
public static final String PERSONAL_OPENID = "PERSONAL_OPENID";
/**
* 个人sub_openid
*/
public static final String PERSONAL_SUB_OPENID = "PERSONAL_SUB_OPENID";
}
}

View File

@ -0,0 +1,26 @@
package com.github.binarywang.wxpay.service;
import com.github.binarywang.wxpay.bean.profitsharing.ProfitSharingResult;
import com.github.binarywang.wxpay.bean.profitsharing.ProfitsharingRequest;
import com.github.binarywang.wxpay.exception.WxPayException;
/**
* @author Wang GuangXin 2019/10/22 10:05
* @version 1.0
*/
public interface ProfitSharingService {
/**
* 单次分账请求按照传入的分账接收方账号和资金进行分账同时会将订单剩余的待分账金额解冻给特约商户故操作成功后订单不能再进行分账也不能进行分账完结
* <p>
* 接口频率30QPS
* 文档详见: https://pay.weixin.qq.com/wiki/doc/api/allocation_sl.php?chapter=25_1&index=1
* 接口链接https://api.mch.weixin.qq.com/secapi/pay/profitsharing
*
* @param profitsharingRequest
* @return
* @throws WxPayException the wx pay exception
*/
ProfitSharingResult profitsharing(ProfitsharingRequest profitsharingRequest) throws WxPayException;
;
}

View File

@ -65,6 +65,13 @@ public interface WxPayService {
*/
EntPayService getEntPayService();
/**
* 获取分账服务类.
*
* @return the ent pay service
*/
ProfitSharingService getProfitSharingService();
/**
* 设置企业付款服务类允许开发者自定义实现类.
*
@ -304,6 +311,7 @@ public interface WxPayService {
* @throws WxPayException the wx pay exception
*/
WxPayRedpackQueryResult queryRedpack(String mchBillNo) throws WxPayException;
/**
* <pre>
* 查询红包记录.

View File

@ -18,6 +18,7 @@ import com.github.binarywang.wxpay.constant.WxPayConstants.SignType;
import com.github.binarywang.wxpay.constant.WxPayConstants.TradeType;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.EntPayService;
import com.github.binarywang.wxpay.service.ProfitSharingService;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.util.SignUtils;
import com.google.common.base.Joiner;
@ -59,7 +60,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
static ThreadLocal<WxPayApiData> wxApiData = new ThreadLocal<>();
private EntPayService entPayService = new EntPayServiceImpl(this);
private ProfitSharingService profitSharingService = new ProfitSharingServiceImpl(this);
/**
* The Config.
*/
@ -70,6 +71,11 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
return entPayService;
}
@Override
public ProfitSharingService getProfitSharingService() {
return profitSharingService;
}
@Override
public void setEntPayService(EntPayService entPayService) {
this.entPayService = entPayService;

View File

@ -0,0 +1,31 @@
package com.github.binarywang.wxpay.service.impl;
import com.github.binarywang.wxpay.bean.entpay.EntPayResult;
import com.github.binarywang.wxpay.bean.profitsharing.ProfitSharingResult;
import com.github.binarywang.wxpay.bean.profitsharing.ProfitsharingRequest;
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.ProfitSharingService;
import com.github.binarywang.wxpay.service.WxPayService;
/**
* @author Wang GuangXin 2019/10/22 10:13
* @version 1.0
*/
public class ProfitSharingServiceImpl implements ProfitSharingService {
private WxPayService payService;
public ProfitSharingServiceImpl(WxPayService payService) {
this.payService = payService;
}
@Override
public ProfitSharingResult profitsharing(ProfitsharingRequest request) throws WxPayException {
request.checkAndSign(this.payService.getConfig());
String url = this.payService.getPayBaseUrl() + "/secapi/pay/profitsharing";
String responseContent = this.payService.post(url, request.toXML(), true);
ProfitSharingResult result = BaseWxPayResult.fromXML(responseContent, ProfitSharingResult.class);
result.checkResult(this.payService, request.getSignType(), true);
return result;
}
}

View File

@ -0,0 +1,40 @@
package com.github.binarywang.wxpay.service.impl;
import com.github.binarywang.wxpay.bean.profitsharing.ProfitsharingRequest;
import com.github.binarywang.wxpay.bean.profitsharing.Receiver;
import com.github.binarywang.wxpay.bean.profitsharing.ReceiverList;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.testbase.ApiTestModule;
import com.google.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
@Test
@Guice(modules = ApiTestModule.class)
public class ProfitSharingServiceImplTest {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Inject
private WxPayService payService;
@Test
public void testProfitsharing() throws WxPayException {
ReceiverList instance = ReceiverList.getInstance();
instance.add(new Receiver(WxPayConstants.ReceiverType.PERSONAL_OPENID,
"oyOUE5ql4TtzrBg5cVOwxq6tbjOs",
100,
"分到用户"));
ProfitsharingRequest request = ProfitsharingRequest
.newBuilder()
.outOrderNo("P20150806125346")
.transactionId("4208450740201411110007820472")
// .receivers("[{\"type\": \"PERSONAL_OPENID\",\"account\":\"oyOUE5ql4TtzrBg5cVOwxq6tbjOs\",\"amount\":100,\"description\": \"分到用户\"}]")
.receivers(instance.toJSONString())
.build();
this.logger.info(this.payService.getProfitSharingService().profitsharing(request).toString());
}
}