Преглед изворни кода

提现代付封装了慧算平台

mac пре 2 година
родитељ
комит
598c2fb922
36 измењених фајлова са 908 додато и 23 уклоњено
  1. 43 0
      kxs-common/kxs-common-cash/pom.xml
  2. 43 0
      kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/CashAutoConfiguration.java
  3. 17 0
      kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/constant/CashConstants.java
  4. 22 0
      kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/factory/CashFactory.java
  5. 32 0
      kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/handlers/CashEventHandlers.java
  6. 24 0
      kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/handlers/CashMessageHandler.java
  7. 31 0
      kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/handlers/DefaultCashMessageHandler.java
  8. 33 0
      kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/model/HsCashBackMessage.java
  9. 17 0
      kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/model/HsCashPayRes.java
  10. 52 0
      kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/model/HsCashRequest.java
  11. 23 0
      kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/model/common/CashMessage.java
  12. 20 0
      kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/model/common/CashRequest.java
  13. 23 0
      kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/model/common/HsCashCommRes.java
  14. 27 0
      kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/model/params/IsvParams.java
  15. 46 0
      kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/model/params/hs/HsIsvParams.java
  16. 50 0
      kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/service/CashService.java
  17. 59 0
      kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/service/ConfigContextService.java
  18. 174 0
      kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/service/hs/HsCashService.java
  19. 1 0
      kxs-common/kxs-common-cash/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  20. 3 0
      kxs-common/kxs-common-core/src/main/java/com/kxs/common/core/util/SpringContextHolder.java
  21. 1 0
      kxs-common/kxs-common-pay/pom.xml
  22. 3 1
      kxs-common/kxs-common-pay/src/main/java/com/kxs/common/pay/PayConfiguration.java
  23. 1 1
      kxs-common/kxs-common-pay/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  24. 1 0
      kxs-common/pom.xml
  25. 0 7
      kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/mq/RabbitShopQueueListener.java
  26. 12 0
      kxs-system/kxs-system-api/src/main/java/com/kxs/system/api/feign/RemoteSysService.java
  27. 6 11
      kxs-system/kxs-system-api/src/main/java/com/kxs/system/api/model/KxsInterfaceConfig.java
  28. 1 0
      kxs-system/kxs-system-biz/pom.xml
  29. 9 0
      kxs-system/kxs-system-biz/src/main/java/com/kxs/system/biz/controller/admin/SysInterfaceConfigController.java
  30. 0 2
      kxs-system/kxs-system-biz/src/main/resources/mapper/KxsInterfaceConfigMapper.xml
  31. 15 0
      kxs-user/kxs-user-api/src/main/java/com/kxs/user/api/dto/admin/leader/SysLeaderPageDto.java
  32. 13 0
      kxs-user/kxs-user-api/src/main/java/com/kxs/user/api/vo/admin/leader/SysLeaderPageVO.java
  33. 4 1
      kxs-user/kxs-user-biz/pom.xml
  34. 60 0
      kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/controller/admin/SysLeaderController.java
  35. 36 0
      kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/handlers/HsCashBackHandler.java
  36. 6 0
      pom.xml

+ 43 - 0
kxs-common/kxs-common-cash/pom.xml

@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.kxs</groupId>
+        <artifactId>kxs-common</artifactId>
+        <version>1.1.0</version>
+    </parent>
+
+    <artifactId>kxs-common-cash</artifactId>
+    <description>代付提现插件</description>
+
+    <properties>
+        <maven.compiler.source>17</maven.compiler.source>
+        <maven.compiler.target>17</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.kxs</groupId>
+            <artifactId>kxs-system-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-http</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-json</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-extra</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.kxs</groupId>
+            <artifactId>kxs-common-core</artifactId>
+        </dependency>
+    </dependencies>
+</project>

+ 43 - 0
kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/CashAutoConfiguration.java

@@ -0,0 +1,43 @@
+package com.kxs.common.cash;
+
+import com.kxs.common.cash.factory.CashFactory;
+import com.kxs.common.cash.service.ConfigContextService;
+import com.kxs.common.cash.service.hs.HsCashService;
+import com.kxs.system.api.feign.RemoteSysService;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+/**
+ * 提现自动配置
+ *
+ * @author 没秃顶的码农
+ * @date 2024-07-23
+ */
+@EnableAsync
+@Configuration(proxyBeanMethods = false)
+public class CashAutoConfiguration {
+
+
+	@Bean
+	@ConditionalOnMissingBean
+	public ConfigContextService configContextService(RemoteSysService remoteSysService) {
+
+		return new ConfigContextService(remoteSysService);
+	}
+
+	@Bean
+	@ConditionalOnMissingBean
+	public HsCashService hsCashService(ConfigContextService configContextService) {
+
+		return new HsCashService(configContextService);
+	}
+
+	@Bean
+	@ConditionalOnMissingBean
+	public CashFactory cashFactory() {
+
+		return new CashFactory();
+	}
+}

+ 17 - 0
kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/constant/CashConstants.java

@@ -0,0 +1,17 @@
+
+package com.kxs.common.cash.constant;
+
+/**
+ * @author 没秃顶的码农
+ * @date 2021年01月01日
+ * <p>
+ * 缓存的key 常量
+ */
+public interface CashConstants {
+
+
+	String PUBLIC_PARAMS = "IsvParams";
+	String PUBLIC_SERVICE = "CashService";
+	String CASH_HS = "hs";
+
+}

+ 22 - 0
kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/factory/CashFactory.java

@@ -0,0 +1,22 @@
+package com.kxs.common.cash.factory;
+
+import com.kxs.common.cash.constant.CashConstants;
+import com.kxs.common.cash.service.CashService;
+import com.kxs.common.core.util.SpringContextHolder;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * 工厂类
+ *
+ * @author 没秃顶的码农
+ * @date 2024-04-26
+ */
+@RequiredArgsConstructor
+public class CashFactory {
+
+    public CashService getCashService(String ifCode) {
+
+        return SpringContextHolder.getBean(ifCode + CashConstants.PUBLIC_SERVICE, CashService.class);
+    }
+
+}

+ 32 - 0
kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/handlers/CashEventHandlers.java

@@ -0,0 +1,32 @@
+package com.kxs.common.cash.handlers;
+
+import com.kxs.common.cash.factory.CashFactory;
+import com.kxs.common.cash.service.CashService;
+import jakarta.servlet.http.HttpServletRequest;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 提现事件处理程序
+ *
+ * @author 没秃顶的码农
+ * @date 2024-04-28
+ */
+@RestController
+@RequestMapping("/cash")
+@RequiredArgsConstructor
+public class CashEventHandlers {
+
+    private final CashFactory cashFactory;
+
+
+    @RequestMapping(value = "cashBack/{ifCode}")
+    public String payBack(HttpServletRequest request, @PathVariable String ifCode) {
+
+        CashService cashService = cashFactory.getCashService(ifCode);
+        return cashService.cashBack(request, ifCode);
+    }
+
+}

+ 24 - 0
kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/handlers/CashMessageHandler.java

@@ -0,0 +1,24 @@
+package com.kxs.common.cash.handlers;
+
+import com.kxs.common.cash.model.common.CashMessage;
+import org.springframework.core.Ordered;
+
+/**
+ * 支付消息处理程序
+ *
+ * @author 没秃顶的码农
+ * @date 2024-04-28
+ */
+public interface CashMessageHandler<M extends CashMessage>  extends Ordered {
+
+    String handle(M var1);
+
+    /**
+     * 是否支持此支付平台
+     *
+     * @return boolean
+     */
+    default boolean support(String ifCode) {
+        return true;
+    }
+}

+ 31 - 0
kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/handlers/DefaultCashMessageHandler.java

@@ -0,0 +1,31 @@
+package com.kxs.common.cash.handlers;
+
+import com.alibaba.fastjson.JSON;
+import com.kxs.common.cash.model.common.CashMessage;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 默认支付回调处理程序
+ *
+ * @author 没秃顶的码农
+ * @date 2024-04-28
+ */
+@Slf4j
+public class DefaultCashMessageHandler implements CashMessageHandler<CashMessage> {
+
+    public DefaultCashMessageHandler() {
+    }
+
+    public String handle(CashMessage cashMessage) {
+        log.info("回调提现消息处理器,回调消息:" + JSON.toJSONString(cashMessage));
+
+        return "{" +
+                " \"code\": 0\n" +
+                "}";
+    }
+
+    @Override
+    public int getOrder() {
+        return Integer.MIN_VALUE;
+    }
+}

+ 33 - 0
kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/model/HsCashBackMessage.java

@@ -0,0 +1,33 @@
+package com.kxs.common.cash.model;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.kxs.common.cash.model.common.CashMessage;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 慧算提现通知地址
+ *
+ * @author 没秃顶的码农
+ * @date 2024-07-23
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class HsCashBackMessage  extends CashMessage {
+
+    private BigDecimal amount;//金额
+    private BigDecimal fee;//手续费
+    private String appCode;//应用编号
+    private String outOrderNo;//自定义订单号
+    private String outBatchNo;//批次号
+    private String orderNo;//出款内部订单号
+    private String batchNo;//出款内部批次号
+    @JsonFormat(pattern = "MMM dd, yyyy hh:mm:ss a")
+    private Date finalStateTime;//出款最终时间
+    private Integer state;//状态
+    private String sign;//签名
+    private String errorMsg;//失败原因
+}

+ 17 - 0
kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/model/HsCashPayRes.java

@@ -0,0 +1,17 @@
+package com.kxs.common.cash.model;
+
+import lombok.Data;
+
+/**
+ * 提现公共响应
+ *
+ * @author 没秃顶的码农
+ * @date 2024-07-23
+ */
+@Data
+public class HsCashPayRes {
+
+    private String orderNo;
+
+
+}

+ 52 - 0
kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/model/HsCashRequest.java

@@ -0,0 +1,52 @@
+package com.kxs.common.cash.model;
+
+import com.kxs.common.cash.model.common.CashRequest;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.math.BigDecimal;
+
+/**
+ * 提交请求公共参数
+ *
+ * @author 没秃顶的码农
+ * @date 2024-07-23
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class HsCashRequest extends CashRequest {
+
+    /**
+     * 提现金额 分
+     */
+    private BigDecimal amount;
+
+    /**
+     * 收款人身份证姓名
+     */
+    private String acctName;
+
+    /**
+     * 收款人银行卡号
+     */
+    private String acctNo;
+    /**
+     * 收款人身份证号
+     */
+    private String acctIdCard;
+    /**
+     * 出单号
+     */
+    private String outOrderNo;
+    /**
+     * 银行名称
+     */
+    private String bankName;
+    /**
+     * 银行预留手机号
+     */
+    private String acctMobile;
+
+
+
+}

+ 23 - 0
kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/model/common/CashMessage.java

@@ -0,0 +1,23 @@
+package com.kxs.common.cash.model.common;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 回调公共
+ *
+ * @author 没秃顶的码农
+ * @date 2024-04-28
+ */
+@Data
+public class CashMessage implements Serializable {
+
+
+    /**
+     * 标识
+     */
+    private String ifCode;
+
+
+}

+ 20 - 0
kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/model/common/CashRequest.java

@@ -0,0 +1,20 @@
+package com.kxs.common.cash.model.common;
+
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+
+/**
+ * 提交请求公共参数
+ *
+ * @author 没秃顶的码农
+ * @date 2024-07-23
+ */
+@Data
+public class CashRequest {
+
+    @NotBlank(message = "ifCode不能为空")
+    private String ifCode;
+
+
+
+}

+ 23 - 0
kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/model/common/HsCashCommRes.java

@@ -0,0 +1,23 @@
+package com.kxs.common.cash.model.common;
+
+import lombok.Data;
+
+/**
+ * 提现公共响应
+ *
+ * @author 没秃顶的码农
+ * @date 2024-07-23
+ */
+@Data
+public class HsCashCommRes<T> {
+
+    private T data;
+
+    private String ifCode;
+    private Integer code;
+    private String errorCode;
+    private String errorDesc;
+    private String success;
+
+
+}

+ 27 - 0
kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/model/params/IsvParams.java

@@ -0,0 +1,27 @@
+package com.kxs.common.cash.model.params;
+
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.kxs.common.cash.constant.CashConstants;
+
+/**
+ * 平台公共 参数
+ *
+ * @author 没秃顶的码农
+ * @date 2024-07-23
+ */
+public abstract class IsvParams {
+
+    public static IsvParams factory(String ifCode, String paramsStr){
+
+        try {
+
+            return (IsvParams) JSONObject.parseObject(paramsStr, Class.forName(IsvParams.class.getPackage().getName() +
+                    StrUtil.DOT + ifCode + StrUtil.DOT + StrUtil.upperFirst(ifCode) + CashConstants.PUBLIC_PARAMS));
+
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException("IsvParams is not found");
+        }
+    }
+
+}

+ 46 - 0
kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/model/params/hs/HsIsvParams.java

@@ -0,0 +1,46 @@
+package com.kxs.common.cash.model.params.hs;
+
+import com.kxs.common.cash.model.params.IsvParams;
+import lombok.Data;
+
+
+/**
+ * 慧算配置参数
+ *
+ * @author 系统
+ * @since 2024-07-12 16:45:55
+ */
+@Data
+public class HsIsvParams extends IsvParams {
+
+
+    /**
+     * appId
+     */
+    private String appId;
+
+    /**
+     * 密钥
+     */
+    private String secret;
+
+    /**
+     * 签名类型
+     */
+    private String signType;
+
+    /**
+     * 网址
+     */
+    private String url;
+
+    /**
+     * 回调 URL
+     */
+    private String callbackUrl;
+
+
+
+
+}
+

+ 50 - 0
kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/service/CashService.java

@@ -0,0 +1,50 @@
+package com.kxs.common.cash.service;
+
+import cn.hutool.extra.spring.SpringUtil;
+import com.kxs.common.cash.constant.CashConstants;
+import com.kxs.common.cash.handlers.CashMessageHandler;
+import com.kxs.common.cash.model.common.CashRequest;
+import com.kxs.common.core.exception.GlobalCustomerException;
+import com.kxs.common.core.util.SpringContextHolder;
+import jakarta.servlet.http.HttpServletRequest;
+import org.springframework.core.Ordered;
+
+import java.util.Comparator;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * 提现代付公共service
+ *
+ * @author 没秃顶的码农
+ * @date 2024-07-23
+ */
+public interface CashService {
+
+    /**
+     * 提现发起
+     */
+    Boolean cash(CashRequest payReq);
+
+
+    /**
+     * 回调
+     */
+    String cashBack(HttpServletRequest request, String ifCode);
+
+    default CashMessageHandler getCashMessageHandler(String ifCode){
+        Map<String, CashMessageHandler> payMessageHandlerMap = SpringUtil
+                .getBeansOfType(CashMessageHandler.class);
+        Optional<CashMessageHandler> optional = payMessageHandlerMap.values()
+                .stream()
+                .filter(service -> service.support(ifCode))
+                .max(Comparator.comparingInt(Ordered::getOrder));
+
+        if (optional.isEmpty()) {
+            throw new GlobalCustomerException("DefaultCashMessageHandler error , not register");
+        }
+        return optional.get();
+    }
+
+
+}

+ 59 - 0
kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/service/ConfigContextService.java

@@ -0,0 +1,59 @@
+package com.kxs.common.cash.service;
+
+import com.kxs.common.cash.model.params.IsvParams;
+import com.kxs.common.core.constant.SecurityConstants;
+import com.kxs.common.core.exception.GlobalCustomerException;
+import com.kxs.common.core.util.R;
+import com.kxs.common.core.util.RetOps;
+import com.kxs.system.api.feign.RemoteSysService;
+import com.kxs.system.api.model.KxsInterfaceConfig;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.InitializingBean;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 配置上下文服务
+ *
+ * @author 没秃顶的码农
+ * @date 2024-07-23
+ */
+@RequiredArgsConstructor
+@Slf4j
+public class ConfigContextService implements InitializingBean {
+
+    private final RemoteSysService remoteSysService;
+
+    /**
+     * 每个平台的都封装到map里
+     */
+    private static final Map<String, String> CASH_ISV_PARAM_MAP = new ConcurrentHashMap<>();
+
+    public IsvParams getParams(String ifCode) {
+
+        if (CASH_ISV_PARAM_MAP.isEmpty()) {
+            throw new GlobalCustomerException("未配置提现参数");
+        }
+        return IsvParams.factory(ifCode, CASH_ISV_PARAM_MAP.get(ifCode));
+    }
+
+    @Override
+    public void afterPropertiesSet() {
+        try {
+
+            R<List<KxsInterfaceConfig>> interfaceConfigsRes = remoteSysService.loadIsvParams(SecurityConstants.FROM_IN);
+
+            List<KxsInterfaceConfig> interfaceConfigs = RetOps.of(interfaceConfigsRes)
+                    .getData()
+                    .orElseThrow(() -> new GlobalCustomerException("IsvParams get is null"));
+
+            interfaceConfigs.forEach(kxsInterfaceConfig -> CASH_ISV_PARAM_MAP.put(kxsInterfaceConfig.getIfCode(), kxsInterfaceConfig.getParams()));
+        } catch (Exception e) {
+            log.error("system server is not start");
+        }
+
+    }
+}

+ 174 - 0
kxs-common/kxs-common-cash/src/main/java/com/kxs/common/cash/service/hs/HsCashService.java

