Browse Source

调试

master
zhaoyiran 5 months ago
parent
commit
bb26c2aec8
  1. 188
      pom.xml
  2. 21
      src/main/java/com/win/bank/Application.java
  3. 28
      src/main/java/com/win/bank/config/MyBatisConfig.java
  4. 5
      src/main/java/com/win/bank/dal/dataobject/BaseDO.java
  5. 77
      src/main/java/com/win/bank/dal/dataobject/bank/BankDO.java
  6. 9
      src/main/java/com/win/bank/dal/mysql/bank/BankMapper.java
  7. 29
      src/main/java/com/win/bank/service/MainService.java
  8. 10
      src/main/java/com/win/bank/service/bank/BankService.java
  9. 21
      src/main/java/com/win/bank/service/bank/BankServiceImpl.java
  10. 73
      src/main/java/com/win/bank/service/cmb/ApiDemo.java
  11. 31
      src/main/java/com/win/bank/service/cmb/CmbServiceImpl.java
  12. 369
      src/main/java/com/win/bank/service/cmb/DcHelper.java
  13. 39
      src/main/java/com/win/bank/service/cmb/DeviceInfo.java
  14. 56
      src/main/java/com/win/bank/service/demo/Student.java
  15. 48
      src/main/java/com/win/bank/service/demo/Test.java
  16. 20
      src/main/java/com/win/bank/service/demo/XStreamUtil.java
  17. 27
      src/main/resources/application-dev.yml
  18. 10
      src/main/resources/application.yml
  19. 12
      src/main/resources/mapper/bank/BankMapper.xml

188
pom.xml

@ -1,100 +1,118 @@
<?xml version="1.0" encoding="UTF-8"?> <?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" <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.15</version> <version>2.7.15</version>
<relativePath/> <!-- lookup parent from repository --> <relativePath/> <!-- lookup parent from repository -->
</parent> </parent>
<groupId>com.win</groupId> <groupId>com.win</groupId>
<artifactId>qad</artifactId> <artifactId>bank</artifactId>
<version>1.0.0</version> <version>1.0.0</version>
<name>mq</name> <name>bank</name>
<description>win mq</description> <description>win bank</description>
<properties> <properties>
<java.version>17</java.version> <java.version>17</java.version>
</properties> </properties>
<dependencies> <dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.61</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
<dependency> <dependency>
<groupId>com.jcraft</groupId> <groupId>org.apache.commons</groupId>
<artifactId>jsch</artifactId> <artifactId>commons-lang3</artifactId>
<version>0.1.55</version> <version>3.14.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>mysql</groupId>
<artifactId>commons-lang3</artifactId> <artifactId>mysql-connector-java</artifactId>
<version>3.9</version> <version>8.0.33</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>com.alibaba</groupId>
<artifactId>commons-exec</artifactId> <artifactId>fastjson</artifactId>
<version>1.3</version> <version>1.2.83</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>org.projectlombok</groupId>
<artifactId>fastjson</artifactId> <artifactId>lombok</artifactId>
<version>1.2.83</version> <version>1.18.28</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>com.alibaba</groupId>
<artifactId>lombok</artifactId> <artifactId>druid-spring-boot-starter</artifactId>
<version>1.18.28</version> <version>1.2.19</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.baomidou</groupId>
<artifactId>druid-spring-boot-starter</artifactId> <artifactId>mybatis-plus-boot-starter</artifactId>
<version>1.2.19</version> <version>3.5.3.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.baomidou</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId> <artifactId>spring-boot-starter</artifactId>
<version>3.5.3.2</version> </dependency>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId> <artifactId>spring-boot-starter-test</artifactId>
</dependency> <scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-web</artifactId>
<scope>test</scope> </dependency>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
</dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies> <build>
<!-- 设置构建的 jar 包名 -->
<build> <finalName>${project.artifactId}</finalName>
<!-- 设置构建的 jar 包名 --> <plugins>
<finalName>${project.artifactId}</finalName> <!-- 打包 -->
<plugins> <plugin>
<!-- 打包 --> <groupId>org.springframework.boot</groupId>
<plugin> <artifactId>spring-boot-maven-plugin</artifactId>
<groupId>org.springframework.boot</groupId> <executions>
<artifactId>spring-boot-maven-plugin</artifactId> <execution>
<executions> <goals>
<execution> <goal>repackage</goal> <!-- 将引入的 jar 打入其中 -->
<goals> </goals>
<goal>repackage</goal> <!-- 将引入的 jar 打入其中 --> </execution>
</goals> </executions>
</execution> </plugin>
</executions> </plugins>
</plugin> </build>
</plugins>
</build>
</project> </project>

