自动化立体仓库 - WMS系统
6fcdb6d00b69a3438fa661c3d56eb84d20e20e92..ffb382ba34aca2dce08ab9e4ef09adc946cf23c8
18 小时以前 ZY
双数据源
ffb382 对比 | 目录
22 小时以前 ZY
1
1b5c00 对比 | 目录
23个文件已添加
9个文件已修改
1815 ■■■■■ 已修改文件
pom.xml 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/BareBoardScheduler.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/ErrorStockScheduler.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/NotifyLogScheduler.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/OverYearLogScheduler.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/PlcLogScheduler.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/WorkLogScheduler.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/WorkMastScheduler.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/config/ds/AbstractRoutingDataSource.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/config/ds/DataSourceAop.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/config/ds/DataSourceConfig.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/config/ds/DataSourceType.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/config/ds/DynamicDataSource.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/config/ds/PrimaryDataSourceConfig.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/config/ds/SecondaryDataSourceConfig.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/nc/Test.java 430 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/nc/util/Base64Util.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/nc/util/CipherConstant.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/nc/util/CompressUtil.java 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/nc/util/Decryption.java 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/nc/util/Encryption.java 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/nc/util/KeyPairs.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/nc/util/KeysFactory.java 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/nc/util/ResultMessageUtil.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/nc/util/SHA256Util.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/nc/util/SecureRandomProxy.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/nc/vo/SaleOutBodyVO.java 257 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/nc/vo/SaleOutHeadVO.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 80 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/config.properties 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/lib/caffeine-2.8.8.jar 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper2/test 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -16,7 +16,7 @@
    <properties>
        <java.version>1.8</java.version>
        <cool.version>3.4.0</cool.version>
        <mysql-driver.version>5.1.47</mysql-driver.version>
        <mysql-driver.version>8.0.28</mysql-driver.version>
        <mybatis-plus.version>2.3.2</mybatis-plus.version>
        <fastjson.version>1.2.58</fastjson.version>
        <springfox.version>2.7.0</springfox.version>
@@ -50,6 +50,7 @@
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql-driver.version}</version>
        </dependency>
        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>mssql-jdbc</artifactId>