@@ -0,0 +1,174 @@
+package com.kxs.common.cash.service.hs;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.hutool.core.lang.TypeReference;
+import cn.hutool.core.map.MapBuilder;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSON;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.kxs.common.cash.handlers.CashMessageHandler;
+import com.kxs.common.cash.model.HsCashBackMessage;
+import com.kxs.common.cash.model.HsCashPayRes;
+import com.kxs.common.cash.model.HsCashRequest;
+import com.kxs.common.cash.model.params.hs.HsIsvParams;
+import com.kxs.common.cash.model.common.CashRequest;
+import com.kxs.common.cash.model.common.HsCashCommRes;
+import com.kxs.common.cash.model.params.IsvParams;
+import com.kxs.common.cash.service.CashService;
+import com.kxs.common.cash.service.ConfigContextService;
+import com.kxs.common.core.exception.GlobalCustomerException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.validation.Valid;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.StreamUtils;
+
+import java.io.ByteArrayOutputStream;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.time.LocalDateTime;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * 慧算提现服务
+ *
+ * @author 没秃顶的码农
+ * @date 2024-07-23
+ */
+@RequiredArgsConstructor
+@Slf4j
+public class HsCashService implements CashService {
+
+    private final ConfigContextService configContextService;
+
+    @Override
+    public Boolean cash(CashRequest cashReq) {
+
+        IsvParams isvParams = configContextService.getParams(cashReq.getIfCode());
+        if (isvParams instanceof HsIsvParams hsIsvParams && cashReq instanceof HsCashRequest hsCashRequest) {
+
+            try {
+
+                String response = send(hsIsvParams, hsCashRequest);
+                HsCashCommRes<HsCashPayRes> commRes = JSONUtil.toBean(response, new TypeReference<>() {}, true);
+                if(commRes.getCode() != 0){
+                    throw new RuntimeException(commRes.getErrorDesc());
+                }
+                return Boolean.TRUE;
+
+            } catch (Exception e) {
+                log.error("发起提现任务失败{}", JSON.toJSONString(hsCashRequest), e);
+                throw new GlobalCustomerException("发起提现任务失败,请联系管理员");
+            }
+        }
+        return Boolean.FALSE;
+    }
+
+    @Override
+    public String cashBack(HttpServletRequest request, String ifCode) {
+
+        IsvParams isvParams = configContextService.getParams(ifCode);
+        if (isvParams instanceof HsIsvParams hsIsvParams) {
+
+            try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+
+                StreamUtils.copy(request.getInputStream(), baos);
+                String bodyStr = baos.toString();
+                HsCashBackMessage cashBackMessage = JSON.parseObject(bodyStr, HsCashBackMessage.class);
+                String timestamp = request.getHeader("X-Timestamp");
+                //验证签名
+                if (!checkSign(cashBackMessage, hsIsvParams, timestamp)) {
+                    throw new GlobalCustomerException("签名错误");
+                }
+                //获取处理的handler方法
+                CashMessageHandler cashMessageHandler = getCashMessageHandler(ifCode);
+
+                return cashMessageHandler.handle(cashBackMessage);
+            } catch (Exception e) {
+                throw new GlobalCustomerException("慧算回调地址获取参数异常");
+            }
+        }
+
+        return "{" +
+                " \"code\": 0\n" +
+                "}";
+    }
+
+    private String send(HsIsvParams hsIsvParams, HsCashRequest req) throws Exception {
+
+        Map<String, Object> requestParam = MapBuilder
+                .create(new HashMap<String, Object>())
+                .put("amount", req.getAmount())
+                .put("acctName", req.getAcctName())
+                .put("acctNo", req.getAcctNo())
+                .put("acctIdCard", req.getAcctIdCard())
+                .put("outOrderNo", req.getOutOrderNo())
+                .put("bankName", req.getBankName())
+                .put("callbackUrl", hsIsvParams.getCallbackUrl())
+                .put("acctMobile", req.getAcctMobile()).map();
+
+        String timestamp = LocalDateTimeUtil.format(LocalDateTime.now(), DatePattern.NORM_DATETIME_PATTERN);
+        // 计算签名
+        String requestJsonStr = generateRequestBody(requestParam);
+        String waitSignStr = timestamp + hsIsvParams.getSecret() + requestJsonStr;
+        String sign = generateSignature(waitSignStr, hsIsvParams.getSignType());
+
+        return HttpRequest.post(hsIsvParams.getUrl())
+                .header("X-Up-AppId", hsIsvParams.getAppId())
+                .header("X-Timestamp", timestamp)
+                .header("X-Sign-Type", hsIsvParams.getSignType())
+                .header("X-Sign", sign)
+                .body(JSON.toJSONString(requestParam))
+                .timeout(50000)//超时,毫秒
+                .execute().body();
+
+    }
+
+
+    /**
+     * 验证签名
+     *
+     * @param cashBackMessage 回调参数
+     * @param hsIsvParams       isv参数
+     * @param timestamp       时间
+     * @return {@link Boolean}
+     */
+    private Boolean checkSign(HsCashBackMessage cashBackMessage, HsIsvParams hsIsvParams, String timestamp) throws Exception {
+        String sign = cashBackMessage.getSign();
+        Map<String, Object> requestParam = BeanUtil.beanToMap(cashBackMessage);
+        requestParam.remove("sign");
+
+        // 计算签名
+        String requestJsonStr = generateRequestBody(requestParam);
+        String waitSignStr = timestamp + hsIsvParams.getSecret() + requestJsonStr;
+        String checkSign = generateSignature(waitSignStr, hsIsvParams.getSignType());
+
+        return ObjectUtil.equals(sign, checkSign);
+    }
+
+    private String generateRequestBody(Map<String, Object> requestParam) throws Exception {
+        ObjectMapper objectMapper = new ObjectMapper();
+
+        return objectMapper.writeValueAsString(requestParam);
+    }
+
+
+    /**
+     * 生成签名
+     *
+     */
+    private String generateSignature(String waitSignStr, String signType) throws Exception {
+        MessageDigest messageDigest = MessageDigest.getInstance(signType);
+        messageDigest.reset();
+        messageDigest.update(waitSignStr.getBytes(StandardCharsets.UTF_8));
+        byte[] signBytes = messageDigest.digest();
+        return Base64.getEncoder().encodeToString(signBytes);
+    }
+}