21
src/main/java/com/win/bank/Application.java

@ -1,18 +1,27 @@
package com.win.bank; package com.win.bank;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
/** /**
* 启动程序 * 启动程序
* *
* @author win * @author win
*/ */
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) // @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@SuppressWarnings("SpringComponentScan") // 忽略 IDEA 无法识别 ${win.info.base-package}
// @SpringBootApplication(scanBasePackages = {"${win.info.base-package}.server", "${win.info.base-package}.module"},
// exclude = {DataSourceAutoConfiguration.class, DruidDataSourceAutoConfigure.class})
@SpringBootApplication(scanBasePackages = {"${win.info.base-package}.server", "${win.info.base-package}.module"})
@EnableScheduling
@ComponentScan("com.win")
@MapperScan("com.win.bank.dal.mysql")
public class Application { public class Application {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(Application.class, args); SpringApplication.run(Application.class, args);
System.out.println("闻音启动成功"); System.out.println("闻音启动成功");
} }
} }

28
src/main/java/com/win/bank/config/MyBatisConfig.java

@ -0,0 +1,28 @@
package com.win.bank.config;
import javax.sql.DataSource;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan(value = "com.win.bank", annotationClass = Mapper.class) // Mapper 懒加载,目前仅用于单元测试
public class MyBatisConfig {
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean.getObject();
}
@Bean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}

5
src/main/java/com/win/bank/dal/dataobject/BaseDO.java

@ -0,0 +1,5 @@
package com.win.bank.dal.dataobject;
import java.io.Serializable;
public abstract class BaseDO implements Serializable {}

77
src/main/java/com/win/bank/dal/dataobject/bank/BankDO.java

@ -0,0 +1,77 @@
package com.win.bank.dal.dataobject.bank;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.win.bank.dal.dataobject.BaseDO;
import lombok.*;
/**
* 银企直联 DO
*
* @author 超级管理员
*/
@TableName("basic_bank")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BankDO extends BaseDO {
/**
* id
*/
@TableId
private Long id;
/**
* 状态0:未处理;1:支付中;2:支付成功;3:支付失败
*/
private String status;
/**
* 付款银行编码CMB:招商银行;ICBC:工商银行;BC:中国银行
*/
private String payBankCode;
/**
* 付款账号
*/
private String payAccount;
/**
* 收款账号
*/
private String rcvAccount;
/**
* 收款户名
*/
private String rcvUserName;
/**
* 收款方开户行名称
*/
private String rcvBankName;
/**
* 收款方开户行地址
*/
private String rcvBankAddress;
/**
* 收款方联行号
*/
private String rcvBankNumber;
/**
* 交易金额
*/
private BigDecimal amount;
/**
* 用途
*/
private String purpose;
/**
* 提示信息
*/
private String message;
/**
* 流水号
*/
private String serialNumber;
}

9
src/main/java/com/win/bank/dal/mysql/bank/BankMapper.java

@ -0,0 +1,9 @@
package com.win.bank.dal.mysql.bank;
import org.apache.ibatis.annotations.Mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.win.bank.dal.dataobject.bank.BankDO;
@Mapper
public interface BankMapper extends BaseMapper<BankDO> {}

29
src/main/java/com/win/bank/service/MainService.java

@ -0,0 +1,29 @@
package com.win.bank.service;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.win.bank.dal.dataobject.bank.BankDO;
import com.win.bank.service.bank.BankService;
@Component
public class MainService {
@Resource
private BankService bankService;
@Scheduled(cron = "* * * * * ?")
public void task() {
System.out.println(System.currentTimeMillis());
List<BankDO> bankDOList = bankService.listByStatus("0");
for (BankDO bankDO : bankDOList) {
System.out.println(bankDO);
}
}
}

10
src/main/java/com/win/bank/service/bank/BankService.java

@ -0,0 +1,10 @@
package com.win.bank.service.bank;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.IService;
import com.win.bank.dal.dataobject.bank.BankDO;
public interface BankService extends IService<BankDO> {
List<BankDO> listByStatus(String status);
}

21
src/main/java/com/win/bank/service/bank/BankServiceImpl.java

@ -0,0 +1,21 @@
package com.win.bank.service.bank;
import java.util.List;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.win.bank.dal.dataobject.bank.BankDO;
import com.win.bank.dal.mysql.bank.BankMapper;
@Service
public class BankServiceImpl extends ServiceImpl<BankMapper, BankDO> implements BankService {
@Override
public List<BankDO> listByStatus(String status) {
QueryWrapper<BankDO> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("status", status);
return list(queryWrapper);
}
}

73
src/main/java/com/win/bank/service/cmb/ApiDemo.java

@ -0,0 +1,73 @@
package com.win.bank.service.cmb;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.Security;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
/**
* 招商银行银企直联国密免前置/SaaS对接示例本示例仅供参考不保证各种异常场景运行请勿直接使用如有错漏请联系对接人员运行时请使用所获取的测试资源替换 用户编号公私钥对称密钥服务商编号等信息
*
* @author cmb.firmbank
* @date 2023/7/20
*/
public class ApiDemo {
private static final int BOUND_START = 1000000;
private static final int BOUND_END = 9000000;
// 测试地址,生产需要替换
private static String url = "http://192.168.0.142:8080/cdcserver/api/v2";
// private static String url = "http://cdctest.cmburl.cn:80/cdcserver/api/v2";
// 生产地址
// private static String url = "https://cdc.cmbchina.com/cdcserver/api/v2";
// 银行公钥,生产需要替换
private static String publicKey = "BNsIe9U0x8IeSe4h/dxUzVEz9pie0hDSfMRINRXc7s1UIXfkExnYECF4QqJ2SnHxLv3z/99gsfDQrQ6dzN5lZj0=";
// 生产环境银行公钥
// private static String publicKey =
// "BEynMEZOjNpwZIiD9jXtZSGr3Ecpwn7r+m+wtafXHb6VIZTnugfuxhcKASq3hX+KX9JlHODDl9/RDKQv4XLOFak=";
// 客户私钥,生产需要替换
private static String privateKey = "NBtl7WnuUtA2v5FaebEkU0/Jj1IodLGT6lQqwkzmd2E=";
// 对称密钥,生产需要替换
private static String symKey = "VuAzSWQhsoNqzn0K";
// 企业网银用户号,生产需要替换
private static String uid = "N002986522";
private static Random random = new Random();
private ApiDemo() {}
public static void main(String[] args) throws GeneralSecurityException, IOException, CryptoException {
// 装载BC库,必须在应用的启动类中调用此函数
Security.addProvider(new BouncyCastleProvider());
System.setProperty("sun.net.http.retryPost", "false");
// 业务接口名,这里是查询业务模式接口,生产请替换为对应接口名
String funcode = "BB1PAYQR";
// 准备接口数据,生产请替换为具体接口请求报文,包含所需的请求字段
String currentDatetime = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
String reqid = new SimpleDateFormat("yyyyMMddHHmmssSSSS").format(new Date()) + (BOUND_START + random.nextInt(BOUND_END));
String data =
"{\"request\":{\"body\":{\"bb1paybmx1\":[{\"busCod\":\"N02030\",\"busMod\":\"00002\"}],\"bb1payopx1\":[{\"ccyNbr\":\"10\",\"crtAcc\":\"6214831150131511\",\"crtNam\":\"吴极客\",\"dbtAcc\":\"755936045010501\",\"nusAge\":\"用途\",\"bnkFlg\":\"Y\",\"trsAmt\":\"1.05\",\"yurRef\":\"2024041709400601\"}]},\"head\":{\"funcode\":\"BB1PAYOP\",\"userid\":\"N002986522\"}}}";
// String data =
// "{\"request\":{\"body\":{\"bb1payqrx1\":[{\"busCod\":\"N02030\",\"yurRef\":\"2024041709400602\"}]},\"head\":{\"funcode\":\"BB1PAYQR\",\"userid\":\"N002986522\"}}}";
System.out.println(data);
DcHelper dchelper = new DcHelper(url, uid, privateKey, publicKey, symKey);
// 添加设备信息,请根据文档指引填写真实的信息,参数按顺序分别为:出口IP(无需)、MAC地址、CPU-ID、计算机名、主板ID、主板厂商
// DeviceInfo deviceInfo = new DeviceInfo(null, "9822EFF12C6B", "AABBCCDDEEFFGGHH", "XXX", "XXX", "XXX");
// String response = dchelper.sendRequest(data, funcode);
// process("Api请求1成功,响应报文:\r\n" + response);
// String response2 = dchelper.sendRequest(data, funcode, deviceInfo);
// process("Api请求2成功,响应报文:\r\n" + response2);
}
private static void process(String response) {
}
}