src/main/java/com/zy/asrs/task/BareBoardScheduler.java
@@ -29,7 +29,7 @@
    * 自动调空板出库
    * */
    @Scheduled(cron = "0/3 * * * * ? ")
    private void execute(){
    public void execute(){
        if (slaveWmsParameterProperties.isAutomaticFillingBoardStaNosBoolean()){
            Config config = configService.selectConfigByCode("AutomaticFillingBoard");
            if (!Cools.isEmpty(config) && !Cools.isEmpty(config.getValue()) && config.getValue().equals("true")){
src/main/java/com/zy/asrs/task/ErrorStockScheduler.java
@@ -20,7 +20,7 @@
    private ErrorStockHandler errorStockHandler;
    @Scheduled(cron = "0/3 * * * * ? ")
    private void execute(){
    public void execute(){
        ReturnT<String> returnT = errorStockHandler.start();
        if (!returnT.isSuccess()) {
            log.error(returnT.getMsg());
src/main/java/com/zy/asrs/task/NotifyLogScheduler.java
@@ -20,7 +20,7 @@
    private NotifyLogHandler notifyLogHandler;
    @Scheduled(cron = "0/3 * * * * ? ")
    private void execute(){
    public void execute(){
        ReturnT<String> returnT = notifyLogHandler.start();
        if (!returnT.isSuccess()) {
            log.error(returnT.getMsg());
src/main/java/com/zy/asrs/task/OverYearLogScheduler.java
@@ -20,7 +20,7 @@
    private OverYearLogHandler overYearLogHandler;
    @Scheduled(cron = "0 0 1 * * ? ")
    private void execute(){
    public void execute(){
        ReturnT<String> returnT = overYearLogHandler.start();
        if (!returnT.isSuccess()) {
            log.error(returnT.getMsg());
src/main/java/com/zy/asrs/task/PlcLogScheduler.java
@@ -20,7 +20,7 @@
    private PlcLogHandler plcLogHandler;
    @Scheduled(cron = "0/3 * * * * ? ")
    private void execute(){
    public void execute(){
        ReturnT<String> returnT = plcLogHandler.start();
        if (!returnT.isSuccess()) {
            log.error(returnT.getMsg());
src/main/java/com/zy/asrs/task/WorkLogScheduler.java
@@ -24,7 +24,7 @@
    private WrkMastService wrkMastService;
    @Scheduled(cron = "0/3 * * * * ? ")
    private void execute(){
    public void execute(){
        List<WrkMast> wrkMasts = wrkMastService.selectToBeHistoryData();
        if (wrkMasts.isEmpty()) {
            return;
src/main/java/com/zy/asrs/task/WorkMastScheduler.java
@@ -27,7 +27,7 @@
    private WorkMastHandler workMastHandler;
    @Scheduled(cron = "0/3 * * * * ? ")
    private void execute(){
    public void execute(){
        List<WrkMast> wrkMasts = wrkMastService.selectToBeCompleteData();
        if (wrkMasts.isEmpty()) {
            return;
src/main/java/com/zy/common/config/ds/AbstractRoutingDataSource.java
New file
@@ -0,0 +1,38 @@
package com.zy.common.config.ds;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.datasource.AbstractDataSource;
import org.springframework.util.Assert;
import javax.sql.DataSource;
import java.util.Map;
public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {
    //多数据源map集合
    private Map<Object, Object> targetDataSources;
    //默认数据源
    private Object defaultTargetDataSource;
    //其实就是targetDataSources,后面的afterPropertiesSet()方法会将targetDataSources赋值给resolvedDataSources
    private Map<Object, DataSource> resolvedDataSources;
    private DataSource resolvedDefaultDataSource;
    public void setTargetDataSources(Map<Object, Object> targetDataSources) {
        this.targetDataSources = targetDataSources;
    }
    protected DataSource determineTargetDataSource() {
        Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
        Object lookupKey = this.determineCurrentLookupKey();
        DataSource dataSource = (DataSource) this.resolvedDataSources.get(lookupKey);
        if (dataSource == null && ( lookupKey == null)) {
            dataSource = this.resolvedDefaultDataSource;
        }
        if (dataSource == null) {
            throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
        } else {
            return dataSource;
        }
    }
    protected abstract Object determineCurrentLookupKey();
}
src/main/java/com/zy/common/config/ds/DataSourceAop.java
New file
@@ -0,0 +1,27 @@
package com.zy.common.config.ds;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class DataSourceAop {
    @Before("execution(* com.zy.asrs..*(..))")
    public void setDataSource2test01() {
        System.err.println("test01业务");
        DataSourceType.setDataBaseType(DataSourceType.DataBaseType.TEST01);
    }
    @Before("execution(* com.zy.system..*(..))")
    public void setDataSource2test012() {
        System.err.println("test01业务");
        DataSourceType.setDataBaseType(DataSourceType.DataBaseType.TEST01);
    }
    @Before("execution(* com.zy.nc..*(..))")
    public void setDataSource2test02() {
        System.err.println("test02业务");
        DataSourceType.setDataBaseType(DataSourceType.DataBaseType.TEST02);
    }
}
src/main/java/com/zy/common/config/ds/DataSourceConfig.java
New file
@@ -0,0 +1,49 @@
package com.zy.common.config.ds;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import static com.sun.xml.internal.ws.spi.db.BindingContextFactory.LOGGER;
@Configuration
public class DataSourceConfig {
    @Value("${other.datasource.jdbc-url}")
    private String url;
    @Value("${other.datasource.username}")
    private String username;
    @Value("${other.datasource.password}")
    private String password;
    @Value("${other.datasource.driver-class-name}")
    private String driverClassName;
    // 主数据源
    @Bean(name = "dataSource")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }
    // 次数据源
    @Bean(name = "slaveDataSource")
    public DataSource secondaryDataSource() {
        System.out.println(driverClassName);
        return DataSourceBuilder.create()
                .driverClassName(driverClassName)
                .url(url)
                .username(username)
                .password(password)
                .build();
    }
}
src/main/java/com/zy/common/config/ds/DataSourceType.java
New file
@@ -0,0 +1,32 @@
package com.zy.common.config.ds;
public class DataSourceType {
    public enum DataBaseType {
        TEST01, TEST02
    }
    // 使用ThreadLocal保证线程安全
    private static final ThreadLocal<DataBaseType> TYPE = new ThreadLocal<DataBaseType>();
    // 往当前线程里设置数据源类型
    public static void setDataBaseType(DataBaseType dataBaseType) {
        if (dataBaseType == null) {
            throw new NullPointerException();
        }
        System.err.println("[将当前数据源改为]:" + dataBaseType);
        TYPE.set(dataBaseType);
    }
    // 获取数据源类型
    public static DataBaseType getDataBaseType() {
        DataBaseType dataBaseType = TYPE.get() == null ? DataBaseType.TEST01 : TYPE.get();
        System.err.println("[获取当前数据源的类型为]:" + dataBaseType);
        return dataBaseType;
    }
    // 清空数据类型
    public static void clearDataBaseType() {
        TYPE.remove();
    }
}
src/main/java/com/zy/common/config/ds/DynamicDataSource.java
New file
@@ -0,0 +1,11 @@
package com.zy.common.config.ds;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource  extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        DataSourceType.DataBaseType dataBaseType = DataSourceType.getDataBaseType();
        return dataBaseType;
    }
}
src/main/java/com/zy/common/config/ds/PrimaryDataSourceConfig.java
New file
@@ -0,0 +1,35 @@
package com.zy.common.config.ds;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = {"com.zy.asrs.*.*", "com.zy.system.*.*"}, sqlSessionFactoryRef = "primarySqlSessionFactory")
public class PrimaryDataSourceConfig {
    @Bean(name = "primarySqlSessionFactory")
    @Primary
    public SqlSessionFactory primarySqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        // 设置MyBatis的Mapper XML文件路径
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:mapper/*.xml"));
        return sessionFactory.getObject();
    }
    @Bean(name = "transactionManager")
    @Primary
    public DataSourceTransactionManager primaryTransactionManager(@Qualifier("dataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}
src/main/java/com/zy/common/config/ds/SecondaryDataSourceConfig.java
New file
@@ -0,0 +1,32 @@
package com.zy.common.config.ds;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = "com.zy.nc", sqlSessionFactoryRef = "secondarySqlSessionFactory")
public class SecondaryDataSourceConfig {
    @Bean(name = "secondarySqlSessionFactory")
    public SqlSessionFactory secondarySqlSessionFactory(@Qualifier("slaveDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        // 设置MyBatis的Mapper XML文件路径
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:mapper2/*.xml"));
        return sessionFactory.getObject();
    }
    @Bean(name = "secondaryTransactionManager")
    public DataSourceTransactionManager secondaryTransactionManager(@Qualifier("slaveDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}
src/main/java/com/zy/nc/Test.java
New file
@@ -0,0 +1,430 @@
package com.zy.nc;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.core.common.Cools;
import com.zy.nc.util.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
 * 1.从resources/config.properties中读取测试api相关的数据 2.运行程序,测试查看测试结果
 *
 * @author lizhmf
 * @date 2019年6月20日上午10:53:11
 */
public class Test {
    // app_secret
    private static String client_secret = null;
    // 公钥
    private static String pubKey = null;
    // app_id
    private static String client_id = null;
    // ncc用户名
    private static String username = null;
    private static String usercode = null;
    // ncc用户名密码
    private static String pwd = null;
    // ncc账套
    private static String busi_center = null;
    private static String dsname = null;
    // 获取token方式:client_credentials、password
    private static String grant_type = null;
    // 服务器ip:port
    private static String baseUrl = null;
    // 返回值压缩加密级别
    private static String secret_level = null;
    // 请求参数
    private static String requestBody = null;
    // openapi请求路径
    private static String apiUrl = null;
    // 访问api获取到的access_token
    public static String token = null;
    // 重复调用检查
    public static String repeat_check = null;
    // 接口调用业务标识
    public static String busi_id = null;
    /**
     * 启动入口
     *
     * @param args
     */
    public static void main(String[] args) {
        try {
//            // 初始化数据
            init();
//            // 请求token
            if (token == null) {
                token = getToken();
            }
            System.out.println("getTokenData:" + token);
            // 测试openapi
            testApi(token);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 获取access_token
     *
     * @return
     * @throws Exception
     */
    private static String getToken() throws Exception {
        String token = null;
        if ("password".equals(grant_type)) {
            // 密码模式
            token = getTokenByPWD();
        } else if ("client_credentials".equals(grant_type)) {
            // 客户端模式
            token = getTokenByClient();
        }
        return token;
    }
    /**
     * 客户端模式获取token
     *
     * @return
     * @throws Exception
     */
    private static String getTokenByClient() throws Exception {
        Map<String, String> paramMap = new HashMap<String, String>();
        // 密码模式认证
        paramMap.put("grant_type", "client_credentials");
        // 第三方应用id
        paramMap.put("client_id", client_id);
        // 第三方应用secret 公钥加密
        String secret_entryption = Encryption.pubEncrypt(pubKey, client_secret);
        System.out.println("secret_entryption::" + secret_entryption);
        paramMap.put("client_secret", URLEncoder.encode(secret_entryption, "utf-8"));
        // 账套编码
        paramMap.put("biz_center", busi_center);
        // // TODO 传递数据源和ncc登录用户
//        paramMap.put("dsname", dsname);
        paramMap.put("usercode", usercode);
        // 签名
        String sign = SHA256Util.getSHA256(client_id + client_secret + pubKey, pubKey);
        paramMap.put("signature", sign);
        System.out.println("##gettoken sign::" + sign);
        String url = baseUrl + "/nccloud/opm/accesstoken";
        String mediaType = "application/x-www-form-urlencoded";
        String token = doPost(url, paramMap, mediaType, null, "");
        return token;
    }
    /**
     * 密码模式获取token
     *
     * @return
     * @throws Exception
     */
    @SuppressWarnings("unused")
    private static String getTokenByPWD() throws Exception {
        Map<String, String> paramMap = new HashMap<String, String>();
        // 密码模式认证
        paramMap.put("grant_type", "password");
        // 第三方应用id
        paramMap.put("client_id", client_id);
        // 第三方应用secret 公钥加密
        paramMap.put("client_secret", URLEncoder.encode(Encryption.pubEncrypt(pubKey, client_secret), "utf-8"));
//        paramMap.put("client_secret", client_secret);
        // ncc用户名
        paramMap.put("username", username);
        // 密码 公钥加密
        paramMap.put("password", URLEncoder.encode(Encryption.pubEncrypt(pubKey, pwd), "utf-8"));
//        paramMap.put("password", pwd);
        // 账套编码
        paramMap.put("biz_center", busi_center);
        // 签名
        String sign = SHA256Util.getSHA256(client_id + client_secret + username + pwd + pubKey, pubKey);
        System.out.println("sign_getToken::" + sign);
        paramMap.put("signature", sign);
        String url = baseUrl + "/nccloud/opm/accesstoken";
        String mediaType = "application/x-www-form-urlencoded";
        String token = doPost(url, paramMap, mediaType, null, "");
        return token;
    }
    /**
     * 请求openapi
     *
     * @param token
     * @throws Exception
     */
    private static void testApi(String token) throws Exception {
        // token转对象,获取api访问所用token和secret
        ResultMessageUtil returnData = JSONObject.parseObject(token, ResultMessageUtil.class);
        Map<String, Object> data = (Map<String, Object>) returnData.getData();
        String access_token = (String) data.get("access_token");
        String security_key = (String) data.get("security_key");
        String refresh_token = (String) data.get("refresh_token");
        long expire_in = new Double((double) data.get("expires_in")).longValue();
        long ts = new Double((double) data.get("ts")).longValue();
        if (ts + expire_in < System.currentTimeMillis()) {
            token = getToken();
            returnData = JSONObject.parseObject(token, ResultMessageUtil.class);
            data = (Map<String, Object>) returnData.getData();
            access_token = (String) data.get("access_token");
            security_key = (String) data.get("security_key");
            refresh_token = (String) data.get("refresh_token");
        }
        System.out.println("【ACCESS_TOKEN】:" + access_token);
        // 请求路径
        String url = baseUrl + apiUrl;
        // header 参数
        Map<String, String> headermap = new HashMap<>();
        headermap.put("access_token", access_token);
        headermap.put("client_id", client_id);
        StringBuffer sb = new StringBuffer();
        sb.append(client_id);
        if (!Cools.isEmpty(requestBody)) {
            // sb.append(requestBody.replaceAll("\\s*|\t|\r|\n", "").trim());
            sb.append(requestBody);
        }
        sb.append(pubKey);
        String sign = SHA256Util.getSHA256(sb.toString(), pubKey);
        headermap.put("signature", sign);
        if (!Cools.isEmpty(busi_id)) {
            headermap.put("busi_id", busi_id);
        }
        if (!Cools.isEmpty(repeat_check)) {
            headermap.put("repeat_check", repeat_check);
        }
//        headermap.put("ucg_flag", "y");
        String mediaType = "application/json;charset=utf-8";
        // 表体数据json
        // 根据安全级别选择加密或压缩请求表体参数
        String json = dealRequestBody(requestBody, security_key, secret_level);
        // 返回值
        String result = doPost(url, null, mediaType, headermap, json);
        String result2 = dealResponseBody(result, security_key, secret_level);
        System.out.println("【RESULT】:" + result);
        System.out.println("result解密:" + result2);
    }
    /**
     * 返回值进行过加密和压缩,对返回值进行解压和解密
     *
     * @param source
     * @param security_key
     * @param level
     * @return
     * @throws Exception
     */
    private static String dealResponseBody(String source, String security_key, String level) throws Exception {
        String result = null;
        if (StringUtils.isEmpty(level) || SecretConst.LEVEL0.equals(level)) {
            result = source;
        } else if (SecretConst.LEVEL1.equals(level)) {
            result = Decryption.symDecrypt(security_key, source);
        } else if (SecretConst.LEVEL2.equals(level)) {
            result = CompressUtil.gzipDecompress(source);
        } else if (SecretConst.LEVEL3.equals(level)) {
            result = CompressUtil.gzipDecompress(Decryption.symDecrypt(security_key, source));
        } else if (SecretConst.LEVEL4.equals(level)) {
            result = Decryption.symDecrypt(security_key, CompressUtil.gzipDecompress(source));
        } else {
            throw new Exception("无效的安全等级");
        }
        return result;
    }
    /**
     * 初始化参数
     */
    private static void init() {
        // TODO Auto-generated method stub
        Properties properties = new Properties();
        String filepath = "config.properties";
        ClassLoader classloader = Thread.currentThread().getContextClassLoader();
        InputStream inputStream = classloader.getResourceAsStream(filepath);
        try {
            InputStreamReader reader = new InputStreamReader(inputStream, "UTF-8");
            properties.load(reader);
            client_secret = new String(properties.getProperty("client_secret").getBytes("utf-8"), "utf-8");
            client_id = properties.getProperty("client_id");
            pubKey = properties.getProperty("pubKey");
            username = properties.getProperty("username");
            usercode = properties.getProperty("usercode");
            pwd = properties.getProperty("pwd");
            busi_center = properties.getProperty("busi_center");
            dsname = properties.getProperty("dsname");
            baseUrl = properties.getProperty("baseUrl");
            requestBody = new String(properties.getProperty("requestBody").getBytes("utf-8"), "utf-8");
            apiUrl = properties.getProperty("apiUrl");
            grant_type = properties.getProperty("grant_type");
            secret_level = properties.getProperty("secret_level");
            repeat_check = properties.getProperty("repeat_check");
            busi_id = properties.getProperty("busi_id");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    // 根据安全级别设置,表体是否加密或压缩
    private static String dealRequestBody(String source, String security_key, String level) throws Exception {
        String result = null;
        if (StringUtils.isEmpty(level) || SecretConst.LEVEL0.equals(level)) {
            result = source;
        } else if (SecretConst.LEVEL1.equals(level)) {
            result = Encryption.symEncrypt(security_key, source);
        } else if (SecretConst.LEVEL2.equals(level)) {
            result = CompressUtil.gzipCompress(source);
        } else if (SecretConst.LEVEL3.equals(level)) {
            result = Encryption.symEncrypt(security_key, CompressUtil.gzipCompress(source));
        } else if (SecretConst.LEVEL4.equals(level)) {
            result = CompressUtil.gzipCompress(Encryption.symEncrypt(security_key, source));
        } else {
            throw new Exception("无效的安全等级");
        }
        return result;
    }
    /**
     * 发送post请求
     *
     * @param baseUrl
     * @param paramMap
     * @param mediaType
     * @param headers
     * @param json
     * @return
     */
    private static String doPost(String baseUrl, Map<String, String> paramMap, String mediaType,
                                 Map<String, String> headers, String json) throws Exception {
        HttpURLConnection urlConnection = null;
        InputStream in = null;
        OutputStream out = null;
        BufferedReader bufferedReader = null;
        String result = null;
        try {
            StringBuffer sb = new StringBuffer();
            sb.append(baseUrl);
            if (paramMap != null) {
                sb.append("?");
                for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                    String key = entry.getKey();
                    String value = entry.getValue();
                    sb.append(key + "=" + value).append("&");
                }
                baseUrl = sb.toString().substring(0, sb.toString().length() - 1);
            }
            URL urlObj = new URL(baseUrl);
            urlConnection = (HttpURLConnection) urlObj.openConnection();
            urlConnection.setConnectTimeout(50000);
            urlConnection.setRequestMethod("POST");
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setUseCaches(false);
            urlConnection.addRequestProperty("content-type", mediaType);
            if (headers != null) {
                for (String key : headers.keySet()) {
                    urlConnection.addRequestProperty(key, headers.get(key));
                }
            }
            out = urlConnection.getOutputStream();
            out.write(json.getBytes("utf-8"));
            out.flush();
            int resCode = urlConnection.getResponseCode();
            System.out.println("状态码::" + resCode);
//            if (resCode == HttpURLConnection.HTTP_OK || resCode == HttpURLConnection.HTTP_CREATED || resCode == HttpURLConnection.HTTP_ACCEPTED) {
            in = urlConnection.getInputStream();
//            } else {
//                in = urlConnection.getErrorStream();
//            }
            bufferedReader = new BufferedReader(new InputStreamReader(in, "utf-8"));
            StringBuffer temp = new StringBuffer();
            String line = bufferedReader.readLine();
            while (line != null) {
                temp.append(line).append("\r\n");
                line = bufferedReader.readLine();
            }
            String ecod = urlConnection.getContentEncoding();
            if (ecod == null) {
                ecod = Charset.forName("utf-8").name();
            }
            result = new String(temp.toString().getBytes("utf-8"), ecod);
            System.out.println(result);
        } catch (Exception e) {
            System.out.println(e);
            throw e;
        } finally {
            if (null != bufferedReader) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != in) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            urlConnection.disconnect();
        }
        return result;
    }
    class SecretConst {
        /**
         * LEVEL0 不压缩、不加密
         */
        public static final String LEVEL0 = "L0";
        /**
         * LEVEL1 只加密、不压缩
         */
        public static final String LEVEL1 = "L1";
        /**
         * LEVEL2 只压缩、不加密
         */
        public static final String LEVEL2 = "L2";
        /**
         * LEVEL3 先压缩、后加密
         */
        public static final String LEVEL3 = "L3";
        /**
         * LEVEL4 先加密、后压缩
         */
        public static final String LEVEL4 = "L4";
    }
}
src/main/java/com/zy/nc/util/Base64Util.java
New file
@@ -0,0 +1,31 @@
package com.zy.nc.util;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import java.io.IOException;
/**
 * Base64������
 *
 * @author liyang
 */
public class Base64Util {
    /**
     * Base64����
     */
    public static String encryptBASE64(byte[] key) {
        return (new BASE64Encoder()).encodeBuffer(key);
    }
    /**
     * Base64����
     *
     * @throws IOException
     */
    public static byte[] decryptBASE64(String key) throws IOException {
        return (new BASE64Decoder()).decodeBuffer(key);
    }
}
src/main/java/com/zy/nc/util/CipherConstant.java
New file
@@ -0,0 +1,12 @@
package com.zy.nc.util;
public class CipherConstant {
    // �����㷨����AES�ԳƼ���
    public static final String AES = "AES";
    //    public static final String AES_ALGORITHM = "AES";
    public static final String AES_ALGORITHM = "AES/CTR/NoPadding";
    // �����㷨����RSA�ǶԳƼ���
    public static final String RSA = "RSA";
    //    public static final String RSA_ALGORITHM = "RSA";
    public static final String RSA_ALGORITHM = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
}
src/main/java/com/zy/nc/util/CompressUtil.java
New file
@@ -0,0 +1,160 @@
package com.zy.nc.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.zip.*;
/**
 * ѹ��������
 *
 * @author liyang
 */
public class CompressUtil {
    private static int buffSize = 1024;
    /**
     * deflaterCompress Ĭ��ѹ��
     *
     * @param source ԭ��
     * @return
     * @throws IOException
     * @throws Exception
     */
    public static String deflaterCompress(String source) throws Exception {
        String value = null;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        Deflater compressor = new Deflater();
        try {
            byte[] input = source.getBytes(StandardCharsets.UTF_8);
            // ����ѹ���Ǽ�
            compressor.setLevel(Deflater.DEFAULT_COMPRESSION);
            compressor.setInput(input);
            compressor.finish();
            final byte[] buf = new byte[buffSize];
            while (!compressor.finished()) {
                int count = compressor.deflate(buf);
                bos.write(buf, 0, count);
            }
            value = Base64Util.encryptBASE64(bos.toByteArray());
        } finally {
            bos.close();
            compressor.end();
        }
        return value;
    }
    /**
     * deflaterDecompress Ĭ�Ͻ�ѹ
     *
     * @param source ѹ�����ı�
     * @return
     * @throws IOException
     * @throws @throws     Exception
     */
    public static String deflaterDecompress(String source) throws Exception {
        String value = null;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        Inflater decompressor = new Inflater();
        try {
            byte[] input = Base64Util.decryptBASE64(source);
            decompressor.setInput(input);
            final byte[] buf = new byte[buffSize];
            while (!decompressor.finished()) {
                int count = decompressor.inflate(buf);
                bos.write(buf, 0, count);
            }
            value = new String(bos.toByteArray(), StandardCharsets.UTF_8);
        } catch (IOException | DataFormatException e) {
            throw new Exception("��ѹ�쳣 " + e.getMessage());
        } finally {
            bos.close();
            decompressor.end();
        }
        return value;
    }
    /**
     * gzipCompress ����gzipѹ��
     *
     * @param source ԭ��
     * @return
     * @throws IOException
     * @throws Exception
     */
    public static String gzipCompress(String source) throws Exception {
        String value = null;
        ByteArrayOutputStream out = null;
        try {
            out = new ByteArrayOutputStream();
            GZIPOutputStream gzip = new GZIPOutputStream(out);
            byte[] input = source.getBytes(StandardCharsets.UTF_8);
            gzip.write(input);
            gzip.close();
            value = Base64Util.encryptBASE64(out.toByteArray());
        } catch (IOException e) {
            throw new Exception("ѹ���쳣 " + e.getMessage());
        } finally {
            if (out != null) {
                out.close();
            }
        }
        return value;
    }
    /**
     * gzipDecompress gzip��ѹ
     *
     * @param source ѹ�����ı�
     * @return
     * @throws Exception
     */
    public static String gzipDecompress(String source) throws Exception {
        String value = null;
        ByteArrayOutputStream out = null;
        ByteArrayInputStream in = null;
        try {
            byte[] input = Base64Util.decryptBASE64(source);
            out = new ByteArrayOutputStream();
            in = new ByteArrayInputStream(input);
            GZIPInputStream ungzip = new GZIPInputStream(in);
            byte[] buffer = new byte[buffSize];
            int n;
            while ((n = ungzip.read(buffer)) >= 0) {
                out.write(buffer, 0, n);
            }
            ungzip.close();
            value = new String(out.toByteArray(), StandardCharsets.UTF_8);
        } catch (IOException e) {
            throw new Exception("ѹ���쳣 " + e.getMessage());
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
        return value;
    }
}
src/main/java/com/zy/nc/util/Decryption.java
New file
@@ -0,0 +1,103 @@
package com.zy.nc.util;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.spec.MGF1ParameterSpec;
/**
 * ������
 *
 * @author liyang
 */
public class Decryption {
    // RSA���������Ĵ�С
    private static final int MAX_DECRYPT_BLOCK = 256;
    /**
     * symDecrypt �Գƽ���
     *
     * @param strkey �Գ���Կ
     * @param src    ����
     * @return ԭ��
     * @throws IOException
     * @throws Exception
     */
    public static String symDecrypt(String strkey, String src) throws Exception {
        String target = null;
        try {
            Key key = KeysFactory.getSymKey(strkey);
            // ����
            Cipher cipher = Cipher.getInstance(CipherConstant.AES_ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(strkey.substring(0, 16).getBytes());
            cipher.init(Cipher.DECRYPT_MODE, key, iv);
            byte[] decodeResult = cipher.doFinal(Base64Util.decryptBASE64(src));
            target = new String(decodeResult, StandardCharsets.UTF_8);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException |
                 InvalidKeyException e) {
            throw new Exception("����ʧ��" + e.getMessage());
        }
        return target;
    }
    /**
     * priDecrypt ˽Կ����
     *
     * @param priKey ˽Կ
     * @param src    ����
     * @return ԭ��
     * @throws IOException
     * @throws Exception
     */
    public static String priDecrypt(String priKey, String src) throws Exception {
        String target = null;
        ByteArrayOutputStream out = null;
        try {
            Key key = KeysFactory.getPrivateKey(priKey);
            // ����
            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
            cipher.init(Cipher.DECRYPT_MODE, key, new OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), PSource.PSpecified.DEFAULT));
            byte[] data = Base64Util.decryptBASE64(src);
            int inputLen = data.length;
            out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // �����ݷֶν���
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                    cache = cipher.doFinal(data, offSet, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_DECRYPT_BLOCK;
            }
            target = new String(out.toByteArray());
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException |
                 BadPaddingException e) {
            throw new Exception("����ʧ��" + e.getMessage());
        } finally {
            if (out != null) {
                out.close();
            }
        }
        return target;
    }
}
src/main/java/com/zy/nc/util/Encryption.java
New file
@@ -0,0 +1,100 @@
package com.zy.nc.util;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.spec.MGF1ParameterSpec;
/**
 * ������
 *
 * @author liyang
 */
public class Encryption {
    // RSA���������Ĵ�С
    private static final int MAX_ENCRYPT_BLOCK = 117;
    /**
     * symEncrypt �ԳƼ���
     *
     * @param strkey �Գ���Կ
     * @param src    ԭ��
     * @return ����
     */
    public static String symEncrypt(String strkey, String src) throws Exception {
        String target = null;
        try {
            Key key = KeysFactory.getSymKey(strkey);
            //����
            Cipher cipher = Cipher.getInstance(CipherConstant.AES_ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(strkey.substring(0, 16).getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, key, iv);
            byte[] encodeResult = cipher.doFinal(src.getBytes(StandardCharsets.UTF_8));
            target = Base64Util.encryptBASE64(encodeResult);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | UnsupportedEncodingException |
                 InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
            throw new Exception("����ʧ��" + e.getMessage());
        }
        return target;
    }
    /**
     * pubEncrypt ��Կ����
     *
     * @param pubKey ��Կ
     * @param src    ԭ��
     * @return ����
     * @throws IOException
     * @throws Exception
     */
    public static String pubEncrypt(String pubKey, String src) throws Exception {
        String target = null;
        ByteArrayOutputStream out = null;
        try {
            Key key = KeysFactory.getPublicKey(pubKey);
            Cipher cipher = Cipher.getInstance(CipherConstant.RSA_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, key, new OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), PSource.PSpecified.DEFAULT));
            byte[] data = src.getBytes();
            int inputLen = data.length;
            out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // �����ݷֶμ���
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            target = Base64Util.encryptBASE64(out.toByteArray());
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException |
                 BadPaddingException e) {
            throw new Exception("����ʧ��" + e.getMessage());
        } finally {
            if (out != null) {
                out.close();
            }
        }
        return target;
    }
}
src/main/java/com/zy/nc/util/KeyPairs.java
New file
@@ -0,0 +1,27 @@
package com.zy.nc.util;
import java.security.KeyPair;
/**
 * KeyPairs
 * ������
 *
 * @author liyang
 * @date: 2019-5-20����4:34:51
 */
public class KeyPairs {
    private KeyPair keyPair;
    public KeyPairs(KeyPair keyPair) {
        this.keyPair = keyPair;
    }
    public String getPublicKey() {
        return Base64Util.encryptBASE64(keyPair.getPublic().getEncoded());
    }
    public String getPrivateKey() {
        return Base64Util.encryptBASE64(keyPair.getPrivate().getEncoded());
    }
}
src/main/java/com/zy/nc/util/KeysFactory.java
New file
@@ -0,0 +1,103 @@
package com.zy.nc.util;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
/**
 * Key������
 *
 * @author liyang
 */
public class KeysFactory {
    /**
     * buildAsymKey ����һ��ǶԳ���Կ
     *
     * @return KeyPair key��PublicKey��PrivateKey
     * @throws NoSuchAlgorithmException
     */
    public static KeyPairs buildAsymKey() throws Exception {
        /* ��ʼ����Կ������ */
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(CipherConstant.RSA);
        keyPairGenerator.initialize(2048, SecureRandomProxy.getRandomInstance());
        /* ������Կ */
        return new KeyPairs(keyPairGenerator.generateKeyPair());
    }
    /**
     * buildAsymKey ����һ���Գ���Կ
     *
     * @return �Գ���Կ
     * @throws NoSuchAlgorithmException
     * @throws Exception
     */
    public static String buildSymKey() throws Exception {
        // ����Key
        KeyGenerator keyGenerator = KeyGenerator.getInstance(CipherConstant.AES);
        keyGenerator.init(256, SecureRandomProxy.getRandomInstance());
        // ʹ���������ֳ�ʼ�����������ض�������������Կ���������ܺ��������Ψһ�̶��ġ�
        SecretKey secretKey = keyGenerator.generateKey();
        return Base64Util.encryptBASE64(secretKey.getEncoded());
    }
    public static Key getPublicKey(String pubKey) throws Exception {
        Key key = null;
        try {
            byte[] keyBytes = Base64Util.decryptBASE64(pubKey);
            KeyFactory keyFactory = KeyFactory.getInstance(CipherConstant.RSA);
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
            key = keyFactory.generatePublic(x509KeySpec);
        } catch (Exception e) {
            throw new Exception("��Ч����Կ  " + e.getMessage());
        }
        return key;
    }
    public static Key getPrivateKey(String priKey) throws Exception {
        Key key = null;
        try {
            byte[] keyBytes = Base64Util.decryptBASE64(priKey);
            KeyFactory keyFactory = KeyFactory.getInstance(CipherConstant.RSA);
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
            key = keyFactory.generatePrivate(pkcs8KeySpec);
        } catch (Exception e) {
            throw new Exception("��Ч��Կ " + e.getMessage());
        }
        return key;
    }
    public static Key getSymKey(String symKey) throws Exception {
        Key key = null;
        try {
            byte[] keyBytes = Base64Util.decryptBASE64(symKey);
            // Keyת��
            key = new SecretKeySpec(keyBytes, CipherConstant.AES);
        } catch (Exception e) {
            throw new Exception("��Ч��Կ " + e.getMessage());
        }
        return key;
    }
}
src/main/java/com/zy/nc/util/ResultMessageUtil.java
New file
@@ -0,0 +1,45 @@
package com.zy.nc.util;
public class ResultMessageUtil {
    private boolean success;
    private Object data;
    private String code;
    private String errorMessage;
    public boolean isSuccess() {
        return success;
    }
    public void setSuccess(boolean success) {
        this.success = success;
    }
    public Object getData() {
        return data;
    }
    public void setData(Object data) {
        this.data = data;
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    public String getErrorMessage() {
        return errorMessage;
    }
    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }
}
src/main/java/com/zy/nc/util/SHA256Util.java
New file
@@ -0,0 +1,52 @@
package com.zy.nc.util;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class SHA256Util {
    public static String getSHA256(String str, String key) {
        //����
        byte[] salt = new byte[16];
        try {
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(key.getBytes());
            random.nextBytes(salt);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        String salt_string = Base64Util.encryptBASE64(salt);
        System.out.println("salt_String::" + salt_string);
        return getSHA256(str + salt_string.replaceAll("\r|\n", ""));
    }
    private static String getSHA256(String str) {
        MessageDigest messageDigest;
        String encodestr = "";
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(str.getBytes(StandardCharsets.UTF_8));
            encodestr = byte2Hex(messageDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        return encodestr;
    }
    private static String byte2Hex(byte[] bytes) {
        StringBuffer stringBuffer = new StringBuffer();
        String temp = null;
        for (int i = 0; i < bytes.length; i++) {
            temp = Integer.toHexString(bytes[i] & 0xFF);
            if (temp.length() == 1) {
                // 1得到�?��的进行补0操作
                stringBuffer.append("0");
            }
            stringBuffer.append(temp);
        }
        return stringBuffer.toString();
    }
}
src/main/java/com/zy/nc/util/SecureRandomProxy.java
New file
@@ -0,0 +1,26 @@
package com.zy.nc.util;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
/**
 * @Describe
 * @Author lizhmf
 * @Date 2021/3/16 19:32
 * @Version 1.0
 */
public class SecureRandomProxy {
    public static SecureRandom getRandomInstance() {
        SecureRandom random = null;
        try {
            random = SecureRandom.getInstance("SHA1PRNG");
//                random = SecureRandom.getInstance("NativePRNG");
//                random = SecureRandom.getInstance("NativePRNGNonBlocking");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return random;
    }
}
src/main/java/com/zy/nc/vo/SaleOutBodyVO.java
New file
@@ -0,0 +1,257 @@
package com.zy.nc.vo;
import lombok.Data;
@Data
public class SaleOutBodyVO {
    // 必填字段
    private String csourcebillbid; // 来源单据表体主键
    private String csourcebillhid; // 来源单据表头主键
    private String csourcetype; // 来源单据类型
    private Double nnum; // 实发主数量
    // 可选字段
    private Boolean badvfeeflag; // 代垫运费
    private Boolean bbarcodeclose; // 单据行是否条码关闭
    private Boolean bcloseordflag; // 出库关闭
    private Boolean binvoiceflag; // 开票
    private Boolean blendoutflag; // 借出转销售
    private Boolean bonroadflag; // 在途
    private Boolean breturnprofit; // 返利
    private Boolean bsafeprice; // 价保
    private Boolean bsample; // 样品
    private Boolean bsourcelargess; // 上游赠品行
    private Boolean btou8rm; // 已下发零售
    private Boolean btranendflag; // 运输关闭
    private Boolean bwastageflag; // 签收
    private String casscustid; // 客户
    private String castunitid; // 单位
    private String cbodytranstypecode; // 出入库类型
    private String cbodywarehouseid; // 库存仓库
    private String ccorrespondbid; // 对应入库单据表体主键
    private String ccorrespondcode; // 对应入库单单据号
    private String ccorrespondhid; // 对应入库单主键
    private String ccorrespondrowno; // 对应入库单行号
    private String ccorrespondtranstype; // 对应入库单交易类型
    private String ccorrespondtype; // 对应入库单类型
    private String ccostobject; // 成本对象
    private String ccurrencyid; // 本位币
    private String ccustmaterialid; // 客户物料码
    private String cdelivery_bbid; // 发货单报检单据主键
    private String cffileid; // 特征码
    private String cfirstbillbid; // 源头单据表体主键
    private String cfirstbilldate; // 源头单据日期
    private String cfirstbillhid; // 源头单据表头主键
    private String cfirsttranstype; // 源头交易类型
    private String cfirsttype; // 源头单据类型
    private String cgeneralbid; // 出库单表体主键
    private String cglobalcurrencyid; // 全局本位币
    private String cgroupcurrencyid; // 集团本位币
    private String cinvoicecustid; // 开票客户
    private String cioliabilityoid; // 发货利润中心
    private String cioliabilityvid; // 发货利润中心
    private String cliabilityoid; // 结算利润中心
    private String cliabilityvid; // 结算利润中心
    private String clocationid; // 货位
    private String cmaterialoid; // 物料
    private String cmaterialvid; // 物料编码
    private String corigareaid; // 原产地区
    private String corigcountryid; // 原产国
    private String corigcurrencyid; // 币种
    private String cprodlineid; // 产品线
    private String cproductorid; // 生产厂商
    private String cprojectid; // 项目
    private String cqtunitid; // 报价单位
    private String cqualitylevelid; // 质量等级
    private String creceieveid; // 收货客户
    private String creceiveareaid; // 收货地区
    private String creceivepointid; // 收货地点
    private String crowno; // 行号
    private String cselastunitid; // 选择拆解单位
    private String csignwastbid; // 出入库单其它来源单据行主键
    private String csignwasthid; // 出入库单其它来源单据主键
    private String csignwasttype; // 出入库单其它来源类型
    private String csnqualitylevelid; // 序列号质量等级
    private String csnunitid; // 序列号单位
    private String csourcebilldate; // 来源单据日期
    private String csourcematerialoid; // 来源单据物料
    private String csourcetranstype; // 来源交易类型
    private String csourcewastbid; // 来源途损单据表体主键
    private String csourcewasthid; // 来源途损单据主键
    private String csourcewasttranstype; // 来源途损交易类型
    private String csourcewasttype; // 来源途损单据类型
    private String csrc2billbid; // 其他来源单行主键
    private String csrc2billhid; // 其他来源单主键
    private String csrc2billtype; // 其他来源单据类型编码
    private String csrc2transtype; // 其他来源交易类型编码
    private String csrcmaterialoid; // 来源物料
    private String csrcmaterialvid; // 来源物料编码
    private String cstateid; // 库存状态
    private String csumid; // VMI汇总
    private String ctaxcodeid; // 税码
    private String ctplcustomerid; // 货主客户
    private String cunitid; // 主单位
    private String cvendorid; // 供应商
    private String cvmivenderid; // 寄存供应商
    private String dbizdate; // 出库日期
    private String ddeliverdate; // 要求收货日期
    private String dinbounddate; // 首次入库日期
    private String dproducedate; // 生产日期
    private String dvalidate; // 失效日期
    private Integer fbillrowflag; // 配套标志
    private Boolean flargess; // 赠品
    private Integer ftaxtypeflag; // 扣税类别
    private Integer ibcversion; // 批次版本
    private Integer idesatype; // 拆解类型
    private Double naccumoutbacknum; // 累计出库退回主数量
    private Double naccumoutsignnum; // 累计签收主数量
    private Double naccumvminum; // 累计汇总匹配主数量
    private Double naccumwastnum; // 累计途损主数量
    private Double nassistnum; // 实发数量
    private Double nbarcodenum; // 条码主数量
    private Double nbdiscountrate; // 整单折扣
    private Double ncaltaxmny; // 计税金额
    private Double nchangestdrate; // 折本汇率
    private Double ncorrespondastnum; // 累计出库数量
    private Double ncorrespondgrsnum; // 累计出库毛重主数量
    private Double ncorrespondnum; // 累计出库主数量
    private Double ncostmny; // 金额
    private Double ncostprice; // 单价
    private Double ncountnum; // 箱数
    private Double nglobalexchgrate; // 全局本位币汇率
    private Double nglobalmny; // 全局本币无税金额
    private Double nglobaltaxmny; // 全局本币价税合计
    private Double ngrossnum; // 毛重主数量
    private Double ngroupexchgrate; // 集团本位币汇率
    private Double ngroupmny; // 集团本币无税金额
    private Double ngrouptaxmny; // 集团本币价税合计
    private Double ninvoicemny; // 可开票金额
    private Double ninvoicenum; // 可开票数量
    private Double nitemdiscountrate; // 单品折扣
    private Double nmny; // 本币无税金额
    private Double nnetprice; // 主本币无税净价
    private Double norigmny; // 无税金额
    private Double norignetprice; // 主无税净价
    private Double norigprice; // 主无税单价
    private Double norigtaxmny; // 价税合计
    private Double norigtaxnetprice; // 主含税净价
    private Double norigtaxprice; // 主含税单价
    private Double npiece; // 件数
    private Double nplannedmny; // 计划金额
    private Double nplannedprice; // 计划单价
    private Double nprice; // 主本币无税单价
    private Double nqtnetprice; // 本币无税净价
    private Double nqtorignetprice; // 无税净价
    private Double nqtorigprice; // 无税单价
    private Double nqtorigtaxnetprc; // 报价单位含税净价
    private Double nqtorigtaxnetprice; // 含税净价
    private Double nqtorigtaxprice; // 含税单价
    private Double nqtprice; // 本币无税单价
    private Double nqttaxnetprice; // 本币含税净价
    private Double nqttaxprice; // 本币含税单价
    private Double nqtunitnum; // 报价数量
    private Double nreplenishednum; // 累计退货主数量
    private Double nrushnum; // 累计对冲主数量
    private Double nshouldassistnum; // 应发数量
    private Double nshouldnum; // 应发主数量
    private Double nsignnum; // 累计开票主数量
    private Double ntarenum; // 皮重主数量
    private Double ntax; // 税额
    private Double ntaxmny; // 本币价税合计
    private Double ntaxnetprice; // 主本币含税净价
    private Double ntaxprice; // 主本币含税单价
    private Double ntaxrate; // 税率
    private Double ntotaltrannum; // 累计运输主数量
    private Double nvolume; // 体积
    private Double nweight; // 重量
    private String pk_batchcode; // 批次主键
    private String pk_group; // 集团
    private String pk_measware; // 计量器具
    private String pk_org; // 库存组织最新版本
    private String pk_org_v; // 库存组织
    private String pk_packsort; // 包装类型
    private String pk_returnreason; // 退货原因
    private String pk_serialcode; // 序列号主键
    private String tchecktime; // 检验时间
    private String tsourcebbts; // 来源发货单报检单时间戳
    private String tsourcebodyts; // 来源表体时间戳
    private String tsourceheadts; // 来源表头时间戳
    private String vbatchcode; // 批次号
    private String vbatchcodenote; // 批次备注
    private String vbcdef1; // 批次自定义项1
    private String vbcdef10; // 批次自定义项10
    private String vbcdef11; // 批次自定义项11
    private String vbcdef12; // 批次自定义项12
    private String vbcdef13; // 批次自定义项13
    private String vbcdef14; // 批次自定义项14
    private String vbcdef15; // 批次自定义项15
    private String vbcdef16; // 批次自定义项16
    private String vbcdef17; // 批次自定义项17
    private String vbcdef18; // 批次自定义项18
    private String vbcdef19; // 批次自定义项19
    private String vbcdef2; // 批次自定义项2
    private String vbcdef20; // 批次自定义项20
    private String vbcdef3; // 批次自定义项3
    private String vbcdef4; // 批次自定义项4
    private String vbcdef5; // 批次自定义项5
    private String vbcdef6; // 批次自定义项6
    private String vbcdef7; // 批次自定义项7
    private String vbcdef8; // 批次自定义项8
    private String vbcdef9; // 批次自定义项9
    private String vbdef1; // 表体自定义项1
    private String vbdef10; // 表体自定义项10
    private String vbdef11; // 表体自定义项11
    private String vbdef12; // 表体自定义项12
    private String vbdef13; // 表体自定义项13
    private String vbdef14; // 表体自定义项14
    private String vbdef15; // 表体自定义项15
    private String vbdef16; // 表体自定义项16
    private String vbdef17; // 表体自定义项17
    private String vbdef18; // 表体自定义项18
    private String vbdef19; // 表体自定义项19
    private String vbdef2; // 表体自定义项2
    private String vbdef20; // 表体自定义项20
    private String vbdef3; // 表体自定义项3
    private String vbdef4; // 表体自定义项4
    private String vbdef5; // 表体自定义项5
    private String vbdef6; // 表体自定义项6
    private String vbdef7; // 表体自定义项7
    private String vbdef8; // 表体自定义项8
    private String vbdef9; // 表体自定义项9
    private String vbillbarcode; // 单据条码
    private String vbilltypeu8rm; // 来自于零售之单据类型
    private String vchangerate; // 换算率
    private String vexigencybid; // 紧急放行申请单行主键
    private String vexigencycode; // 紧急放行申请单号
    private String vexigencyhid; // 紧急放行申请单主键
    private String vexigencyrowno; // 紧急放行申请单行号
    private String vexigencytype; // 紧急放行单据类型
    private String vfirstbillcode; // 源头单据号
    private String vfirstrowno; // 源头单据行号
    private String vfree1; // 自由辅助属性1
    private String vfree10; // 自由辅助属性10
    private String vfree2; // 自由辅助属性2
    private String vfree3; // 自由辅助属性3
    private String vfree4; // 自由辅助属性4
    private String vfree5; // 自由辅助属性5
    private String vfree6; // 自由辅助属性6
    private String vfree7; // 自由辅助属性7
    private String vfree8; // 自由辅助属性8
    private String vfree9; // 自由辅助属性9
    private String vnotebody; // 行备注
    private String vpickdetailbid; // 拣配明细行
    private String vpickdetailrowno; // 拣配明细行号
    private String vqtunitrate; // 报价换算率
    private String vreceiveaddress; // 收货地址
    private String vserialcode; // 序列号
    private String vsignwastcode; // 出入库单其它来源单据号
    private String vsignwastrowno; // 出入库单其它来源单据行标识
    private String vsndef1; // 序列号自定义项1
    private String vsndef10; // 序列号自定义项10
    private String vsndef11; // 序列号自定义项11
    private String vsndef12; // 序列号自定义项12
    private String vsndef13; // 序列号自定义项13
    private String vsndef14; // 序列号自定义项14
    private String vsndef15; // 序列号自定义项15
    private String vsndef16; // 序列号自定义项16
}
src/main/java/com/zy/nc/vo/SaleOutHeadVO.java
New file
@@ -0,0 +1,89 @@
package com.zy.nc.vo;
import lombok.Data;
@Data
public class SaleOutHeadVO {
    // 必填字段
    private String pkOrg; // 库存组织最新版本
    private String cwarehouseid; // 仓库
    // 可选字段
    private String approver; // 签字人
    private String billmaker; // 制单人
    private Boolean boutretflag; // 销售退回
    private Boolean bsalecooppur; // 已协同生成采购入库单
    private Boolean btriatradeflag; // 三角贸易
    private String cbizid; // 业务员
    private String cbiztype; // 业务流程
    private String ccostdomainid; // 结算成本域
    private String ccustomerid; // 订单客户
    private String cdilivertypeid; // 运输方式
    private String cdptid; // 部门最新版本
    private String cdptvid; // 部门
    private String cfanaceorgoid; // 结算财务组织最新版本
    private String cfanaceorgvid; // 结算财务组织
    private String cgeneralhid; // 出库单表头主键
    private String corpoid; // 公司最新版本
    private String corpvid; // 公司
    private String cothercalbodyoid; // 入库库存组织最新版本
    private String cothercalbodyvid; // 入库库存组织
    private String cotherwhid; // 入库仓库
    private String creationtime; // 创建时间
    private String creator; // 创建人
    private String crececountryid; // 收货国
    private String creceivfinorgoid; // 应收财务组织最新版本
    private String creceivfinorgvid; // 应收财务组织
    private String csaleorgoid; // 销售组织最新版本
    private String csaleorgvid; // 销售组织
    private String csendcountryid; // 发货国
    private String ctaxcountryid; // 报税国
    private String ctradewordid; // 贸易术语
    private String ctrancustid; // 承运商
    private String ctrantypeid; // 出入库类型
    private String cwhsmanagerid; // 库管员
    private String dbilldate; // 单据日期
    private String dmakedate; // 制单日期
    private Integer fbillflag; // 单据状态
    private Integer fbuysellflag; // 购销类型
    private Boolean freplenishflag; // 销售退货
    private Integer iprintcount; // 打印次数
    private String modifiedtime; // 最后修改时间
    private String modifier; // 最后修改人
    private Double ntotalnum; // 总数量
    private Double ntotalpiece; // 总件数
    private Double ntotalvolume; // 总体积
    private Double ntotalweight; // 总重量
    private String pkGroup; // 集团
    private String pkMeasware; // 计量器具
    private String pkOrgV; // 库存组织
    private String taudittime; // 签字日期
    private String trafficorgoid; // 物流组织最新版本
    private String trafficorgvid; // 物流组织
    private String vbillcode; // 单据号
    private String vdef1; // 表头自定义项1
    private String vdef10; // 表头自定义项10
    private String vdef11; // 表头自定义项11
    private String vdef12; // 表头自定义项12
    private String vdef13; // 表头自定义项13
    private String vdef14; // 表头自定义项14
    private String vdef15; // 表头自定义项15
    private String vdef16; // 表头自定义项16
    private String vdef17; // 表头自定义项17
    private String vdef18; // 表头自定义项18
    private String vdef19; // 表头自定义项19
    private String vdef2; // 表头自定义项2
    private String vdef20; // 表头自定义项20
    private String vdef3; // 表头自定义项3
    private String vdef4; // 表头自定义项4
    private String vdef5; // 表头自定义项5
    private String vdef6; // 表头自定义项6
    private String vdef7; // 表头自定义项7
    private String vdef8; // 表头自定义项8
    private String vdef9; // 表头自定义项9
    private String vdiliveraddress; // 运输地址
    private String vnote; // 备注
    private String vtrantypecode; // 出入库类型编码
}
src/main/resources/application.yml
@@ -10,26 +10,28 @@
    enabled: false
  datasource:
    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
#    url: jdbc:sqlserver://192.168.4.191:1433;databasename=integrationasrs
#    username: sa
#    password: sa@123
    url: jdbc:sqlserver://192.168.4.191:50948;databasename=source
    jdbc-url: jdbc:sqlserver://127.0.0.1:1433;databasename=ytflasrs
    username: sa
    password: sa@123
#    url: jdbc:sqlserver://127.0.0.1:51433;databasename=source
#    username: sa
#    password: Zoneyung@zy56$
  mvc:
    static-path-pattern: /**
  redis:
    host: localhost
    port: 6379
    database: 0
#    password: xltys1995
  #    password: xltys1995
  servlet:
    multipart:
      maxFileSize: 100MB
      maxRequestSize: 100MB
other:
  datasource:
    jdbc-url: jdbc:mysql://192.168.5.61:3306/datareports
    username: liku
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
  mapper-locations: classpath:mapper/*.xml
@@ -74,8 +76,64 @@
  # 自动移库功能开关 穿梭
  autoLocMoveUnilateralBoolean: false
comb:
  limit: 5000
# 用友NC对接
NYNC:
  ip:
  prot:
  #1.销售出库单参照发货单新增
  saveRefDelivery: http://${ip}:${port}/nccloud/api/ic/saleout/saveRefDelivery
  #2.其他入库单参照转库新增
  saveRefWhsTrans: http://ip:port/nccloud/api/ic/generalin/saveRefWhsTrans
  #3.新增采购入库单
  purchasein: http://ip:port/nccloud/api/ic/purchasein/save
  #4.1新增转库单
  whstrans: http://ip:port/nccloud/api/ic/whstrans/save
  #4.2其他出库单新增
  generalout: http://ip:port/nccloud/api/ic/generalout/save
  #4.3.其他入库单参照转库新增
  #saveRefWhsTrans: http://ip:port/nccloud/api/ic/generalin/saveRefWhsTrans
  #5.1新增转库单
  #whstrans: http://ip:port/nccloud/api/ic/whstrans/save
  #5.2其他出库单新增
  #generalout: http://ip:port/nccloud/api/ic/generalout/save
  #5.3.其他入库单参照转库新增
  #saveRefWhsTrans: http://ip:port/nccloud/api/ic/generalin/saveRefWhsTrans
  #6.调拨订单查询
  #saveRefWhsTrans: http://ip:port/nccloud/api/ic/generalin/saveRefWhsTrans
  #7.盘点单查询
  invcount: http://ip:port/nccloud/api/ic/invcount/query
#erp对接
erp:
@@ -103,7 +161,7 @@
    #结果上报(审核)单地址
    outaddressAudit: K3CLOUD/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Audit.common.kdsvc
  #  登录账号管理
  login :
  login:
    acctID: "647e849ab6fa0f"
    username: "llw"
    password: "666666"
src/main/resources/config.properties
New file
@@ -0,0 +1,59 @@
#####不变参数
client_id=WMS
client_secret=b5ee040e00584e518c06
pubKey=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhxRFEtPfreu+ROWtC5IQZVy1Vkkqi0Fk7A4tGvyfLIw2qPNLWrTmCJeJwXLmgiB+EU0RW9U8jFYRAhSKaQY1HTjHMZcXdfH6m7WitT+sIyDVfTO3wVWtvjFBF1o6qi+T7pNsmCjstArnm/OS55kn0zJcRiTTwP1UU1LrkQbytf9ZHOcbKfqjIL8amsinjdxd6ioUM3JT3PpOXCIRDHsQgvAnFx2q7Y902S0PFzc40FwtuwsuKqesvEbIImUcq1wbIDtMegixy+TfJMWcByNLp2iv8/+Zos+hePhfWRPlD2x0vk30xDXMiUVgq0dhxC5C3yeD2QEbLxIlDqK2WebzZQIDAQAB
secret_level=L0
#autotest=ture
#client_id=intelliv
#client_secret=14af9d2c86ea4232a090
#pubKey=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCAvcAJGq8gUmfWXlkq7RnZu0LpPMn6p8/vtGEmrvWorymVmhP7IpxaWxr5/gUQcoZn0U1UXIGomFOIjIHq8pwg0O2AUNpFQYSyjjmzBu+Yzd7Kcn+0pucmu7PLX1zkPrMKSLcZ8gEtxa4YBA4x8L5af7uq+vIPXBgT2RZyWK0ceQIDAQAB
#secret_level=L0
#client_id=ublinker
#client_secret=4a7499ac19b744958e30
#pubKey=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCS5avjb7GbHWNXB5XPC4gJRJHmvwyPMCvyKV6EJ7mq6kjiJBIf+t5Q8guRD41rswF7Nt+hWKs0rnWCc9ypqcTJwtbtHTkjOlD/I7C1KszyEbPT8mBRr0nQd203rfWZ+oKkPl1ENpmlDiNgStRjHZWvZM1ZzPd3yDhHZaUma0iCHwIDAQAB
#secret_level=L0
## 服务器地址
#baseUrl=http://10.16.7.160:9088
#baseUrl=http://10.10.4.166:9080
baseUrl=http://192.168.5.200:1105
#baseUrl=http://192.168.61.18:21322
#baseUrl=https://ncc.yyncc.com
## 账套code
### ncc用户密码
#busi_center=t8l33936
#username=zhangmeng10
#pwd=123456a
#username=3
#pwd=123456a!
#busi_center=1001
username=wmsliku
pwd=liku@135
busi_center=F
#username=01
#pwd=123456a!
#busi_center=gh
#usercode=34
#busi_id=111
#repeat_check=y
## 获取token方式
#grant_type=client_credentials
grant_type=password
## 请求参数
requestBody={"head":{"pk_org":"Duxiaoman (Cayman) Limited","pk_currtype":"USD","bill_type":"F5","trade_type":"D5","source_flag":"17","bill_date":"2020-08-07 00:00:00","primal_money":"12400.00","memo":"P2P付款申请|礼品||测试 线下支付回传、境外银行swift、外币汇率","def1":"ZPO810002020000319Y2","def2":"http://uatcaigou.duxiaoman-int.com/p2p/pages/plainPages.html#/payment_apply?tenantId=2&pageType=preview&paymentHeaderId=782&token=77f0842d6e9e5fadd1b165220ae27fd3","def3":"2008100100005","def30":"duxiaoman"},"body":[{"pk_org":"Duxiaoman (Cayman) Limited","pk_currtype":"USD","pk_balatype":"0","memo":"P2P付款申请|礼品||测试 线下支付回传、境外银行swift、外币汇率","bill_type":"F5","trade_type":"D5","direction":"-1","pk_supplier":"1001AA10000000000L68","objecttype":"4","pk_oppaccount":"pk_oppaccount","accountcode":"110907597010206","accountopenbank":"MEGA INTERNATIONAL COMMERCIAL BANK CO., LTD., HONG KONG BRANCH","accountname":"北京京东世纪信息技术有限公司","bill_date":"2020-08-07 00:00:00","creationtime":"2020-08-10 11:27:39","pay_primal":"12400.00","def1":"","swift":"911910000001","paymemo":"P2P付款申请|礼品||测试 线下支付回传、境外银行swift、外币汇率","remark":"测试 线下支付回传、境外银行swift、外币汇率","accounttype":"0"}]}
#requestBody={}
## api访问路径
apiUrl=/nccloud/api/imag/invoice/ocr/syncrecord
#apiUrl=/nccloud/api/uapbd/ublinker/dealreq
#apiUrl=/nccloud/api/arap/gatheringbill/insert
#apiUrl=/nccloud/api/riasm/ctmsmanager/ctms/ctmstransfer
src/main/resources/lib/caffeine-2.8.8.jar
Binary files differ
src/main/resources/mapper2/test