"src/main/webapp/templets/1/default/footer.htm" did not exist on "c9bf4f7e66b8fafcfe4ad7ff795c691daab54f8b"
Commit de3de82d authored by dingzhiwei's avatar dingzhiwei
Browse files

初始化Jeepay项目

parent 40dcaf4a
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.utils;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
/*
* 文件工具类
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:50
*/
public class FileKit {
/**
* 获取文件的后缀名
* @param appendDot 是否拼接.
* @return
*/
public static String getFileSuffix(String fullFileName, boolean appendDot){
if(fullFileName == null || fullFileName.indexOf(".") < 0 || fullFileName.length() <= 1) return "";
return (appendDot? "." : "") + fullFileName.substring(fullFileName.lastIndexOf(".") + 1);
}
/** 获取有效的图片格式, 返回null: 不支持的图片类型 **/
public static String getImgSuffix(String filePath){
String suffix = getFileSuffix(filePath, false).toLowerCase();
if(CS.ALLOW_UPLOAD_IMG_SUFFIX.contains(suffix)){
return suffix;
}
throw new BizException("不支持的图片类型");
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.utils;
import cn.hutool.crypto.SecureUtil;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import sun.misc.BASE64Decoder;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
/*
* jeepay工具类
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:50
*/
@Slf4j
public class JeepayKit {
public static byte[] AES_KEY = null;
static{
try {
AES_KEY = new BASE64Decoder().decodeBuffer("4ChT08phkz59hquD795X7w==");
} catch (IOException e) {
}
}
/** 加密 **/
public static String aesEncode(String str){
return SecureUtil.aes(JeepayKit.AES_KEY).encryptHex(str);
}
public static String aesDecode(String str){
return SecureUtil.aes(JeepayKit.AES_KEY).decryptStr(str);
}
private static String encodingCharset = "UTF-8";
/**
* <p><b>Description: </b>计算签名摘要
* <p>2018年9月30日 上午11:32:46
* @param map 参数Map
* @param key 商户秘钥
* @return
*/
public static String getSign(Map<String,Object> map, String key){
ArrayList<String> list = new ArrayList<String>();
for(Map.Entry<String,Object> entry:map.entrySet()){
if(null != entry.getValue() && !"".equals(entry.getValue())){
list.add(entry.getKey() + "=" + entry.getValue() + "&");
}
}
int size = list.size();
String [] arrayToSort = list.toArray(new String[size]);
Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
StringBuilder sb = new StringBuilder();
for(int i = 0; i < size; i ++) {
sb.append(arrayToSort[i]);
}
String result = sb.toString();
result += "key=" + key;
log.info("signStr:{}", result);
result = md5(result, encodingCharset).toUpperCase();
log.info("sign:{}", result);
return result;
}
/**
* <p><b>Description: </b>MD5
* <p>2018年9月30日 上午11:33:19
* @param value
* @param charset
* @return
*/
public static String md5(String value, String charset) {
MessageDigest md = null;
try {
byte[] data = value.getBytes(charset);
md = MessageDigest.getInstance("MD5");
byte[] digestData = md.digest(data);
return toHex(digestData);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
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();
}
/** map 转换为 url参数 **/
public static String genUrlParams(Map<String, Object> paraMap) {
if(paraMap == null || paraMap.isEmpty()) return "";
StringBuffer urlParam = new StringBuffer();
Set<String> keySet = paraMap.keySet();
int i = 0;
for(String key:keySet) {
urlParam.append(key).append("=").append( paraMap.get(key) == null ? "" : paraMap.get(key) );
if(++i == keySet.size()) break;
urlParam.append("&");
}
return urlParam.toString();
}
/** 校验微信/支付宝二维码是否符合规范, 并根据支付类型返回对应的支付方式 **/
public static String getPayWayCodeByBarCode(String barCode){
if(StringUtils.isEmpty(barCode)) throw new BizException("条码为空");
//微信 : 用户付款码条形码规则:18位纯数字,以10、11、12、13、14、15开头
//文档: https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=5_1
if(barCode.length() == 18 && Pattern.matches("^(10|11|12|13|14|15)(.*)", barCode)){
return CS.PAY_WAY_CODE.WX_BAR;
}
//支付宝: 25~30开头的长度为16~24位的数字
//文档: https://docs.open.alipay.com/api_1/alipay.trade.pay/
else if(barCode.length() >= 16 && barCode.length() <= 24 && Pattern.matches("^(25|26|27|28|29|30)(.*)", barCode)){
return CS.PAY_WAY_CODE.ALI_BAR;
}
//云闪付: 二维码标准: 19位 + 62开头
//文档:https://wenku.baidu.com/view/b2eddcd09a89680203d8ce2f0066f5335a8167fa.html
else if(barCode.length() == 19 && Pattern.matches("^(62)(.*)", barCode)){
return CS.PAY_WAY_CODE.YSF_BAR;
}
else{ //暂时不支持的条码类型
throw new BizException("不支持的条码");
}
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.utils;
import com.alibaba.fastjson.JSONObject;
/*
* json工具类
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:51
*/
public class JsonKit {
public static JSONObject newJson(String key, Object val){
JSONObject result = new JSONObject();
result.put(key, val);
return result;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.utils;
/*
*
* 正则验证kit
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:56
*/
public class RegKit {
public static final String REG_MOBILE = "^1\\d{10}$"; //判断是否是手机号
public static boolean isMobile(String str){
return match(str, REG_MOBILE);
}
/** 正则验证 */
public static boolean match(String text, String reg){
if(text == null) return false;
return text.matches(reg);
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.utils;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import java.util.Date;
import java.util.concurrent.atomic.AtomicLong;
/*
* 序列号生成 工具类
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:56
*/
public class SeqKit {
private static final AtomicLong BUY_ORDER_SEQ = new AtomicLong(0L);
private static final String BUY_ORDER_SEQ_PREFIX = "P";
/** 生成购买订单ID **/
public static String genPayOrderId() {
return String.format("%s%s%04d",BUY_ORDER_SEQ_PREFIX,
DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN),
(int) BUY_ORDER_SEQ.getAndIncrement() % 10000);
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.utils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* @description: Spring 框架下, 获取Beans静态函数方法。
* @Author terrfly
* @Date 2019/12/31 13:57
*/
@Component
public class SpringBeansUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(SpringBeansUtil.applicationContext == null){
SpringBeansUtil.applicationContext = applicationContext;
}
}
/** 获取applicationContext */
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/** 通过name获取 Bean. */
public static Object getBean(String name){
if(!getApplicationContext().containsBean(name)){
return null;
}
return getApplicationContext().getBean(name);
}
/** 通过class获取Bean. */
public static <T> T getBean(Class<T> clazz){
try {
return getApplicationContext().getBean(clazz);
} catch (BeansException e) {
return null;
}
}
/** 通过name,以及Clazz返回指定的Bean */
public static <T> T getBean(String name, Class<T> clazz){
if(!getApplicationContext().containsBean(name)){
return null;
}
return getApplicationContext().getBean(name, clazz);
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.utils;
import java.util.UUID;
/*
* String 工具类
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:58
*/
public class StringKit {
public static String getUUID(){
return UUID.randomUUID().toString().replace("-", "") + Thread.currentThread().getId();
}
public static String getUUID(int endAt){
return getUUID().substring(0, endAt);
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.utils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/*
* [ 通用树状结构构造器 ]
* 解决: 将数据库查询到的多行List, 转换为层级关系的树状结构。
* 使用方式:
* 1. 先将查询的到对象List转换为JSONObject List,
* 在转换过程中JSONObject中必须包含 [id, pid](字段名称可自定义) 【!!必须是String类型!!】 ;
* 2. 使用构造函数创建对象,参数为转换好的对象, 如果自定义字段key 则将字段名称一并传入;
* 3. 使用buildTreeString() 或者 buildTreeObject() 生成所需对象;
*
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2019/12/8 06:37
*/
public class TreeDataBuilder {
/** 私有构造器 + 指定参数构造器 **/
private TreeDataBuilder(){}
public TreeDataBuilder(Collection nodes) {
super();
this.nodes = nodes;
}
public TreeDataBuilder(Collection nodes, String idName, String pidName, String childrenName) {
super();
this.nodes = nodes;
this.idName = idName;
this.sortName = idName; //排序字段,按照idName
this.pidName = pidName;
this.childrenName = childrenName;
}
/** 自定义字段 + 排序标志 **/
public TreeDataBuilder(Collection nodes, String idName, String pidName, String childrenName, String sortName, boolean isAscSort) {
super();
this.nodes = nodes;
this.idName = idName;
this.pidName = pidName;
this.childrenName = childrenName;
this.sortName = sortName;
this.isAscSort = isAscSort;
}
/** 所有数据集合 **/
private Collection<JSONObject> nodes;
/** 默认数据中的主键key */
private String idName = "id";
/** 默认数据中的父级id的key */
private String pidName = "pid";
/** 默认数据中的子类对象key */
private String childrenName = "children";
/** 排序字段, 默认按照ID排序 **/
private String sortName = idName;
/** 默认按照升序排序 **/
private boolean isAscSort = true;
// 构建JSON树形结构
public String buildTreeString() {
List<JSONObject> nodeTree = buildTreeObject();
JSONArray jsonArray = new JSONArray();
nodeTree.stream().forEach(item -> jsonArray.add(item));
return jsonArray.toString();
}
// 构建树形结构
public List<JSONObject> buildTreeObject() {
//定义待返回的对象
List<JSONObject> resultNodes = new ArrayList<>();
//获取所有的根节点 (考虑根节点有多个的情况, 将根节点单独处理)
List<JSONObject> rootNodes = getRootNodes();
listSort(rootNodes); //排序
//遍历根节点对象
for (JSONObject rootNode : rootNodes) {
buildChildNodes(rootNode); //递归查找子节点并设置
resultNodes.add(rootNode); //添加到对象信息
}
return resultNodes;
}
/** 递归查找并赋值子节点 **/
private void buildChildNodes(JSONObject node) {
List<JSONObject> children = getChildNodes(node);
if (!children.isEmpty()) {
for (JSONObject child : children) {
buildChildNodes(child);
}
listSort(children); //排序
node.put(childrenName, children);
}
}
/** 查找当前节点的子节点 */
private List<JSONObject> getChildNodes(JSONObject currentNode) {
List<JSONObject> childNodes = new ArrayList<>();
for (JSONObject n : nodes) {
if (currentNode.getString(idName).equals(n.getString(pidName))) {
childNodes.add(n);
}
}
return childNodes;
}
/** 判断是否为根节点 */
private boolean isRootNode(JSONObject node) {
boolean isRootNode = true;
for (JSONObject n : nodes) {
if (node.getString(pidName) != null && node.getString(pidName).equals(n.getString(idName))) {
isRootNode = false;
break;
}
}
return isRootNode;
}
/** 获取集合中所有的根节点 */
private List<JSONObject> getRootNodes() {
List<JSONObject> rootNodes = new ArrayList<>();
for (JSONObject n : nodes) {
if (isRootNode(n)) {
rootNodes.add(n);
}
}
return rootNodes;
}
/** 将list进行排序 */
private void listSort(List<JSONObject> list){
Collections.sort(list, (o1, o2) -> {
int result;
if(o1.get(sortName) instanceof Integer){
result = o1.getInteger(sortName).compareTo(o2.getInteger(sortName));
}else{
result = o1.get(sortName).toString().compareTo(o2.get(sortName).toString());
}
if(!isAscSort){ //倒序, 取反数
return -result;
}
return result;
});
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <!-- POM模型版本 -->
<groupId>com.jeequan</groupId> <!-- 组织名, 类似于包名 -->
<artifactId>jeepay-manager</artifactId> <!-- 项目名称 -->
<packaging>jar</packaging> <!-- 项目的最终打包类型/发布形式, 可选[jar, war, pom, maven-plugin]等 -->
<version>${isys.version}</version> <!-- 项目当前版本号 -->
<description>Jeepay计全支付系统 [运营后台管理端]</description> <!-- 项目描述 -->
<url>https://www.jeequan.com</url>
<parent>
<groupId>com.jeequan</groupId>
<artifactId>jeepay</artifactId>
<version>1.0.0</version>
</parent>
<!-- 项目依赖声明 -->
<dependencies>
<!-- 依赖[ service ]包, 会自动传递依赖[ core ]包。 -->
<dependency>
<groupId>com.jeequan</groupId>
<artifactId>jeepay-service</artifactId>
<version>${isys.version}</version>
</dependency>
<!-- 依赖 sping-boot-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion> <!-- 删除spring boot默认json映射器: Jackson, 引入fastJSON -->
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
</exclusion>
<exclusion> <!-- hibernate.validator插件一般不使用 -->
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- spring-security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<!-- spring-aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- freemarker -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- 添加redis支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 添加对activeMQ的支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
</dependencies>
<!-- 作为可执行jar -->
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.aop;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.beans.RequestKitBean;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.SysLog;
import com.jeequan.jeepay.core.model.security.JeeUserDetails;
import com.jeequan.jeepay.service.impl.SysLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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.lang.reflect.Method;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
/**
* 方法级日志切面组件
*
* @author terrfly
* @modify pangxiaoyu
* @site https://www.jeepay.vip
* @date 2021-06-07 07:15
*/
@Component
@Aspect
public class MethodLogAop {
private static final Logger logger = LoggerFactory.getLogger(MethodLogAop.class);
@Autowired
private SysLogService sysLogService;
@Autowired private RequestKitBean requestKitBean;
/**
* 异步处理线程池
*/
private final static ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10);
/**
* 切点
*/
@Pointcut("@annotation(com.jeequan.jeepay.core.aop.MethodLog)")
public void methodCachePointcut() { }
/**
* 切面
* @param point
* @return
* @throws Throwable
*/
@Around("methodCachePointcut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
final SysLog sysLog = new SysLog();
// 基础日志信息
setBaseLogInfo(point, sysLog);
//处理切面任务 发生异常将向外抛出 不记录日志
Object result = point.proceed();
try {
sysLog.setUserId(JeeUserDetails.getCurrentUserDetails().getSysUser().getSysUserId());
sysLog.setUserName(JeeUserDetails.getCurrentUserDetails().getSysUser().getRealname());
sysLog.setSystem(JeeUserDetails.getCurrentUserDetails().getSysUser().getSystem());
sysLog.setOptResInfo(JSONObject.toJSON(result).toString());
scheduledThreadPool.execute(() -> sysLogService.save(sysLog));
} catch (Exception e) {
logger.error("methodLogError", e);
}
return result;
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 14:04
* @describe: 记录异常操作请求信息
*/
@AfterThrowing(pointcut = "methodCachePointcut()", throwing="e")
public void doException(JoinPoint joinPoint, Throwable e) throws Exception{
final SysLog sysLog = new SysLog();
// 基础日志信息
setBaseLogInfo(joinPoint, sysLog);
sysLog.setOptResInfo("请求异常");
scheduledThreadPool.execute(() -> sysLogService.save(sysLog));
}
/**
* 获取方法中的中文备注
* @param joinPoint
* @return
* @throws Exception
*/
public static String getAnnotationRemark(JoinPoint joinPoint) throws Exception {
Signature sig = joinPoint.getSignature();
Method m = joinPoint.getTarget().getClass().getMethod(joinPoint.getSignature().getName(), ((MethodSignature) sig).getParameterTypes());
MethodLog methodCache = m.getAnnotation(MethodLog.class);
if (methodCache != null) {
return methodCache.remark();
}
return "";
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 14:12
* @describe: 日志基本信息 公共方法
*/
private void setBaseLogInfo(JoinPoint joinPoint, SysLog sysLog) throws Exception {
// 使用point.getArgs()可获取request,仅限于spring MVC参数包含request,改为通过contextHolder获取。
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//请求参数
sysLog.setOptReqParam( requestKitBean.getReqParamJSON().toJSONString() );
//注解备注
sysLog.setMethodRemark(getAnnotationRemark(joinPoint));
//包名 方法名
String methodName = joinPoint.getSignature().getName();
String packageName = joinPoint.getThis().getClass().getName();
if (packageName.indexOf("$$EnhancerByCGLIB$$") > -1 || packageName.indexOf("$$EnhancerBySpringCGLIB$$") > -1) { // 如果是CGLIB动态生成的类
packageName = packageName.substring(0, packageName.indexOf("$$"));
}
sysLog.setMethodName(packageName + "." + methodName);
sysLog.setReqUrl(request.getRequestURL().toString());
sysLog.setUserIp(requestKitBean.getClientIp());
sysLog.setCreatedAt(new Date());
sysLog.setSystem(CS.SYS_TYPE.MGR);
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.bootstrap;
import cn.hutool.core.date.DatePattern;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.Date;
/*
* 项目初始化操作
* 比如初始化配置文件, 读取基础数据, 资源初始化等。 避免在Main函数中写业务代码。
* CommandLineRunner / ApplicationRunner都可以达到要求, 只是调用参数有所不同。
*
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:04
*/
@Component
public class InitRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
//初始化处理fastjson格式
SerializeConfig serializeConfig = SerializeConfig.getGlobalInstance();
serializeConfig.put(Date.class, new SimpleDateFormatSerializer(DatePattern.NORM_DATETIME_PATTERN));
//解决json 序列化时候的 $ref:问题
JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.bootstrap;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.EnableScheduling;
import java.util.Arrays;
/*
* spring-boot 主启动程序
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2019/11/7 15:19
*/
@SpringBootApplication
@EnableScheduling
@MapperScan("com.jeequan.jeepay.service.mapper") //Mybatis mapper接口路径
@ComponentScan(basePackages = "com.jeequan.jeepay.*") //由于MainApplication没有在项目根目录, 需要配置basePackages属性使得成功扫描所有Spring组件;
@Configuration
public class JeepayMgrApplication {
/** main启动函数 **/
public static void main(String[] args) {
//启动项目
SpringApplication.run(JeepayMgrApplication.class, args);
}
/** fastJson 配置信息 **/
@Bean
public HttpMessageConverters fastJsonConfig(){
//新建fast-json转换器
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
//fast-json 配置信息
FastJsonConfig config = new FastJsonConfig();
config.setDateFormat("yyyy-MM-dd HH:mm:ss");
converter.setFastJsonConfig(config);
//设置响应的 Content-Type
converter.setSupportedMediaTypes(Arrays.asList(new MediaType[]{MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON_UTF8}));
return new HttpMessageConverters(converter);
}
/** Mybatis plus 分页插件 **/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
// paginationInterceptor.setLimit(500);
return paginationInterceptor;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.config;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
/*
* Redis配置类
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:05
*/
@Configuration
public class RedisConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private Integer port;
@Value("${spring.redis.timeout}")
private Integer timeout;
@Value("${spring.redis.database}")
private Integer defaultDatabase;
@Value("${spring.redis.password}")
private String password;
/** 当前系统的redis缓存操作对象 (主对象) **/
@Primary
@Bean(name = "defaultStringRedisTemplate")
public StringRedisTemplate sysStringRedisTemplate() {
StringRedisTemplate template = new StringRedisTemplate();
LettuceConnectionFactory jedisConnectionFactory = new LettuceConnectionFactory();
jedisConnectionFactory.setHostName(host);
jedisConnectionFactory.setPort(port);
jedisConnectionFactory.setTimeout(timeout);
if (!StringUtils.isEmpty(password)) {
jedisConnectionFactory.setPassword(password);
}
if (defaultDatabase != 0) {
jedisConnectionFactory.setDatabase(defaultDatabase);
}
jedisConnectionFactory.afterPropertiesSet();
template.setConnectionFactory(jedisConnectionFactory);
return template;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.stereotype.Component;
/**
* 系统Yml配置参数定义Bean
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021-04-27 15:50
*/
@Data
@Component
@ConfigurationProperties(prefix="isys")
public class SystemYmlConfig {
/** 是否允许跨域请求 [生产环境建议关闭, 若api与前端项目没有在同一个域名下时,应开启此配置或在nginx统一配置允许跨域] **/
private Boolean allowCors;
/** 生成jwt的秘钥。 要求每个系统有单独的秘钥管理机制。 **/
private String jwtSecret;
@NestedConfigurationProperty //指定该属性为嵌套值, 否则默认为简单值导致对象为空(外部类不存在该问题, 内部static需明确指定)
private OssFile ossFile;
/** 系统oss配置信息 **/
@Data
public static class OssFile{
/** 存储根路径 **/
private String rootPath;
/** 公共读取块 **/
private String publicPath;
/** 私有读取块 **/
private String privatePath;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl;
import com.jeequan.jeepay.core.ctrls.AbstractCtrl;
import com.jeequan.jeepay.core.model.security.JeeUserDetails;
import com.jeequan.jeepay.mgr.config.SystemYmlConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
/*
* 定义通用CommonCtrl
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:09
*/
public abstract class CommonCtrl extends AbstractCtrl {
@Autowired
protected SystemYmlConfig mainConfig;
/** 获取当前用户ID */
protected JeeUserDetails getCurrentUser(){
return (JeeUserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
}
/**
* 获取当前用户登录IP
* @return
*/
protected String getIp() {
return getClientIp();
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.cache.ITokenService;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.SysEntitlement;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.utils.TreeDataBuilder;
import com.jeequan.jeepay.core.model.security.JeeUserDetails;
import com.jeequan.jeepay.service.impl.SysEntitlementService;
import com.jeequan.jeepay.service.impl.SysUserAuthService;
import com.jeequan.jeepay.service.impl.SysUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
/*
* 当前登录者的信息相关接口
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:10
*/
@RestController
@RequestMapping("api/current")
public class CurrentUserController extends CommonCtrl{
@Autowired private SysEntitlementService sysEntitlementService;
@Autowired private SysUserService sysUserService;
@Autowired private SysUserAuthService sysUserAuthService;
@RequestMapping(value="/user", method = RequestMethod.GET)
public ApiRes currentUserInfo() {
///当前用户信息
JeeUserDetails jeeUserDetails = getCurrentUser();
SysUser user = jeeUserDetails.getSysUser();
//1. 当前用户所有权限ID集合
List<String> entIdList = new ArrayList<>();
jeeUserDetails.getAuthorities().stream().forEach(r->entIdList.add(r.getAuthority()));
List<SysEntitlement> allMenuList = new ArrayList<>(); //所有菜单集合
//2. 查询出用户所有菜单集合 (包含左侧显示菜单 和 其他类型菜单 )
if(entIdList != null && !entIdList.isEmpty()){
allMenuList = sysEntitlementService.list(SysEntitlement.gw()
.in(SysEntitlement::getEntId, entIdList)
.in(SysEntitlement::getEntType, Arrays.asList(CS.ENT_TYPE.MENU_LEFT, CS.ENT_TYPE.MENU_OTHER))
.eq(SysEntitlement::getSystem, CS.SYS_TYPE.MGR)
.eq(SysEntitlement::getState, CS.PUB_USABLE));
}
//4. 转换为json树状结构
JSONArray jsonArray = (JSONArray) JSONArray.toJSON(allMenuList);
List<JSONObject> allMenuRouteTree = new TreeDataBuilder(jsonArray,
"entId", "pid", "children", "entSort", true)
.buildTreeObject();
//1. 所有权限ID集合
user.addExt("entIdList", entIdList);
user.addExt("allMenuRouteTree", allMenuRouteTree);
return ApiRes.ok(getCurrentUser().getSysUser());
}
/** 修改个人信息 */
@RequestMapping(value="/user", method = RequestMethod.PUT)
@MethodLog(remark = "修改信息")
public ApiRes modifyCurrentUserInfo() {
//修改头像
String avatarUrl = getValString("avatarUrl");
String realname = getValString("realname");
Byte sex = getValByte("sex");
SysUser updateRecord = new SysUser();
updateRecord.setSysUserId(getCurrentUser().getSysUser().getSysUserId());
if (StringUtils.isNotEmpty(avatarUrl)) updateRecord.setAvatarUrl(avatarUrl);
if (StringUtils.isNotEmpty(realname)) updateRecord.setRealname(realname);
if (sex != null) updateRecord.setSex(sex);
sysUserService.updateById(updateRecord);
//保存redis最新数据
JeeUserDetails currentUser = getCurrentUser();
currentUser.setSysUser(sysUserService.getById(getCurrentUser().getSysUser().getSysUserId()));
ITokenService.refData(currentUser);
return ApiRes.ok();
}
/** 修改密码 */
@RequestMapping(value="modifyPwd", method = RequestMethod.PUT)
@MethodLog(remark = "修改密码")
public ApiRes modifyPwd() throws BizException{
//更改密码, 验证当前用户信息
String currentUserPwd = getValStringRequired("originalPwd"); //当前用户登录密码
//验证当前密码是否正确
if(!sysUserAuthService.validateCurrentUserPwd(currentUserPwd)){
throw new BizException("原密码验证失败!");
}
String opUserPwd = getValStringRequired("confirmPwd");
// 验证原密码与新密码是否相同
if (opUserPwd.equals(currentUserPwd)) {
throw new BizException("新密码与原密码不能相同!");
}
sysUserAuthService.resetAuthInfo(getCurrentUser().getSysUser().getSysUserId(), null, null, opUserPwd, CS.SYS_TYPE.MGR);
//调用登出接口
return logout();
}
// /** 登出 */
// @RequestMapping(value="logout", method = RequestMethod.POST)
// @MethodLog(remark = "登出")
public ApiRes logout() throws BizException{
ITokenService.removeIToken(getCurrentUser().getCacheKey(), getCurrentUser().getSysUser().getSysUserId());
return ApiRes.ok();
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.anon;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.cache.RedisUtil;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.mgr.service.AuthService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/*
* 认证接口
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:09
*/
@RestController
@RequestMapping("/api/anon/auth")
public class AuthController extends CommonCtrl {
@Autowired private AuthService authService;
/** 用户信息认证 获取iToken **/
@RequestMapping(value = "/validate", method = RequestMethod.POST)
@MethodLog(remark = "登录认证")
public ApiRes validate() throws BizException {
String account = Base64.decodeStr(getValStringRequired("ia")); //用户名 i account, 已做base64处理
String ipassport = Base64.decodeStr(getValStringRequired("ip")); //密码 i passport, 已做base64处理
String vercode = Base64.decodeStr(getValStringRequired("vc")); //验证码 vercode, 已做base64处理
String vercodeToken = Base64.decodeStr(getValStringRequired("vt")); //验证码token, vercode token , 已做base64处理
String cacheCode = RedisUtil.getString(CS.getCacheKeyImgCode(vercodeToken));
if(StringUtils.isEmpty(cacheCode) || !cacheCode.equalsIgnoreCase(vercode)){
throw new BizException("验证码有误!");
}
// 返回前端 accessToken
String accessToken = authService.auth(account, ipassport);
// 删除图形验证码缓存数据
RedisUtil.del(CS.getCacheKeyImgCode(vercodeToken));
return ApiRes.ok4newJson(CS.ACCESS_TOKEN_NAME, accessToken);
}
/** 图片验证码 **/
@RequestMapping(value = "/vercode", method = RequestMethod.GET)
public ApiRes vercode() throws BizException {
//定义图形验证码的长和宽 // 4位验证码
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(137, 40, 4, 80);
lineCaptcha.createCode(); //生成code
//redis
String vercodeToken = UUID.fastUUID().toString();
RedisUtil.setString(CS.getCacheKeyImgCode(vercodeToken), lineCaptcha.getCode(), 60 ); //图片验证码缓存时间: 1分钟
JSONObject result = new JSONObject();
result.put("imageBase64Data", lineCaptcha.getImageBase64Data());
result.put("vercodeToken", vercodeToken);
return ApiRes.ok(result);
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.common;
import cn.hutool.core.lang.UUID;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.OssFileConfig;
import com.jeequan.jeepay.core.utils.FileKit;
import com.jeequan.jeepay.mgr.config.SystemYmlConfig;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.SysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
/*
* 统一文件上传接口(ossFile)
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:07
*/
@RestController
@RequestMapping("/api/ossFiles")
public class OssFileController extends CommonCtrl {
@Autowired private SystemYmlConfig systemYmlConfig;
@Autowired private SysConfigService sysConfigService;
/** 上传文件 (单文件上传) */
@PostMapping("/{bizType}")
public ApiRes singleFileUpload(@RequestParam("file") MultipartFile file, @PathVariable("bizType") String bizType) {
if( file == null ) return ApiRes.fail(ApiCodeEnum.SYSTEM_ERROR, "选择文件不存在");
try {
OssFileConfig ossFileConfig = OssFileConfig.getOssFileConfigByBizType(bizType);
//1. 判断bizType 是否可用
if(ossFileConfig == null){
throw new BizException("类型有误");
}
// 2. 判断文件是否支持
String fileSuffix = FileKit.getFileSuffix(file.getOriginalFilename(), false);
if( !ossFileConfig.isAllowFileSuffix(fileSuffix) ){
throw new BizException("上传文件格式不支持!");
}
// 3. 判断文件大小是否超限
if( !ossFileConfig.isMaxSizeLimit(file.getSize()) ){
throw new BizException("上传大小请限制在["+ossFileConfig.getMaxSize() / 1024 / 1024 +"M]以内!");
}
boolean isAllowPublicRead = ossFileConfig.isAllowPublicRead(); //是否允许公共读, true:公共读, false:私有文件
//公共读 & 是否上传到oss
boolean isYunOss = false; //TODO 暂时不支持云oss方式
if(isAllowPublicRead && isYunOss){
return null;
}
//以下为文件上传到本地
// 新文件地址
String newFileName = UUID.fastUUID() + "." + fileSuffix;
// 保存的文件夹名称
String saveFilePath = isAllowPublicRead ? systemYmlConfig.getOssFile().getPublicPath() : systemYmlConfig.getOssFile().getPrivatePath();
saveFilePath = saveFilePath + File.separator + bizType + File.separator + newFileName;
//保存文件
saveFile(file, saveFilePath);
//返回响应结果
String resultUrl = bizType + "/" + newFileName;
if(isAllowPublicRead){ //允许公共读取
resultUrl = sysConfigService.getDBApplicationConfig().getOssPublicSiteUrl() + "/" + resultUrl;
}
return ApiRes.ok(resultUrl);
} catch (BizException biz) {
throw biz;
} catch (Exception e) {
logger.error("upload error, fileName = {}", file == null ? null :file.getOriginalFilename(), e);
throw new BizException(ApiCodeEnum.SYSTEM_ERROR);
}
}
}
\ No newline at end of file
Supports Markdown
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