31
src/main/java/com/win/bank/service/cmb/CmbServiceImpl.java

@ -0,0 +1,31 @@
package com.win.bank.service.cmb;
import org.springframework.stereotype.Service;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.win.bank.dal.dataobject.bank.BankDO;
@Service
public class CmbServiceImpl {
public String payment(BankDO bankDO) {
String data = "{\"request\":{\"body\":{\"bb1paybmx1\":[{\"busCod\":\"N02030\",\"busMod\":\"00002\"}]},\"head\":{\"funcode\":\"BB1PAYOP\",\"userid\":\"N002986522\"}}}";
JsonObject requestJson = new Gson().fromJson(data, JsonObject.class);
JsonArray bb1payopx1 = new JsonArray();
JsonObject info = new JsonObject();
info.addProperty("dbtAcc", bankDO.getPayAccount());
info.addProperty("crtAcc", bankDO.getRcvAccount());
info.addProperty("crtNam", bankDO.getRcvUserName());
info.addProperty("ccyNbr", "10");
info.addProperty("trsAmt", bankDO.getAmount().toString());
info.addProperty("nusAge", bankDO.getPurpose());
info.addProperty("bnkFlg", "Y");
info.addProperty("yurRef", bankDO.getId().toString());
bb1payopx1.add(info);
requestJson.getAsJsonObject("request").getAsJsonObject("body").add("bb1payopx1", bb1payopx1);
System.out.println(requestJson);
return null;
}
}

369
src/main/java/com/win/bank/service/cmb/DcHelper.java

