Commit 5dddac74 authored by 黎博's avatar 黎博

first commit

parents
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**
!**/src/test/**
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
### VS Code ###
.vscode/
### local log ###
*.log
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.qg</groupId>
<artifactId>holmes</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>holmes</name>
<description>QG QA project</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--common-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.0</version>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.2</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
<!--集成redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>cn.quantgroup</groupId>
<artifactId>spring-boot-starter-sentry</artifactId>
<version>1.0.9</version>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.1.35</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.12</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package cn.qg.holmes;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan(value = "cn.qg.holmes.mapper")
public class HolmesApplication {
public static void main(String[] args) {
SpringApplication.run(HolmesApplication.class, args);
}
}
package cn.qg.holmes.aspect;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.apache.commons.io.IOUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Map;
/**
* 日志切面
*/
@Aspect
@Component
public class HttpLogAspect {
private static final Logger logger = LoggerFactory.getLogger(HttpLogAspect.class);
@Pointcut("execution(public * cn.qg.holmes.controller..*.*(..))")
public void httpRequestLog() {}
/**
* 前置通知:在连接点之前执行的通知
*
* @param joinPoint
* @throws Throwable
*/
@Before("httpRequestLog()")
public void doBefore(JoinPoint joinPoint) throws JsonProcessingException {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
logger.info("请求发起ip地址: {}, 请求url: {}, 请求参数:{}", request.getRemoteAddr(), request.getRequestURI(), getQuery(request));
}
/**
* 后置通知:在连接点之后执行的通知
*
* @param ret
* @throws Throwable
*/
@AfterReturning(returning = "ret", pointcut = "httpRequestLog()")
public void doAfterReturning(Object ret) throws Throwable {
// 处理完请求,返回内容
logger.info("response:" + JSON.toJSONString(ret));
}
private String getQuery(HttpServletRequest request) {
if (isPostPutRequest(request)) {
return getParameters(request) + getRequestBody(request);
} else {
return getParameters(request);
}
}
private boolean isPostPutRequest(HttpServletRequest request) {
return "POST".equalsIgnoreCase(request.getMethod()) || "PUT".equalsIgnoreCase(request.getMethod());
}
private String getParameters(HttpServletRequest request) {
StringBuilder sb = new StringBuilder();
Map<String, String[]> params = request.getParameterMap();
for (String key : params.keySet()) {
sb.append('[')
.append(key)
.append('=')
.append(request.getParameter(key))
.append("] ");
}
return sb.toString();
}
private String getRequestBody(HttpServletRequest request) {
try {
return IOUtils.toString(request.getInputStream(), String.valueOf(Charset.defaultCharset()));
} catch (IOException e) {
return "";
}
}
}
package cn.qg.holmes.common;
import lombok.Data;
import java.io.Serializable;
@Data
public class JsonResult<T> implements Serializable {
private static final Long SUCCESS_CODE = 0L;
private static final String SUCCESS_MSG = "SUCCESS";
private static final Long ERROR_STATE_CODE = 1L;
private static final Long SUCCESS_BUSSINESS_CODE = 0L;
private static final Long ERROR_BUSSINESS_CODE = 1L;
private static final long serialVersionUID = -1L;
public static final Long API_INVOKE_UNEXPECTED_RESULT_CODE = 2L;
public static final String ZERO_FILL_TEMPLATE = "%04d";
private String msg = "";
// 0成功,1失败
private String code = "0000";
// 业务错误码
private String businessCode = "0000";
// 业务状态码
private String businessFlag = "0000";
private Object data = null;
public JsonResult() {
}
/**
* @param msg
* @param code
* @param data
*/
public JsonResult(String msg, Long code, Object data) {
this.msg = msg;
this.code = String.format(ZERO_FILL_TEMPLATE, code);
this.data = data;
}
public JsonResult(String msg, Long code, Object data, Long businessCode) {
this.msg = msg;
this.code = String.format(ZERO_FILL_TEMPLATE, code);
this.data = data;
this.businessCode = String.format(ZERO_FILL_TEMPLATE, businessCode);
}
public JsonResult(String msg, Long code, Object data, Long businessFlag, Long businessCode) {
this.msg = msg;
this.code = String.format(ZERO_FILL_TEMPLATE, code);
this.data = data;
this.businessCode = String.format(ZERO_FILL_TEMPLATE, businessCode);
this.businessFlag = String.format(ZERO_FILL_TEMPLATE, businessFlag);
}
/**
* 构造成功的JsonResult
*
* @param msg String
* @param data Object
* @return JsonResult
*/
public static JsonResult buildSuccessResult(String msg, Object data) {
return new JsonResult(msg, SUCCESS_CODE, data, SUCCESS_BUSSINESS_CODE);
}
public static JsonResult buildSuccessResult(Object data) {
return new JsonResult(SUCCESS_MSG, SUCCESS_CODE, data, SUCCESS_BUSSINESS_CODE);
}
public static JsonResult buildSuccessResult(String msg, Object data, Long bussinessId) {
return new JsonResult(msg, SUCCESS_CODE, data, bussinessId);
}
public static JsonResult buildSuccessResult(String msg, Object data, Long businessFlag, Long bussinessCode) {
return new JsonResult(msg, SUCCESS_CODE, data, businessFlag, bussinessCode);
}
/**
* 构造状态不正确的JsonResult
*
* @param msg String
* @param data Object
* @return JsonResult
*/
public static JsonResult buildErrorStateResult(String msg, Object data) {
return new JsonResult(msg, SUCCESS_CODE, data, ERROR_BUSSINESS_CODE);
}
public static JsonResult buildErrorStateResult(String msg, Object data, Long busniessId) {
return new JsonResult(msg, SUCCESS_CODE, data, busniessId);
}
public static JsonResult buildFatalErrorStateResult(String msg, Object data, Long busniessId) {
return new JsonResult(msg, ERROR_STATE_CODE, data, busniessId);
}
public static JsonResult buildFatalErrorStateResult(String msg, Object data) {
return new JsonResult(msg, ERROR_STATE_CODE, data, 1L);
}
public static JsonResult buildApiInvokeUnexpectedResult(String msg, Object data) {
return new JsonResult(msg, SUCCESS_CODE, data, API_INVOKE_UNEXPECTED_RESULT_CODE);
}
public JsonResult(Object data) {
this.data = data;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
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 getBusinessCode() {
return businessCode;
}
public void setBusinessCode(String businessCode) {
this.businessCode = businessCode;
}
public String getBusinessFlag() {
return businessFlag;
}
public void setBusinessFlag(String businessFlag) {
this.businessFlag = businessFlag;
}
@Override
public String toString() {
return "JsonResult{" + "businessCode='" + businessCode + '\'' + ", code='" + code + '\'' + ", data=" + data
+ ",businessFlag=" + businessFlag + '}';
}
public boolean isSuccess() {
return "0000".equals(code) && "0000".equals(businessCode);
}
}
package cn.qg.holmes.config;
import cn.qg.holmes.interceptor.YeebaoInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 拦截器,用于Mock
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Bean
public YeebaoInterceptor yeebaoInterceptor() {
return new YeebaoInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(yeebaoInterceptor()).addPathPatterns("/mock/tzt-api/**", "/mock/balance-board/**");
}
}
package cn.qg.holmes.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig {
/**
* 分页配置
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
// paginationInterceptor.setLimit(500);
// 开启 count 的 join 优化,只针对部分 left join
paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
return paginationInterceptor;
}
}
package cn.qg.holmes.config;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
/**
* 配置自定义redisTemplate
*/
@Bean
RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
// 设置值(value)的序列化采用Jackson2JsonRedisSerializer。
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
// 设置键(key)的序列化采用StringRedisSerializer。
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
package cn.qg.holmes.controller.mock;
import cn.qg.holmes.common.JsonResult;
import cn.qg.holmes.entity.mock.Mock;
import cn.qg.holmes.service.mock.MockService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@CrossOrigin
@RestController
public class MockController {
@Autowired
MockService mockService;
@RequestMapping(value = "/mock/**", method = { RequestMethod.GET, RequestMethod.POST})
public void mockMethod() {}
@PostMapping("/add/mock")
public JsonResult addMock(@RequestBody Mock mock) {
return JsonResult.buildSuccessResult(mockService.save(mock));
}
@GetMapping("/list/mock")
public JsonResult getMockList(Integer pageNum, Integer pageSize) {
IPage<Mock> page = new Page<>(pageNum, pageSize);
IPage<Mock> pageEntity = mockService.page(page);
Map<String, Object> map = new HashMap<>();
map.put("list", pageEntity.getRecords());
map.put("total", pageEntity.getTotal());
return JsonResult.buildSuccessResult(map);
}
@PostMapping("/edit/mock")
public JsonResult modifyMock(@RequestBody Mock mock) {
return JsonResult.buildSuccessResult(mockService.saveOrUpdate(mock));
}
}
package cn.qg.holmes.encrypt;
public interface EncryptConvertor {
String encrypt(String response);
String decrypt(String request);
}
package cn.qg.holmes.encrypt;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class EncryptFactory {
public static EncryptConvertor produce(String type) {
if ("yeebao".equals(type)) {
return new YeebaoEncryptConvertor();
} else {
log.info("请输入正确的加密类型类型!");
return null;
}
}
}
package cn.qg.holmes.encrypt;
import cn.qg.holmes.encrypt.yeebao.Aes;
import cn.qg.holmes.encrypt.yeebao.Rsa;
import com.alibaba.fastjson.JSON;
import java.util.HashMap;
import java.util.Map;
public class YeebaoEncryptConvertor implements EncryptConvertor{
private final String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANSBQSc0Hlr+mS7uoIjYS71X2DJ6ZrCcbB1uICqty9QY6W16nZ8tLN/d9k2Z+e2rGG8s7PskpU2T+WuJeDSXs/vpPllG8/tSRVaWcr9EzPaSti3ltSUH0QOLSypZEjTT/slscExj4PMOmQXUXP3gewjNWz1cYRI7dGnKPm+ZFah/AgMBAAECgYB8AcFngz6DkzcI8C+2K6JnJ6/+JPdv8JgWxID45tqfNrphLMB2dwJM0VY+CrCSRNnJZsoT9FqSXtuaKWqAJlbchhPZjupA9RkWFzlGpCQ63/CC71RYYY03eCnc7AIpn52whkjfWG/yf57jKzEwUT+U034uvXdaA+lVvJ0xqpj3gQJBAOmLODjecn450TJbNQaop+7Q5Hz2TUIxbYakzPpcLGv1QYgHa657r7PJ23ZltDBGldMaNTZfqJrtDcq0rTA4lBECQQDo8CcdUhMZ3JbR2UZN0CG8ljMbNWgNWBa37ebE3ZG5yYldc7zY9US/+/7lhxNDqG0saTvM9pJwEc3ccVMvksOPAkEAqq7V+zIQKVJmItBn06MFgNNoei+kTUFEk8f0CvG8gXYwW5NYzp+UzOg1HbW82B9uNmeMBl4pInknwEMF5B0lkQJAdRxQPgCGk+kAdo6LNxHd9Ed7eEF4h8Ty3xQfgnh3DHYTtsU6e8WMBA24kENB3zEtejeKFjkdVHTPD/Z1wSRDZwJAAvNuq0YuRDsESOAerkBZKonA5CD0M4vHTRqihHrjBohv6yxBU8P7gALrX7qmoaZ3aLmN8wHdOAGTR6LZjQdkoQ==";
private String aesKey = null;
private String encryptKey = null;
/**
* 易宝加密
* @param response
* @return
*/
@Override
public String encrypt(String response) {
try {
Map responseMap = JSON.parseObject(response, Map.class);
Map<String, Object> signData = new HashMap<>();
responseMap.put("sign", Rsa.sign(response, privateKey));
signData.put("encryptkey", encryptKey);
signData.put("data", Aes.encryptToBase64(JSON.toJSONString(responseMap), aesKey));
return JSON.toJSONString(signData);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 易宝解密
* @param request Http请求的request
* @return
*/
@Override
public String decrypt(String request) {
try {
Map requestMap = JSON.parseObject(request, Map.class);
encryptKey = requestMap.get("encryptkey").toString();
aesKey = Rsa.decrypt(encryptKey, privateKey);
return Aes.decryptFromBase64((String) requestMap.get("data"), aesKey);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
package cn.qg.holmes.encrypt.yeebao;
public abstract class AbstractConvertUtils {
private AbstractConvertUtils() {
}
public static String toHex(byte input[]) {
if (input == null) {
return null;
}
StringBuffer output = new StringBuffer(input.length * 2);
for (int i = 0; i < input.length; i++) {
int current = input[i] & 0xff;
if (current < 16) {
output.append("0");
}
output.append(Integer.toString(current, 16));
}
return output.toString();
}
}
package cn.qg.holmes.encrypt.yeebao;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class Aes {
private static final int KEY_LENGTH = 16;
/**
* 加密
*
* @param data 需要加密的内容
* @param key 加密密码
*/
public static byte[] encrypt(byte[] data, byte[] key) {
CheckUtils.notEmpty(data, "data");
CheckUtils.notEmpty(key, "key");
if (key.length != KEY_LENGTH) {
throw new RuntimeException("Invalid Aes key length (must be 16 bytes)");
}
try {
SecretKeySpec secretKey = new SecretKeySpec(key, "Aes");
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, "Aes");
Cipher cipher = Cipher.getInstance(ConfigureEncryptAndDecrypt.AES_ALGORITHM);// 创建密码器
cipher.init(Cipher.ENCRYPT_MODE, seckey);// 初始化
byte[] result = cipher.doFinal(data);
return result; // 加密
} catch (Exception e) {
throw new RuntimeException("encrypt fail!", e);
}
}
/**
* 解密
*
* @param data 待解密内容
* @param key 解密密钥
*/
public static byte[] decrypt(byte[] data, byte[] key) {
CheckUtils.notEmpty(data, "data");
CheckUtils.notEmpty(key, "key");
if (key.length != KEY_LENGTH) {
throw new RuntimeException("Invalid Aes key length (must be 16 bytes)");
}
try {
SecretKeySpec secretKey = new SecretKeySpec(key, "Aes");
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, "Aes");
Cipher cipher = Cipher.getInstance(ConfigureEncryptAndDecrypt.AES_ALGORITHM);// 创建密码器
cipher.init(Cipher.DECRYPT_MODE, seckey);// 初始化
byte[] result = cipher.doFinal(data);
return result; // 加密
} catch (Exception e) {
throw new RuntimeException("decrypt fail!", e);
}
}
public static String encryptToBase64(String data, String key) {
try {
byte[] valueByte = encrypt(data.getBytes(ConfigureEncryptAndDecrypt.CHAR_ENCODING),
key.getBytes(ConfigureEncryptAndDecrypt.CHAR_ENCODING));
return new String(Base64.encode(valueByte));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("encrypt fail!", e);
}
}
public static String decryptFromBase64(String data, String key) {
try {
byte[] originalData = Base64.decode(data.getBytes());
byte[] valueByte =
decrypt(originalData, key.getBytes(ConfigureEncryptAndDecrypt.CHAR_ENCODING));
return new String(valueByte, ConfigureEncryptAndDecrypt.CHAR_ENCODING);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("decrypt fail!", e);
}
}
public static String encryptWithKeyBase64(String data, String key) {
try {
byte[] valueByte = encrypt(data.getBytes(ConfigureEncryptAndDecrypt.CHAR_ENCODING),
Base64.decode(key.getBytes()));
return new String(Base64.encode(valueByte));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("encrypt fail!", e);
}
}
public static String decryptWithKeyBase64(String data, String key) {
try {
byte[] originalData = Base64.decode(data.getBytes());
byte[] valueByte = decrypt(originalData, Base64.decode(key.getBytes()));
return new String(valueByte, ConfigureEncryptAndDecrypt.CHAR_ENCODING);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("decrypt fail!", e);
}
}
public static byte[] genarateRandomKey() {
KeyGenerator keygen = null;
try {
keygen = KeyGenerator.getInstance(ConfigureEncryptAndDecrypt.AES_ALGORITHM);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(" genarateRandomKey fail!", e);
}
SecureRandom random = new SecureRandom();
keygen.init(random);
Key key = keygen.generateKey();
return key.getEncoded();
}
public static String genarateRandomKeyWithBase64() {
return new String(Base64.encode(genarateRandomKey()));
}
}
package cn.qg.holmes.encrypt.yeebao;
import java.io.UnsupportedEncodingException;
public class Base64 {
/**
* Chunk size per RFC 2045 section 6.8.
* <p/>
* <p>The {@value} character limit does not count the trailing CRLF, but counts
* all other characters, including any equal signs.</p>
*
* @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 6.8</a>
*/
static final int CHUNK_SIZE = 76;
/**
* Chunk separator per RFC 2045 section 2.1.
*
* @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 2.1</a>
*/
static final byte[] CHUNK_SEPARATOR = "\r\n".getBytes();
/**
* The basis length.
*/
static final int BASELENGTH = 255;
/**
* Lookup length.
*/
static final int LOOKUPLENGTH = 64;
/**
* Used to calculate the number of bits in a byte.
*/
static final int EIGHTBIT = 8;
/**
* Used when encoding something which has fewer than 24 bits.
*/
static final int SIXTEENBIT = 16;
/**
* Used to determine how many bits data contains.
*/
static final int TWENTYFOURBITGROUP = 24;
/**
* Used to get the number of Quadruples.
*/
static final int FOURBYTE = 4;
/**
* Used to test the sign of a byte.
*/
static final int SIGN = -128;
/**
* Byte used to pad output.
*/
static final byte PAD = (byte) '=';
// Create arrays to hold the base64 characters and a
// lookup for base64 chars
private static byte[] base64Alphabet = new byte[BASELENGTH];
private static byte[] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
// Populating the lookup and character arrays
static {
for (int i = 0; i < BASELENGTH; i++) {
base64Alphabet[i] = (byte) -1;
}
for (int i = 'Z'; i >= 'A'; i--) {
base64Alphabet[i] = (byte) (i - 'A');
}
for (int i = 'z'; i >= 'a'; i--) {
base64Alphabet[i] = (byte) (i - 'a' + 26);
}
for (int i = '9'; i >= '0'; i--) {
base64Alphabet[i] = (byte) (i - '0' + 52);
}
base64Alphabet['+'] = 62;
base64Alphabet['/'] = 63;
for (int i = 0; i <= 25; i++) {
lookUpBase64Alphabet[i] = (byte) ('A' + i);
}
for (int i = 26, j = 0; i <= 51; i++, j++) {
lookUpBase64Alphabet[i] = (byte) ('a' + j);
}
for (int i = 52, j = 0; i <= 61; i++, j++) {
lookUpBase64Alphabet[i] = (byte) ('0' + j);
}
lookUpBase64Alphabet[62] = (byte) '+';
lookUpBase64Alphabet[63] = (byte) '/';
}
private static boolean isBase64(byte octect) {
if (octect == PAD) {
return true;
} else {
return base64Alphabet[octect] != -1;
}
}
/**
* Tests a given byte array to see if it contains
* only valid characters within the Base64 alphabet.
*
* @param arrayOctect byte array to test
* @return true if all bytes are valid characters in the Base64 alphabet or if the byte array is
* empty; false, otherwise
*/
public static boolean isArrayByteBase64(byte[] arrayOctect) {
arrayOctect = discardWhitespace(arrayOctect);
int length = arrayOctect.length;
if (length == 0) {
// shouldn't a 0 length array be valid base64 data?
// return false;
return true;
}
for (int i = 0; i < length; i++) {
if (!isBase64(arrayOctect[i])) {
return false;
}
}
return true;
}
/**
* Encodes binary data using the base64 algorithm but
* does not chunk the output.
*
* @param binaryData binary data to encode
* @return Base64 characters
*/
public static byte[] encodeBase64(byte[] binaryData) {
return encodeBase64(binaryData, false);
}
/**
* Encodes binary data using the base64 algorithm and chunks
* the encoded output into 76 character blocks
*
* @param binaryData binary data to encode
* @return Base64 characters chunked in 76 character blocks
*/
public static byte[] encodeBase64Chunked(byte[] binaryData) {
return encodeBase64(binaryData, true);
}
/**
* Decodes a byte[] containing containing
* characters in the Base64 alphabet.
*
* @param pArray A byte array containing Base64 character data
* @return a byte array containing binary data
*/
public static byte[] decode(byte[] pArray) {
return decodeBase64(pArray);
}
/**
* Encodes binary data using the base64 algorithm, optionally
* chunking the output into 76 character blocks.
*
* @param binaryData Array containing binary data to encode.
* @param isChunked if isChunked is true this encoder will chunk the base64 output into 76
* character blocks
* @return Base64-encoded data.
*/
public static byte[] encodeBase64(byte[] binaryData, boolean isChunked) {
int lengthDataBits = binaryData.length * EIGHTBIT;
int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
byte encodedData[] = null;
int encodedDataLength = 0;
int nbrChunks = 0;
if (fewerThan24bits != 0) {
//data not divisible by 24 bit
encodedDataLength = (numberTriplets + 1) * 4;
} else {
// 16 or 8 bit
encodedDataLength = numberTriplets * 4;
}
// If the output is to be "chunked" into 76 character sections,
// for compliance with RFC 2045 MIME, then it is important to
// allow for extra length to account for the separator(s)
if (isChunked) {
nbrChunks =
(CHUNK_SEPARATOR.length == 0 ? 0
: (int) Math.ceil((double) encodedDataLength / CHUNK_SIZE));
encodedDataLength += nbrChunks * CHUNK_SEPARATOR.length;
}
encodedData = new byte[encodedDataLength];
byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
int encodedIndex = 0;
int dataIndex = 0;
int i = 0;
int nextSeparatorIndex = CHUNK_SIZE;
int chunksSoFar = 0;
for (i = 0; i < numberTriplets; i++) {
dataIndex = i * 3;
b1 = binaryData[dataIndex];
b2 = binaryData[dataIndex + 1];
b3 = binaryData[dataIndex + 2];
l = (byte) (b2 & 0x0f);
k = (byte) (b1 & 0x03);
byte val1 =
((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
byte val2 =
((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
byte val3 =
((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);
encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
encodedData[encodedIndex + 1] =
lookUpBase64Alphabet[val2 | (k << 4)];
encodedData[encodedIndex + 2] =
lookUpBase64Alphabet[(l << 2) | val3];
encodedData[encodedIndex + 3] = lookUpBase64Alphabet[b3 & 0x3f];
encodedIndex += 4;
// If we are chunking, let's put a chunk separator down.
if (isChunked) {
// this assumes that CHUNK_SIZE % 4 == 0
if (encodedIndex == nextSeparatorIndex) {
System.arraycopy(
CHUNK_SEPARATOR,
0,
encodedData,
encodedIndex,
CHUNK_SEPARATOR.length);
chunksSoFar++;
nextSeparatorIndex =
(CHUNK_SIZE * (chunksSoFar + 1)) +
(chunksSoFar * CHUNK_SEPARATOR.length);
encodedIndex += CHUNK_SEPARATOR.length;
}
}
}
// form integral number of 6-bit groups
dataIndex = i * 3;
if (fewerThan24bits == EIGHTBIT) {
b1 = binaryData[dataIndex];
k = (byte) (b1 & 0x03);
byte val1 =
((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
encodedData[encodedIndex + 1] = lookUpBase64Alphabet[k << 4];
encodedData[encodedIndex + 2] = PAD;
encodedData[encodedIndex + 3] = PAD;
} else if (fewerThan24bits == SIXTEENBIT) {
b1 = binaryData[dataIndex];
b2 = binaryData[dataIndex + 1];
l = (byte) (b2 & 0x0f);
k = (byte) (b1 & 0x03);
byte val1 =
((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
byte val2 =
((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
encodedData[encodedIndex + 1] =
lookUpBase64Alphabet[val2 | (k << 4)];
encodedData[encodedIndex + 2] = lookUpBase64Alphabet[l << 2];
encodedData[encodedIndex + 3] = PAD;
}
if (isChunked) {
// we also add a separator to the end of the final chunk.
if (chunksSoFar < nbrChunks) {
System.arraycopy(
CHUNK_SEPARATOR,
0,
encodedData,
encodedDataLength - CHUNK_SEPARATOR.length,
CHUNK_SEPARATOR.length);
}
}
return encodedData;
}
/**
* Decodes Base64 data into octects
*
* @param base64Data Byte array containing Base64 data
* @return Array containing decoded data.
*/
public static byte[] decodeBase64(byte[] base64Data) {
// RFC 2045 requires that we discard ALL non-Base64 characters
base64Data = discardNonBase64(base64Data);
// handle the edge case, so we don't have to worry about it later
if (base64Data.length == 0) {
return new byte[0];
}
int numberQuadruple = base64Data.length / FOURBYTE;
byte decodedData[] = null;
byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0;
// Throw away anything not in base64Data
int encodedIndex = 0;
int dataIndex = 0;
{
// this sizes the output array properly - rlw
int lastData = base64Data.length;
// ignore the '=' padding
while (base64Data[lastData - 1] == PAD) {
if (--lastData == 0) {
return new byte[0];
}
}
decodedData = new byte[lastData - numberQuadruple];
}
for (int i = 0; i < numberQuadruple; i++) {
dataIndex = i * 4;
marker0 = base64Data[dataIndex + 2];
marker1 = base64Data[dataIndex + 3];
b1 = base64Alphabet[base64Data[dataIndex]];
b2 = base64Alphabet[base64Data[dataIndex + 1]];
if (marker0 != PAD && marker1 != PAD) {
//No PAD e.g 3cQl
b3 = base64Alphabet[marker0];
b4 = base64Alphabet[marker1];
decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
decodedData[encodedIndex + 1] =
(byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4);
} else if (marker0 == PAD) {
//Two PAD e.g. 3c[Pad][Pad]
decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
} else if (marker1 == PAD) {
//One PAD e.g. 3cQ[Pad]
b3 = base64Alphabet[marker0];
decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
decodedData[encodedIndex + 1] =
(byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
}
encodedIndex += 3;
}
return decodedData;
}
/**
* Discards any whitespace from a basis-64 encoded block.
*
* @param data The basis-64 encoded data to discard the whitespace from.
* @return The data, less whitespace (see RFC 2045).
*/
static byte[] discardWhitespace(byte[] data) {
byte groomedData[] = new byte[data.length];
int bytesCopied = 0;
for (int i = 0; i < data.length; i++) {
switch (data[i]) {
case (byte) ' ':
case (byte) '\n':
case (byte) '\r':
case (byte) '\t':
break;
default:
groomedData[bytesCopied++] = data[i];
}
}
byte packedData[] = new byte[bytesCopied];
System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
return packedData;
}
/**
* Discards any characters outside of the base64 alphabet, per
* the requirements on page 25 of RFC 2045 - "Any characters
* outside of the base64 alphabet are to be ignored in base64
* encoded data."
*
* @param data The basis-64 encoded data to groom
* @return The data, less non-base64 characters (see RFC 2045).
*/
static byte[] discardNonBase64(byte[] data) {
byte groomedData[] = new byte[data.length];
int bytesCopied = 0;
for (int i = 0; i < data.length; i++) {
if (isBase64(data[i])) {
groomedData[bytesCopied++] = data[i];
}
}
byte packedData[] = new byte[bytesCopied];
System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
return packedData;
}
/**
* Encodes a byte[] containing binary data, into a byte[] containing
* characters in the Base64 alphabet.
*
* @param pArray a byte array containing binary data
* @return A byte array containing only Base64 character data
*/
public static byte[] encode(byte[] pArray) {
return encodeBase64(pArray, false);
}
public static String encode(String str) throws UnsupportedEncodingException {
String baseStr = new String(encode(str.getBytes("UTF-8")));
String tempStr = Digest.digest(str).toUpperCase();
String result = tempStr + baseStr;
return new String(encode(result.getBytes("UTF-8")));
}
public static String decode(String cryptoStr) throws
UnsupportedEncodingException {
if (cryptoStr.length() < 40) {
return "";
}
try {
String tempStr = new String(decode(cryptoStr.getBytes("UTF-8")));
String result = tempStr.substring(40, tempStr.length());
return new String(decode(result.getBytes("UTF-8")));
} catch (ArrayIndexOutOfBoundsException ex) {
return "";
}
}
/**
* Decodes Base64 data into octects
*
* @param encoded string containing Base64 data
* @return Array containind decoded data.
*/
public static byte[] decode2(String encoded) {
if (encoded == null) {
return null;
}
char[] base64Data = encoded.toCharArray();
// remove white spaces
int len = removeWhiteSpace(base64Data);
if (len % FOURBYTE != 0) {
return null;//should be divisible by four
}
int numberQuadruple = (len / FOURBYTE);
if (numberQuadruple == 0) {
return new byte[0];
}
byte decodedData[] = null;
byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
int i = 0;
int encodedIndex = 0;
int dataIndex = 0;
decodedData = new byte[(numberQuadruple) * 3];
for (; i < numberQuadruple - 1; i++) {
if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))
|| !isData((d3 = base64Data[dataIndex++]))
|| !isData((d4 = base64Data[dataIndex++]))) {
return null;
}//if found "no data" just return null
b1 = base64Alphabet[d1];
b2 = base64Alphabet[d2];
b3 = base64Alphabet[d3];
b4 = base64Alphabet[d4];
decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
}
if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) {
return null;//if found "no data" just return null
}
b1 = base64Alphabet[d1];
b2 = base64Alphabet[d2];
d3 = base64Data[dataIndex++];
d4 = base64Data[dataIndex++];
if (!isData((d3)) || !isData((d4))) {//Check if they are PAD characters
if (isPad(d3) && isPad(d4)) {
if ((b2 & 0xf) != 0)//last 4 bits should be zero
{
return null;
}
byte[] tmp = new byte[i * 3 + 1];
System.arraycopy(decodedData, 0, tmp, 0, i * 3);
tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
return tmp;
} else if (!isPad(d3) && isPad(d4)) {
b3 = base64Alphabet[d3];
if ((b3 & 0x3) != 0)//last 2 bits should be zero
{
return null;
}
byte[] tmp = new byte[i * 3 + 2];
System.arraycopy(decodedData, 0, tmp, 0, i * 3);
tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
return tmp;
} else {
return null;
}
} else { //No PAD e.g 3cQl
b3 = base64Alphabet[d3];
b4 = base64Alphabet[d4];
decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
}
return decodedData;
}
private static boolean isWhiteSpace(char octect) {
return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
}
private static boolean isData(char octect) {
return (octect < BASELENGTH && base64Alphabet[octect] != -1);
}
private static boolean isPad(char octect) {
return (octect == PAD);
}
/**
* remove WhiteSpace from MIME containing encoded Base64 data.
*
* @param data the byte array of base64 data (with WS)
* @return the new length
*/
private static int removeWhiteSpace(char[] data) {
if (data == null) {
return 0;
}
// count characters that's not whitespace
int newSize = 0;
int len = data.length;
for (int i = 0; i < len; i++) {
if (!isWhiteSpace(data[i])) {
data[newSize++] = data[i];
}
}
return newSize;
}
}
package cn.qg.holmes.encrypt.yeebao;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;
public class CheckUtils {
/**
* 验证对象是否为NULL,空字符串,空数组,空的Collection或Map(只有空格的字符串也认为是空串)
*
* @param obj 被验证的对象
* @param message 异常信息
*/
@SuppressWarnings("rawtypes")
public static void notEmpty(Object obj, String message) {
if (obj == null) {
throw new IllegalArgumentException(message + " must be specified");
}
if (obj instanceof String && obj.toString().trim().length() == 0) {
throw new IllegalArgumentException(message + " must be specified");
}
if (obj.getClass().isArray() && Array.getLength(obj) == 0) {
throw new IllegalArgumentException(message + " must be specified");
}
if (obj instanceof Collection && ((Collection) obj).isEmpty()) {
throw new IllegalArgumentException(message + " must be specified");
}
if (obj instanceof Map && ((Map) obj).isEmpty()) {
throw new IllegalArgumentException(message + " must be specified");
}
}
}
package cn.qg.holmes.encrypt.yeebao;
public class ConfigureEncryptAndDecrypt {
public static final String CHAR_ENCODING = "UTF-8";
public static final String AES_ALGORITHM = "Aes/ECB/PKCS5Padding";
public static final String RSA_ALGORITHM = "Rsa/ECB/PKCS1Padding";
}
package cn.qg.holmes.encrypt.yeebao;
import lombok.extern.slf4j.Slf4j;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
@Slf4j
public class Digest {
public static final String ENCODE = "UTF-8";
public static String signMD5(String aValue, String encoding) {
try {
byte[] input = aValue.getBytes(encoding);
MessageDigest md = MessageDigest.getInstance("MD5");
return AbstractConvertUtils.toHex(md.digest(input));
} catch (NoSuchAlgorithmException e) {
log.error("{}", e);
return null;
} catch (UnsupportedEncodingException e) {
log.error("{}", e);
return null;
}
}
public static String hmacSign(String aValue) {
try {
byte[] input = aValue.getBytes();
MessageDigest md = MessageDigest.getInstance("MD5");
return AbstractConvertUtils.toHex(md.digest(input));
} catch (NoSuchAlgorithmException e) {
log.error("{}", e);
return null;
}
}
public static String hmacSign(String aValue, String aKey) {
return hmacSign(aValue, aKey, ENCODE);
}
public static String hmacSign(String aValue, String aKey, String encoding) {
byte k_ipad[] = new byte[64];
byte k_opad[] = new byte[64];
byte keyb[];
byte value[];
try {
keyb = aKey.getBytes(encoding);
value = aValue.getBytes(encoding);
} catch (UnsupportedEncodingException e) {
keyb = aKey.getBytes();
value = aValue.getBytes();
}
Arrays.fill(k_ipad, keyb.length, 64, (byte) 54);
Arrays.fill(k_opad, keyb.length, 64, (byte) 92);
for (int i = 0; i < keyb.length; i++) {
k_ipad[i] = (byte) (keyb[i] ^ 0x36);
k_opad[i] = (byte) (keyb[i] ^ 0x5c);
}
MessageDigest md = null;
try {
md = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
log.error("{}", e);
return null;
}
md.update(k_ipad);
md.update(value);
byte dg[] = md.digest();
md.reset();
md.update(k_opad);
md.update(dg, 0, 16);
dg = md.digest();
return AbstractConvertUtils.toHex(dg);
}
public static String hmacSHASign(String aValue, String aKey, String encoding) {
byte k_ipad[] = new byte[64];
byte k_opad[] = new byte[64];
byte keyb[];
byte value[];
try {
keyb = aKey.getBytes(encoding);
value = aValue.getBytes(encoding);
} catch (UnsupportedEncodingException e) {
keyb = aKey.getBytes();
value = aValue.getBytes();
}
Arrays.fill(k_ipad, keyb.length, 64, (byte) 54);
Arrays.fill(k_opad, keyb.length, 64, (byte) 92);
for (int i = 0; i < keyb.length; i++) {
k_ipad[i] = (byte) (keyb[i] ^ 0x36);
k_opad[i] = (byte) (keyb[i] ^ 0x5c);
}
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA");
} catch (NoSuchAlgorithmException e) {
log.error("{}", e);
return null;
}
md.update(k_ipad);
md.update(value);
byte dg[] = md.digest();
md.reset();
md.update(k_opad);
md.update(dg, 0, 20);
dg = md.digest();
return AbstractConvertUtils.toHex(dg);
}
public static String digest(String aValue) {
return digest(aValue, ENCODE);
}
public static String digest(String aValue, String encoding) {
aValue = aValue.trim();
byte value[];
try {
value = aValue.getBytes(encoding);
} catch (UnsupportedEncodingException e) {
value = aValue.getBytes();
}
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA");
} catch (NoSuchAlgorithmException e) {
log.error("{}", e);
return null;
}
return AbstractConvertUtils.toHex(md.digest(value));
}
public static String digest(String aValue, String alg, String encoding) {
aValue = aValue.trim();
byte value[];
try {
value = aValue.getBytes(encoding);
} catch (UnsupportedEncodingException e) {
value = aValue.getBytes();
}
MessageDigest md = null;
try {
md = MessageDigest.getInstance(alg);
} catch (NoSuchAlgorithmException e) {
log.error("{}", e);
return null;
}
return AbstractConvertUtils.toHex(md.digest(value));
}
public static String udpSign(String aValue) {
try {
byte[] input = aValue.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("SHA1");
return new String(Base64.encode(md.digest(input)), ENCODE);
} catch (Exception e) {
return null;
}
}
}
package cn.qg.holmes.encrypt.yeebao;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.util.Map.Entry;
import java.util.TreeMap;
@Slf4j
public class EncryUtil {
/**
* 生成RSA签名
*/
public static String handleRSA(TreeMap<String, Object> map,
String privateKey) {
StringBuffer sbuffer = new StringBuffer();
for (Entry<String, Object> entry : map.entrySet()) {
sbuffer.append(entry.getValue());
}
String signTemp = sbuffer.toString();
String sign = "";
if (StringUtils.isNotEmpty(privateKey)) {
sign = Rsa.sign(signTemp, privateKey);
}
return sign;
}
/**
* 对易宝支付返回的结果进行验签
*
* @param data 易宝支付返回的业务数据密文
* @param encrypt_key 易宝支付返回的对ybAesKey加密后的密文
* @param yibaoPublickKey 易宝支付提供的公钥
* @param merchantPrivateKey 商户自己的私钥
* @return 验签是否通过
* @throws Exception
*/
public static boolean checkDecryptAndSign(String data, String encrypt_key,
String yibaoPublickKey, String merchantPrivateKey) {
/** 1.使用YBprivatekey解开aesEncrypt。 */
String AESKey;
try {
AESKey = Rsa.decrypt(encrypt_key, merchantPrivateKey);
} catch (Exception e) {
/** AES密钥解密失败 */
log.error("{}", e);
return false;
}
/** 2.用aeskey解开data。取得data明文 */
String realData = Aes.decryptFromBase64(data, AESKey);
TreeMap<String, String> map = JSON.parseObject(realData,
new TypeReference<TreeMap<String, String>>() {
});
/** 3.取得data明文sign。 */
String sign = StringUtils.trimToEmpty(map.get("sign"));
StringBuilder signData = new StringBuilder();
for (Entry<String, String> entry : map.entrySet()) {
if (StringUtils.equals(entry.getKey(), "sign")) {
continue;
}
signData.append(entry.getValue() == null ? "" : entry.getValue());
}
/** 5. result为true时表明验签通过 */
String str = signData.toString();
return Rsa.checkSign(str, sign,
yibaoPublickKey);
}
}
package cn.qg.holmes.encrypt.yeebao;
import java.security.SecureRandom;
public class RandomUtil {
public static final SecureRandom random = new SecureRandom();
public static String getRandom(int length) {
StringBuilder ret = new StringBuilder();
for (int i = 0; i < length; i++) {
boolean isChar = (random.nextInt(2) % 2 == 0);// 输出字母还是数字
if (isChar) { // 字符串
int choice = random.nextInt(2) % 2 == 0 ? 65 : 97; // 取得大写字母还是小写字母
ret.append((char) (choice + random.nextInt(26)));
} else { // 数字
ret.append(Integer.toString(random.nextInt(10)));
}
}
return ret.toString();
}
}
package cn.qg.holmes.encrypt.yeebao;
import lombok.extern.slf4j.Slf4j;
import javax.crypto.Cipher;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public class Rsa {
/**
* 指定key的大小
*/
private static int KEYSIZE = 1024;
/**
* 生成密钥对
*/
public static Map<String, String> generateKeyPair() throws Exception {
/** RSA算法要求有一个可信任的随机数源 */
SecureRandom sr = new SecureRandom();
/** 为RSA算法创建一个KeyPairGenerator对象 */
KeyPairGenerator kpg = KeyPairGenerator.getInstance("Rsa");
/** 利用上面的随机数据源初始化这个KeyPairGenerator对象 */
kpg.initialize(KEYSIZE, sr);
/** 生成密匙对 */
KeyPair kp = kpg.generateKeyPair();
/** 得到公钥 */
Key publicKey = kp.getPublic();
byte[] publicKeyBytes = publicKey.getEncoded();
String pub = new String(Base64.encodeBase64(publicKeyBytes),
ConfigureEncryptAndDecrypt.CHAR_ENCODING);
/** 得到私钥 */
Key privateKey = kp.getPrivate();
byte[] privateKeyBytes = privateKey.getEncoded();
String pri = new String(Base64.encodeBase64(privateKeyBytes),
ConfigureEncryptAndDecrypt.CHAR_ENCODING);
Map<String, String> map = new HashMap<String, String>();
map.put("publicKey", pub);
map.put("privateKey", pri);
RSAPublicKey rsp = (RSAPublicKey) kp.getPublic();
BigInteger bint = rsp.getModulus();
byte[] b = bint.toByteArray();
byte[] deBase64Value = Base64.encodeBase64(b);
String retValue = new String(deBase64Value);
map.put("modulus", retValue);
return map;
}
/**
* 加密方法 source: 源数据
*/
public static String encrypt(String source, String publicKey)
throws Exception {
Key key = getPublicKey(publicKey);
/** 得到Cipher对象来实现对源数据的RSA加密 */
Cipher cipher = Cipher.getInstance(ConfigureEncryptAndDecrypt.RSA_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] b = source.getBytes();
/** 执行加密操作 */
byte[] b1 = cipher.doFinal(b);
return new String(Base64.encodeBase64(b1),
ConfigureEncryptAndDecrypt.CHAR_ENCODING);
}
/**
* 解密算法 cryptograph:密文
*/
public static String decrypt(String cryptograph, String privateKey)
throws Exception {
Key key = getPrivateKey(privateKey);
/** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */
Cipher cipher = Cipher.getInstance(ConfigureEncryptAndDecrypt.RSA_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] b1 = Base64.decodeBase64(cryptograph.getBytes());
/** 执行解密操作 */
byte[] b = cipher.doFinal(b1);
return new String(b);
}
/**
* 得到公钥
*
* @param key 密钥字符串(经过base64编码)
* @throws Exception
*/
public static PublicKey getPublicKey(String key) throws Exception {
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(
Base64.decodeBase64(key.getBytes()));
KeyFactory keyFactory = KeyFactory.getInstance("Rsa");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}
/**
* 得到私钥
*
* @param key 密钥字符串(经过base64编码)
* @throws Exception
*/
public static PrivateKey getPrivateKey(String key) throws Exception {
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(
Base64.decodeBase64(key.getBytes()));
KeyFactory keyFactory = KeyFactory.getInstance("Rsa");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
public static String sign(String content, String privateKey) {
String charset = ConfigureEncryptAndDecrypt.CHAR_ENCODING;
try {
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
Base64.decodeBase64(privateKey.getBytes()));
KeyFactory keyf = KeyFactory.getInstance("Rsa");
PrivateKey priKey = keyf.generatePrivate(priPKCS8);
Signature signature = Signature.getInstance("SHA1WithRSA");
signature.initSign(priKey);
signature.update(content.getBytes(charset));
byte[] signed = signature.sign();
return new String(Base64.encodeBase64(signed));
} catch (Exception e) {
}
return null;
}
public static boolean checkSign(String content, String sign, String publicKey) {
try {
KeyFactory keyFactory = KeyFactory.getInstance("Rsa");
byte[] encodedKey = Base64.decode2(publicKey);
PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
Signature signature = Signature
.getInstance("SHA1WithRSA");
signature.initVerify(pubKey);
signature.update(content.getBytes("utf-8"));
boolean bverify = signature.verify(Base64.decode2(sign));
return bverify;
} catch (Exception e) {
log.error("{}", e);
}
return false;
}
}
package cn.qg.holmes.entity.mock;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
@Data
@TableName(value = "mock")
public class Mock {
@TableId(type = IdType.AUTO)
private Integer id;
private String url;
private String description;
private String success;
private String fail;
/**
* 0-返回失败,1-返回成功
*/
private Integer flag;
/**
* 0-不加密,1-加密
*/
private Integer encrypt;
/**
* 1-json,2-字符串
*/
private Integer type;
/**
* 所属模块
*/
private Integer module;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}
package cn.qg.holmes.interceptor;
import cn.qg.holmes.encrypt.EncryptConvertor;
import cn.qg.holmes.encrypt.EncryptFactory;
import cn.qg.holmes.entity.mock.Mock;
import cn.qg.holmes.mapper.mock.MockMapper;
import cn.qg.holmes.utils.BankCardUtils;
import cn.qg.holmes.utils.RedisUtils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
public class YeebaoInterceptor implements HandlerInterceptor {
@Autowired
MockMapper mockMapper;
@Autowired
RedisUtils redisUtils;
/**
* 将HttpServletRequest的parameterMap由Map<String, String[]>转换成Map<String, Object>
* @param parameterMap
* @return
*/
public Map<String, Object> requestMapTrans(Map<String, String[]> parameterMap) {
Map<String, Object> map = new HashMap<>();
for (Map.Entry<String, String[]> entry: parameterMap.entrySet()) {
String key = entry.getKey();
String value = entry.getValue()[0];
map.put(key, value);
}
return map;
}
/**
* 接口/tzt-api/api/bankcard/check 请求的mock响应
* @param cardNo 银行卡号
* @param merchantno 商户号
* @return 响应Map
*/
public Map<String, Object> getBankcardCheckResponse(String cardNo, String merchantno) {
Map<String, Object> map = new HashMap<>();
String bankCode = BankCardUtils.getCardCode(cardNo);
String bankName = BankCardUtils.getBankName(bankCode);
map.put("bankcode", bankCode);
map.put("bankname", bankName);
map.put("cardtop", cardNo.substring(0, 5));
map.put("cardlast", cardNo.substring(cardNo.length()-4));
map.put("cardtype", "DEBIT");
map.put("errorcode", "");
map.put("errormsg", "");
map.put("isvalid", "VALID");
map.put("merchantno", merchantno);
return map;
}
/**
* 解析从数据库获取的响应,赋对应的值
* @param requestMap
* @param responseMap
* @return
*/
public Map<String, Object> handleResponseMap(Map<String, Object> requestMap, Map<String, Object> responseMap) {
for (Map.Entry<String, Object> entry: responseMap.entrySet()) {
if (entry.getValue() instanceof List) {
List<Map> list = (List) entry.getValue();
for (Map<String, Object> map: list) {
for (Map.Entry<String, Object> entry2: map.entrySet()) {
String value2 = entry2.getValue().toString();
if (value2.startsWith("$request")) {
entry2.setValue(requestMap.get(value2.split("\\.")[1]));
}
}
}
} else if (entry.getValue() instanceof String) {
String value = entry.getValue().toString();
if (value.startsWith("$request")) {
entry.setValue(requestMap.get(value.split("\\.")[1]));
}
if (value.equals("true")) {
entry.setValue(true);
}
if (value.equals("false")) {
entry.setValue(false);
}
}
}
return responseMap;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String uri = request.getRequestURI().substring(5);
Map<String, String[]> parameterMap = request.getParameterMap();
QueryWrapper<Mock> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("url", uri);
Mock mock = mockMapper.selectOne(queryWrapper);
Map<String, Object> requestMap;
Map responseMap = new HashMap<>();
String responseStr = null;
if (mock.getFlag().equals(1)) {
if (mock.getType() == 1) {
responseMap = JSON.parseObject(mock.getSuccess(), Map.class);
} else if (mock.getType() == 2) {
responseStr = mock.getSuccess();
}
} else if (mock.getFlag().equals(0)) {
if (mock.getType() == 1) {
responseMap = JSON.parseObject(mock.getSuccess(), Map.class);
} else if (mock.getType() == 2) {
responseStr = mock.getSuccess();
}
}
if (mock.getEncrypt() == 1) {
EncryptConvertor encryptConvertor = EncryptFactory.produce("yeebao");
requestMap = JSON.parseObject(encryptConvertor.decrypt(JSON.toJSONString(requestMapTrans(parameterMap))), Map.class);
// 针对 /tzt-api/api/bankcard/check 接口特殊处理
if (uri.equals("/tzt-api/api/bankcard/check")) {
String cardNo = requestMap.get("cardno").toString();
String merchantno = requestMap.get("merchantno").toString();
responseMap = getBankcardCheckResponse(cardNo, merchantno);
modifyResponse(response, encryptConvertor.encrypt(JSON.toJSONString(responseMap)));
return true;
}
// 判断返回是字符串还是json,1-json,2-字符串
if (mock.getType() == 1) {
responseMap = handleResponseMap(requestMap, responseMap);
if (uri.equals("/tzt-api/api/bindcard/request")) {
redisUtils.set(requestMap.get("requestno").toString(), responseMap);
log.info("保存redis值, key: {}, value: {}", requestMap.get("requestno"), requestMap);
responseMap.put("yborderid", "TZAUba0c7b8" + requestMap.get("requestno") + "95c929ca802e");
redisUtils.set(requestMap.get("requestno").toString() + "_response", responseMap);
log.info("保存redis值, key: {}, value: {}", requestMap.get("requestno").toString() + "_response", requestMap);
}
if (uri.equals("/tzt-api/api/bindcard/confirm")) {
Map bindcardCheckRedisValue = (Map) redisUtils.get(requestMap.get("requestno").toString());
Map bincardCheckRespRedisValue = (Map) redisUtils.get(requestMap.get("requestno").toString() + "_response");
responseMap.put("bankcode", bindcardCheckRedisValue.get("bankcode"));
responseMap.put("bankname", bindcardCheckRedisValue.get("bankname"));
responseMap.put("cardlast", bindcardCheckRedisValue.get("cardlast"));
responseMap.put("cardtop", bindcardCheckRedisValue.get("cardtop"));
responseMap.put("yborderid", bincardCheckRespRedisValue.get("yborderid"));
}
modifyResponse(response, encryptConvertor.encrypt(JSON.toJSONString(responseMap)), "application/json; charset=utf-8");
return true;
} else if (mock.getType() == 2) {
modifyResponse(response, encryptConvertor.encrypt(responseStr));
return true;
}
} else if (mock.getEncrypt() == 0) {
requestMap = requestMapTrans(parameterMap);
// 针对 /balance-board/transfer 接口特殊处理
if (uri.equals("/balance-board/transfer")) {
BufferedReader br = request.getReader();
String str="";
StringBuilder requestData = new StringBuilder();
while((str = br.readLine()) != null){
requestData.append(str);
}
br.close();
String cmd = requestData.toString().split("<cmd>")[1].split("</cmd>")[0];
log.info("yeepay-transfer cmd-------- {}", cmd);
String transferResponse = null;
if("AccountBalanaceQuery".equals(cmd)){
//查询余额的返回值
transferResponse = "<data><cmd>AccountBalanaceQuery</cmd><hmac>MIIE6QYJKoZIhvcNAQcCoIIE2jCCBNYCAQExCzAJBgUrDgMCGgUAMC8GCSqGSIb3DQEHAaAiBCAxYTcyYmQwZWVmMWIyNDRkNTFlNmEzYTAwMjk1Mjk1OKCCA7EwggOtMIIDFqADAgECAhAuyfCgPbMcigfvVyGazeQRMA0GCSqGSIb3DQEBBQUAMCQxCzAJBgNVBAYTAkNOMRUwEwYDVQQKEwxDRkNBIFRFU1QgQ0EwHhcNMTExMTI4MDcwOTUzWhcNMTMxMTI4MDcwOTUzWjBzMQswCQYDVQQGEwJDTjEVMBMGA1UEChMMQ0ZDQSBURVNUIENBMQ8wDQYDVQQLEwZZRUVQQVkxEjAQBgNVBAsTCUN1c3RvbWVyczEoMCYGA1UEAxQfMDQxQFoxMjNxd2VAemhpd2VuLm1laUAwMDAwMDAwMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzrITNElBaFF7xPXtPguWeTnGOI1gVMMkUDI57ZQz+Gg9PPcfF+ExrtDgMQEOwfRs7X4XiraPE2l6ub0Xkpl0ftu8ELnii91wUKAqsvp88NIdAdLQnC7PeveWlquVSAf//2WtAkdBI7xnhXaL/ObUkhHheT0aR5miYmDyLAkTBj8CAwEAAaOCAY8wggGLMB8GA1UdIwQYMBaAFEZy3CVynwJOVYO1gPkL2+mTs/RFMB0GA1UdDgQWBBS0k6A7ZSwLRwbIhFsgcChrYd27PDALBgNVHQ8EBAMCBaAwDAYDVR0TBAUwAwEBADA7BgNVHSUENDAyBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDBAYIKwYBBQUHAwgwgfAGA1UdHwSB6DCB5TBPoE2gS6RJMEcxCzAJBgNVBAYTAkNOMRUwEwYDVQQKEwxDRkNBIFRFU1QgQ0ExDDAKBgNVBAsTA0NSTDETMBEGA1UEAxMKY3JsMTI2XzE5NDCBkaCBjqCBi4aBiGxkYXA6Ly90ZXN0bGRhcC5jZmNhLmNvbS5jbjozODkvQ049Y3JsMTI2XzE5NCxPVT1DUkwsTz1DRkNBIFRFU1QgQ0EsQz1DTj9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0P2Jhc2U/b2JqZWN0Y2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnQwDQYJKoZIhvcNAQEFBQADgYEAKX4CXCPQEE4RWGsZTXZXLBct2gcPYEjqpgPZ5ERiUrYLTDGuIT90ECfSoxCrcTJEeY7EJBojig9gLRoMn/4xXW/XscGarQ3XxyZw8VxTMFkotuUkAPoaacYlIrc34t2DR0DqvU6umgFL3yTMYxl5WLjOh47OH7Aw7VPscmrtzEIxgd0wgdoCAQEwODAkMQswCQYDVQQGEwJDTjEVMBMGA1UEChMMQ0ZDQSBURVNUIENBAhAuyfCgPbMcigfvVyGazeQRMAkGBSsOAwIaBQAwDQYJKoZIhvcNAQEBBQAEgYBW4+qU8lVs4gEk/o+ln33umTlBDViDf+VMA/6vDhfECTy1fbBHqqr84QFBagMqEXGHzXzzP8qGRRAhmKLhn4RimcrvRh3BRbcQig6OEL/Zz1SphFEH0+BRAN+jhLYRt7+zQZvBx65rE52ivMqCpmEQ+6F4BbNCWwJ+0/xbCE4m5Q==</hmac><ret_Code>1</ret_Code><balance_Amount>291227.76</balance_Amount><valid_Amount>291227.76</valid_Amount></data>";
}else if("TransferBatch".equals(cmd)){
String batchNo = requestData.toString().split("<batch_No>")[1].split("</batch_No>")[0];
//申请易宝放款的返回值
transferResponse = "<?xml version='1.0' encoding='GBK'?><data><cmd>TransferBatch</cmd><hmac>MIIE6QYJKoZIhvcNAQcCoIIE2jCCBNYCAQExCzAJBgUrDgMCGgUAMC8GCSqGSIb3DQEHAaAiBCAyYjM0NGJiNmVlZDliYmY1Mjk3MGNkMGFjMjNlMTA5NqCCA7EwggOtMIIDFqADAgECAhAuyfCgPbMcigfvVyGazeQRMA0GCSqGSIb3DQEBBQUAMCQxCzAJBgNVBAYTAkNOMRUwEwYDVQQKEwxDRkNBIFRFU1QgQ0EwHhcNMTExMTI4MDcwOTUzWhcNMTMxMTI4MDcwOTUzWjBzMQswCQYDVQQGEwJDTjEVMBMGA1UEChMMQ0ZDQSBURVNUIENBMQ8wDQYDVQQLEwZZRUVQQVkxEjAQBgNVBAsTCUN1c3RvbWVyczEoMCYGA1UEAxQfMDQxQFoxMjNxd2VAemhpd2VuLm1laUAwMDAwMDAwMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzrITNElBaFF7xPXtPguWeTnGOI1gVMMkUDI57ZQz+Gg9PPcfF+ExrtDgMQEOwfRs7X4XiraPE2l6ub0Xkpl0ftu8ELnii91wUKAqsvp88NIdAdLQnC7PeveWlquVSAf//2WtAkdBI7xnhXaL/ObUkhHheT0aR5miYmDyLAkTBj8CAwEAAaOCAY8wggGLMB8GA1UdIwQYMBaAFEZy3CVynwJOVYO1gPkL2+mTs/RFMB0GA1UdDgQWBBS0k6A7ZSwLRwbIhFsgcChrYd27PDALBgNVHQ8EBAMCBaAwDAYDVR0TBAUwAwEBADA7BgNVHSUENDAyBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDBAYIKwYBBQUHAwgwgfAGA1UdHwSB6DCB5TBPoE2gS6RJMEcxCzAJBgNVBAYTAkNOMRUwEwYDVQQKEwxDRkNBIFRFU1QgQ0ExDDAKBgNVBAsTA0NSTDETMBEGA1UEAxMKY3JsMTI2XzE5NDCBkaCBjqCBi4aBiGxkYXA6Ly90ZXN0bGRhcC5jZmNhLmNvbS5jbjozODkvQ049Y3JsMTI2XzE5NCxPVT1DUkwsTz1DRkNBIFRFU1QgQ0EsQz1DTj9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0P2Jhc2U/b2JqZWN0Y2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnQwDQYJKoZIhvcNAQEFBQADgYEAKX4CXCPQEE4RWGsZTXZXLBct2gcPYEjqpgPZ5ERiUrYLTDGuIT90ECfSoxCrcTJEeY7EJBojig9gLRoMn/4xXW/XscGarQ3XxyZw8VxTMFkotuUkAPoaacYlIrc34t2DR0DqvU6umgFL3yTMYxl5WLjOh47OH7Aw7VPscmrtzEIxgd0wgdoCAQEwODAkMQswCQYDVQQGEwJDTjEVMBMGA1UEChMMQ0ZDQSBURVNUIENBAhAuyfCgPbMcigfvVyGazeQRMAkGBSsOAwIaBQAwDQYJKoZIhvcNAQEBBQAEgYAC38fZ2TRB7Myf2VWcQSmGMCO2lGcuAtUfA2m9pHiZ1CZ/cUd/Jj1bmN94QT+7IcPOXw2ZPBbCufeClYHSZRLy3hk3P+WhpGQenlp5zTkJjGvKFKxOdDp6ymlruCE/wQRwH9rMrxhuLkyEauAOQEAeE8EtBsKtBhVanSxEWYlSug==</hmac><ret_Code>1</ret_Code><mer_Id>10000449592</mer_Id><batch_No>" + batchNo + "</batch_No><total_Amt>0.01</total_Amt><total_Num>1</total_Num><r1_Code>0025</r1_Code></data>";
}else if("BatchDetailQuery".equals(cmd)){
String batchNo = requestData.toString().split("<batch_No>")[1].split("</batch_No>")[0];
//放款结果查询的返回值
transferResponse = "<data><cmd>BatchDetailQuery</cmd><hmac>MIIE6QYJKoZIhvcNAQcCoIIE2jCCBNYCAQExCzAJBgUrDgMCGgUAMC8GCSqGSIb3DQEHAaAiBCA2ZWU1ODE3Y2UwNDg4NDczNmJlNWFlNGM0MDViZGNlYaCCA7EwggOtMIIDFqADAgECAhAuyfCgPbMcigfvVyGazeQRMA0GCSqGSIb3DQEBBQUAMCQxCzAJBgNVBAYTAkNOMRUwEwYDVQQKEwxDRkNBIFRFU1QgQ0EwHhcNMTExMTI4MDcwOTUzWhcNMTMxMTI4MDcwOTUzWjBzMQswCQYDVQQGEwJDTjEVMBMGA1UEChMMQ0ZDQSBURVNUIENBMQ8wDQYDVQQLEwZZRUVQQVkxEjAQBgNVBAsTCUN1c3RvbWVyczEoMCYGA1UEAxQfMDQxQFoxMjNxd2VAemhpd2VuLm1laUAwMDAwMDAwMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzrITNElBaFF7xPXtPguWeTnGOI1gVMMkUDI57ZQz+Gg9PPcfF+ExrtDgMQEOwfRs7X4XiraPE2l6ub0Xkpl0ftu8ELnii91wUKAqsvp88NIdAdLQnC7PeveWlquVSAf//2WtAkdBI7xnhXaL/ObUkhHheT0aR5miYmDyLAkTBj8CAwEAAaOCAY8wggGLMB8GA1UdIwQYMBaAFEZy3CVynwJOVYO1gPkL2+mTs/RFMB0GA1UdDgQWBBS0k6A7ZSwLRwbIhFsgcChrYd27PDALBgNVHQ8EBAMCBaAwDAYDVR0TBAUwAwEBADA7BgNVHSUENDAyBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDBAYIKwYBBQUHAwgwgfAGA1UdHwSB6DCB5TBPoE2gS6RJMEcxCzAJBgNVBAYTAkNOMRUwEwYDVQQKEwxDRkNBIFRFU1QgQ0ExDDAKBgNVBAsTA0NSTDETMBEGA1UEAxMKY3JsMTI2XzE5NDCBkaCBjqCBi4aBiGxkYXA6Ly90ZXN0bGRhcC5jZmNhLmNvbS5jbjozODkvQ049Y3JsMTI2XzE5NCxPVT1DUkwsTz1DRkNBIFRFU1QgQ0EsQz1DTj9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0P2Jhc2U/b2JqZWN0Y2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnQwDQYJKoZIhvcNAQEFBQADgYEAKX4CXCPQEE4RWGsZTXZXLBct2gcPYEjqpgPZ5ERiUrYLTDGuIT90ECfSoxCrcTJEeY7EJBojig9gLRoMn/4xXW/XscGarQ3XxyZw8VxTMFkotuUkAPoaacYlIrc34t2DR0DqvU6umgFL3yTMYxl5WLjOh47OH7Aw7VPscmrtzEIxgd0wgdoCAQEwODAkMQswCQYDVQQGEwJDTjEVMBMGA1UEChMMQ0ZDQSBURVNUIENBAhAuyfCgPbMcigfvVyGazeQRMAkGBSsOAwIaBQAwDQYJKoZIhvcNAQEBBQAEgYCD/g83n6KyattYAEPqff/9z613+4AaZDHVxY9xEb3lBGRRosVQptgkZItEc9cM2Em/o9GfV/mqj5T6CP5glvbbtFnrz2Z0GGNbDR/gqOIPhpACRZozZipwUeQESVhRCiCJa4sPuoEkgSSq5XvL5nIvAxc59DeKWIv/LGqYq9dK8Q==</hmac><ret_Code>1</ret_Code><batch_No>' + batchNo + '</batch_No><total_Num>1</total_Num><end_Flag>Y</end_Flag><list><items><item><remarksInfo></remarksInfo><amount>0.01</amount><fee></fee><abstractInfo>提现打款</abstractInfo><note/><order_Id>PAYMENT78162155286528</order_Id><payee_Bank_Account>1506213009022200623</payee_Bank_Account><refund_Date></refund_Date><real_pay_amount>0.01</real_pay_amount><payee_BankName>工商银行</payee_BankName><complete_Date>2020-01-16 18:20:09</complete_Date><request_Date>2020-01-16 18:20:08</request_Date><payee_Name>蒋素霞</payee_Name><bank_Status>S</bank_Status><r1_Code>0026</r1_Code><fail_Desc></fail_Desc></item></items></list></data>";
}
modifyResponse(response, transferResponse);
return false;
}
if (mock.getType() == 1) {
responseMap = handleResponseMap(requestMap, responseMap);
modifyResponse(response, JSON.toJSONString(responseMap), "application/json; charset=utf-8");
return true;
} else if (mock.getType() == 2) {
modifyResponse(response, responseStr);
return true;
}
}
return true;
}
/**
* 修改返回响应
* @param response HttpServletResponse
* @param result 返回的json或字符串
*/
private void modifyResponse(HttpServletResponse response, String result) {
PrintWriter writer = null;
response.setCharacterEncoding("UTF-8");
// response.setContentType("application/json; charset=utf-8");
try {
writer = response.getWriter();
writer.print(result);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (writer != null) {
writer.close();
}
}
}
/**
* 修改返回响应
* @param response HttpServletResponse
* @param result 返回的json或字符串
* @param contentType content-type
*/
private void modifyResponse(HttpServletResponse response, String result, String contentType) {
PrintWriter writer = null;
response.setCharacterEncoding("UTF-8");
response.setContentType(contentType);
try {
writer = response.getWriter();
writer.print(result);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (writer != null) {
writer.close();
}
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
}
}
package cn.qg.holmes.mapper.mock;
import cn.qg.holmes.entity.mock.Mock;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface MockMapper extends BaseMapper<Mock> {
}
package cn.qg.holmes.service.mock;
import cn.qg.holmes.entity.mock.Mock;
import com.baomidou.mybatisplus.extension.service.IService;
public interface MockService extends IService<Mock> {
}
package cn.qg.holmes.service.mock.impl;
import cn.qg.holmes.entity.mock.Mock;
import cn.qg.holmes.mapper.mock.MockMapper;
import cn.qg.holmes.service.mock.MockService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service
public class MockServiceImpl extends ServiceImpl<MockMapper, Mock> implements MockService {
}
package cn.qg.holmes.utils;
import com.alibaba.fastjson.JSONObject;
public class BankCardUtils {
public static String getCardCode(String cardNo) {
String url = "https://ccdcapi.alipay.com/validateAndCacheCardInfo.json?_input_charset=utf-8&cardNo=" + cardNo + "&cardBinCheck=true";
JSONObject resposne = HttpClientUtils.doGetReturnJson(url);
return resposne.get("bank").toString();
}
public static void main(String[] args) {
System.out.println(getBankName("CCB"));
}
public static String getBankName(String code){
int a = 0;
for (int i = 0; i < bankBin.length-165; i++) {
if(code.equals(bankBin[i+a])){
return bankBin[i+a+1];
}
a++;
}
return "";
}
private final static String[] bankBin = {
"SRCB", "深圳农村商业银行",
"BGB", "广西北部湾银行",
"SHRCB", "上海农村商业银行",
"BJBANK", "北京银行",
"WHCCB", "威海市商业银行",
"BOZK", "周口银行",
"KORLABANK", "库尔勒市商业银行",
"SPABANK", "平安银行",
"SDEB", "顺德农商银行",
"HURCB", "湖北省农村信用社",
"WRCB", "无锡农村商业银行",
"BOCY", "朝阳银行",
"CZBANK", "浙商银行",
"HDBANK", "邯郸银行",
"BOC", "中国银行",
"BOD", "东莞银行",
"CCB", "中国建设银行",
"ZYCBANK", "遵义市商业银行",
"SXCB", "绍兴银行",
"GZRCU", "贵州省农村信用社",
"ZJKCCB", "张家口市商业银行",
"BOJZ", "锦州银行",
"BOP", "平顶山银行",
"HKB", "汉口银行",
"SPDB", "上海浦东发展银行",
"NXRCU", "宁夏黄河农村商业银行",
"NYNB", "广东南粤银行",
"GRCB", "广州农商银行",
"BOSZ", "苏州银行",
"HZCB", "杭州银行",
"HSBK", "衡水银行",
"HBC", "湖北银行",
"JXBANK", "嘉兴银行",
"HRXJB", "华融湘江银行",
"BODD", "丹东银行",
"AYCB", "安阳银行",
"EGBANK", "恒丰银行",
"CDB", "国家开发银行",
"TCRCB", "江苏太仓农村商业银行",
"NJCB", "南京银行",
"ZZBANK", "郑州银行",
"DYCB", "德阳商业银行",
"YBCCB", "宜宾市商业银行",
"SCRCU", "四川省农村信用",
"KLB", "昆仑银行",
"LSBANK", "莱商银行",
"YDRCB", "尧都农商行",
"CCQTGB", "重庆三峡银行",
"FDB", "富滇银行",
"JSRCU", "江苏省农村信用联合社",
"JNBANK", "济宁银行",
"CMB", "招商银行",
"JINCHB", "晋城银行JCBANK",
"FXCB", "阜新银行",
"WHRCB", "武汉农村商业银行",
"HBYCBANK", "湖北银行宜昌分行",
"TZCB", "台州银行",
"TACCB", "泰安市商业银行",
"XCYH", "许昌银行",
"CEB", "中国光大银行",
"NXBANK", "宁夏银行",
"HSBANK", "徽商银行",
"JJBANK", "九江银行",
"NHQS", "农信银清算中心",
"MTBANK", "浙江民泰商业银行",
"LANGFB", "廊坊银行",
"ASCB", "鞍山银行",
"KSRB", "昆山农村商业银行",
"YXCCB", "玉溪市商业银行",
"DLB", "大连银行",
"DRCBCL", "东莞农村商业银行",
"GCB", "广州银行",
"NBBANK", "宁波银行",
"BOYK", "营口银行",
"SXRCCU", "陕西信合",
"GLBANK", "桂林银行",
"BOQH", "青海银行",
"CDRCB", "成都农商银行",
"QDCCB", "青岛银行",
"HKBEA", "东亚银行",
"HBHSBANK", "湖北银行黄石分行",
"WZCB", "温州银行",
"TRCB", "天津农商银行",
"QLBANK", "齐鲁银行",
"GDRCC", "广东省农村信用社联合社",
"ZJTLCB", "浙江泰隆商业银行",
"GZB", "赣州银行",
"GYCB", "贵阳市商业银行",
"CQBANK", "重庆银行",
"DAQINGB", "龙江银行",
"CGNB", "南充市商业银行",
"SCCB", "三门峡银行",
"CSRCB", "常熟农村商业银行",
"SHBANK", "上海银行",
"JLBANK", "吉林银行",
"CZRCB", "常州农村信用联社",
"BANKWF", "潍坊银行",
"ZRCBANK", "张家港农村商业银行",
"FJHXBC", "福建海峡银行",
"ZJNX", "浙江省农村信用社联合社",
"LZYH", "兰州银行",
"JSB", "晋商银行",
"BOHAIB", "渤海银行",
"CZCB", "浙江稠州商业银行",
"YQCCB", "阳泉银行",
"SJBANK", "盛京银行",
"XABANK", "西安银行",
"BSB", "包商银行",
"JSBANK", "江苏银行",
"FSCB", "抚顺银行",
"HNRCU", "河南省农村信用",
"COMM", "交通银行",
"XTB", "邢台银行",
"CITIC", "中信银行",
"HXBANK", "华夏银行",
"HNRCC", "湖南省农村信用社",
"DYCCB", "东营市商业银行",
"ORBANK", "鄂尔多斯银行",
"BJRCB", "北京农村商业银行",
"XYBANK", "信阳银行",
"ZGCCB", "自贡市商业银行",
"CDCB", "成都银行",
"HANABANK", "韩亚银行",
"CMBC", "中国民生银行",
"LYBANK", "洛阳银行",
"GDB", "广东发展银行",
"ZBCB", "齐商银行",
"CBKF", "开封市商业银行",
"H3CB", "内蒙古银行",
"CIB", "兴业银行",
"CRCBANK", "重庆农村商业银行",
"SZSBK", "石嘴山银行",
"DZBANK", "德州银行",
"SRBANK", "上饶银行",
"LSCCB", "乐山市商业银行",
"JXRCU", "江西省农村信用",
"ICBC", "中国工商银行",
"JZBANK", "晋中市商业银行",
"HZCCB", "湖州市商业银行",
"NHB", "南海农村信用联社",
"XXBANK", "新乡银行",
"JRCB", "江苏江阴农村商业银行",
"YNRCC", "云南省农村信用社",
"ABC", "中国农业银行",
"GXRCU", "广西省农村信用",
"PSBC", "中国邮政储蓄银行",
"BZMD", "驻马店银行",
"ARCU", "安徽省农村信用社",
"GSRCU", "甘肃省农村信用",
"LYCB", "辽阳市商业银行",
"JLRCU", "吉林农信",
"URMQCCB", "乌鲁木齐市商业银行",
"XLBANK", "中山小榄村镇银行",
"CSCB", "长沙银行",
"JHBANK", "金华银行",
"BHB", "河北银行",
"NBYZ", "鄞州银行",
"LSBC", "临商银行",
"BOCD", "承德银行",
"SDRCU", "山东农信",
"NCB", "南昌银行",
"TCCB", "天津银行",
"WJRCB", "吴江农商银行",
"CBBQS", "城市商业银行资金清算中心",
"HBRCU", "河北省农村信用社"
};
}
package cn.qg.holmes.utils;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.util.*;
@Slf4j
public class HttpClientUtils {
private static final CloseableHttpClient client = HttpClients.createDefault();
/**
* 不带参数的GET请求
* @param url 请求的url
* @return json
*/
public static JSONObject doGetReturnJson(String url) {
JSONObject jsonResult = new JSONObject();
HttpGet get = new HttpGet(url);
try {
CloseableHttpResponse response = client.execute(get);
HttpEntity httpEntity = response.getEntity();
String respStr = EntityUtils.toString(httpEntity, "utf-8");
jsonResult = JSONObject.parseObject(respStr);
} catch (IOException e) {
e.printStackTrace();
}
return jsonResult;
}
/**
* 不带参数的GET请求
* @param url 请求的url
* @return html代码
*/
public static String doGetReturnHtml(String url) {
String strResult = null;
HttpGet get = new HttpGet(url);
try {
CloseableHttpResponse response = client.execute(get);
HttpEntity httpEntity = response.getEntity();
strResult = EntityUtils.toString(httpEntity, "utf-8");
} catch (IOException e) {
e.printStackTrace();
}
return strResult;
}
/**
* 带参数的GET请求
* @param url 请求url
* @param params 请求参数
* @param headers 请求头
* @throws URISyntaxException
* @return
*/
public static String doGetReturnHtml(String url, Map<String, Object> params, Map<String, Object> headers) throws URISyntaxException {
URIBuilder uriBuilder = new URIBuilder(url);
String strResult = null;
// 设置请求参数
if (params != null && !params.isEmpty()) {
Set<String> keySet = params.keySet();
for (String key : keySet) {
uriBuilder.setParameter(key, params.get(key).toString());
}
}
HttpGet get = new HttpGet(uriBuilder.build());
// 设置请求头
if (headers != null && !headers.isEmpty()) {
Set<String> keySet = headers.keySet();
for (String s : keySet) {
get.addHeader(s, headers.get(s).toString());
}
}
try {
CloseableHttpResponse response = client.execute(get);
HttpEntity httpEntity = response.getEntity();
strResult = EntityUtils.toString(httpEntity, "utf-8");
} catch (IOException e) {
e.printStackTrace();
}
return strResult;
}
/**
* 带参数的GET请求
* @param url url
* @param params 参数
* @param headers 请求头
* @return json
* @throws URISyntaxException
*/
public static JSONObject doGetReturnJson(String url, Map<String, Object> params, Map<String, Object> headers) throws URISyntaxException {
JSONObject jsonResult = new JSONObject();
URIBuilder uriBuilder = new URIBuilder(url);
// 设置参数
if (params != null && !params.isEmpty()) {
Set<String> keySet = params.keySet();
for (String key : keySet) {
uriBuilder.setParameter(key, params.get(key).toString());
}
}
HttpGet get = new HttpGet(uriBuilder.build());
if (headers != null && !headers.isEmpty()) {
Set<String> keySet = headers.keySet();
for (String s : keySet) {
get.addHeader(s, headers.get(s).toString());
}
}
try {
CloseableHttpResponse response = client.execute(get);
HttpEntity httpEntity = response.getEntity();
String respStr = EntityUtils.toString(httpEntity, "utf-8");
jsonResult = JSONObject.parseObject(respStr);
} catch (IOException e) {
e.printStackTrace();
}
return jsonResult;
}
/**
* 带参数的post请求
* @param url
* @param params
* @return
*/
public static JSONObject doPost(String url, String params) {
JSONObject jsonResult = new JSONObject();
try {
HttpPost post = new HttpPost(url);
List<NameValuePair> list = new ArrayList<>();
if (StringUtils.isNotEmpty(params)) {
String[] splitStrings = params.split("&");
for (String splitString : splitStrings) {
String[] split = splitString.split("=");
list.add(new BasicNameValuePair(split[0], split[1]));
}
UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(list, "utf-8");
post.setEntity(urlEncodedFormEntity);
}
CloseableHttpResponse response = client.execute(post);
HttpEntity responseEntity = response.getEntity();
String responseString = EntityUtils.toString(responseEntity, "utf-8");
try {
jsonResult = JSONObject.parseObject(responseString);
} catch (JSONException e) {
jsonResult.put("content", responseString);
}
} catch (IOException e) {
e.printStackTrace();
}
return jsonResult;
}
public static JSONObject doPost(String url, Map<String, Object> params) {
JSONObject jsonResult = new JSONObject();
try {
HttpPost post = new HttpPost(url);
List list = new ArrayList();
if (params != null && !params.isEmpty()) {
Set<String> keySet = params.keySet();
for (String key : keySet) {
list.add(new BasicNameValuePair(key, params.get(key).toString()));
}
UrlEncodedFormEntity urlEncodedFormEntity =
new UrlEncodedFormEntity(list, "utf-8");
post.setEntity(urlEncodedFormEntity);
}
CloseableHttpResponse response = client.execute(post);
HttpEntity entity = response.getEntity();
String respEntity = EntityUtils.toString(entity, "utf-8");
try {
jsonResult = JSONObject.parseObject(respEntity);
} catch (JSONException e) {
// e.printStackTrace();
jsonResult.put("content", respEntity.toString());
}
} catch (IOException e) {
e.printStackTrace();
}
return jsonResult;
}
public static JSONObject doPost(String url, Map<String, Object> params, Map<String, Object> headers) {
JSONObject jsonResult = new JSONObject();
String responseString = null;
try {
HttpPost post = new HttpPost(url);
List list = new ArrayList();
if (params != null && !params.isEmpty()) {
Set<String> keySet = params.keySet();
for (String key : keySet) {
list.add(new BasicNameValuePair(key, params.get(key).toString()));
}
UrlEncodedFormEntity urlEncodedFormEntity =
new UrlEncodedFormEntity(list, "utf-8");
post.setEntity(urlEncodedFormEntity);
}
if (headers != null && !headers.isEmpty()) {
Set<String> keySet = headers.keySet();
for (String s : keySet) {
post.addHeader(s, headers.get(s).toString());
}
}
try {
CloseableHttpResponse response = client.execute(post);
HttpEntity responseEntity = response.getEntity();
responseString = EntityUtils.toString(responseEntity, "utf-8");
jsonResult = JSONObject.parseObject(responseString);
} catch (JSONException e) {
// e.printStackTrace();
jsonResult.put("content", responseString);
}
} catch (IOException e) {
e.printStackTrace();
}
return jsonResult;
}
public static JSONObject doPostJson(String url, String params) {
JSONObject result = new JSONObject();
HttpPost httpPost = new HttpPost(url);
if (StringUtils.isNotEmpty(params)) {
StringEntity stringEntity = new StringEntity(params, "utf-8");
httpPost.setEntity(stringEntity);
}
// if (StringUtils.isNotEmpty(headers)) {
// httpPost.setHeader("Content-Type", "application/json");
// }
httpPost.setHeader("Content-Type", "application/json");
try {
CloseableHttpResponse response = client.execute(httpPost);
HttpEntity responseEntity = response.getEntity();
String responseString = EntityUtils.toString(responseEntity, "utf-8");
result = JSONObject.parseObject(responseString);
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
public static JSONObject doPostJson(String url, String params, Map<String, Object> headers) {
JSONObject result = new JSONObject();
HttpPost httpPost = new HttpPost(url);
if (StringUtils.isNotEmpty(params)) {
StringEntity stringEntity = new StringEntity(params, "utf-8");
httpPost.setEntity(stringEntity);
}
if (headers != null && !headers.isEmpty()) {
Set<String> keySet = headers.keySet();
for (String s : keySet) {
httpPost.addHeader(s, headers.get(s).toString());
}
}
try {
CloseableHttpResponse response = client.execute(httpPost);
HttpEntity responseEntity = response.getEntity();
String responseString = EntityUtils.toString(responseEntity, "utf-8");
result = JSONObject.parseObject(responseString);
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
public static void main(String[] args) throws UnsupportedEncodingException {
String url = "http://passportapi-qa.liangkebang.net/user/login/fastV1";
String phoneNo = "13712345678:0000";
Base64.Encoder encoder = Base64.getEncoder();
byte[] textByte = phoneNo.getBytes("UTF-8");
String phoneNoBase64 = encoder.encodeToString(textByte);
Map<String, Object> headers = new HashMap<>();
Map<String, Object> formData = new HashMap<>();
headers.put("Content-Type", "application/x-www-form-urlencoded");
headers.put("Authorization", "Verification " + phoneNoBase64);
formData.put("channelId", 1);
formData.put("createdFrom", 1);
formData.put("key", "xyqb");
formData.put("btRegisterChannelId", "");
formData.put("dimension", "");
formData.put("click_id", "");
JSONObject result = doPost(url, formData, headers);
System.out.println(result);
System.out.println(result.get("data"));
}
}
package cn.qg.holmes.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Component
public class RedisUtils {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public RedisUtils(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
/**
* 指定缓存失效时间
*
* @param key 键
* @param time 时间(秒)
* @return
*/
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据key 获取过期时间
*
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* 判断key是否存在
*
* @param key 键
* @return true 存在 false不存在
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除缓存
*
* @param key 可以传一个值 或多个
*/
@SuppressWarnings("unchecked")
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
//============================String=============================
/**
* 普通缓存获取
*
* @param key 键
* @return 值
*/
public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 普通缓存放入并设置时间
*
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public boolean set(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 递增
*
* @param key 键
* @param delta 要增加几(大于0)
* @return
*/
public long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* 递减
*
* @param key 键
* @param delta 要减少几(小于0)
* @return
*/
public long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, -delta);
}
//================================Map=================================
/**
* HashGet
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return 值
*/
public Object hget(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}
/**
* 获取hashKey对应的所有键值
*
* @param key 键
* @return 对应的多个键值
*/
public Map<Object, Object> hmget(String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* HashSet
*
* @param key 键
* @param map 对应多个键值
* @return true 成功 false 失败
*/
public boolean hmset(String key, Map<String, Object> map) {
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* HashSet 并设置时间
*
* @param key 键
* @param map 对应多个键值
* @param time 时间(秒)
* @return true成功 false失败
*/
public boolean hmset(String key, Map<String, Object> map, long time) {
try {
redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value, long time) {
try {
redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除hash表中的值
*
* @param key 键 不能为null
* @param item 项 可以使多个 不能为null
*/
public void hdel(String key, Object... item) {
redisTemplate.opsForHash().delete(key, item);
}
/**
* 判断hash表中是否有该项的值
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return true 存在 false不存在
*/
public boolean hHasKey(String key, String item) {
return redisTemplate.opsForHash().hasKey(key, item);
}
/**
* hash递增 如果不存在,就会创建一个 并把新增后的值返回
*
* @param key 键
* @param item 项
* @param by 要增加几(大于0)
* @return
*/
public double hincr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, by);
}
/**
* hash递减
*
* @param key 键
* @param item 项
* @param by 要减少记(小于0)
* @return
*/
public double hdecr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, -by);
}
//============================set=============================
/**
* 根据key获取Set中的所有值
*
* @param key 键
* @return
*/
public Set<Object> sGet(String key) {
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 根据value从一个set中查询,是否存在
*
* @param key 键
* @param value 值
* @return true 存在 false不存在
*/
public boolean sHasKey(String key, Object value) {
try {
return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将数据放入set缓存
*
* @param key 键
* @param values 值 可以是多个
* @return 成功个数
*/
public long sSet(String key, Object... values) {
try {
return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 将set数据放入缓存
*
* @param key 键
* @param time 时间(秒)
* @param values 值 可以是多个
* @return 成功个数
*/
public long sSetAndTime(String key, long time, Object... values) {
try {
Long count = redisTemplate.opsForSet().add(key, values);
if (time > 0) {
expire(key, time);
}
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 获取set缓存的长度
*
* @param key 键
* @return
*/
public long sGetSetSize(String key) {
try {
return redisTemplate.opsForSet().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 移除值为value的
*
* @param key 键
* @param values 值 可以是多个
* @return 移除的个数
*/
public long setRemove(String key, Object... values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
//===============================list=================================
/**
* 获取list缓存的内容
*
* @param key 键
* @param start 开始
* @param end 结束 0 到 -1代表所有值
* @return
*/
public List<Object> lGet(String key, long start, long end) {
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 获取list缓存的长度
*
* @param key 键
* @return
*/
public long lGetListSize(String key) {
try {
return redisTemplate.opsForList().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 通过索引 获取list中的值
*
* @param key 键
* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
* @return
*/
public Object lGetIndex(String key, long index) {
try {
return redisTemplate.opsForList().index(key, index);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return
*/
public boolean lSet(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, Object value, long time) {
try {
redisTemplate.opsForList().rightPush(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return
*/
public boolean lSet(String key, List<Object> value) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, List<Object> value, long time) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据索引修改list中的某条数据
*
* @param key 键
* @param index 索引
* @param value 值
* @return
*/
public boolean lUpdateIndex(String key, long index, Object value) {
try {
redisTemplate.opsForList().set(key, index, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 移除N个值为value
*
* @param key 键
* @param count 移除多少个
* @param value 值
* @return 移除的个数
*/
public long lRemove(String key, long count, Object value) {
try {
Long remove = redisTemplate.opsForList().remove(key, count, value);
return remove;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 模糊查询获取key值
*
* @param pattern
* @return
*/
public Set keys(String pattern) {
return redisTemplate.keys(pattern);
}
/**
* 使用Redis的消息队列
*
* @param channel
* @param message 消息内容
*/
public void convertAndSend(String channel, Object message) {
redisTemplate.convertAndSend(channel, message);
}
/**
* 根据起始结束序号遍历Redis中的list
*
* @param listKey
* @param start 起始序号
* @param end 结束序号
* @return
*/
public List<Object> rangeList(String listKey, long start, long end) {
//绑定操作
BoundListOperations<String, Object> boundValueOperations = redisTemplate.boundListOps(listKey);
//查询数据
return boundValueOperations.range(start, end);
}
/**
* 弹出右边的值 --- 并且移除这个值
*
* @param listKey
*/
public Object rifhtPop(String listKey) {
//绑定操作
BoundListOperations<String, Object> boundValueOperations = redisTemplate.boundListOps(listKey);
return boundValueOperations.rightPop();
}
}
spring:
datasource:
url: jdbc:mysql://172.17.5.5:32178/holmes
username: qa
password: qatest
driver-class-name: com.mysql.jdbc.Driver
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
redis:
host: 172.17.5.12
port: 32236
database: 0
jedis:
pool:
max-active: 8
max-wait: -1
max-idle: 8
application:
name: holmes
server:
port: 8084
mybatis-plus:
mapper-locations: classpath:mapper/*/*.xml
type-aliases-package: cn.qg.holmes.entity
configuration:
map-underscore-to-camel-case: true
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 日志配置 -->
<configuration>
<property name="DEV_HOME" value="."/>
<springProperty name="spring.application.name" source="spring.application.name"/>
<property name="LOG_LEVEL_PATTERN"
value="%clr(%5p) %clr([${spring.application.name:-},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}]){yellow}"/>
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%10.10t]){faint} [%40.40file:%4.4line] %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!-- 这里面定义了 CONSOLE_LOG_PATTERN, FILE_LOG_PATTERN 等日志格式, 还定义了一些日志级别 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<!--滚动文件日志-->
<appender name="fileLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${DEV_HOME}/debug.log</file>
<append>true</append>
<encoder>
<!--日志输出格式-->
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily -->
<fileNamePattern>${DEV_HOME}/debug.%d{yyyy-MM-dd}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>300MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>
<logger name="com.example.demo" level="DEBUG"/>
<logger name="org.apache" level="warn"/>
<logger name="org.springframework" level="warn"/>
<logger name="ch.qos.logback" level="warn"/>
<!--基础的日志输出-->
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="fileLog"/>
</root>
</configuration>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 日志配置 -->
<configuration>
<springProperty name="spring.application.name" source="spring.application.name"/>
<property name="LOG_LEVEL_PATTERN" value="%5p [${spring.application.name:-},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}]"/>
<property name="FILE_LOG_PATTERN"
value="${FILE_LOG_PATTERN:-%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%5p} --- [%thread] [%file:%line] %logger - %msg%n}"/>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/home/quant_group/logs/qa-platform.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/home/quant_group/logs/qa-platform.log.%d{yyyy-MM-dd}</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<appender name="Sentry" class="cn.quantgroup.sentry.appender.StandardSentryAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>WARN</level>
<!-- level:基本建议ERROR or WARN -->
</filter>
</appender>
<logger name="org.springframework" level="warn"/>
<logger name="org.hibernate" level="warn"/>
<logger name="org.apache" level="warn"/>
<logger name="ch.qos.logback" level="warn"/>
<!--基础的日志输出-->
<root level="INFO">
<appender-ref ref="FILE"/>
<appender-ref ref="Sentry"/>
</root>
</configuration>
\ No newline at end of file
package cn.qg.holmes;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class HolmesApplicationTests {
@Test
void contextLoads() {
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment