diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharing/ProfitSharingResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharing/ProfitSharingResult.java new file mode 100644 index 000000000..122821cf9 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharing/ProfitSharingResult.java @@ -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; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharing/ProfitsharingRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharing/ProfitsharingRequest.java new file mode 100644 index 000000000..10ed0d93b --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharing/ProfitsharingRequest.java @@ -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; + + /** + *
+ * 字段名:微信订单号. + * 变量名:transaction_id + * 是否必填:是 + * String(32) + * 示例值:4208450740201411110007820472 + * 描述:微信支付订单号 + *+ */ + @XStreamAlias("transaction_id") + @Required + private String transactionId; + + /** + *
+ * 字段名:商户分账单号. + * 变量名:out_order_no + * 是否必填:是 + * String(64) + * 示例值:P20150806125346 + * 描述:商户系统内部的分账单号,在商户系统内部唯一(单次分账、多次分账、完结分账应使用不同的商户分账单号),同一分账单号多次请求等同一次。只能是数字、大小写字母_-|*@ + *+ */ + @XStreamAlias("out_order_no") + @Required + private String outOrderNo; + + /** + *
+ * 字段名:分账接收方列表. + * 变量名:receivers + * 是否必填:是 + * String(10240) + * 示例值:[ + * { + * "type": "MERCHANT_ID", + * "account":"190001001", + * "amount":100, + * "description": "分到商户" + * }, + * { + * "type": "PERSONAL_WECHATID", + * "account":"86693952", + * "amount":888, + * "description": "分到个人" + * } + * ] + * 描述:分账接收方列表,不超过50个json对象,不能设置分账方作为分账接受方,使用Json格式 + *+ */ + @XStreamAlias("receivers") + @Required + private String receivers; + + + @Override + protected void checkConstraints() throws WxPayException { + /** + * 目前仅支持HMAC-SHA256 + */ + this.setSignType(WxPayConstants.SignType.HMAC_SHA256); + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharing/Receiver.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharing/Receiver.java new file mode 100644 index 000000000..439b60a2c --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharing/Receiver.java @@ -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; + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharing/ReceiverList.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharing/ReceiverList.java new file mode 100644 index 000000000..d3d8c07d3 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/profitsharing/ReceiverList.java @@ -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); + } + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java index 76f823ccf..4f8480b6a 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java @@ -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; - /** *
* 微信支付常量类 @@ -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"; + } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/ProfitSharingService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/ProfitSharingService.java new file mode 100644 index 000000000..754c7c2fd --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/ProfitSharingService.java @@ -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 { + /** + * 单次分账请求按照传入的分账接收方账号和资金进行分账,同时会将订单剩余的待分账金额解冻给特约商户。故操作成功后,订单不能再进行分账,也不能进行分账完结。 + *+ * 接口频率: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; + + ; +} 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 51d46512a..555362e66 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 @@ -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; + /** *
* 查询红包记录. 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 2f671488a..13473a5d4 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 @@ -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 ThreadLocalwxApiData = 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; diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/ProfitSharingServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/ProfitSharingServiceImpl.java new file mode 100644 index 000000000..dd6c23d06 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/ProfitSharingServiceImpl.java @@ -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; + } +} diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/ProfitSharingServiceImplTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/ProfitSharingServiceImplTest.java new file mode 100644 index 000000000..5d955e51d --- /dev/null +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/ProfitSharingServiceImplTest.java @@ -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()); + } +}