@ -0,0 +1,369 @@
package com.win.bank.service.cmb;
import java.io.*;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.util.*;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.*;
import org.bouncycastle.asn1.*;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithID;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.math.ec.ECPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
/**
* 招商银行银企直联国密免前置/SaaS对接示例本示例仅供参考不保证各种异常场景运行请勿直接使用如有错漏请联系对接人员运行时请使用所获取的测试资源替换 用户编号公私钥对称密钥服务商编号等信息
*
* @author cmb.firmbank
* @date 2023/7/20
*/
public class DcHelper {
private static final int LENGTH_32 = 32;
private static final int USERID_LEN = 16;
private static final int CONNECT_TIMEOUT = 15000;
private static final int READ_TIMEOUT = 60000;
private static final int STATUS_OK = 200;
private static Base64.Encoder encoder = Base64.getEncoder();
private static Base64.Decoder decoder = Base64.getDecoder();
// 请求URL
private final String url;
// 企业网银用户号
private final String uid;
// 国密算法向量,根据用户号生成
private final byte[] userId;
// 算法,固定为国密算法
private final String alg;
// 客户私钥
private final byte[] privateKey;
// 银行公钥
private final byte[] publicKey;
// 协商的对称密钥
private final byte[] symKey;
private static final Logger logger = LoggerFactory.getLogger(DcHelper.class);
public DcHelper(String url, String uid, String privateKey, String publicKey, String symKey) {
this.url = url;
this.uid = uid;
this.userId = getUserId(uid);
this.alg = "SM";
this.privateKey = decoder.decode(privateKey);
this.publicKey = decoder.decode(publicKey);
this.symKey = symKey.getBytes(StandardCharsets.UTF_8);
}
public String sendRequest(String data, String funcode) throws IOException, CryptoException, GeneralSecurityException {
// 增加设备信息
JsonObject requestJson = new Gson().fromJson(data, JsonObject.class);
// requestJson.getAsJsonObject("request").add("exthdr", deviceInfo.toJson());
// 对请求报文做排序
String source = recursiveKeySort(requestJson);
// 生成签名
// byte[] signature = cmbSM2SignWithSM3(userId, privateKey, source.getBytes(StandardCharsets.UTF_8));
// 替换签名字段
// requestJson.getAsJsonObject("signature").addProperty("sigdat", new String(encoder.encode(signature),
// StandardCharsets.UTF_8));
// 对数据进行对称加密
// String request = requestJson.toString();
// byte[] encryptRequest = cmbSM4Crypt(symKey, userId, request.getBytes(StandardCharsets.UTF_8), 1);
// String encryptedRequest = new String(encoder.encode(encryptRequest), StandardCharsets.UTF_8);
logger.debug(data);
// 发送请求
HashMap<String, String> map = new HashMap<>();
map.put("UID", uid);
map.put("ALG", alg);
map.put("DATA", URLEncoder.encode(data, StandardCharsets.UTF_8.displayName()));
// map.put("DATA", URLEncoder.encode(encryptedRequest, StandardCharsets.UTF_8.displayName()));
map.put("FUNCODE", funcode);
String response = httpPost(url, map);
// logger.debug(response);
printJson(data);
if (response.startsWith("CDCServer:")) {
throw new IOException("访问目标地址 " + url + " 失败:" + response);
}
// 返回结果解密
// response = new String((cmbSM4Crypt(symKey, userId, decoder.decode(response), 2)), StandardCharsets.UTF_8);
// 验证签名是否正确
// JsonObject responseJson = new Gson().fromJson(response, JsonObject.class);
// JsonObject signatureJson = responseJson.getAsJsonObject("signature");
// String responseSignature = signatureJson.get("sigdat").getAsString();
// signatureJson.addProperty("sigdat", "__signature_sigdat__");
// responseJson.add("signature", signatureJson);
// String responseSorted = recursiveKeySort(responseJson);
// boolean verify = cmbSM2VerifyWithSM3(userId, publicKey, responseSorted.getBytes(StandardCharsets.UTF_8),
// decoder.decode(responseSignature));
// if (!verify) {
// throw new IOException("响应报文的签名无效");
// }
printJson(response);
return response;
}
private static String recursiveKeySort(JsonObject json) {
StringBuilder appender = new StringBuilder();
appender.append("{");
Iterator<String> keys = new TreeSet<>(json.keySet()).iterator();
boolean isFirstEle = true;
while (keys.hasNext()) {
if (!isFirstEle) {
appender.append(",");
}
String key = keys.next();
Object val = json.get(key);
if (val instanceof JsonObject) {
appender.append("\"").append(key).append("\":");
appender.append(recursiveKeySort((JsonObject)val));
} else if (val instanceof JsonArray) {
JsonArray jarray = (JsonArray)val;
appender.append("\"").append(key).append("\":[");
boolean isFirstArrEle = true;
for (int i = 0; i < jarray.size(); i++) {
if (!isFirstArrEle) {
appender.append(",");
}
Object obj = jarray.get(i);
if (obj instanceof JsonObject) {
appender.append(recursiveKeySort((JsonObject)obj));
} else {
appender.append(obj.toString());
}
isFirstArrEle = false;
}
appender.append("]");
} else {
String value = val.toString();
appender.append("\"").append(key).append("\":").append(value);
}
isFirstEle = false;
}
appender.append("}");
return appender.toString();
}
private static byte[] getUserId(String uid) {
return (uid + "0000000000000000").substring(0, USERID_LEN).getBytes();
}
private static String httpPost(String httpUrl, Map<String, String> param) throws IOException, GeneralSecurityException {
HttpURLConnection connection = null;
String result;
try {
URL url = new URL(httpUrl);
SSLContext sslcontext;
sslcontext = SSLContext.getInstance("SSL");
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init((KeyStore)null);
X509TrustManager defaultTm = null;
for (TrustManager tm : tmf.getTrustManagers()) {
if (tm instanceof X509TrustManager) {
defaultTm = (X509TrustManager)tm;
break;
}
}
sslcontext.init(null, new TrustManager[] {defaultTm}, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setConnectTimeout(CONNECT_TIMEOUT);
connection.setReadTimeout(READ_TIMEOUT);
connection.setInstanceFollowRedirects(true);
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
try (OutputStream os = connection.getOutputStream()) {
os.write(createLinkString(param).getBytes());
if (connection.getResponseCode() != STATUS_OK) {
InputStream is = connection.getErrorStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
StringBuilder sbf = new StringBuilder();
String temp;
while ((temp = br.readLine()) != null) {
sbf.append(temp);
sbf.append("\r\n");
}
result = sbf.toString();
br.close();
is.close();
} else {
InputStream is = connection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
StringBuilder sbf = new StringBuilder();
String temp;
while ((temp = br.readLine()) != null) {
sbf.append(temp);
}
result = sbf.toString();
br.close();
is.close();
}
}
} finally {
if (connection != null) {
connection.disconnect();
}
}
return result;
}
private static String createLinkString(Map<String, String> params) {
ArrayList<String> keys = new ArrayList<>(params.keySet());
Collections.sort(keys);
StringBuilder prestr = new StringBuilder();
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
String value = params.get(key);
if (i == keys.size() - 1) {
prestr.append(key).append("=").append(value);
} else {
prestr.append(key).append("=").append(value).append("&");
}
}
return prestr.toString();
}
// 以下是加解密相关的函数
private static byte[] cmbSM2SignWithSM3(byte[] id, byte[] privkey, byte[] msg) throws IOException, CryptoException {
if (privkey == null || msg == null) {
throw new CryptoException("CMBSM2SignWithSM3 input error");
}
ECPrivateKeyParameters privateKey = encodePrivateKey(privkey);
SM2Signer signer = new SM2Signer();
ParametersWithID parameters = new ParametersWithID(privateKey, id);
signer.init(true, parameters);
signer.update(msg, 0, msg.length);
return decodeDERSignature(signer.generateSignature());
}
private static ECPrivateKeyParameters encodePrivateKey(byte[] value) {
BigInteger d = new BigInteger(1, value);
ECParameterSpec spec = ECNamedCurveTable.getParameterSpec("sm2p256v1");
ECDomainParameters ecParameters = new ECDomainParameters(spec.getCurve(), spec.getG(), spec.getN(), spec.getH(), spec.getSeed());
return new ECPrivateKeyParameters(d, ecParameters);
}
private static byte[] decodeDERSignature(byte[] signature) throws IOException {
ASN1InputStream stream = new ASN1InputStream(new ByteArrayInputStream(signature));
ASN1Sequence primitive = (ASN1Sequence)stream.readObject();
Enumeration<ASN1Integer> enumeration = primitive.getObjects();
BigInteger intR = enumeration.nextElement().getValue();
BigInteger intS = enumeration.nextElement().getValue();
byte[] bytes = new byte[LENGTH_32 * 2];
byte[] r = format(intR.toByteArray());
byte[] s = format(intS.toByteArray());
System.arraycopy(r, 0, bytes, 0, LENGTH_32);
System.arraycopy(s, 0, bytes, LENGTH_32, LENGTH_32);
return bytes;
}
private static byte[] format(byte[] value) {
if (value.length == LENGTH_32) {
return value;
} else {
byte[] bytes = new byte[LENGTH_32];
if (value.length > LENGTH_32) {
System.arraycopy(value, value.length - LENGTH_32, bytes, 0, LENGTH_32);
} else {
System.arraycopy(value, 0, bytes, LENGTH_32 - value.length, value.length);
}
return bytes;
}
}
private static byte[] cmbSM4Crypt(byte[] key, byte[] iv, byte[] input, int mode) throws GeneralSecurityException {
SecretKeySpec spec = new SecretKeySpec(key, "SM4");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS7Padding", BouncyCastleProvider.PROVIDER_NAME);
cipher.init(mode, spec, ivParameterSpec);
return cipher.doFinal(input);
}
private static boolean cmbSM2VerifyWithSM3(byte[] id, byte[] pubkey, byte[] msg, byte[] signature) throws IOException {
if (pubkey == null || msg == null || signature == null) {
throw new IllegalArgumentException("CMBSM2VerifyWithSM3 input error");
}
ECPublicKeyParameters publicKey = encodePublicKey(pubkey);
SM2Signer signer = new SM2Signer();
ParametersWithID parameters = new ParametersWithID(publicKey, id);
signer.init(false, parameters);
signer.update(msg, 0, msg.length);
return signer.verifySignature(encodeDERSignature(signature));
}
private static ECPublicKeyParameters encodePublicKey(byte[] value) {
byte[] x = new byte[LENGTH_32];
byte[] y = new byte[LENGTH_32];
System.arraycopy(value, 1, x, 0, LENGTH_32);
System.arraycopy(value, LENGTH_32 + 1, y, 0, LENGTH_32);
BigInteger intX = new BigInteger(1, x);
BigInteger intY = new BigInteger(1, y);
ECParameterSpec spec = ECNamedCurveTable.getParameterSpec("sm2p256v1");
ECPoint intQ = spec.getCurve().createPoint(intX, intY);
ECDomainParameters ecParameters = new ECDomainParameters(spec.getCurve(), spec.getG(), spec.getN(), spec.getH(), spec.getSeed());
return new ECPublicKeyParameters(intQ, ecParameters);
}
private static byte[] encodeDERSignature(byte[] signature) throws IOException {
byte[] r = new byte[LENGTH_32];
byte[] s = new byte[LENGTH_32];
System.arraycopy(signature, 0, r, 0, LENGTH_32);
System.arraycopy(signature, LENGTH_32, s, 0, LENGTH_32);
ASN1EncodableVector vector = new ASN1EncodableVector();
vector.add(new ASN1Integer(new BigInteger(1, r)));
vector.add(new ASN1Integer(new BigInteger(1, s)));
return (new DERSequence(vector)).getEncoded();
}
private void printJson(String jsonStr) {
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
try {
// 原始的JSON字符串
// String jsonStr = "{\"name\": \"Alice\", \"age\": 30, \"city\": \"Beijing\"}";
// 格式化打印JSON字符串
Object json = mapper.readValue(jsonStr, Object.class);
String formattedJsonStr = mapper.writeValueAsString(json);
// System.out.println(formattedJsonStr);
logger.debug(formattedJsonStr);
} catch (Exception e) {
e.printStackTrace();
}
}
}