+ 1 - 0
kxs-common/kxs-common-cash/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

@@ -0,0 +1 @@
+com.kxs.common.cash.CashAutoConfiguration

+ 3 - 0
kxs-common/kxs-common-core/src/main/java/com/kxs/common/core/util/SpringContextHolder.java

@@ -56,6 +56,9 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
 	 * 通过name,以及Clazz返回指定的Bean
 	 */
 	public static <T> T getBean(String name, Class<T> clazz){
+		if(!applicationContext.containsBean(name)){
+			return null;
+		}
 		return applicationContext.getBean(name, clazz);
 	}
 

+ 1 - 0
kxs-common/kxs-common-pay/pom.xml

@@ -10,6 +10,7 @@
     </parent>
 
     <artifactId>kxs-common-pay</artifactId>
+    <description>三方支付插件</description>
 
     <properties>
         <maven.compiler.source>17</maven.compiler.source>

+ 3 - 1
kxs-common/kxs-common-pay/src/main/java/com/kxs/common/pay/config/PayConfiguration.java → kxs-common/kxs-common-pay/src/main/java/com/kxs/common/pay/PayConfiguration.java

@@ -1,9 +1,11 @@
-package com.kxs.common.pay.config;
+package com.kxs.common.pay;
 
 import com.alipay.api.AlipayApiException;
 import com.alipay.api.AlipayClient;
 import com.alipay.api.AlipayConfig;
 import com.alipay.api.DefaultAlipayClient;
+import com.kxs.common.pay.config.AliPayAccountConfig;
+import com.kxs.common.pay.config.WechatAccountConfig;
 import com.kxs.common.pay.factory.PaymentFactory;
 import com.kxs.common.pay.handlers.PayEventHandlers;
 import com.kxs.common.pay.service.ali.AliPayService;

+ 1 - 1
kxs-common/kxs-common-pay/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

@@ -1 +1 @@
-com.kxs.common.pay.config.PayConfiguration
+com.kxs.common.pay.PayConfiguration

+ 1 - 0
kxs-common/pom.xml

@@ -27,6 +27,7 @@
         <module>kxs-common-pay</module>
         <module>kxs-common-mq</module>
         <module>kxs-common-idempotent</module>
+        <module>kxs-common-cash</module>
     </modules>
     <dependencyManagement>
         <dependencies>

+ 0 - 7
kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/mq/RabbitShopQueueListener.java

@@ -1,13 +1,7 @@
 package com.kxs.product.biz.mq;
 
 import com.alibaba.fastjson.JSON;
-import com.kxs.common.pay.enums.PayPlatformEnum;
-import com.kxs.common.pay.enums.PayStatusCommEnum;
 import com.kxs.common.pay.factory.PaymentFactory;
-import com.kxs.common.pay.model.PayResponse;
-import com.kxs.common.pay.model.QueryRequest;
-import com.kxs.common.pay.model.QueryResponse;
-import com.kxs.common.pay.service.PayService;
 import com.kxs.product.api.amqp.rabbit.RabbitShopTimeoutQueueMQ;
 import com.kxs.product.api.model.KxsShopOrder;
 import com.kxs.product.biz.constant.enums.KxsShopEnum;
@@ -18,7 +12,6 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.amqp.core.Message;
 import org.springframework.amqp.rabbit.annotation.RabbitHandler;
 import org.springframework.amqp.rabbit.annotation.RabbitListener;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Component;
 
 import java.io.IOException;

+ 12 - 0
kxs-system/kxs-system-api/src/main/java/com/kxs/system/api/feign/RemoteSysService.java

