From b4f8aa48b14b87553b8493fb61efbcc4374c4e83 Mon Sep 17 00:00:00 2001 From: wangzecheng Date: Wed, 31 Mar 2021 10:17:05 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=BE=AE=E4=BF=A1=E6=94=AF=E4=BB=98V2?= =?UTF-8?q?=E5=88=86=E8=B4=A6=E6=8E=A5=E5=8F=A3=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wechat/v2/WechatAllocationApi.java | 247 ++++++++++++++++++ .../payment/wechat/v2/model/BaseModel.java | 48 +++- .../allocation/BaseProfitSharingModel.java | 25 ++ .../BaseProfitSharingReceiverModel.java | 27 ++ .../allocation/MultiProfitSharingModel.java | 8 + .../allocation/MultiProfitSharingSModel.java | 8 + .../ProfitSharingAddReceiverModel.java | 72 +++++ .../ProfitSharingAddReceiverSModel.java | 15 ++ .../allocation/ProfitSharingFinishModel.java | 49 ++++ .../model/allocation/ProfitSharingModel.java | 23 ++ .../ProfitSharingOrderAmountQueryModel.java | 28 ++ .../allocation/ProfitSharingQueryModel.java | 35 +++ .../ProfitSharingRemoveReceiverModel.java | 23 ++ .../ProfitSharingRemoveReceiverSModel.java | 15 ++ .../allocation/ProfitSharingReturnModel.java | 35 +++ .../ProfitSharingReturnQueryModel.java | 51 ++++ .../model/allocation/ProfitSharingSModel.java | 18 ++ .../wechat/v2/model/allocation/Receiver.java | 46 ++++ .../v2/model/allocation/RelationType.java | 17 ++ .../wechat/v2/model/allocation/Type.java | 14 + .../payment/wechat/v3/WechatApiProvider.java | 16 ++ .../payment/wechat/v3/WechatPayCallback.java | 21 ++ .../v3/model/ProfitSharingConsumeData.java | 76 ++++++ 23 files changed, 910 insertions(+), 7 deletions(-) create mode 100644 payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/WechatAllocationApi.java create mode 100644 payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/BaseProfitSharingModel.java create mode 100644 payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/BaseProfitSharingReceiverModel.java create mode 100644 payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/MultiProfitSharingModel.java create mode 100644 payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/MultiProfitSharingSModel.java create mode 100644 payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingAddReceiverModel.java create mode 100644 payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingAddReceiverSModel.java create mode 100644 payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingFinishModel.java create mode 100644 payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingModel.java create mode 100644 payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingOrderAmountQueryModel.java create mode 100644 payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingQueryModel.java create mode 100644 payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingRemoveReceiverModel.java create mode 100644 payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingRemoveReceiverSModel.java create mode 100644 payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingReturnModel.java create mode 100644 payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingReturnQueryModel.java create mode 100644 payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingSModel.java create mode 100644 payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/Receiver.java create mode 100644 payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/RelationType.java create mode 100644 payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/Type.java create mode 100644 payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/model/ProfitSharingConsumeData.java diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/WechatAllocationApi.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/WechatAllocationApi.java new file mode 100644 index 0000000..48b7814 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/WechatAllocationApi.java @@ -0,0 +1,247 @@ +/* + * Copyright 2019-2021 felord.cn + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * Website: + * https://felord.cn + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.felord.payment.wechat.v2; + +import cn.felord.payment.wechat.WechatPayProperties; +import cn.felord.payment.wechat.v2.model.allocation.*; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpMethod; + +import java.util.List; + +/** + * 微信支付分账 + *

+ * + * @since 1.0.10.RELEASE + */ +@Slf4j +public class WechatAllocationApi { + /** + * The constant MAPPER. + */ + private static final ObjectMapper MAPPER = new ObjectMapper(); + + static { + MAPPER.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE) + .setSerializationInclusion(JsonInclude.Include.NON_NULL) + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true) + .registerModule(new JavaTimeModule()); + } + + private final WechatV2Client wechatV2Client; + + /** + * Instantiates a new Wechat allocation api. + * + * @param wechatV2Client the wechat v 2 client + */ + public WechatAllocationApi(WechatV2Client wechatV2Client) { + this.wechatV2Client = wechatV2Client; + } + + /** + * 请求单次分账 + * + * @param profitSharingModel the profit sharing model + * @return json node + */ + @SneakyThrows + public JsonNode profitSharing(ProfitSharingModel profitSharingModel) { + ProfitSharingSModel profitSharingSModel = new ProfitSharingSModel(); + List receivers = profitSharingModel.getReceivers(); + profitSharingSModel.setReceivers(MAPPER.writeValueAsString(receivers)); + + WechatPayProperties.V3 v3 = wechatV2Client.getWechatMetaBean().getV3(); + profitSharingSModel.setAppid(v3.getAppId()); + profitSharingSModel.setMchId(v3.getMchId()); + + profitSharingSModel.setTransactionId(profitSharingModel.getTransactionId()); + profitSharingSModel.setOutOrderNo(profitSharingModel.getOutOrderNo()); + + profitSharingSModel.certPath(v3.getCertPath()); + profitSharingSModel.signType("HMAC-SHA256"); + return wechatV2Client.wechatPayRequest(profitSharingSModel, + HttpMethod.POST, + "https://api.mch.weixin.qq.com/secapi/pay/profitsharing"); + } + + /** + * 请求单次分账 + * + * @param multiProfitSharingModel the multi profit sharing model + * @return json node + */ + @SneakyThrows + public JsonNode multiProfitSharing(MultiProfitSharingModel multiProfitSharingModel) { + MultiProfitSharingSModel multiProfitSharingSModel = new MultiProfitSharingSModel(); + List receivers = multiProfitSharingModel.getReceivers(); + multiProfitSharingSModel.setReceivers(MAPPER.writeValueAsString(receivers)); + + WechatPayProperties.V3 v3 = wechatV2Client.getWechatMetaBean().getV3(); + multiProfitSharingSModel.setAppid(v3.getAppId()); + multiProfitSharingSModel.setMchId(v3.getMchId()); + + multiProfitSharingSModel.setTransactionId(multiProfitSharingModel.getTransactionId()); + multiProfitSharingSModel.setOutOrderNo(multiProfitSharingModel.getOutOrderNo()); + + multiProfitSharingSModel.certPath(v3.getCertPath()); + multiProfitSharingSModel.signType("HMAC-SHA256"); + return wechatV2Client.wechatPayRequest(multiProfitSharingSModel, + HttpMethod.POST, + "https://api.mch.weixin.qq.com/secapi/pay/multiprofitsharing"); + } + + /** + * 查询分账结果 + * + * @param profitSharingQueryModel the profit sharing query model + * @return json node + */ + public JsonNode profitSharingQuery(ProfitSharingQueryModel profitSharingQueryModel) { + WechatPayProperties.V3 v3 = wechatV2Client.getWechatMetaBean().getV3(); + profitSharingQueryModel.setMchId(v3.getMchId()); + profitSharingQueryModel.certPath(v3.getCertPath()); + profitSharingQueryModel.signType("HMAC-SHA256"); + return wechatV2Client.wechatPayRequest(profitSharingQueryModel, + HttpMethod.POST, + "https://api.mch.weixin.qq.com/pay/profitsharingquery"); + } + + /** + * 添加分账接收方 + * + * @param profitSharingAddReceiverModel the profit sharing add receiver model + * @return json node + */ + @SneakyThrows + public JsonNode profitSharingAddReceiver(ProfitSharingAddReceiverModel profitSharingAddReceiverModel) { + ProfitSharingAddReceiverSModel profitSharingAddReceiverSModel = new ProfitSharingAddReceiverSModel(); + ProfitSharingAddReceiverModel.Receiver receiver = profitSharingAddReceiverModel.getReceiver(); + profitSharingAddReceiverSModel.setReceiver(MAPPER.writeValueAsString(receiver)); + + WechatPayProperties.V3 v3 = wechatV2Client.getWechatMetaBean().getV3(); + profitSharingAddReceiverSModel.setAppid(v3.getAppId()); + profitSharingAddReceiverSModel.setMchId(v3.getMchId()); + + profitSharingAddReceiverSModel.certPath(v3.getCertPath()); + profitSharingAddReceiverSModel.signType("HMAC-SHA256"); + return wechatV2Client.wechatPayRequest(profitSharingAddReceiverSModel, + HttpMethod.POST, + "https://api.mch.weixin.qq.com/pay/profitsharingaddreceiver"); + } + + /** + * 删除分账接收方 + * + * @param profitSharingRemoveReceiverModel the profit sharing remove receiver model + * @return json node + */ + @SneakyThrows + public JsonNode profitSharingRemoveReceiver(ProfitSharingRemoveReceiverModel profitSharingRemoveReceiverModel) { + ProfitSharingRemoveReceiverSModel profitSharingRemoveReceiverSModel = new ProfitSharingRemoveReceiverSModel(); + ProfitSharingRemoveReceiverModel.Receiver receiver = profitSharingRemoveReceiverModel.getReceiver(); + profitSharingRemoveReceiverSModel.setReceiver(MAPPER.writeValueAsString(receiver)); + + WechatPayProperties.V3 v3 = wechatV2Client.getWechatMetaBean().getV3(); + profitSharingRemoveReceiverSModel.setAppid(v3.getAppId()); + profitSharingRemoveReceiverSModel.setMchId(v3.getMchId()); + + profitSharingRemoveReceiverSModel.certPath(v3.getCertPath()); + profitSharingRemoveReceiverSModel.signType("HMAC-SHA256"); + return wechatV2Client.wechatPayRequest(profitSharingRemoveReceiverSModel, + HttpMethod.POST, + "https://api.mch.weixin.qq.com/pay/profitsharingremovereceiver"); + } + + /** + * 完结分账 + * + * @param profitSharingFinishModel the profit sharing finish model + * @return json node + */ + public JsonNode profitSharingFinish(ProfitSharingFinishModel profitSharingFinishModel) { + WechatPayProperties.V3 v3 = wechatV2Client.getWechatMetaBean().getV3(); + profitSharingFinishModel.setAppid(v3.getAppId()); + profitSharingFinishModel.setMchId(v3.getMchId()); + profitSharingFinishModel.certPath(v3.getCertPath()); + profitSharingFinishModel.signType("HMAC-SHA256"); + return wechatV2Client.wechatPayRequest(profitSharingFinishModel, + HttpMethod.POST, + "https://api.mch.weixin.qq.com/secapi/pay/profitsharingfinish"); + } + + /** + * 查询订单待分账金额 + * + * @param profitSharingOrderAmountQueryModel the profit sharing order amount query model + * @return json node + */ + public JsonNode profitSharingOrderAmountQuery(ProfitSharingOrderAmountQueryModel profitSharingOrderAmountQueryModel) { + WechatPayProperties.V3 v3 = wechatV2Client.getWechatMetaBean().getV3(); + profitSharingOrderAmountQueryModel.setMchId(v3.getMchId()); + profitSharingOrderAmountQueryModel.certPath(v3.getCertPath()); + profitSharingOrderAmountQueryModel.signType("HMAC-SHA256"); + return wechatV2Client.wechatPayRequest(profitSharingOrderAmountQueryModel, + HttpMethod.POST, + "https://api.mch.weixin.qq.com/pay/profitsharingorderamountquery"); + } + + /** + * 分账回退 + * + * @param profitSharingReturnModel the profit sharing return model + * @return json node + */ + public JsonNode profitSharingReturn(ProfitSharingReturnModel profitSharingReturnModel) { + WechatPayProperties.V3 v3 = wechatV2Client.getWechatMetaBean().getV3(); + profitSharingReturnModel.setAppid(v3.getAppId()); + profitSharingReturnModel.setMchId(v3.getMchId()); + profitSharingReturnModel.certPath(v3.getCertPath()); + profitSharingReturnModel.signType("HMAC-SHA256"); + return wechatV2Client.wechatPayRequest(profitSharingReturnModel, + HttpMethod.POST, + "https://api.mch.weixin.qq.com/secapi/pay/profitsharingreturn"); + } + + /** + * 回退结果查询 + * + * @param profitSharingReturnQueryModel the profit sharing return query model + * @return json node + */ + public JsonNode profitSharingReturnQuery(ProfitSharingReturnQueryModel profitSharingReturnQueryModel) { + WechatPayProperties.V3 v3 = wechatV2Client.getWechatMetaBean().getV3(); + profitSharingReturnQueryModel.setAppid(v3.getAppId()); + profitSharingReturnQueryModel.setMchId(v3.getMchId()); + profitSharingReturnQueryModel.certPath(v3.getCertPath()); + profitSharingReturnQueryModel.signType("HMAC-SHA256"); + return wechatV2Client.wechatPayRequest(profitSharingReturnQueryModel, + HttpMethod.POST, + "https://api.mch.weixin.qq.com/pay/profitsharingreturnquery"); + } + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/BaseModel.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/BaseModel.java index f1d5fe8..7203ecc 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/BaseModel.java +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/BaseModel.java @@ -48,6 +48,8 @@ import org.springframework.util.IdGenerator; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import java.io.IOException; @@ -84,13 +86,27 @@ public abstract class BaseModel { private String sign; @JsonIgnore private String appSecret; - + @JsonIgnore + private String certPath; + @JsonIgnore + private String signType; public BaseModel appSecret(String appSecret) { this.appSecret = appSecret; return this; } + public BaseModel certPath(String certPath) { + this.certPath = certPath; + return this; + } + + + public BaseModel signType(String signType) { + this.signType = signType; + return this; + } + /** * Xml string. * @@ -99,7 +115,11 @@ public abstract class BaseModel { @SneakyThrows private String xml() { String link = link(this); - this.sign = this.md5(link); + if ("HMAC-SHA256".equals(signType)) { + this.sign = this.hmacSha256(link); + } else { + this.sign = this.md5(link); + } return XML_MAPPER.writer() .withRootName("xml") .writeValueAsString(this); @@ -120,6 +140,21 @@ public abstract class BaseModel { return Hex.toHexString(md5Bytes).toUpperCase(); } + /** + * hmacSha256. + * + * @param src the src + * @return the string + */ + @SneakyThrows + private String hmacSha256(String src) { + Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); + SecretKeySpec secret_key = new SecretKeySpec(appSecret.getBytes(),"HmacSHA256"); + sha256_HMAC.init(secret_key); + byte[] bytes = sha256_HMAC.doFinal(src.getBytes(StandardCharsets.UTF_8)); + return Hex.toHexString(bytes).toUpperCase(); + } + /** * 按照格式拼接参数以生成签名 * @@ -130,14 +165,13 @@ public abstract class BaseModel { @SneakyThrows private String link(T t) { Assert.hasText(appSecret, "wechat pay appSecret is required"); - return OBJECT_MAPPER + String link = OBJECT_MAPPER .writer() .writeValueAsString(t) .replaceAll("\":\"", "=") .replaceAll("\",\"", "&") - .replaceAll("\\{\"", "") - .replaceAll("\"}", "") - .concat("&key=").concat(this.appSecret); + .replaceAll("\\\\\"", "\""); + return link.substring(2, link.length() - 2).concat("&key=").concat(this.appSecret); } @@ -164,7 +198,7 @@ public abstract class BaseModel { private RestTemplate getRestTemplateClientAuthentication(String mchId) throws IOException, UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException { - ClassPathResource resource = new ClassPathResource("wechat/apiclient_cert.p12"); + ClassPathResource resource = new ClassPathResource(certPath == null ? "wechat/apiclient_cert.p12" : certPath); char[] pem = mchId.toCharArray(); diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/BaseProfitSharingModel.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/BaseProfitSharingModel.java new file mode 100644 index 0000000..7b6deb5 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/BaseProfitSharingModel.java @@ -0,0 +1,25 @@ +package cn.felord.payment.wechat.v2.model.allocation; + +import cn.felord.payment.wechat.v2.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @since 1.0.10.RELEASE + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class BaseProfitSharingModel extends BaseModel { + + + /** + * 商户号. + *

+ * 微信支付分配的商户号 + */ + private String mchId; + private String appid; + private String transactionId; + private String outOrderNo; + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/BaseProfitSharingReceiverModel.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/BaseProfitSharingReceiverModel.java new file mode 100644 index 0000000..cad5cb3 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/BaseProfitSharingReceiverModel.java @@ -0,0 +1,27 @@ +package cn.felord.payment.wechat.v2.model.allocation; + +import cn.felord.payment.wechat.v2.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @since 1.0.10.RELEASE + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class BaseProfitSharingReceiverModel extends BaseModel { + /** + * 商户号. + *

+ * 微信支付分配的商户号 + */ + private String mchId; + + /** + * 公众账号ID. + *

+ * 微信分配的公众账号ID + */ + private String appid; + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/MultiProfitSharingModel.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/MultiProfitSharingModel.java new file mode 100644 index 0000000..9bf11c9 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/MultiProfitSharingModel.java @@ -0,0 +1,8 @@ +package cn.felord.payment.wechat.v2.model.allocation; + +/** + * @since 1.0.10.RELEASE + */ +public class MultiProfitSharingModel extends ProfitSharingModel { + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/MultiProfitSharingSModel.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/MultiProfitSharingSModel.java new file mode 100644 index 0000000..50adf70 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/MultiProfitSharingSModel.java @@ -0,0 +1,8 @@ +package cn.felord.payment.wechat.v2.model.allocation; + +/** + * @since 1.0.10.RELEASE + */ +public class MultiProfitSharingSModel extends ProfitSharingSModel { + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingAddReceiverModel.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingAddReceiverModel.java new file mode 100644 index 0000000..3c7c5e5 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingAddReceiverModel.java @@ -0,0 +1,72 @@ +package cn.felord.payment.wechat.v2.model.allocation; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @since 1.0.10.RELEASE + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class ProfitSharingAddReceiverModel extends BaseProfitSharingReceiverModel { + + private Receiver receiver; + + @Data + public static class Receiver { + + /** + * 分账接收方类型. + *

+ * MERCHANT_ID:商户号(mch_id或者sub_mch_id) + * PERSONAL_OPENID:个人openid + */ + private Type type; + + /** + * 分账接收方帐号. + *

+ * 类型是MERCHANT_ID时,是商户号(mch_id或者sub_mch_id) + * 类型是PERSONAL_OPENID时,是个人openid + */ + private String account; + + /** + * 分账接收方全称. + *

+ * 分账接收方类型是MERCHANT_ID时,是商户全称(必传),当商户是小微商户或个体户时,是开户人姓名 + * 分账接收方类型是PERSONAL_OPENID时,是个人姓名(选传,传则校验) + */ + private String name; + + /** + * 与分账方的关系类型. + *

+ * 子商户与接收方的关系。 + * 本字段值为枚举: + * SERVICE_PROVIDER:服务商 + * STORE:门店 + * STAFF:员工 + * STORE_OWNER:店主 + * PARTNER:合作伙伴 + * HEADQUARTER:总部 + * BRAND:品牌方 + * DISTRIBUTOR:分销商 + * USER:用户 + * SUPPLIER:供应商 + * CUSTOM:自定义 + */ + private RelationType relationType; + + /** + * 自定义的分账关系. + *

+ * 子商户与接收方具体的关系,本字段最多10个字。 + * 当字段relation_type的值为CUSTOM时,本字段必填 + * 当字段relation_type的值不为CUSTOM时,本字段无需填写 + */ + private String customRelation; + + } + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingAddReceiverSModel.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingAddReceiverSModel.java new file mode 100644 index 0000000..66ac762 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingAddReceiverSModel.java @@ -0,0 +1,15 @@ +package cn.felord.payment.wechat.v2.model.allocation; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @since 1.0.10.RELEASE + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class ProfitSharingAddReceiverSModel extends BaseProfitSharingReceiverModel { + + private String receiver; + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingFinishModel.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingFinishModel.java new file mode 100644 index 0000000..c5014fd --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingFinishModel.java @@ -0,0 +1,49 @@ +package cn.felord.payment.wechat.v2.model.allocation; + +import cn.felord.payment.wechat.v2.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @since 1.0.10.RELEASE + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class ProfitSharingFinishModel extends BaseModel { + + /** + * 商户号. + *

+ * 微信支付分配的商户号 + */ + private String mchId; + + /** + * 公众账号ID. + *

+ * 微信分配的公众账号ID + */ + private String appid; + + /** + * 微信订单号. + *

+ * 微信支付订单号 + */ + private String transactionId; + + /** + * 商户分账单号. + *

+ * 查询分账结果,输入申请分账时的商户分账单号; 查询分账完结执行的结果,输入发起分账完结时的商户分账单号 + */ + private String outOrderNo; + + /** + * 分账完结描述. + *

+ * 分账完结的原因描述 + */ + private String description; + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingModel.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingModel.java new file mode 100644 index 0000000..08269e8 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingModel.java @@ -0,0 +1,23 @@ +package cn.felord.payment.wechat.v2.model.allocation; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * 单次分账请求按照传入的分账接收方账号和资金进行分账,同时会将订单剩余的待分账金额解冻给本商户。 + * 故操作成功后,订单不能再进行分账,也不能进行分账完结。 + * + * @since 1.0.10.RELEASE + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class ProfitSharingModel extends BaseProfitSharingModel { + + /** + * 分账接收方列表,不超过50个json对象,不能设置分账方作为分账接受方 + */ + private List receivers; + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingOrderAmountQueryModel.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingOrderAmountQueryModel.java new file mode 100644 index 0000000..310b9f5 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingOrderAmountQueryModel.java @@ -0,0 +1,28 @@ +package cn.felord.payment.wechat.v2.model.allocation; + +import cn.felord.payment.wechat.v2.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @since 1.0.10.RELEASE + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class ProfitSharingOrderAmountQueryModel extends BaseModel { + + /** + * 商户号. + *

+ * 微信支付分配的商户号 + */ + private String mchId; + + /** + * 微信订单号. + *

+ * 微信支付订单号 + */ + private String transactionId; + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingQueryModel.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingQueryModel.java new file mode 100644 index 0000000..7777b6a --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingQueryModel.java @@ -0,0 +1,35 @@ +package cn.felord.payment.wechat.v2.model.allocation; + +import cn.felord.payment.wechat.v2.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @since 1.0.10.RELEASE + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class ProfitSharingQueryModel extends BaseModel { + + /** + * 商户号. + *

+ * 微信支付分配的商户号 + */ + private String mchId; + + /** + * 微信订单号. + *

+ * 微信支付订单号 + */ + private String transactionId; + + /** + * 商户分账单号. + *

+ * 查询分账结果,输入申请分账时的商户分账单号; 查询分账完结执行的结果,输入发起分账完结时的商户分账单号 + */ + private String outOrderNo; + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingRemoveReceiverModel.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingRemoveReceiverModel.java new file mode 100644 index 0000000..b1dc962 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingRemoveReceiverModel.java @@ -0,0 +1,23 @@ +package cn.felord.payment.wechat.v2.model.allocation; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @since 1.0.10.RELEASE + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class ProfitSharingRemoveReceiverModel extends BaseProfitSharingReceiverModel { + + private Receiver receiver; + + @Data + public static class Receiver { + + private Type type; + private String account; + + } + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingRemoveReceiverSModel.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingRemoveReceiverSModel.java new file mode 100644 index 0000000..8327eeb --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingRemoveReceiverSModel.java @@ -0,0 +1,15 @@ +package cn.felord.payment.wechat.v2.model.allocation; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @since 1.0.10.RELEASE + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class ProfitSharingRemoveReceiverSModel extends BaseProfitSharingReceiverModel { + + private String receiver; + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingReturnModel.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingReturnModel.java new file mode 100644 index 0000000..7b0381e --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingReturnModel.java @@ -0,0 +1,35 @@ +package cn.felord.payment.wechat.v2.model.allocation; + +import cn.felord.payment.wechat.v2.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @since 1.0.10.RELEASE + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class ProfitSharingReturnModel extends BaseModel { + + /** + * 商户号. + *

+ * 微信支付分配的商户号 + */ + private String mchId; + + /** + * 公众账号ID. + *

+ * 微信分配的公众账号ID + */ + private String appid; + private String orderId; + private String outOrderNo; + private String outReturnNo; + private String returnAccountType; + private String returnAccount; + private String returnAmount; + private String description; + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingReturnQueryModel.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingReturnQueryModel.java new file mode 100644 index 0000000..3ce2299 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingReturnQueryModel.java @@ -0,0 +1,51 @@ +package cn.felord.payment.wechat.v2.model.allocation; + +import cn.felord.payment.wechat.v2.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @since 1.0.10.RELEASE + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class ProfitSharingReturnQueryModel extends BaseModel { + + /** + * 商户号. + *

+ * 微信支付分配的商户号 + */ + private String mchId; + + /** + * 公众账号ID. + *

+ * 微信分配的公众账号ID + */ + private String appid; + + /** + * 微信分账订单号. + *

+ * 原发起分账请求时,微信返回的微信分账单号,与商户分账单号一一对应。 + * 微信分账单号与商户分账单号二选一填写 + */ + private String orderId; + + /** + * 商户分账单号. + *

+ * 原发起分账请求时使用的商户系统内部的分账单号。 + * 微信分账单号与商户分账单号二选一填写 + */ + private String outOrderNo; + + /** + * 商户回退单号. + *

+ * 调用回退接口提供的商户系统内部的回退单号 + */ + private String outReturnNo; + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingSModel.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingSModel.java new file mode 100644 index 0000000..8ec518d --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/ProfitSharingSModel.java @@ -0,0 +1,18 @@ +package cn.felord.payment.wechat.v2.model.allocation; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @since 1.0.10.RELEASE + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class ProfitSharingSModel extends BaseProfitSharingModel { + + /** + * 分账接收方列表,不超过50个json对象,不能设置分账方作为分账接受方。 + */ + private String receivers; + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/Receiver.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/Receiver.java new file mode 100644 index 0000000..322c4cc --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/Receiver.java @@ -0,0 +1,46 @@ +package cn.felord.payment.wechat.v2.model.allocation; + +import lombok.Data; + +@Data +public class Receiver { + + /** + * 分账接收方类型. + *

+ * MERCHANT_ID:商户号(mch_id或者sub_mch_id) + * PERSONAL_OPENID:个人openid + */ + private Type type; + + /** + * 分账接收方帐号. + *

+ * 类型是MERCHANT_ID时,是商户号(mch_id或者sub_mch_id) + * 类型是PERSONAL_OPENID时,是个人openid + */ + private String account; + + /** + * 分账金额. + *

+ * 单位为分,只能为整数,不能超过原订单支付金额及最大分账比例金额 + */ + private Integer amount; + + /** + * 分账描述. + *

+ * 分账的原因描述,分账账单中需要体现 + */ + private String description; + + /** + * 分账个人接收方姓名. + *

+ * 可选项,在接收方类型为个人的时可选填,若有值,会检查与 name 是否实名匹配,不匹配会拒绝分账请求. + * 1、分账接收方类型是PERSONAL_OPENID时,是个人姓名(选传,传则校验) + */ + private String name; + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/RelationType.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/RelationType.java new file mode 100644 index 0000000..0c0cbcc --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/RelationType.java @@ -0,0 +1,17 @@ +package cn.felord.payment.wechat.v2.model.allocation; + +public enum RelationType { + + SERVICE_PROVIDER, + STORE, + STAFF, + STORE_OWNER, + PARTNER, + HEADQUARTER, + BRAND, + DISTRIBUTOR, + USER, + SUPPLIER, + CUSTOM + +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/Type.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/Type.java new file mode 100644 index 0000000..9fc1be9 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/allocation/Type.java @@ -0,0 +1,14 @@ +package cn.felord.payment.wechat.v2.model.allocation; + +public enum Type { + + /** + * 商户号(mch_id或者sub_mch_id) + */ + MERCHANT_ID, + + /** + * 个人openid + */ + PERSONAL_OPENID; +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatApiProvider.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatApiProvider.java index bab8d0e..b7c9778 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatApiProvider.java +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatApiProvider.java @@ -18,6 +18,7 @@ */ package cn.felord.payment.wechat.v3; +import cn.felord.payment.wechat.v2.WechatAllocationApi; import cn.felord.payment.wechat.v2.WechatPayRedpackApi; import cn.felord.payment.wechat.v2.WechatPayTransfersApi; import cn.felord.payment.wechat.v2.WechatV2Client; @@ -177,4 +178,19 @@ public class WechatApiProvider { return new WechatPayTransfersApi(wechatV2Client); } + /** + * 微信支付分账,基于V2 + * + * @param tenantId the tenant id + * @return wechat allocation api + * @since 1.0.10.RELEASE + */ + public WechatAllocationApi allocationApi(String tenantId) { + WechatMetaBean wechatMeta = wechatPayClient.signatureProvider() + .wechatMetaContainer() + .getWechatMeta(tenantId); + WechatV2Client wechatV2Client = new WechatV2Client(wechatMeta); + return new WechatAllocationApi(wechatV2Client); + } + } diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatPayCallback.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatPayCallback.java index 77d41df..35b2c59 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatPayCallback.java +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatPayCallback.java @@ -91,6 +91,27 @@ public class WechatPayCallback { } + /** + * 微信支付分账回调. + * + * @param params the params + * @param consumeDataConsumer the consume data consumer + * @return the map + * @since 1.0.10.RELEASE + */ + @SneakyThrows + public Map profitSharingCallback(ResponseSignVerifyParams params, Consumer consumeDataConsumer) { + String data = this.callback(params, EventType.COUPON_USE); + ProfitSharingConsumeData consumeData = MAPPER.readValue(data, ProfitSharingConsumeData.class); + consumeDataConsumer.accept(consumeData); + Map responseBody = new HashMap<>(2); + responseBody.put("code", 200); + responseBody.put("message", "SUCCESS"); + return responseBody; + + } + + /** * 微信支付代金券核销回调. * diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/model/ProfitSharingConsumeData.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/model/ProfitSharingConsumeData.java new file mode 100644 index 0000000..613d13d --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/model/ProfitSharingConsumeData.java @@ -0,0 +1,76 @@ +/* + * + * Copyright 2019-2020 felord.cn + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * Website: + * https://felord.cn + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package cn.felord.payment.wechat.v3.model; + +import cn.felord.payment.wechat.v2.model.allocation.Receiver; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.time.OffsetDateTime; + +/** + * 微信支付分账通知参数 + * + * @since 1.0.10.RELEASE + */ +@Data +public class ProfitSharingConsumeData { + + /** + * 直连商户号. + *

+ * 直连模式分账发起和出资商户 + */ + private String mchid; + + /** + * 微信订单号. + *

+ * 微信支付订单号 + */ + private String transactionId; + + /** + * 微信分账/回退单号. + */ + private String orderId; + + /** + * 商户分账/回退单号. + *

+ * 分账方系统内部的分账/回退单号 + */ + private String outOrderNo; + + /** + * 分账接收方. + *

+ * 分账接收方对象 + */ + private Receiver receiver; + + /** + * 成功时间. + *

+ * Rfc3339标准 + */ + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX", timezone = "GMT+8") + private OffsetDateTime successTime; + +}