39
src/main/java/com/win/bank/service/cmb/DeviceInfo.java

@ -0,0 +1,39 @@
package com.win.bank.service.cmb;
import com.google.gson.JsonObject;
/**
* 设备信息
*/
public class DeviceInfo {
private String ipVal;
private String macVal;
private String cpuInfo;
private String computerName;
private String mainBoardId;
private String mainBoardName;
public DeviceInfo(String ipVal, String macVal, String cpuInfo, String computerName, String mainBoardId, String mainBoardName) {
this.ipVal = ipVal;
this.macVal = macVal;
this.cpuInfo = cpuInfo;
this.computerName = computerName;
this.mainBoardId = mainBoardId;
this.mainBoardName = mainBoardName;
}
public JsonObject toJson() {
JsonObject deviceInfo = new JsonObject();
if (ipVal != null) {
deviceInfo.addProperty("ipType", ipVal.indexOf(':') != -1 ? "6" : "4");
deviceInfo.addProperty("ipVal", ipVal);
}
deviceInfo.addProperty("macVal", macVal);
deviceInfo.addProperty("cpuInfo", cpuInfo);
deviceInfo.addProperty("cmpName", computerName);
deviceInfo.addProperty("mbId", mainBoardId);
deviceInfo.addProperty("mbMf", mainBoardName);
return deviceInfo;
}
}