@@ -5,12 +5,15 @@ import com.kxs.common.core.util.R;
 import com.kxs.system.api.dto.kxsapp.camp.CampAddBcqtTeamDTO;
 import com.kxs.system.api.dto.kxsapp.camp.CampOpenNumStatDTO;
 import com.kxs.system.api.dto.kxsapp.camp.PrizePoolDTO;
+import com.kxs.system.api.model.KxsInterfaceConfig;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestHeader;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.service.annotation.GetExchange;
 import org.springframework.web.service.annotation.PostExchange;
 
+import java.util.List;
+
 /**
  * 定时任务调用系统模块的服务
  *
@@ -54,4 +57,13 @@ public interface RemoteSysService {
 	 */
 	@PostExchange("/camp/campOpenNumStat")
 	void campOpenNumStat(@RequestBody CampOpenNumStatDTO param, @RequestHeader(SecurityConstants.FROM) String fromIn);
+
+	/**
+	 * 加载 ISV 参数
+	 *
+	 * @param fromIn 从中
+	 * @return {@link List}<{@link KxsInterfaceConfig}>
+	 */
+	@GetExchange("/interfaceConfig/loadIsvParams")
+	R<List<KxsInterfaceConfig>> loadIsvParams( @RequestHeader(SecurityConstants.FROM) String fromIn);
 }

+ 6 - 11
kxs-system/kxs-system-api/src/main/java/com/kxs/system/api/model/KxsInterfaceConfig.java

