diff --git a/pom.xml b/pom.xml
index b4ae482..e25b444 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,100 +1,118 @@
- 4.0.0
-
- org.springframework.boot
- spring-boot-starter-parent
- 2.7.15
-
-
- com.win
- qad
- 1.0.0
- mq
- win mq
-
- 17
-
-
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.7.15
+
+
+ com.win
+ bank
+ 1.0.0
+ bank
+ win bank
+
+ 17
+
+
+
+ org.bouncycastle
+ bcprov-jdk15on
+ 1.61
+
+
+ com.google.code.gson
+ gson
+ 2.8.6
+
+
+ dom4j
+ dom4j
+ 1.1
+
+
+ com.jcraft
+ jsch
+ 0.1.55
+
-
- com.jcraft
- jsch
- 0.1.55
-
+
+ org.apache.commons
+ commons-lang3
+ 3.14.0
+
-
- org.apache.commons
- commons-lang3
- 3.9
-
+
+ mysql
+ mysql-connector-java
+ 8.0.33
+
-
- org.apache.commons
- commons-exec
- 1.3
-
+
+ com.alibaba
+ fastjson
+ 1.2.83
+
-
- com.alibaba
- fastjson
- 1.2.83
-
+
+ org.projectlombok
+ lombok
+ 1.18.28
+
-
- org.projectlombok
- lombok
- 1.18.28
-
+
+ com.alibaba
+ druid-spring-boot-starter
+ 1.2.19
+
-
- com.alibaba
- druid-spring-boot-starter
- 1.2.19
-
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ 3.5.3.2
+
-
- com.baomidou
- mybatis-plus-boot-starter
- 3.5.3.2
-
+
+ org.springframework.boot
+ spring-boot-starter
+
-
- org.springframework.boot
- spring-boot-starter
-
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
-
- org.springframework.boot
- spring-boot-starter-web
-
-
-
-
-
- ${project.artifactId}
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
- repackage
-
-
-
-
-
-
+
+
+ ${project.artifactId}
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ repackage
+
+
+
+
+
+
diff --git a/src/main/java/com/win/bank/Application.java b/src/main/java/com/win/bank/Application.java
index 3d5dce2..1a00085 100644
--- a/src/main/java/com/win/bank/Application.java
+++ b/src/main/java/com/win/bank/Application.java
@@ -1,18 +1,27 @@
package com.win.bank;
+import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
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
*/
-@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 static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- System.out.println("闻音启动成功");
- }
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ System.out.println("闻音启动成功");
+ }
}
diff --git a/src/main/java/com/win/bank/config/MyBatisConfig.java b/src/main/java/com/win/bank/config/MyBatisConfig.java
new file mode 100644
index 0000000..ab76912
--- /dev/null
+++ b/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);
+ }
+}
diff --git a/src/main/java/com/win/bank/dal/dataobject/BaseDO.java b/src/main/java/com/win/bank/dal/dataobject/BaseDO.java
new file mode 100644
index 0000000..cb2c7bb
--- /dev/null
+++ b/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 {}
diff --git a/src/main/java/com/win/bank/dal/dataobject/bank/BankDO.java b/src/main/java/com/win/bank/dal/dataobject/bank/BankDO.java
new file mode 100644
index 0000000..b3b2227
--- /dev/null
+++ b/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;
+}
diff --git a/src/main/java/com/win/bank/dal/mysql/bank/BankMapper.java b/src/main/java/com/win/bank/dal/mysql/bank/BankMapper.java
new file mode 100644
index 0000000..99cccaa
--- /dev/null
+++ b/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 {}
diff --git a/src/main/java/com/win/bank/service/MainService.java b/src/main/java/com/win/bank/service/MainService.java
new file mode 100644
index 0000000..81a701d
--- /dev/null
+++ b/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 bankDOList = bankService.listByStatus("0");
+
+ for (BankDO bankDO : bankDOList) {
+ System.out.println(bankDO);
+ }
+ }
+}
diff --git a/src/main/java/com/win/bank/service/bank/BankService.java b/src/main/java/com/win/bank/service/bank/BankService.java
new file mode 100644
index 0000000..803ff9e
--- /dev/null
+++ b/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 {
+ List listByStatus(String status);
+}
diff --git a/src/main/java/com/win/bank/service/bank/BankServiceImpl.java b/src/main/java/com/win/bank/service/bank/BankServiceImpl.java
new file mode 100644
index 0000000..aa1c83f
--- /dev/null
+++ b/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 implements BankService {
+
+ @Override
+ public List listByStatus(String status) {
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("status", status);
+ return list(queryWrapper);
+ }
+}
diff --git a/src/main/java/com/win/bank/service/cmb/ApiDemo.java b/src/main/java/com/win/bank/service/cmb/ApiDemo.java
new file mode 100644
index 0000000..508525f
--- /dev/null
+++ b/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) {
+
+ }
+}
diff --git a/src/main/java/com/win/bank/service/cmb/CmbServiceImpl.java b/src/main/java/com/win/bank/service/cmb/CmbServiceImpl.java
new file mode 100644
index 0000000..c80222e
--- /dev/null
+++ b/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;
+ }
+}
diff --git a/src/main/java/com/win/bank/service/cmb/DcHelper.java b/src/main/java/com/win/bank/service/cmb/DcHelper.java
new file mode 100644
index 0000000..a0698ed
--- /dev/null
+++ b/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 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 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 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 params) {
+ ArrayList 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 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();
+ }
+ }
+}
diff --git a/src/main/java/com/win/bank/service/cmb/DeviceInfo.java b/src/main/java/com/win/bank/service/cmb/DeviceInfo.java
new file mode 100644
index 0000000..fc25a66
--- /dev/null
+++ b/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;
+ }
+}
diff --git a/src/main/java/com/win/bank/service/demo/Student.java b/src/main/java/com/win/bank/service/demo/Student.java
new file mode 100644
index 0000000..d7650ca
--- /dev/null
+++ b/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;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/win/bank/service/demo/Test.java b/src/main/java/com/win/bank/service/demo/Test.java
new file mode 100644
index 0000000..3be63fc
--- /dev/null
+++ b/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;
+ }
+
+}
diff --git a/src/main/java/com/win/bank/service/demo/XStreamUtil.java b/src/main/java/com/win/bank/service/demo/XStreamUtil.java
new file mode 100644
index 0000000..a81fd87
--- /dev/null
+++ b/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();
+ }
+
+}
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index c2fbfa8..f336f5b 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -17,13 +17,10 @@ server:
min-spare: 10
spring:
- autoconfigure:
- exclude:
- - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
datasource:
type: com.alibaba.druid.pool.DruidDataSource
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
password: Microdoft@2021
@@ -34,25 +31,3 @@ logging:
level:
com.win: debug
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
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 6c3ef23..80b7eda 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -25,9 +25,17 @@ mybatis-plus:
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
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:
password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成
mybatis-plus-join:
banner: false # 关闭控制台的 Banner 打印
+
+win:
+ info:
+ base-package: com.win
+ codegen:
+ base-package: ${win.info.base-package}
\ No newline at end of file
diff --git a/src/main/resources/mapper/bank/BankMapper.xml b/src/main/resources/mapper/bank/BankMapper.xml
new file mode 100644
index 0000000..11861aa
--- /dev/null
+++ b/src/main/resources/mapper/bank/BankMapper.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
\ No newline at end of file