56
src/main/java/com/win/bank/service/demo/Student.java

@ -0,0 +1,56 @@
package com.win.bank.service.demo;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Student {
private String name; // 姓名
private String sex; // 性别
private int number; // 学号
private String className; // 班级
public Student(){}
public Student(String string, String string2, int i, String string3) {
this.name = string;
this.sex = string2;
this.className = string3;
}
@XmlElement(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlElement(name = "sex")
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@XmlElement(name = "number")
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
@XmlElement(name = "className")
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
}

48
src/main/java/com/win/bank/service/demo/Test.java

@ -0,0 +1,48 @@
package com.win.bank.service.demo;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
/**
* @author admin
*/
public class Test {
public static void main(String[] args) throws Exception {
Student st = new Student("张三", "男", 10001, "尖");
String xml = XStreamUtil.marshal(st, Student.class);
System.out.println(xml);
// System.out.println(formatXML(xml));
}
public static String formatXML(String inputXML) throws Exception {
SAXReader reader = new SAXReader();
Document document = reader.read(new StringReader(inputXML));
String requestXML = null;
XMLWriter writer = null;
if (document != null) {
try {
StringWriter stringWriter = new StringWriter();
OutputFormat format = new OutputFormat(" ", true);
writer = new XMLWriter(stringWriter, format);
writer.write(document);
writer.flush();
requestXML = stringWriter.getBuffer().toString();
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
}
}
}
}
return requestXML;
}
}