@@ -7,6 +7,7 @@ import java.time.LocalDateTime;
 
 import com.baomidou.mybatisplus.annotation.*;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -39,6 +40,7 @@ public class KxsInterfaceConfig extends Model<KxsInterfaceConfig> implements Ser
      */
     @TableField(fill = FieldFill.INSERT)
     @Schema(description = "新增时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
 
@@ -47,6 +49,7 @@ public class KxsInterfaceConfig extends Model<KxsInterfaceConfig> implements Ser
      */
     @TableField(fill = FieldFill.UPDATE)
     @Schema(description = "更新时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime updateTime;
 
 
@@ -114,19 +117,11 @@ public class KxsInterfaceConfig extends Model<KxsInterfaceConfig> implements Ser
     @Schema(description = "类型 0-代付平台 1-支付平台")
     private Integer paramType;
 
-
-    /**
-     * 网关地址
-     */
-    @Schema(description = "网关地址")
-    private String url;
-
-
     /**
-     * 回调地址
+     * 标识
      */
-    @Schema(description = "回调地址")
-    private String callbackUrl;
+    @Schema(description = "标识")
+    private String ifCode;
 
 
 

+ 1 - 0
kxs-system/kxs-system-biz/pom.xml

@@ -97,6 +97,7 @@
             <groupId>com.kxs</groupId>
             <artifactId>kxs-stat-api</artifactId>
         </dependency>
+
     </dependencies>
 
     <build>

+ 9 - 0
kxs-system/kxs-system-biz/src/main/java/com/kxs/system/biz/controller/admin/SysInterfaceConfigController.java

@@ -5,8 +5,10 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.kxs.common.core.constant.CacheConstants;
+import com.kxs.common.core.constant.CommonConstants;
 import com.kxs.common.core.util.R;
 import com.kxs.common.log.annotation.SysLog;
+import com.kxs.common.security.annotation.Inner;
 import com.kxs.system.api.model.KxsInterfaceConfig;
 import com.kxs.system.biz.service.KxsInterfaceConfigService;
 import io.swagger.v3.oas.annotations.Operation;
@@ -31,6 +33,13 @@ public class SysInterfaceConfigController {
 
     private final KxsInterfaceConfigService interfaceConfigService;
 
+    @Inner
+    @GetMapping("/loadIsvParams")
+    public R getSysPublicParamPage() {
+
+        return R.ok(interfaceConfigService.list(Wrappers.<KxsInterfaceConfig>lambdaQuery()
+                .eq(KxsInterfaceConfig::getStatus, CommonConstants.SUCCESS)));
+    }
 
     /**
      * 分页查询

+ 0 - 2
kxs-system/kxs-system-biz/src/main/resources/mapper/KxsInterfaceConfigMapper.xml

@@ -15,8 +15,6 @@
         <result column="params" property="params" />
         <result column="status" property="status" />
         <result column="param_type" property="paramType" />
-        <result column="url" property="url" />
-        <result column="callback_url" property="callbackUrl" />
 
     </resultMap>
 

+ 15 - 0
kxs-user/kxs-user-api/src/main/java/com/kxs/user/api/dto/admin/leader/SysLeaderPageDto.java

@@ -0,0 +1,15 @@
+package com.kxs.user.api.dto.admin.leader;
+
+import lombok.Data;
+
+/**
+ * 盟主列表 DTO
+ *
+ * @author 没秃顶的码农
+ * @date 2024-07-23
+ */
+@Data
+public class SysLeaderPageDto {
+
+
+}

+ 13 - 0
kxs-user/kxs-user-api/src/main/java/com/kxs/user/api/vo/admin/leader/SysLeaderPageVO.java

@@ -0,0 +1,13 @@
+package com.kxs.user.api.vo.admin.leader;
+
+import lombok.Data;
+
+/**
+ * 创客信息管理盟主管理-盟主列表
+ *
+ * @author 没秃顶的码农
+ * @date 2024-07-23
+ */
+@Data
+public class SysLeaderPageVO {
+}

+ 4 - 1
kxs-user/kxs-user-biz/pom.xml

@@ -83,7 +83,10 @@
             <groupId>com.kxs</groupId>
             <artifactId>kxs-stat-api</artifactId>
         </dependency>
-
+        <dependency>
+            <groupId>com.kxs</groupId>
+            <artifactId>kxs-common-cash</artifactId>
+        </dependency>
     </dependencies>
 
     <build>

+ 60 - 0
kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/controller/admin/SysLeaderController.java

@@ -0,0 +1,60 @@
+package com.kxs.user.biz.controller.admin;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.kxs.common.cash.factory.CashFactory;
+import com.kxs.common.cash.model.HsCashRequest;
+import com.kxs.common.core.util.R;
+import com.kxs.user.api.dto.admin.leader.SysLeaderPageDto;
+import com.kxs.user.api.vo.admin.leader.SysLeaderPageVO;
+import com.kxs.user.biz.service.KxsLeaderService;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import lombok.RequiredArgsConstructor;
+import org.springdoc.core.annotations.ParameterObject;
+import org.springframework.http.HttpHeaders;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.math.BigDecimal;
+
+/**
+ * 盟主控制器
+ *
+ * @author 没秃顶的码农
+ * @date 2024-07-23
+ */
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("sysLeader")
+@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
+public class SysLeaderController {
+
+    private final KxsLeaderService kxsLeaderService;
+
+    private final CashFactory cashFactory;
+
+    /**
+     * 创客信息管理盟主管理-盟主列表
+     *
+     * @param param 查询实体
+     * @return 创客信息管理盟主管理-盟主列表
+     */
+    @GetMapping("page")
+    public R page(@ParameterObject Page<SysLeaderPageVO> page, @ParameterObject SysLeaderPageDto param) {
+
+        HsCashRequest req = new HsCashRequest();
+        req.setIfCode("hs");
+        req.setAmount(new BigDecimal("100"));
+        req.setAcctIdCard("3232423423423432");
+        req.setAcctNo("3232423423423432");
+        req.setAcctMobile("15681218681");
+        req.setAcctName("李先生");
+        req.setOutOrderNo("32423432432423423");
+        req.setBankName("中国银行");
+        Boolean cash = cashFactory.getCashService("hs").cash(req);
+
+        return R.ok(cash);
+    }
+
+}

+ 36 - 0
kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/handlers/HsCashBackHandler.java

@@ -0,0 +1,36 @@
+package com.kxs.user.biz.handlers;
+
+import com.kxs.common.cash.constant.CashConstants;
+import com.kxs.common.cash.handlers.CashMessageHandler;
+import com.kxs.common.cash.model.HsCashBackMessage;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+/**
+ * 慧算代付提现回调处理方法
+ *
+ * @author 没秃顶的码农
+ * @date 2024-07-23
+ */
+@Component
+@Slf4j
+@RequiredArgsConstructor
+public class HsCashBackHandler implements CashMessageHandler<HsCashBackMessage> {
+
+    @Override
+    public String handle(HsCashBackMessage param) {
+
+        return null;
+    }
+
+    @Override
+    public boolean support(String ifCode) {
+        return CashConstants.CASH_HS.equals(ifCode);
+    }
+
+    @Override
+    public int getOrder() {
+        return Integer.MIN_VALUE + 1;
+    }
+}

+ 6 - 0
pom.xml

@@ -84,6 +84,7 @@
         <module>kxs-visual</module>
         <module>kxs-transfer</module>
         <module>kxs-stat</module>
+        <module>kxs-common/kxs-common-cash</module>
     </modules>
 
     <dependencyManagement>
@@ -261,6 +262,11 @@
                 <artifactId>kxs-common-pay</artifactId>
                 <version>${project.version}</version>
             </dependency>
+            <dependency>
+                <groupId>com.kxs</groupId>
+                <artifactId>kxs-common-cash</artifactId>
+                <version>${project.version}</version>
+            </dependency>