20
src/main/java/com/win/bank/service/demo/XStreamUtil.java

@ -0,0 +1,20 @@
package com.win.bank.service.demo;
import java.io.StringWriter;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
public class XStreamUtil {
public static String marshal(Object object, Class<?> clazz) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
StringWriter writer = new StringWriter();
marshaller.marshal(object, writer);
return writer.toString();
}
}

27
src/main/resources/application-dev.yml

@ -17,13 +17,10 @@ server:
min-spare: 10 min-spare: 10
spring: spring:
autoconfigure:
exclude:
- com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
datasource: datasource:
type: com.alibaba.druid.pool.DruidDataSource type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://dev.ccwin-in.com:23113/qad_dev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 url: jdbc:mysql://dev.ccwin-in.com:23113/sfms_hella?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: learun username: learun
password: Microdoft@2021 password: Microdoft@2021
@ -34,25 +31,3 @@ logging:
level: level:
com.win: debug com.win: debug
org.springframework: warn org.springframework: warn
shell:
jlht:
qad-domain: JLHT
company-code: CCWININ
server-id: master
ip: 222.169.228.163
port: 6122
linux-id: mfg
linux-password: mfgpro
qad-user: mfg
qad-password: Qadwin1
jlht2:
qad-domain: JLHT2
company-code: CCWININ
server-id: master
ip: 222.169.228.163
port: 6122
linux-id: mfg
linux-password: mfgpro
qad-user: mfg
qad-password: Qadwin1

10
src/main/resources/application.yml

@ -25,9 +25,17 @@ mybatis-plus:
logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
banner: false # 关闭控制台的 Banner 打印 banner: false # 关闭控制台的 Banner 打印
type-aliases-package: com.win.dao type-aliases-package: com.win.bank.dal.dataobject
mapper-locations: classpath:/mapper/bank/*.xml
# type-aliases-package: ${win.info.base-package}.module.*.dal.dataobject
encryptor: encryptor:
password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成
mybatis-plus-join: mybatis-plus-join:
banner: false # 关闭控制台的 Banner 打印 banner: false # 关闭控制台的 Banner 打印
win:
info:
base-package: com.win
codegen:
base-package: ${win.info.base-package}

12
src/main/resources/mapper/bank/BankMapper.xml

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.win.bank.dal.mysql.bank.BankMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
-->
</mapper>
Loading…
Cancel
Save