Pre Merge pull request !380 from 鲸落/master_zhp

This commit is contained in:
鲸落
2024-10-11 09:33:55 +00:00
committed by Gitee
160 changed files with 13236 additions and 2919 deletions

1
.github/FUNDING.yml vendored
View File

@@ -1 +0,0 @@
custom: http://doc.ruoyi.vip/ruoyi-cloud/other/donate.html

21
LICENSE
View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2020 若依
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -11,7 +11,7 @@
## 平台简介 ## 平台简介
若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。 租研舍是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
* 采用前后端分离的模式,微服务版本前端(基于 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue))。 * 采用前后端分离的模式,微服务版本前端(基于 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue))。
* 后端采用Spring Boot、Spring Cloud & Alibaba。 * 后端采用Spring Boot、Spring Cloud & Alibaba。
@@ -22,7 +22,7 @@
* 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)   * 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)  
* 阿里云优惠券:[点我领取](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)   * 阿里云优惠券:[点我领取](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)  
#### 友情链接 [若依/RuoYi-Cloud](https://gitee.com/zhangmrit/ruoyi-cloud) Ant Design版本。 #### 友情链接 [租研舍/RuoYi-Cloud](https://gitee.com/zhangmrit/ruoyi-cloud) Ant Design版本。
## 系统模块 ## 系统模块
@@ -126,6 +126,6 @@ com.ruoyi
</table> </table>
## 若依微服务交流群 ## 租研舍微服务交流群
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-42799195-blue.svg)](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [![加入QQ群](https://img.shields.io/badge/已满-170157040-blue.svg)](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) [![加入QQ群](https://img.shields.io/badge/已满-130643120-blue.svg)](https://jq.qq.com/?_wv=1027&k=rvxkJtXK) [![加入QQ群](https://img.shields.io/badge/已满-225920371-blue.svg)](https://jq.qq.com/?_wv=1027&k=0Ck3PvTe) [![加入QQ群](https://img.shields.io/badge/已满-201705537-blue.svg)](https://jq.qq.com/?_wv=1027&k=FnHHP4TT) [![加入QQ群](https://img.shields.io/badge/已满-236543183-blue.svg)](https://jq.qq.com/?_wv=1027&k=qdT1Ojpz) [![加入QQ群](https://img.shields.io/badge/已满-213618602-blue.svg)](https://jq.qq.com/?_wv=1027&k=nw3OiyXs) [![加入QQ群](https://img.shields.io/badge/已满-148794840-blue.svg)](https://jq.qq.com/?_wv=1027&k=kiU5WDls) [![加入QQ群](https://img.shields.io/badge/已满-118752664-blue.svg)](https://jq.qq.com/?_wv=1027&k=MtBy6YfT) [![加入QQ群](https://img.shields.io/badge/已满-101038945-blue.svg)](https://jq.qq.com/?_wv=1027&k=FqImHgH2) [![加入QQ群](https://img.shields.io/badge/已满-128355254-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G4jZ4EtdT50PhnMBudTnEwgonxkXOscJ&authKey=FkGHYfoTKlGE6wHdKdjH9bVoOgQjtLP9WM%2Fj7pqGY1msoqw9uxDiBo39E2mLgzYg&noverify=0&group_code=128355254) [![加入QQ群](https://img.shields.io/badge/已满-179219821-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=irnwcXhbLOQEv1g-TwGifjNTA_f4wZiA&authKey=4bpzEwhcUY%2FvsPDHvzYn6xfoS%2FtOArvZ%2BGXzfr7O0%2FEqLfkKA%2BuCDXlzHIFg8t93&noverify=0&group_code=179219821) [![加入QQ群](https://img.shields.io/badge/158753145-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=lx1uEdEDuxeM7rUvF3qmlFdqKqdJ5Z-R&authKey=rgyPW9yhhh4IIURKVFa6NgP3qiqH04WAzrJ0trsgkr3pjzm6sKIOGyA58oOjoj%2FJ&noverify=0&group_code=158753145) 点击按钮入群。 QQ群 [![加入QQ群](https://img.shields.io/badge/已满-42799195-blue.svg)](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [![加入QQ群](https://img.shields.io/badge/已满-170157040-blue.svg)](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) [![加入QQ群](https://img.shields.io/badge/已满-130643120-blue.svg)](https://jq.qq.com/?_wv=1027&k=rvxkJtXK) [![加入QQ群](https://img.shields.io/badge/已满-225920371-blue.svg)](https://jq.qq.com/?_wv=1027&k=0Ck3PvTe) [![加入QQ群](https://img.shields.io/badge/已满-201705537-blue.svg)](https://jq.qq.com/?_wv=1027&k=FnHHP4TT) [![加入QQ群](https://img.shields.io/badge/已满-236543183-blue.svg)](https://jq.qq.com/?_wv=1027&k=qdT1Ojpz) [![加入QQ群](https://img.shields.io/badge/已满-213618602-blue.svg)](https://jq.qq.com/?_wv=1027&k=nw3OiyXs) [![加入QQ群](https://img.shields.io/badge/已满-148794840-blue.svg)](https://jq.qq.com/?_wv=1027&k=kiU5WDls) [![加入QQ群](https://img.shields.io/badge/已满-118752664-blue.svg)](https://jq.qq.com/?_wv=1027&k=MtBy6YfT) [![加入QQ群](https://img.shields.io/badge/已满-101038945-blue.svg)](https://jq.qq.com/?_wv=1027&k=FqImHgH2) [![加入QQ群](https://img.shields.io/badge/已满-128355254-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G4jZ4EtdT50PhnMBudTnEwgonxkXOscJ&authKey=FkGHYfoTKlGE6wHdKdjH9bVoOgQjtLP9WM%2Fj7pqGY1msoqw9uxDiBo39E2mLgzYg&noverify=0&group_code=128355254) [![加入QQ群](https://img.shields.io/badge/已满-179219821-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=irnwcXhbLOQEv1g-TwGifjNTA_f4wZiA&authKey=4bpzEwhcUY%2FvsPDHvzYn6xfoS%2FtOArvZ%2BGXzfr7O0%2FEqLfkKA%2BuCDXlzHIFg8t93&noverify=0&group_code=179219821) [![加入QQ群](https://img.shields.io/badge/158753145-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=lx1uEdEDuxeM7rUvF3qmlFdqKqdJ5Z-R&authKey=rgyPW9yhhh4IIURKVFa6NgP3qiqH04WAzrJ0trsgkr3pjzm6sKIOGyA58oOjoj%2FJ&noverify=0&group_code=158753145) 点击按钮入群。

View File

@@ -1,41 +0,0 @@
#!/bin/sh
# 复制项目的文件到对应docker路径便于一键生成镜像。
usage() {
echo "Usage: sh copy.sh"
exit 1
}
# copy sql
echo "begin copy sql "
cp ../sql/ry_20240629.sql ./mysql/db
cp ../sql/ry_config_20240902.sql ./mysql/db
# copy html
echo "begin copy html "
cp -r ../ruoyi-ui/dist/** ./nginx/html/dist
# copy jar
echo "begin copy ruoyi-gateway "
cp ../ruoyi-gateway/target/ruoyi-gateway.jar ./ruoyi/gateway/jar
echo "begin copy ruoyi-auth "
cp ../ruoyi-auth/target/ruoyi-auth.jar ./ruoyi/auth/jar
echo "begin copy ruoyi-visual "
cp ../ruoyi-visual/ruoyi-monitor/target/ruoyi-visual-monitor.jar ./ruoyi/visual/monitor/jar
echo "begin copy ruoyi-modules-system "
cp ../ruoyi-modules/ruoyi-system/target/ruoyi-modules-system.jar ./ruoyi/modules/system/jar
echo "begin copy ruoyi-modules-file "
cp ../ruoyi-modules/ruoyi-file/target/ruoyi-modules-file.jar ./ruoyi/modules/file/jar
echo "begin copy ruoyi-modules-job "
cp ../ruoyi-modules/ruoyi-job/target/ruoyi-modules-job.jar ./ruoyi/modules/job/jar
echo "begin copy ruoyi-modules-gen "
cp ../ruoyi-modules/ruoyi-gen/target/ruoyi-modules-gen.jar ./ruoyi/modules/gen/jar

View File

@@ -1,67 +0,0 @@
#!/bin/sh
# 使用说明,用来提示输入参数
usage() {
echo "Usage: sh 执行脚本.sh [port|base|modules|stop|rm]"
exit 1
}
# 开启所需端口
port(){
firewall-cmd --add-port=80/tcp --permanent
firewall-cmd --add-port=8080/tcp --permanent
firewall-cmd --add-port=8848/tcp --permanent
firewall-cmd --add-port=9848/tcp --permanent
firewall-cmd --add-port=9849/tcp --permanent
firewall-cmd --add-port=6379/tcp --permanent
firewall-cmd --add-port=3306/tcp --permanent
firewall-cmd --add-port=9100/tcp --permanent
firewall-cmd --add-port=9200/tcp --permanent
firewall-cmd --add-port=9201/tcp --permanent
firewall-cmd --add-port=9202/tcp --permanent
firewall-cmd --add-port=9203/tcp --permanent
firewall-cmd --add-port=9300/tcp --permanent
service firewalld restart
}
# 启动基础环境(必须)
base(){
docker-compose up -d ruoyi-mysql ruoyi-redis ruoyi-nacos
}
# 启动程序模块(必须)
modules(){
docker-compose up -d ruoyi-nginx ruoyi-gateway ruoyi-auth ruoyi-modules-system
}
# 关闭所有环境/模块
stop(){
docker-compose stop
}
# 删除所有环境/模块
rm(){
docker-compose rm
}
# 根据输入参数,选择执行对应方法,不输入则执行使用说明
case "$1" in
"port")
port
;;
"base")
base
;;
"modules")
modules
;;
"stop")
stop
;;
"rm")
rm
;;
*)
usage
;;
esac

View File

@@ -1,140 +0,0 @@
version : '3.8'
services:
ruoyi-nacos:
container_name: ruoyi-nacos
image: nacos/nacos-server
build:
context: ./nacos
environment:
- MODE=standalone
volumes:
- ./nacos/logs/:/home/nacos/logs
- ./nacos/conf/application.properties:/home/nacos/conf/application.properties
ports:
- "8848:8848"
- "9848:9848"
- "9849:9849"
depends_on:
- ruoyi-mysql
ruoyi-mysql:
container_name: ruoyi-mysql
image: mysql:5.7
build:
context: ./mysql
ports:
- "3306:3306"
volumes:
- ./mysql/conf:/etc/mysql/conf.d
- ./mysql/logs:/logs
- ./mysql/data:/var/lib/mysql
command: [
'mysqld',
'--innodb-buffer-pool-size=80M',
'--character-set-server=utf8mb4',
'--collation-server=utf8mb4_unicode_ci',
'--default-time-zone=+8:00',
'--lower-case-table-names=1'
]
environment:
MYSQL_DATABASE: 'ry-cloud'
MYSQL_ROOT_PASSWORD: password
ruoyi-redis:
container_name: ruoyi-redis
image: redis
build:
context: ./redis
ports:
- "6379:6379"
volumes:
- ./redis/conf/redis.conf:/home/ruoyi/redis/redis.conf
- ./redis/data:/data
command: redis-server /home/ruoyi/redis/redis.conf
ruoyi-nginx:
container_name: ruoyi-nginx
image: nginx
build:
context: ./nginx
ports:
- "80:80"
volumes:
- ./nginx/html/dist:/home/ruoyi/projects/ruoyi-ui
- ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/logs:/var/log/nginx
- ./nginx/conf.d:/etc/nginx/conf.d
depends_on:
- ruoyi-gateway
links:
- ruoyi-gateway
ruoyi-gateway:
container_name: ruoyi-gateway
build:
context: ./ruoyi/gateway
dockerfile: dockerfile
ports:
- "8080:8080"
depends_on:
- ruoyi-redis
links:
- ruoyi-redis
ruoyi-auth:
container_name: ruoyi-auth
build:
context: ./ruoyi/auth
dockerfile: dockerfile
ports:
- "9200:9200"
depends_on:
- ruoyi-redis
links:
- ruoyi-redis
ruoyi-modules-system:
container_name: ruoyi-modules-system
build:
context: ./ruoyi/modules/system
dockerfile: dockerfile
ports:
- "9201:9201"
depends_on:
- ruoyi-redis
- ruoyi-mysql
links:
- ruoyi-redis
- ruoyi-mysql
ruoyi-modules-gen:
container_name: ruoyi-modules-gen
build:
context: ./ruoyi/modules/gen
dockerfile: dockerfile
ports:
- "9202:9202"
depends_on:
- ruoyi-mysql
links:
- ruoyi-mysql
ruoyi-modules-job:
container_name: ruoyi-modules-job
build:
context: ./ruoyi/modules/job
dockerfile: dockerfile
ports:
- "9203:9203"
depends_on:
- ruoyi-mysql
links:
- ruoyi-mysql
ruoyi-modules-file:
container_name: ruoyi-modules-file
build:
context: ./ruoyi/modules/file
dockerfile: dockerfile
ports:
- "9300:9300"
volumes:
- ./ruoyi/uploadPath:/home/ruoyi/uploadPath
ruoyi-visual-monitor:
container_name: ruoyi-visual-monitor
build:
context: ./ruoyi/visual/monitor
dockerfile: dockerfile
ports:
- "9100:9100"

View File

@@ -1 +0,0 @@
存放sql目录下的所有脚本用于docker自动执行。

View File

@@ -1,7 +0,0 @@
# 基础镜像
FROM mysql:5.7
# author
MAINTAINER ruoyi
# 执行sql脚本
ADD ./db/*.sql /docker-entrypoint-initdb.d/

View File

@@ -1,32 +0,0 @@
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://ruoyi-mysql:3306/ry-config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user=root
db.password=password
nacos.naming.empty-service.auto-clean=true
nacos.naming.empty-service.clean.initial-delay-ms=50000
nacos.naming.empty-service.clean.period-time-ms=30000
management.endpoints.web.exposure.include=*
management.metrics.export.elastic.enabled=false
management.metrics.export.influx.enabled=false
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D %{User-Agent}i %{Request-Source}i
server.tomcat.basedir=/home/ruoyi/nacos/tomcat/logs
nacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**
nacos.core.auth.system.type=nacos
nacos.core.auth.enabled=false
nacos.core.auth.default.token.expire.seconds=18000
nacos.core.auth.default.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789
nacos.core.auth.caching.enabled=true
nacos.core.auth.enable.userAgentAuthWhite=false
nacos.core.auth.server.identity.key=serverIdentity
nacos.core.auth.server.identity.value=security
nacos.istio.mcp.server.enabled=false

View File

@@ -1,7 +0,0 @@
# 基础镜像
FROM nacos/nacos-server
# author
MAINTAINER ruoyi
# 复制conf文件到路径
COPY ./conf/application.properties /home/nacos/conf/application.properties

View File

@@ -1,41 +0,0 @@
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root /home/ruoyi/projects/ruoyi-ui;
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
location /prod-api/{
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://ruoyi-gateway:8080/;
}
# 避免actuator暴露
if ($request_uri ~ "/actuator") {
return 403;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}

View File

@@ -1,15 +0,0 @@
# 基础镜像
FROM nginx
# author
MAINTAINER ruoyi
# 挂载目录
VOLUME /home/ruoyi/projects/ruoyi-ui
# 创建目录
RUN mkdir -p /home/ruoyi/projects/ruoyi-ui
# 指定路径
WORKDIR /home/ruoyi/projects/ruoyi-ui
# 复制conf文件到路径
COPY ./conf/nginx.conf /etc/nginx/nginx.conf
# 复制html文件到路径
COPY ./html/dist /home/ruoyi/projects/ruoyi-ui

View File

@@ -1 +0,0 @@
存放前端ruoyi-ui构建好的静态文件用于nginx请求访问。

View File

@@ -1 +0,0 @@
# requirepass 123456

View File

@@ -1,13 +0,0 @@
# 基础镜像
FROM redis
# author
MAINTAINER ruoyi
# 挂载目录
VOLUME /home/ruoyi/redis
# 创建目录
RUN mkdir -p /home/ruoyi/redis
# 指定路径
WORKDIR /home/ruoyi/redis
# 复制conf文件到路径
COPY ./conf/redis.conf /home/ruoyi/redis/redis.conf

View File

@@ -1,15 +0,0 @@
# 基础镜像
FROM openjdk:8-jre
# author
MAINTAINER ruoyi
# 挂载目录
VOLUME /home/ruoyi
# 创建目录
RUN mkdir -p /home/ruoyi
# 指定路径
WORKDIR /home/ruoyi
# 复制jar文件到路径
COPY ./jar/ruoyi-auth.jar /home/ruoyi/ruoyi-auth.jar
# 启动认证服务
ENTRYPOINT ["java","-jar","ruoyi-auth.jar"]

View File

@@ -1 +0,0 @@
存放认证中心打包好的jar文件用于docker启动应用。

View File

@@ -1,15 +0,0 @@
# 基础镜像
FROM openjdk:8-jre
# author
MAINTAINER ruoyi
# 挂载目录
VOLUME /home/ruoyi
# 创建目录
RUN mkdir -p /home/ruoyi
# 指定路径
WORKDIR /home/ruoyi
# 复制jar文件到路径
COPY ./jar/ruoyi-gateway.jar /home/ruoyi/ruoyi-gateway.jar
# 启动网关服务
ENTRYPOINT ["java","-jar","ruoyi-gateway.jar"]

View File

@@ -1 +0,0 @@
存放网关模块打包好的jar文件用于docker启动应用。

View File

@@ -1,15 +0,0 @@
# 基础镜像
FROM openjdk:8-jre
# author
MAINTAINER ruoyi
# 挂载目录
VOLUME /home/ruoyi
# 创建目录
RUN mkdir -p /home/ruoyi
# 指定路径
WORKDIR /home/ruoyi
# 复制jar文件到路径
COPY ./jar/ruoyi-modules-file.jar /home/ruoyi/ruoyi-modules-file.jar
# 启动文件服务
ENTRYPOINT ["java","-jar","ruoyi-modules-file.jar"]

View File

@@ -1 +0,0 @@
存放文件服务打包好的jar文件用于docker启动应用。

View File

@@ -1,15 +0,0 @@
# 基础镜像
FROM openjdk:8-jre
# author
MAINTAINER ruoyi
# 挂载目录
VOLUME /home/ruoyi
# 创建目录
RUN mkdir -p /home/ruoyi
# 指定路径
WORKDIR /home/ruoyi
# 复制jar文件到路径
COPY ./jar/ruoyi-modules-gen.jar /home/ruoyi/ruoyi-modules-gen.jar
# 启动代码生成服务
ENTRYPOINT ["java","-jar","ruoyi-modules-gen.jar"]

View File

@@ -1 +0,0 @@
存放代码生成打包好的jar文件用于docker启动应用。

View File

@@ -1,15 +0,0 @@
# 基础镜像
FROM openjdk:8-jre
# author
MAINTAINER ruoyi
# 挂载目录
VOLUME /home/ruoyi
# 创建目录
RUN mkdir -p /home/ruoyi
# 指定路径
WORKDIR /home/ruoyi
# 复制jar文件到路径
COPY ./jar/ruoyi-modules-job.jar /home/ruoyi/ruoyi-modules-job.jar
# 启动定时任务服务
ENTRYPOINT ["java","-jar","ruoyi-modules-job.jar"]

View File

@@ -1 +0,0 @@
存放定时任务打包好的jar文件用于docker启动应用。

View File

@@ -1,15 +0,0 @@
# 基础镜像
FROM openjdk:8-jre
# author
MAINTAINER ruoyi
# 挂载目录
VOLUME /home/ruoyi
# 创建目录
RUN mkdir -p /home/ruoyi
# 指定路径
WORKDIR /home/ruoyi
# 复制jar文件到路径
COPY ./jar/ruoyi-modules-system.jar /home/ruoyi/ruoyi-modules-system.jar
# 启动系统服务
ENTRYPOINT ["java","-jar","ruoyi-modules-system.jar"]

View File

@@ -1 +0,0 @@
存放系统模块打包好的jar文件用于docker启动应用。

View File

@@ -1,15 +0,0 @@
# 基础镜像
FROM openjdk:8-jre
# author
MAINTAINER ruoyi
# 挂载目录
VOLUME /home/ruoyi
# 创建目录
RUN mkdir -p /home/ruoyi
# 指定路径
WORKDIR /home/ruoyi
# 复制jar文件到路径
COPY ./jar/ruoyi-visual-monitor.jar /home/ruoyi/ruoyi-visual-monitor.jar
# 启动系统服务
ENTRYPOINT ["java","-jar","ruoyi-visual-monitor.jar"]

View File

@@ -1 +0,0 @@
存放监控中心打包好的jar文件用于docker启动应用。

20
pom.xml
View File

@@ -10,7 +10,7 @@
<name>ruoyi</name> <name>ruoyi</name>
<url>http://www.ruoyi.vip</url> <url>http://www.ruoyi.vip</url>
<description>若依微服务系统</description> <description>租研舍微服务系统</description>
<properties> <properties>
<ruoyi.version>3.6.4</ruoyi.version> <ruoyi.version>3.6.4</ruoyi.version>
@@ -35,6 +35,9 @@
<poi.version>4.1.2</poi.version> <poi.version>4.1.2</poi.version>
<springdoc.version>1.6.9</springdoc.version> <springdoc.version>1.6.9</springdoc.version>
<transmittable-thread-local.version>2.14.4</transmittable-thread-local.version> <transmittable-thread-local.version>2.14.4</transmittable-thread-local.version>
<mybatis-plus.version>3.5.2</mybatis-plus.version>
<lombok.version>1.18.30</lombok.version>
<hutools.version>5.8.26</hutools.version>
</properties> </properties>
<!-- 依赖声明 --> <!-- 依赖声明 -->
@@ -216,6 +219,21 @@
<artifactId>ruoyi-api-system</artifactId> <artifactId>ruoyi-api-system</artifactId>
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutools.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

View File

@@ -0,0 +1,25 @@
package com.ruoyi.system.api;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.ServiceNameConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.http.CustomerApplyLog;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.system.api.factory.RemoteChannelFallbackFactory;
import com.ruoyi.system.api.factory.RemoteCustomerApplyLogFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
/**
* 用户服务
*
* @author ruoyi
*/
@FeignClient(contextId = "remoteChannelService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteChannelFallbackFactory.class)
public interface RemoteChannelService
{
}

View File

@@ -0,0 +1,54 @@
package com.ruoyi.system.api;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.ServiceNameConstants;
import com.ruoyi.common.core.domain.GetSumDto;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.http.CustomerApplyLog;
import com.ruoyi.common.core.domain.http.Merchant;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.system.api.factory.RemoteCustomerApplyLogFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 用户服务
*
* @author ruoyi
*/
@FeignClient(contextId = "remoteCustomerApplyLogService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteCustomerApplyLogFallbackFactory.class)
public interface RemoteCustomerApplyLogService
{
/**
* 获取商户今日已申请数
*
*
* @param getSumDto
* @param source 请求来源
* @return 结果
*/
@PostMapping("/log/sum")
public R<Integer> sum(@RequestBody GetSumDto getSumDto, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 获取用户今日是否是否已申请
*
*
* @param customerID
* @param source 请求来源
* @return 结果
*/
@GetMapping("/log/customerApply")
public R<Boolean> customerApply(@RequestParam("customerID") Long customerID,@RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 新增用户
* @param customerApplyLog
* @return
*/
@PostMapping("/log")
public AjaxResult add(@RequestBody CustomerApplyLog customerApplyLog);
}

View File

@@ -0,0 +1,63 @@
package com.ruoyi.system.api;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.ServiceNameConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.http.Customer;
import com.ruoyi.system.api.factory.RemoteCustomerFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
/**
* 用户服务
*
* @author ruoyi
*/
@FeignClient(contextId = "remoteCustomerService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteCustomerFallbackFactory.class)
public interface RemoteCustomerService
{
/**
* 通过用户名查询用户信息
*
* @param id 用户名
* @param source 请求来源
* @return 结果
*/
@GetMapping("/customer/{id}")
public R<Customer> getCustomerInfoById(@PathVariable("id") Long id, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 通过手机号MD5查询用户信息
*
* @param phoneMD5 用户名
* @param source 请求来源
* @return 结果
*/
@GetMapping("/customer/getByMd5")
public R<Customer> getCustomerInfoByPhoneMd5(@RequestParam("phoneMD5")String phoneMD5, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 通过手机号MD5更新用户信息
*
* @param customer 用户
* @return 结果
*/
@PostMapping("/customer/updateByPhoneMd5")
public R updateByPhoneMd5(Customer customer ,@RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 新增客户信息
* @return
*/
@PostMapping("/customer/addNewCustomer")
public R add(@RequestBody Customer customer,@RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 获取用户token
* @param phone
* @param channelId
* @return
*/
@GetMapping("/customer/getCustomerToken")
public String getCustomerToken(@RequestParam("phone") String phone,@RequestParam("channelId")Long channelId);
}

View File

@@ -0,0 +1,33 @@
package com.ruoyi.system.api;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.ServiceNameConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.http.Merchant;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.factory.RemoteMerChantFallbackFactory;
import com.ruoyi.system.api.factory.RemoteUserFallbackFactory;
import com.ruoyi.system.api.model.LoginUser;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 用户服务
*
* @author ruoyi
*/
@FeignClient(contextId = "remoteMerchantService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteMerChantFallbackFactory.class)
public interface RemoteMerchantService
{
/**
* 获取合适的产品 前筛
*
* @param source 请求来源
* @return 结果
*/
@GetMapping("/merchant/merchantList")
public R<List<Merchant>> merchantList(@RequestHeader(SecurityConstants.FROM_SOURCE) String source);
}

View File

@@ -0,0 +1,30 @@
package com.ruoyi.system.api.factory;
import com.ruoyi.system.api.RemoteChannelService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
/**
* 用户服务降级处理
*
* @author ruoyi
*/
@Component
@Slf4j
public class RemoteChannelFallbackFactory implements FallbackFactory<RemoteChannelService>
{
@Override
public RemoteChannelService create(Throwable throwable)
{
log.error("用户服务调用失败:{}", throwable.getMessage());
return new RemoteChannelService()
{
};
}
}

View File

@@ -0,0 +1,52 @@
package com.ruoyi.system.api.factory;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.domain.GetSumDto;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.http.CustomerApplyLog;
import com.ruoyi.common.core.domain.http.Merchant;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.system.api.RemoteCustomerApplyLogService;
import com.ruoyi.system.api.RemoteMerchantService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import java.util.List;
/**
* 用户服务降级处理
*
* @author ruoyi
*/
@Component
@Slf4j
public class RemoteCustomerApplyLogFallbackFactory implements FallbackFactory<RemoteCustomerApplyLogService>
{
@Override
public RemoteCustomerApplyLogService create(Throwable throwable)
{
log.error("用户服务调用失败:{}", throwable.getMessage());
return new RemoteCustomerApplyLogService()
{
@Override
public R<Integer> sum(GetSumDto getSumDto, @RequestHeader(SecurityConstants.FROM_SOURCE) String source)
{
return R.fail("获取商户已申请数失败:" + throwable.getMessage());
}
@Override
public R<Boolean> customerApply(Long customerID, String source) {
return null;
}
@Override
public AjaxResult add(CustomerApplyLog customerApplyLog) {
return null;
}
};
}
}

View File

@@ -0,0 +1,54 @@
package com.ruoyi.system.api.factory;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.http.Customer;
import com.ruoyi.system.api.RemoteCustomerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
/**
* 用户服务降级处理
*
* @author ruoyi
*/
@Component
@Slf4j
public class RemoteCustomerFallbackFactory implements FallbackFactory<RemoteCustomerService>
{
@Override
public RemoteCustomerService create(Throwable throwable)
{
log.error("用户服务调用失败:{}", throwable.getMessage());
return new RemoteCustomerService()
{
@Override
public R<Customer> getCustomerInfoById(Long id, String source)
{
return R.fail("获取用户失败:" + throwable.getMessage());
}
@Override
public R<Customer> getCustomerInfoByPhoneMd5(String phoneMD5, String source) {
log.info("查询用户失败:{}",throwable.getMessage());
return R.fail("查询用户失败:" + throwable.getMessage());
}
@Override
public R updateByPhoneMd5(Customer customer, String source) {
return R.fail("更新用户失败:" + throwable.getMessage());
}
@Override
public R add(Customer customer, String source) {
log.info("新增用户失败:{}",throwable.getMessage());
return R.fail("新增用户失败");
}
@Override
public String getCustomerToken(String phone, Long channelId) {
return null;
}
};
}
}

View File

@@ -0,0 +1,37 @@
package com.ruoyi.system.api.factory;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.http.Merchant;
import com.ruoyi.system.api.RemoteMerchantService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 用户服务降级处理
*
* @author ruoyi
*/
@Component
@Slf4j
public class RemoteMerChantFallbackFactory implements FallbackFactory<RemoteMerchantService>
{
@Override
public RemoteMerchantService create(Throwable throwable)
{
log.error("用户服务调用失败:{}", throwable.getMessage());
return new RemoteMerchantService()
{
@Override
public R<List<Merchant>> merchantList(String source)
{
return R.fail("获取用户失败:" + throwable.getMessage());
}
};
}
}

View File

@@ -1,3 +1,6 @@
com.ruoyi.system.api.factory.RemoteUserFallbackFactory com.ruoyi.system.api.factory.RemoteUserFallbackFactory
com.ruoyi.system.api.factory.RemoteLogFallbackFactory com.ruoyi.system.api.factory.RemoteLogFallbackFactory
com.ruoyi.system.api.factory.RemoteFileFallbackFactory com.ruoyi.system.api.factory.RemoteFileFallbackFactory
com.ruoyi.system.api.factory.RemoteCustomerFallbackFactory
com.ruoyi.system.api.factory.RemoteMerChantFallbackFactory
com.ruoyi.system.api.factory.RemoteCustomerApplyLogFallbackFactory

View File

@@ -17,15 +17,6 @@ public class RuoYiAuthApplication
public static void main(String[] args) public static void main(String[] args)
{ {
SpringApplication.run(RuoYiAuthApplication.class, args); SpringApplication.run(RuoYiAuthApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 认证授权中心启动成功 ლ(´ڡ`ლ)゙ \n" + System.out.println("(♥◠‿◠)ノ゙ 认证授权中心启动成功 ლ(´ڡ`ლ)゙ ");
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
} }
} }

View File

@@ -14,10 +14,12 @@ spring:
nacos: nacos:
discovery: discovery:
# 服务注册地址 # 服务注册地址
server-addr: 127.0.0.1:8848 server-addr: 47.109.135.151:8848
namespace: b8ad3fd2-18ea-4cdf-a82c-4ce483392b1a
config: config:
# 配置中心地址 # 配置中心地址
server-addr: 127.0.0.1:8848 server-addr: 47.109.135.151:8848
namespace: b8ad3fd2-18ea-4cdf-a82c-4ce483392b1a
# 配置文件格式 # 配置文件格式
file-extension: yml file-extension: yml
# 共享配置 # 共享配置

View File

@@ -67,7 +67,7 @@
</root> </root>
<!--系统操作日志--> <!--系统操作日志-->
<root level="info"> <root level="INFO">
<appender-ref ref="file_info" /> <appender-ref ref="file_info" />
<appender-ref ref="file_error" /> <appender-ref ref="file_error" />
</root> </root>

View File

@@ -18,6 +18,7 @@
<module>ruoyi-common-sensitive</module> <module>ruoyi-common-sensitive</module>
<module>ruoyi-common-datascope</module> <module>ruoyi-common-datascope</module>
<module>ruoyi-common-datasource</module> <module>ruoyi-common-datasource</module>
<module>ruoyi-common-sms</module>
</modules> </modules>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>

View File

@@ -106,7 +106,21 @@
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-annotation</artifactId>
<version>3.5.2</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -56,4 +56,20 @@ public class CacheConstants
* 登录IP黑名单 cache key * 登录IP黑名单 cache key
*/ */
public static final String SYS_LOGIN_BLACKIPLIST = SYS_CONFIG_KEY + "sys.login.blackIPList"; public static final String SYS_LOGIN_BLACKIPLIST = SYS_CONFIG_KEY + "sys.login.blackIPList";
public static final String PROJET = "xymz:";
/**
* 渠道redis缓存键
*/
public static final String CHANNEL_ID = PROJET + "channel:id:";
/**
* 渠道redis缓存键
*/
public static final String CHANNEL_SIGN = PROJET + "channel:sign:";
/**
* 商户redis缓存键
*/
public static final String MERCHANT = PROJET + "merchant:key:";
} }

View File

@@ -0,0 +1,42 @@
package com.ruoyi.common.core.constant;
public class RedisConstant {
/**
* 用户登录缓存
*/
public final static String APP_CUSTOMER_KEY = CacheConstants.PROJET + ":customer:key:";
/**
* 用户名缓存
*/
public final static String APP_CUSTOMER_USERNAME_KEY = CacheConstants.PROJET + ":app:customer:username:key:";
/**
* 渠道ID缓存
*/
public final static String APP_CUSTOMER_CHANNEL_KEY = CacheConstants.PROJET + ":app:customer:channel:key:";
/**
* 用户登录缓存
*/
public final static String APP_CUSTOMER_TOKEN_KEY = CacheConstants.PROJET + ":app:customer:token:key:";
/**
* app用户设备标识
*/
public final static String APP_DEVICE_IDENTIFICATION = CacheConstants.PROJET + ":app:app:device:identification:";
/**
* H5登录验证码
*/
public final static String H5_LOGIN_CACHE = CacheConstants.PROJET+"H5:login:cache:";
/**
* H5申请幂等校验
*/
public final static String H5_APPLY_CHECK = CacheConstants.PROJET+"H5:apply:check:";
/**
* 撞库幂等校验
*/
public final static String HIT_CHECK_CACHE = CacheConstants.PROJET+"hit:check:cache:";
}

View File

@@ -0,0 +1,9 @@
package com.ruoyi.common.core.domain;
import lombok.Data;
@Data
public class GetSumDto {
private Long merchantId;
}

View File

@@ -0,0 +1,35 @@
package com.ruoyi.common.core.domain;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 概率计算
* @Author: daisi
* @Date: 2022/4/2 9:49
*/
@Data
@Accessors(chain = true)
public class GuestProbabilityReq implements Serializable {
private static final long serialVersionUID = -9096451963988288187L;
/**
* 计划Id
*/
private Long planId;
/**
* 排序价格
*/
private BigDecimal orderPrice;
/**
* 概率
*/
private Double guestProbability;
/**
* 计算结果概率
*/
private Integer resultGuestProbability;
}

View File

@@ -0,0 +1,57 @@
package com.ruoyi.common.core.domain.http;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
/**
* 渠道配置对象 channel
*
* @author ruoyi
* @date 2024-09-15
*/
@Data
public class Channel extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** */
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/** 渠道名称 */
@Excel(name = "渠道名称")
private String channelName;
/** 渠道签名 */
@Excel(name = "渠道签名")
private String channelSign;
/** 渠道类型 1H5 2连登 3半流程 4全流程*/
@Excel(name = "渠道类型")
private String channelType;
/** 扣量比 */
@Excel(name = "扣量比")
private Long score;
/** 推广页名称 */
@Excel(name = "推广页名称")
private String htmlName;
/** 推广页地址 */
@Excel(name = "推广页地址")
private String htmlLocation;
/** 可访问IP */
@Excel(name = "可访问IP")
private String ips;
/** 开启关闭时段 */
@Excel(name = "开启关闭时段")
private String period;
}

View File

@@ -0,0 +1,138 @@
package com.ruoyi.common.core.domain.http;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
/**
* 客户信息对象 customer
*
* @author ruoyi
* @date 2024-09-15
*/
@Data
public class Customer extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** $column.columnComment */
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**渠道ID**/
@Excel(name = "渠道ID")
private Long channelId;
/** 年龄 */
@Excel(name = "年龄")
private Integer age;
/** 0 男 1 女 */
@Excel(name = "0 男 1 女")
private Integer sex;
@Excel(name="身份证号")
private String idCard;
/** 昵称 */
@Excel(name = "昵称")
private String name;
/** 真实姓名 */
@Excel(name = "真实姓名")
private String acturlName;
/** 手机号 */
@Excel(name = "手机号")
private String phone;
/** 手机号MD5 */
@Excel(name = "手机号MD5")
private String phoneMd5;
/** 0 未实名 1已实名 */
@Excel(name = "0 未实名 1已实名")
private Boolean isAuth;
/** 城市 */
@Excel(name = "城市")
private String city;
/** 城市编码 */
@Excel(name = "城市编码")
private Integer cityCode;
/** 首次登录时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "首次登录时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date firstLoginTime;
/** 最后登录时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date lastLoginTime;
/** 最后登录IP */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "最后登录IP", width = 30, dateFormat = "yyyy-MM-dd")
private Date lastLoginIp;
/** 用户状态 1正常 2异常 可继续扩展 */
@Excel(name = "用户状态 1正常 2异常 可继续扩展")
private Integer status;
/** 无社保 */
@Excel(name = "社保")
private Integer socialSecurity;
/** 无车 */
@Excel(name = "")
private Integer car;
/** 保单缴纳不满一年 */
@Excel(name = "保单")
private Integer guaranteeSlip;
/** 初中 */
@Excel(name = "学历")
private Integer education;
/** 公积金未满6个月 */
@Excel(name = "公积金")
private Integer accumulationFund;
/** 本地无房 */
@Excel(name = "")
private Integer hourse;
/** 上班族 */
@Excel(name = "职业")
private Integer career;
/** 花呗5000以下 */
@Excel(name = "花呗")
private Integer huaBei;
/** 白条5000以下 */
@Excel(name = "白条")
private Integer baiTiao;
/** 芝麻分 */
@Excel(name = "芝麻分")
private Integer zhiMa;
/** 月收入 */
@Excel(name = "月收入")
private Integer income;
}

View File

@@ -0,0 +1,51 @@
package com.ruoyi.common.core.domain.http;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
/**
* 客户申请记录对象 customer_apply_log
*
* @author ruoyi
* @date 2024-09-15
*/
@Data
public class CustomerApplyLog extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** $column.columnComment */
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/** 用户id */
@Excel(name = "用户id")
private Long customerId;
/** 商户ID */
@Excel(name = "商户ID")
private Long merchantId;
/** $column.columnComment */
@Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
private Long channelId;
/** 订单状态 0 已申请 1 注册中 2风控中 3下单中 4 下单成功 5已成交 */
@Excel(name = "订单状态 0 已申请 1 注册中 2风控中 3下单中 4 下单成功 5已成交 ")
private Long orderStatus;
/** 成交金额 分 */
@Excel(name = "成交金额 分")
private BigDecimal price;
@Excel(name = "订单号")
private String orderNo;
}

View File

@@ -0,0 +1,243 @@
package com.ruoyi.common.core.domain.http;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
/**
* 商户对象 merchant
*
* @author ruoyi
* @date 2024-09-15
*/
@Data
public class Merchant extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** $column.columnComment */
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/** 商户类型 1H5 2连登 3半流程 4全流程 */
@Excel(name = "商户类型 1H5 2连登 3半流程 4全流程")
private Long merchantType;
/** 商户名称 */
@Excel(name = "商户名称")
private String merchantName;
/** 商户描述 */
@Excel(name = "商户描述")
private String merchantDescribe;
/** 商户主体 */
@Excel(name = "商户主体")
private String merchantCompany;
/** logo文件地址 */
@Excel(name = "logo文件地址")
private String logo;
/** 是否上下架 */
@Excel(name = "是否上下架")
private Integer status;
/** 定量数 */
@Excel(name = "定量数")
private Integer limitNum;
/** 是否定量 0否 1是 */
@Excel(name = "是否定量 0否 1是")
private Integer limitType;
/** 是否开启余额监控 0否 1是 */
@Excel(name = " 是否开启余额监控 0否 1是")
private Integer isBalanceMonitoring;
/** 余额监控余额 */
@Excel(name = "余额")
private Integer balanceMonitoring ;
/** 渠道限制ID */
@Excel(name = "渠道限制ID")
private String channelLimit;
/** 是否通过 0否 1是 */
@Excel(name = "是否通过 0否 1是")
private Integer ispass;
/** 渠道限制类型 0不限 1满足其一 2满足全部 */
@Excel(name = "渠道限制类型 0不限 1满足其一 2满足全部")
private Integer customerInfoFilterType;
/** 渠道限制类型 0不限 1准入 2禁入 */
@Excel(name = "渠道限制类型 0不限 1准入 2禁入")
private Integer channelLimitType;
/** 执行时段 */
@Excel(name = "执行时段")
private String period;
/**撞库地址**/
@Excel(name = "撞库地址")
private String hitUrl;
/**注册地址**/
@Excel(name = "注册地址")
private String registUrl;
/** 年龄限制开始 */
@Excel(name = "年龄限制开始")
private Integer ageLimitStart;
/** 年龄限制结束 */
@Excel(name = "年龄限制结束")
private Integer ageLimitEnd;
/** 手机号禁入号段英文逗号分隔 */
@Excel(name = "手机号禁入号段英文逗号分隔")
private String phoneLimit;
/** 标签 */
@Excel(name = "标签")
private String label;
/** 商户是否开启二要素 0 否 1 是 */
@Excel(name = "商户是否开启二要素")
private Boolean merchantAuth;
@Excel(name = "下游渠道标识")
private String channelSign;
/** 无社保 */
@Excel(name = "无社保")
private Boolean socialSecurityNo;
/** 社保未满6个月 */
@Excel(name = "社保未满6个月")
private Boolean socialSecurityLow;
/** 社保6个月以上 */
@Excel(name = "社保6个月以上")
private Boolean socialSecurityHigh;
/** 无车 */
@Excel(name = "无车")
private Boolean carNo;
/** 有车 */
@Excel(name = "有车")
private Boolean carHave;
/** 保单缴纳不满一年 */
@Excel(name = "保单缴纳不满一年")
private Boolean guaranteeSlipLow;
/** 保单缴纳一年以上 */
@Excel(name = "保单缴纳一年以上")
private Boolean guaranteeSlipCentre;
/** 保单缴纳2年以上 */
@Excel(name = "保单缴纳2年以上")
private Boolean guaranteeSlipHigh;
/** 初中 */
@Excel(name = "初中")
private Boolean educationMiddle;
/** 高中 */
@Excel(name = "高中")
private Boolean educationHighSchool;
/** 中专 */
@Excel(name = "中专")
private Boolean educationPolytechnic;
/** 大专 */
@Excel(name = "大专")
private Boolean educationJuniorCollege;
/** 本科 */
@Excel(name = "本科")
private Boolean educationUndergraduateCourse;
/** 研究生及以上 */
@Excel(name = "研究生及以上")
private Boolean educationPostgraduate;
/** 公积金未满6个月 */
@Excel(name = "公积金未满6个月")
private Boolean accumulationFundLow;
/** 公积金满6个月以上 */
@Excel(name = "公积金满6个月以上")
private Boolean accumulationFundHigh;
/** 本地无房 */
@Excel(name = "本地无房")
private Boolean hourseNo;
/** 本地全款房 */
@Excel(name = "本地全款房")
private Boolean hourseFullPayment;
/** 本地按揭 */
@Excel(name = "本地按揭")
private Boolean hourseMortgaging;
/** 上班族 */
@Excel(name = "上班族")
private Boolean officeWorker;
/** 公务员 */
@Excel(name = "公务员")
private Boolean civilServant;
/** 私营业主 */
@Excel(name = "私营业主")
private Boolean privatePropertyOwners;
/** 个体户 */
@Excel(name = "个体户")
private Boolean selfEmployedPerson;
/** 其他职业 */
@Excel(name = "其他职业")
private Boolean otherOccupations;
/** 花呗5000以下 */
@Excel(name = "花呗5000以下")
private Boolean huaBeiLow;
/** 花呗5000-10000 */
@Excel(name = "花呗5000-10000")
private Boolean huaBeiMiddle;
/** 花呗10000以上 */
@Excel(name = "花呗10000以上")
private Boolean huaBeiHigh;
/** 白条5000以下 */
@Excel(name = "白条5000以下")
private Boolean baiTiaoLow;
/** 白条5000-10000 */
@Excel(name = "白条5000-10000")
private Boolean baiTiaoMiddle;
/** 白条10000以上 */
@Excel(name = "白条10000以上")
private Boolean baiTiaoHigh;
/** 芝麻分 */
@Excel(name = "芝麻分")
private Integer zhiMa;
}

View File

@@ -0,0 +1,636 @@
package com.ruoyi.common.core.utils;
import cn.hutool.core.codec.Base64;
import org.apache.commons.codec.binary.Hex;
import org.springframework.stereotype.Component;
import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.regex.Pattern;
/**
* @program: JieYiHua-Cloud
* @description: 加密解密
* @author: LiYu
* @create: 2021-07-23 17:02
**/
@Component
public class EncryptUtil {
public static final String MD5 = "MD5";
public static final String SHA1 = "SHA1";
public static final String HmacMD5 = "HmacMD5";
public static final String HmacSHA1 = "HmacSHA1";
public static final String DES = "DES";
public static final String AES = "AES";
public static final Charset CHARSET = StandardCharsets.UTF_8;
public static final byte keyStrSize = 16;
public static final byte ivStrSize = 16;
public static final String AES_CBC_NOPADDING = "AES/CBC/NoPadding";
public static final String DES_ECB_PKCS7PADDING = "DES/ECB/PKCS7Padding";
public static final String AES_ECB_PKCS5PADDING = "AES/ECB/PKCS5Padding";
/**
* 编码格式默认使用uft-8
*/
public static String charset = "utf-8";
/**
* DES
*/
public static int keysizeDES = 0;
/**
* AES
*/
public static int keysizeAES = 128;
public static EncryptUtil me;
private EncryptUtil() {
//单例
}
//双重锁
public static EncryptUtil getInstance() {
if (me == null) {
synchronized (EncryptUtil.class) {
if (me == null) {
me = new EncryptUtil();
}
}
}
return me;
}
/**
* 使用MessageDigest进行单向加密无密码
*
* @param res 被加密的文本
* @param algorithm 加密算法名称
* @return
*/
private static String messageDigest(String res, String algorithm) {
try {
MessageDigest md = MessageDigest.getInstance(algorithm);
byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset);
return base64(md.digest(resBytes));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 使用KeyGenerator进行单向/双向加密(可设密码)
*
* @param res 被加密的原文
* @param algorithm 加密使用的算法名称
* @param key 加密使用的秘钥
* @return
*/
private String keyGeneratorMac(String res, String algorithm, String key) {
try {
SecretKey sk = null;
if (key == null) {
KeyGenerator kg = KeyGenerator.getInstance(algorithm);
sk = kg.generateKey();
} else {
byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
sk = new SecretKeySpec(keyBytes, algorithm);
}
Mac mac = Mac.getInstance(algorithm);
mac.init(sk);
byte[] result = mac.doFinal(res.getBytes());
return base64(result);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 使用KeyGenerator双向加密DES/AES注意这里转化为字符串的时候是将2进制转为16进制格式的字符串不是直接转因为会出错
*
* @param res 加密的原文
* @param algorithm 加密使用的算法名称
* @param key 加密的秘钥
* @param keysize
* @param isEncode
* @return
*/
private static String keyGeneratorES(String res, String algorithm, String key, int keysize, boolean isEncode) {
try {
KeyGenerator kg = KeyGenerator.getInstance(algorithm);
if (keysize == 0) {
byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
kg.init(new SecureRandom(keyBytes));
} else if (key == null) {
kg.init(keysize);
} else {
byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
kg.init(keysize, new SecureRandom(keyBytes));
}
SecretKey sk = kg.generateKey();
SecretKeySpec sks = new SecretKeySpec(sk.getEncoded(), algorithm);
Cipher cipher = Cipher.getInstance(algorithm);
if (isEncode) {
cipher.init(Cipher.ENCRYPT_MODE, sks);
byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset);
return parseByte2HexStr(cipher.doFinal(resBytes));
} else {
cipher.init(Cipher.DECRYPT_MODE, sks);
return new String(cipher.doFinal(parseHexStr2Byte(res)));
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Deprecated
private static String base64(byte[] res) {
return Base64.encode(res);
}
/**
* 将二进制转换成16进制
*/
public static String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
/**
* 将16进制转换为二进制
*/
public static byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1) {
return null;
}
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
/**
* md5加密算法进行加密不可逆
*
* @param res 需要加密的原文
* @return
*/
@Deprecated
public String MD5(String res) {
return messageDigest(res, MD5);
}
/**
* md5加密算法进行加密不可逆
*
* @param res 需要加密的原文
* @param key 秘钥
* @return
*/
@Deprecated
public String MD5(String res, String key) {
return keyGeneratorMac(res, HmacMD5, key);
}
/**
* 使用SHA1加密算法进行加密不可逆
*
* @param res 需要加密的原文
* @return
*/
public static String SHA1(String res) {
return messageDigest(res, SHA1);
}
/**
* 使用SHA1加密算法进行加密不可逆
*
* @param res 需要加密的原文
* @param key 秘钥
* @return
*/
public String SHA1(String res, String key) {
return keyGeneratorMac(res, HmacSHA1, key);
}
/**
* 使用DES加密算法进行加密可逆
*
* @param res 需要加密的原文
* @param key 秘钥
* @return
*/
public static String DESencode(String res, String key) {
return keyGeneratorES(res, DES, key, keysizeDES, true);
}
/**
* 对使用DES加密算法的密文进行解密可逆
*
* @param res 需要解密的密文
* @param key 秘钥
* @return
*/
public String DESdecode(String res, String key) {
return keyGeneratorES(res, DES, key, keysizeDES, false);
}
/**
* 使用异或进行加密
*
* @param res 需要加密的密文
* @param key 秘钥
* @return
*/
public String XORencode(String res, String key) {
byte[] bs = res.getBytes();
for (int i = 0; i < bs.length; i++) {
bs[i] = (byte) ((bs[i]) ^ key.hashCode());
}
return parseByte2HexStr(bs);
}
/**
* 使用异或进行解密
*
* @param res 需要解密的密文
* @param key 秘钥
* @return
*/
public String XORdecode(String res, String key) {
byte[] bs = parseHexStr2Byte(res);
for (int i = 0; i < bs.length; i++) {
bs[i] = (byte) ((bs[i]) ^ key.hashCode());
}
return new String(bs);
}
/**
* 直接使用异或(第一调用加密,第二次调用解密)
*
* @param res 密文
* @param key 秘钥
* @return
*/
public int XOR(int res, String key) {
return res ^ key.hashCode();
}
/**
* 使用Base64进行加密
*
* @param res 密文
* @return
*/
public String Base64Encode(String res) {
return Base64.encode(res.getBytes());
}
/**
* 使用Base64进行解密
*
* @param res
* @return
*/
public String Base64Decode(String res) {
return new String(Base64.decode(res));
}
private static final int length = 128;
/**
* 加密
*
* @param content 需要加密的内容
* @param password 加密密码
* @return
* @throws NoSuchAlgorithmException
* @throws NoSuchPaddingException
* @throws UnsupportedEncodingException
* @throws InvalidKeyException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
*/
private static byte[] encrypt(String content, String password)
throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(password.getBytes());
kgen.init(length, secureRandom);
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Cipher cipher = Cipher.getInstance("AES");// 创建密码器
byte[] byteContent = content.getBytes("utf-8");
cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
byte[] result = cipher.doFinal(byteContent);
return result; // 加密
}
/**
* 解密
*
* @param content 待解密内容
* @param password 解密密钥
* @return
*/
private static byte[] decrypt(byte[] content, String password)
throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(password.getBytes());
kgen.init(length, secureRandom);
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Cipher cipher = Cipher.getInstance("AES");// 创建密码器
cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
byte[] result = cipher.doFinal(content);
return result; // 加密
}
/**
* 加密
*
* @param content 需要加密的内容
* @param password 加密密码
* @return
*/
public static byte[] encrypt2(String content, String password) {
try {
SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
byte[] byteContent = content.getBytes("utf-8");
cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
byte[] result = cipher.doFinal(byteContent);
return result; // 加密
} catch (NoSuchAlgorithmException | NoSuchPaddingException | UnsupportedEncodingException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException e) {
e.printStackTrace();
}
return null;
}
@Deprecated
public static String AESencode(String content, String password) {
try {
byte[] encryptResult = encrypt(content, password);
return Base64.encode(encryptResult);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Deprecated
public static String AESdecode(String content, String password) {
try {
byte[] decryptResult = decrypt(Base64.decode(content), password);
return new String(decryptResult, StandardCharsets.UTF_8);
} catch (Exception e) {
e.printStackTrace();
return content;
}
}
public static boolean isBase64(String str) {
String base64Pattern = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$";
return Pattern.matches(base64Pattern, str);
}
public static void main(String[] args) {
// String s = AESencode("430602200007025537", "wfwbkdyrdmr");
// System.out.println(s);
// String s = AESencode("18058743226", "gsdfeygasfw");
// String s1 = AESencode("张三", "gsdfeygasfw");
// System.out.println(s);
// System.out.println(s1);
// System.out.println(Arrays.toString(Base64.decode("5vpdaf8bTigPCRakqzIZXA==")));
// String s = AESdecode("Lsz+2WDokzxEuAaoZYf0cQ==", "gsdfeygasfw");
//
// String phone = AESdecode("j6rj21kehQqc4JJS4NxTug==", "fdsasdfsdds");
// System.out.println("phone:" + phone);
// String s = AESencode("18058743226", "gsdfeygasfw");
// String s1 = AESdecode("CVr/+AgX/sHe00OQnXet9Q==", "wfwbkdyrdmr");许
// System.out.println(s1);
// String s = AESencode("13750869639", "gsdfeygasfw");
// System.out.println(s);
// System.out.println(AESdecode("O1ZWNkiAaIJLDGzwAaTfug==","gsdfeygasfw"));
// String a = AESdecode("罗娜","wfwbkdyrdmr");
// System.out.println(a);
// System.out.println(MD5Utils.encrypt(a));
// System.out.println(AESencode("17707051035","gsdfeygasfw"));
System.out.println(AESdecode("W+/dxhwi5yBWiDnqtLKY+w==", "gsdfeygasfw"));
System.out.println(AESdecode("J88FbYTTmTeKXfIBBedw1A==", "gsdfeygasfw"));
}
/***
* 利用Apache的工具类实现SHA-256加密
* @param str 加密后的报文
* @return
*/
public static String getSHA256Str(String str){
MessageDigest messageDigest;
String encdeStr = "";
try {
messageDigest = MessageDigest.getInstance("SHA-256");
byte[] hash = messageDigest.digest(str.getBytes(StandardCharsets.UTF_8));
encdeStr = Hex.encodeHexString(hash);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return encdeStr;
}
/**
* 用 AES 算法加密 inputStr。
* 使用 secretStr 作为 keyivStr作为 iv。
* 并对加密后的字节数组调用 sun.misc.BASE64Encoder.encode 方法,
* 转换成 base64 字符串返回。
*
* (仅作为测试用途,具体加密流程以接口文档为准)
*
* @param secretStr
* @param inputStr
* @return
*/
public static String base64StrDecode(String secretStr, String ivStr, String inputStr){
byte[] inputBytes;
inputBytes = org.apache.commons.codec.binary.Base64.decodeBase64(inputStr);
String outputStr = new String(decode(secretStr, ivStr, inputBytes), CHARSET);
System.out.println("base64Decode > base64 decrypt " + outputStr);
return outputStr.trim();
}
/**
* 用 AES 算法解密 inputStr。
* 使用 secretStr 作为 keyivStr作为 iv。
*
* @param secretStr
* @param ivStr
* @return
*/
public static byte[] decode(String secretStr, String ivStr, byte[] inputBytes){
if (keyStrSize != secretStr.length() || ivStrSize != ivStr.length()) {
return null;
}
byte[] secretKeyBytes = secretStr.getBytes(CHARSET);
byte[] ivBytes = ivStr.getBytes(CHARSET);
byte[] outputBytes = decryptCBCNoPadding(secretKeyBytes, ivBytes, inputBytes);
return outputBytes;
}
/**
* AES/CBC/NoPadding decrypt
* 16 bytes secretKeyStr
* 16 bytes intVector
*
* @param secretKeyBytes
* @param intVectorBytes
* @param input
* @return
*/
public static byte[] decryptCBCNoPadding(byte[] secretKeyBytes, byte[] intVectorBytes, byte[] input) {
try {
IvParameterSpec iv = new IvParameterSpec(intVectorBytes);
SecretKey secretKey = new SecretKeySpec(secretKeyBytes, AES);
Cipher cipher = Cipher.getInstance(AES_CBC_NOPADDING);
cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
byte[] encryptBytes = cipher.doFinal(input);
return encryptBytes;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* DES 加密加密模式 ECB填充方式 Pkcs7输出方式 Base64字符集 utf8
* @param data
* @param password
* @return
*/
public static String encryptECBPkcs7(String data, String password) {
if (password== null || password.length() < 8) { throw new RuntimeException("加密失败key不能小于8位"); }
if(StringUtils.isBlank(data)){ return null; }
try {
//下面这行在进行PKCS7Padding加密时必须加上否则报错
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
//根据传入的秘钥内容生成符合DES加密解密格式的秘钥内容
DESKeySpec dks = new DESKeySpec(password.getBytes());
//获取DES秘钥生成器对象
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
// 生成秘钥key的长度不能够小于8位字节
Key secretKey = keyFactory.generateSecret(dks);
//获取DES/ECB/PKCS7Padding该种级别的加解密对象
Cipher cipher = Cipher.getInstance(DES_ECB_PKCS7PADDING);
//初始化加解密对象【opmode:确定是加密还是解密模式secretKey是加密解密所用秘钥】
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] bytes = cipher.doFinal(data.getBytes(CHARSET));
return Base64.encode(bytes);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String decryptECBPkcs7(String data, String password) {
if (password== null || password.length() < 8) { throw new RuntimeException("解密失败key不能小于8位"); }
if(StringUtils.isBlank(data)){ return null; }
try {
//下面这行在进行PKCS7Padding加密时必须加上否则报错
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
//根据传入的秘钥内容生成符合DES加密解密格式的秘钥内容
DESKeySpec dks = new DESKeySpec(password.getBytes());
//获取DES秘钥生成器对象
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
// 生成秘钥key的长度不能够小于8位字节
Key secretKey = keyFactory.generateSecret(dks);
//获取DES/ECB/PKCS7Padding该种级别的加解密对象
Cipher cipher = Cipher.getInstance(DES_ECB_PKCS7PADDING);
//初始化加解密对象【opmode:确定是加密还是解密模式secretKey是加密解密所用秘钥】
cipher.init(Cipher.DECRYPT_MODE, secretKey);
return new String(cipher.doFinal(Base64.decode(data.getBytes(charset))), charset);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* AES加密
* @param content 内容
* @param password 密钥
* @return 加密后数据
*/
public static byte[] encryptECBPkcs5(byte[] content, byte[] password) {
if (content == null || password == null)
return null;
try {
Cipher cipher = Cipher.getInstance(AES_ECB_PKCS5PADDING);
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(password, AES));
return cipher.doFinal(content);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* AES解密
* @param content 加密内容
* @param password 密钥
* @return 解密后数据
*/
public static byte[] decryptECBPkcs5(byte[] content, byte[] password) {
if (content == null || password == null)
return null;
try {
Cipher cipher = Cipher.getInstance(AES_ECB_PKCS5PADDING);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(password, AES));
return cipher.doFinal(content);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

View File

@@ -0,0 +1,483 @@
package com.ruoyi.common.core.utils;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
/**
* @program: JieYiHua-Cloud
* @description: 时间工具类
* @author: LiYu
* @create: 2021-08-04 15:45
**/
public class LocalDateTimeUtils {
/**
* 获取指定日期所属周的周一的日期
*
* @param localDate
* @return
*/
public static LocalDateTime getMondayForThisWeek(LocalDate localDate) {
LocalDateTime monday = LocalDateTime.of(localDate, LocalTime.MIN).with(DayOfWeek.MONDAY);
return monday;
}
/**
* 获取指定日期所属周的周日的日期
*
* @param localDate
* @return
*/
public static LocalDateTime getSundayForThisWeek(LocalDate localDate) {
LocalDateTime sunday = LocalDateTime.of(localDate, LocalTime.MIN).with(DayOfWeek.SUNDAY);
return sunday;
}
/**
* 获取指定日期所属周的下周一的日期
*
* @param localDate
* @return
*/
public static LocalDateTime getMondayForNextWeek(LocalDate localDate) {
LocalDateTime monday = LocalDateTime.of(localDate, LocalTime.MIN).plusWeeks(1).with(DayOfWeek.MONDAY);
return monday;
}
/**
* 获取指定日期所属周的下周日的日期
*
* @param localDate
* @return
*/
public static LocalDateTime getSundayForNextWeek(LocalDate localDate) {
LocalDateTime sunday = LocalDateTime.of(localDate, LocalTime.MIN).plusWeeks(1).with(DayOfWeek.SUNDAY);
return sunday;
}
/**
* 指定格式为"yyyy-MM-dd HH:mm:ss"的字符串时间转化为LocalDateTime类型
*
* @param dateStr
* @return
*/
public static LocalDateTime getLocalDateTimeFromString(String dateStr) {
LocalDateTime localDateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
return localDateTime;
}
/**
* 指定格式为"yyyy-MM-ddTHH:mm:ss"的字符串时间转化为LocalDateTime类型
*
* @param dateStr
* @return
*/
public static LocalDateTime getLocalDateTimeFromString2(String dateStr) {
LocalDateTime localDateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd w hh:mm:ss"));
return localDateTime;
}
/**
* LocalDateTime类型转化为格式为"yyyy-MM-dd HH:mm:ss"的字符串时间类型
*
* @param localDateTime
* @return
*/
public static String getStringFromLocalDateTime(LocalDateTime localDateTime) {
String localDateTimeStr = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
return localDateTimeStr;
}
/**
* LocalDateTime类型转化为格式为"yyyy-MM-dd"的字符串时间类型
*
* @param localDateTime 时间
* @return 结果
*/
public static String getStringFromLocalDateTime2(LocalDateTime localDateTime) {
if (localDateTime == null) { return null; }
return localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
}
/**
* LocalDateTime类型转化为格式为"yyyy-MM-dd HH"的字符串时间类型
*
* @param localDateTime 时间
* @return 结果
*/
public static String getStringFromLocalDateTime4(LocalDateTime localDateTime) {
if (localDateTime == null) { return null; }
return localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH"));
}
/**
* LocalDateTime类型转化为格式为"yyyy-MM"的字符串时间类型
*/
public static String getStringFromLocalDateTime3(LocalDateTime localDateTime) {
if (localDateTime == null) {
return null;
}
return localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM"));
}
/**
* Date类型时间转化为LocalDateTime类型
*
* @param date
* @return
*/
public static LocalDateTime getLocalDateTimeFromDate(Date date) {
LocalDateTime localDateTime = date.toInstant().atOffset(ZoneOffset.of("+8")).toLocalDateTime();
return localDateTime;
}
/**
* LocalDateTime类型转化为Date类型时间
*
* @param localDateTime
* @return
*/
public static Date getDateFromLocalDateTime(LocalDateTime localDateTime) {
Date date = Date.from(localDateTime.toInstant(ZoneOffset.of("+8")));
return date;
}
/**
* 获取指定时间的00:00:00
*
* @param localDateTime
* @return
*/
public static LocalDateTime getLocalDateTimeForBegin(LocalDateTime localDateTime) {
LocalDateTime begin = LocalDateTime.of(localDateTime.toLocalDate(), LocalTime.MIN);
return begin;
}
/**
* 获取指定时间的23:59:59
*
* @param localDateTime
* @return
*/
public static LocalDateTime getLocalDateTimeForEnd(LocalDateTime localDateTime) {
LocalDateTime end = LocalDateTime.of(localDateTime.toLocalDate(), LocalTime.MAX);
return end;
}
/**
* 时间戳(毫秒)转化为LocalDateTime格式
*
* @param timestamp
* @return
*/
public static LocalDateTime getLocalDateTimeFromTimestamp(Long timestamp) {
LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(timestamp / 1000, 0, ZoneOffset.ofHours(8));
return localDateTime;
}
/**
* LocalDateTime格式转化为时间戳(毫秒)
*
* @param localDateTime
* @return
*/
public static Long getTimestampFromLocalDateTime(LocalDateTime localDateTime) {
Long timestamp = localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
return timestamp;
}
/**
* 时间戳(毫秒)转 yyyy-MM-dd HH:mm:ss
* @param timestamp
* @return
*/
public static String getStringFromTimestamp(Long timestamp) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return dateFormat.format(timestamp);
}
/**
* 获取本月开始时间
*
* @return 开始时间
*/
public static LocalDateTime getFirstDayOfMonth() {
return LocalDateTime.of(LocalDate.from(LocalDateTime.now().with(TemporalAdjusters.firstDayOfMonth())), LocalTime.MIN);
}
/**
* 获取月初
*
* @param localDateTime 时间
* @return 数据
*/
public static LocalDateTime getTheBeginningOfTheMonth(LocalDateTime localDateTime) {
return LocalDateTime.of(LocalDate.from(localDateTime.with(TemporalAdjusters.firstDayOfMonth())), LocalTime.MIN);
}
/**
* 获取本月结束时间
*
* @return 结束时间
*/
public static LocalDateTime getLastDay() {
return LocalDateTime.of(LocalDate.from(LocalDateTime.now().with(TemporalAdjusters.lastDayOfMonth())), LocalTime.MAX);
}
public static LocalDateTime getTheEndOfTheMonth(LocalDateTime localDateTime) {
return LocalDateTime.of(LocalDate.from(localDateTime.with(TemporalAdjusters.lastDayOfMonth())), LocalTime.MAX);
}
/**
* 获取时间差 (秒)
*
* @param startTime 开始时间
* @param endTime 结束时间
* @return 秒
*/
public static Long getTimeDifference(LocalDateTime startTime, LocalDateTime endTime) {
Duration duration = Duration.between(startTime, endTime);
return duration.toMinutes() * 60;
}
/**
* 获取两个时间差 (天数)
*
* @param localDateTime 时间
* @return 天数
*/
public static Long timeDifferenceByDay(LocalDateTime localDateTime) {
LocalDateTime now = LocalDateTime.now();
Duration duration = Duration.between(localDateTime, now);
return duration.toDays();
}
/**
* 获取两天时间间隔
*
* @param startingTime 开始时间
* @param endTime 结束时间
* @return 结果
*/
public static Long twoDayInterval(LocalDateTime startingTime, LocalDateTime endTime) {
Duration duration = Duration.between(startingTime, endTime);
return duration.toDays();
}
/**
* 转白话
*
* @param localDateTime 时间
* @return 字符串
*/
public static String toTheVernacular(LocalDateTime localDateTime) {
return localDateTime.getYear() + "" + localDateTime.getMonthValue() + "" + localDateTime.getDayOfMonth() + "";
}
/**
* 获取昨天
*
* @return 获取昨天
*/
public static LocalDateTime getYesterdaySDate() {
return LocalDateTime.now().plusDays(1);
}
/**
* 获取昨天
*
* @return 获取昨天
*/
public static LocalDateTime getMinusDays() {
return LocalDateTime.now().minusDays(1);
}
/**
* 获取明天
*
* @return 获取明天
*/
public static LocalDateTime getPlusDays() {
return LocalDateTime.now().plusDays(1);
}
/**
* 获取今年开始时间
*
* @return 开始时间
*/
public static LocalDateTime startThisYear() {
return LocalDateTime.of(LocalDate.from(LocalDateTime.now().with(TemporalAdjusters.firstDayOfYear())), LocalTime.MIN);
}
/**
* 根据日期获取 星期 2019-05-06 ——> 星期一)
*
* @param datetime
* @return
*/
public static int dateToWeek(LocalDateTime datetime) {
//获取当前时间
LocalDateTime currentDate = LocalDateTime.now();
//获取当前周
int week = currentDate.getDayOfWeek().getValue();
System.out.println("获取当前周:" + week);
return week;
}
public static void main(String[] args) {
System.out.println(twoDayInterval(LocalDateTime.now(),LocalDateTime.now()));
System.out.println(getNowBeforeHourTime(-24L));
}
/**
* 获取今天开始时间
*
* @return 结果
*/
public static LocalDateTime getTodayStartTime() {
return getLocalDateTimeForBegin(LocalDateTime.now());
}
/**
* 获取今天结束时间
*
* @return 结果
*/
public static LocalDateTime getTodayEndTime() {
return getLocalDateTimeForEnd(LocalDateTime.now());
}
/**
* 相隔所有时间
*
* @param startingTime 开始时间
* @param endTime 结束时间
* @return 结果
*/
public static List<String> allTimeApart(String startingTime, String endTime) {
Long size = LocalDateTimeUtils.twoDayInterval(LocalDateTimeUtils.getLocalDateTimeFromString(startingTime), LocalDateTimeUtils.getLocalDateTimeFromString(endTime));
List<String> list = new ArrayList<>(Math.toIntExact(size));
LocalDateTime time = getLocalDateTimeFromString(endTime);
for (int i = 0; i <= size; i++) {
LocalDateTime localDateTime = time.minusDays(i);
list.add(getStringFromLocalDateTime2(localDateTime));
}
return list;
}
/**
* 判断当前用户登录时段是否在09:00-18:00
* @param
* @return
*/
public static boolean setFirstLogTime(){
SimpleDateFormat formatter = new SimpleDateFormat("HH:mm");//获取时,分
//当前系统时间
Date data = new Date();
String dateString = formatter.format(data);
String format = "HH:mm";
try{
Date nowTime = new SimpleDateFormat(format).parse(dateString);
Date startTime = new SimpleDateFormat(format).parse("09:00");
Date endTime = new SimpleDateFormat(format).parse("18:00");
return isEffectiveDate(nowTime, startTime, endTime);
}catch (Exception e){
e.printStackTrace();
return false;
}
}
/**
* 判断当前时间是否在[startTime, endTime]区间,注意时间格式要一致
*
* @param nowTime 当前时间
* @param startTime 开始时间
* @param endTime 结束时间
* @return
*/
public static boolean isEffectiveDate(Date nowTime, Date startTime, Date endTime) {
if (nowTime.getTime() == startTime.getTime() || nowTime.getTime() == endTime.getTime()) {
return true;
}
Calendar date = Calendar.getInstance();
date.setTime(nowTime);
Calendar begin = Calendar.getInstance();
begin.setTime(startTime);
Calendar end = Calendar.getInstance();
end.setTime(endTime);
if (date.after(begin) && date.before(end)) {
return true;
} else {
return false;
}
}
/**
* 判断当前日期是否大于某个日期
* @param date yyyy-MM-dd
* @return
*/
public static boolean afterDate(LocalDateTime date){
//针对好享管家图片相反
String times = "2022-08-23";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
//把String转为LocalDate
LocalDate localTime=LocalDate.parse(times,dtf);
//判断当前日期是否大于指定日期
return date.toLocalDate().isAfter(localTime);
}
/**
* 获取当前时间指定偏移多长小时前的时间
* @param hour 负向前偏移 正向后偏移
* @return
*/
public static LocalDateTime getNowBeforeHourTime(Long hour){
LocalDateTime localDateTime = LocalDateTime.now(ZoneId.systemDefault());
return localDateTime.plusHours(hour);
}
public static Long timeDifferenceByLocalDate(LocalDateTime localDateTime) {
LocalDate toLocalDate = localDateTime.toLocalDate();
LocalDate now = LocalDate.now();
long until = toLocalDate.until(now, ChronoUnit.DAYS);
return toLocalDate.until(now, ChronoUnit.DAYS);
}
/**
* 判断时间是否是今天
* @param localDateTime 时间
* @return 结果
*/
public static boolean isToday(LocalDateTime localDateTime) {
return localDateTime.toLocalDate().equals(LocalDate.now());
}
/**
* 判断日期是否是指定天数内
* @param localDateTime 时间
* @param day 天数
* @return 结果
*/
public static boolean isDay(LocalDateTime localDateTime,Long day) {
return localDateTime.toLocalDate().equals(LocalDate.now().plusDays(day));
}
public static long getTimeStamp(String dateTime){
LocalDateTime time = LocalDateTimeUtils.getLocalDateTimeFromString(dateTime);
return time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
}
}

View File

@@ -0,0 +1,155 @@
package com.ruoyi.common.core.utils;
import com.ruoyi.common.core.domain.GuestProbabilityReq;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
import java.util.*;
/**
* 计算助贷计划概率
* @Author: daisi
* @Date: 2022/4/2 11:10
*/
@Slf4j
public class ProbitUtil {
public static GuestProbabilityReq calculatePlanTheProbability(List<GuestProbabilityReq> guestProbabilityReqs) {
//按排序价格排序
Collections.sort(guestProbabilityReqs, new Comparator<GuestProbabilityReq>() {
@Override
public int compare(GuestProbabilityReq o1, GuestProbabilityReq o2) {
return o2.getOrderPrice().compareTo(o1.getOrderPrice());
}
});
List<GuestProbabilityReq> list = new ArrayList<>(5);
for (GuestProbabilityReq guestProbabilityReq : guestProbabilityReqs) {
// if (guestProbabilityReq.getOrderPrice().compareTo(guestProbabilityReqs.get(0).getOrderPrice()) == 0) {
// list.add(guestProbabilityReq);
// }
list.add(guestProbabilityReq);
}
log.info("排序后的数据:{}",list);
//重置概率
resetTranslate(list);
int index = drawGift(list);
return guestProbabilityReqs.get(index);
}
private static List<GuestProbabilityReq> resetTranslate(List<GuestProbabilityReq> reqs) {
if (reqs.size()!=1){
//高值得一部分
int count = 0;
//获取计数
BigDecimal orderPrice = reqs.get(0).getOrderPrice();
for (int i = 0; i < reqs.size(); i++) {
if (i+1<reqs.size()&&reqs.get(i).getOrderPrice().compareTo(reqs.get(i+1).getOrderPrice())==0&&orderPrice.compareTo(reqs.get(i).getOrderPrice())==0){
count++;
}
}
///获取最高的概率
BigDecimal bigDecimal = new BigDecimal(reqs.get(0).getGuestProbability().toString());
if (count!=0){
//用最高的概率除以计数 得到最高价的平均概率
BigDecimal divide = bigDecimal.divide(new BigDecimal(count+1),3,BigDecimal.ROUND_DOWN);
for (int i = 0; i <= count; i++) {
//循环重设最高概率
reqs.get(i).setGuestProbability(divide.doubleValue());
}
}
//低值得一部分
BigDecimal remTotal = new BigDecimal(1).subtract(bigDecimal);
BigDecimal b = remTotal.divide(new BigDecimal((reqs.size()-count-1)==0?1:(reqs.size()-count-1)),3,BigDecimal.ROUND_HALF_UP);
for (int i = count+1; i < reqs.size(); i++) {
reqs.get(i).setGuestProbability(b.doubleValue());
}
}
//log.info("重置概率后的概率,{}",reqs);
return reqs;
}
public static int drawGift(List<GuestProbabilityReq> guestProbabilityReqList) {
if (null != guestProbabilityReqList && guestProbabilityReqList.size() > 0) {
List<Double> orgProbList = new ArrayList<Double>(guestProbabilityReqList.size());
for (GuestProbabilityReq guest : guestProbabilityReqList) {
//按顺序将概率添加到集合中
orgProbList.add(guest.getGuestProbability());
}
return draw(orgProbList);
}
return -1;
}
public static int draw(List<Double> giftProbList) {
List<Double> sortRateList = new ArrayList<Double>();
// 计算概率总和
Double sumRate = 0D;
for (Double prob : giftProbList) {
sumRate += prob;
}
if (sumRate != 0) {
double rate = 0D; //概率所占比例
for (Double prob : giftProbList) {
rate += prob;
// 构建一个比例区段组成的集合(避免概率和不为1)
sortRateList.add(rate / sumRate);
}
// 随机生成一个随机数,并排序
double random = Math.random();
sortRateList.add(random);
Collections.sort(sortRateList);
// 返回该随机数在比例集合中的索引
return sortRateList.indexOf(random);
}
return -1;
}
// public static void main(String[] args) {
//// System.out.println(LocalDateTimeUtils.getStringFromLocalDateTime(LocalDateTimeUtil.beginOfDay(LocalDateTimeUtil.offset(LocalDateTime.now(), -7, ChronoUnit.DAYS))));
//// System.out.println(LocalDateTimeUtils.getStringFromLocalDateTime(LocalDateTimeUtil.endOfDay(LocalDateTimeUtil.offset(LocalDateTime.now(), -1, ChronoUnit.DAYS))));
// int a=0;
// List<GuestProbabilityReq> guestProbabilityReqs = new ArrayList<>();
// for (int i = 0; i < 20; i++) {
// List<GuestProbabilityReq> list = new ArrayList<>();
// GuestProbabilityReq req = new GuestProbabilityReq();
// req.setPlanId(1L).setOrderPrice(new BigDecimal(104.00)).setGuestProbability(0.8D);
//
// GuestProbabilityReq req1 = new GuestProbabilityReq();
// req1.setPlanId(2L).setOrderPrice(new BigDecimal(120)).setGuestProbability(0.8D);
//
// GuestProbabilityReq req2 = new GuestProbabilityReq();
// req2.setPlanId(3L).setOrderPrice(new BigDecimal(90)).setGuestProbability(0.8D);
//
// GuestProbabilityReq req3 = new GuestProbabilityReq();
// req3.setPlanId(4L).setOrderPrice(new BigDecimal(110)).setGuestProbability(0.4D);
//
// GuestProbabilityReq req4 = new GuestProbabilityReq();
// req4.setPlanId(5L).setOrderPrice(new BigDecimal(110)).setGuestProbability(0.6D);
////
//// GuestProbabilityReq req5 = new GuestProbabilityReq();
//// req5.setPlanId(6L).setOrderPrice(new BigDecimal(80)).setGuestProbability(0.6D);
//
// list.add(req);
// list.add(req1);
// list.add(req2);
// list.add(req3);
// list.add(req4);
//// list.add(req5);
//
// guestProbabilityReqs.add(calculatePlanTheProbability(list));
//
// }
// int b = 0;
// int c = 0;
// for (GuestProbabilityReq req:guestProbabilityReqs) {
// if (req.getPlanId()==2){
// b++;
// }else {
// c++;
// }
// }
// System.out.println("几率:"+c+" "+b);
// }
}

View File

@@ -0,0 +1,517 @@
package com.ruoyi.common.core.utils;
import com.ruoyi.common.core.constant.HttpStatus;
import lombok.extern.slf4j.Slf4j;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.Objects;
import java.util.Random;
import java.util.regex.Pattern;
/**
* @author LiYu
* @ClassName SecureUtil.java
* @Description 加解密工具类
* @createTime 2024年05月20日 11:04:00
*/
@Slf4j
public class SecureUtils {
/**
* md5加密
*/
public static class Md5Util {
/**
* 判断是否为md5加密
*
* @param str 字符串
* @return 结果
*/
public static boolean isMd5(String str) {
return str.matches("^[a-f0-9]{32}$");
}
/**
* MD5加密并转大写
*
* @param str 字符串
* @return 结果
*/
public static String md5ToUpperCase(String str) {
return StringUtils.hasText(str) ? isMd5(str) ? str : cn.hutool.crypto.SecureUtil.md5(str).toUpperCase() : null;
}
/**
* MD5加密并转小写
*
* @param str 字符串
* @return 结果
*/
public static String md5ToLowerCase(String str) {
return StringUtils.hasText(str) ? isMd5(str) ? str : cn.hutool.crypto.SecureUtil.md5(str).toLowerCase() : null;
}
/**
* MD5加密
*
* @param str 字符串
* @return 结果
*/
public static String md5(String str) {
return StringUtils.hasText(str) ? isMd5(str) ? str : cn.hutool.crypto.SecureUtil.md5(str) : null;
}
}
/**
* des加密
*/
public static class DesUtil {
/**
* 加密key
*/
public static final String KEY = "_@Ks`Y*9jLb.hvho}C;GwDpw";
/**
* 偏移量
*/
public static final String IV = "2%8iTpSi";
/**
* 创建加密对象
*
* @param iv 偏移量
* @param mode 模式
* @return 结果
*/
private static Cipher createCipher(String iv, int mode) throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, InvalidAlgorithmParameterException {
byte[] key = KEY.getBytes();
Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes());
cipher.init(mode, new SecretKeySpec(key, "DESede"), ivParameterSpec);
return cipher;
}
/**
* 加密
*
* @param data 数据
* @param iv 偏移量
* @return 结果
*/
public static String encrypt(String data, String iv) {
try {
Cipher cipher = createCipher(iv, Cipher.ENCRYPT_MODE);
return URLEncoder.encode(Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes())), "UTF-8");
} catch (Exception e) {
log.error("加密失败", e);
}
return null;
}
/**
* 加密
*
* @param data 数据
* @return 结果
*/
public static String encrypt(String data) {
return encrypt(data, IV);
}
/**
* 解密
*
* @param data 数据
* @param iv 偏移量
* @return 结果
*/
public static String decrypt(String data, String iv) {
try {
Cipher cipher = createCipher(iv, Cipher.DECRYPT_MODE);
return new String(cipher.doFinal(Base64.getDecoder().decode(URLDecoder.decode(data, "UTF-8"))));
} catch (Exception e) {
log.error("解密失败", e);
}
return null;
}
/**
* 解密
*
* @param data 数据
* @return 结果
*/
public static String decrypt(String data) {
return decrypt(data, IV);
}
}
/**
* AES加解密
*/
public static class AesUtil {
/**
* 加密模式之 ECB算法/模式/补码方式
*/
public static final String AES_ECB = "AES/ECB/PKCS5Padding";
/**
* 加密模式之 CBC算法/模式/补码方式
*/
public static final String AES_CBC = "AES/CBC/PKCS5Padding";
/**
* 加密模式之 CFB算法/模式/补码方式
*/
public static final String AES_CFB = "AES/CFB/PKCS5Padding";
/**
* AES 中的 IV 必须是 16 字节128位
*/
public static final Integer IV_LENGTH = 16;
/***
* 空校验
* @param str 需要判断的值
*/
public static boolean isEmpty(Object str) {
return null == str || "".equals(str);
}
/***
* String 转 byte
* @param str 需要转换的字符串
*/
public static byte[] getBytes(String str) {
if (isEmpty(str)) {
return null;
}
try {
return str.getBytes(StandardCharsets.UTF_8);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/***
* 初始化向量IV它是一个随机生成的字节数组用于增加加密和解密的安全性
*/
public static String getIv() {
String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < IV_LENGTH; i++) {
int number = random.nextInt(str.length());
sb.append(str.charAt(number));
}
return sb.toString();
}
/***
* 获取一个 AES 密钥规范
*/
public static SecretKeySpec getSecretKeySpec(String key) {
return new SecretKeySpec(Objects.requireNonNull(getBytes(key)), "AES");
}
/**
* 加密 - 模式 ECB
*
* @param text 需要加密的文本内容
* @param key 加密的密钥 key
*/
public static String encrypt(String text, String key) {
if (isEmpty(text) || isEmpty(key)) {
return null;
}
try {
// 创建AES加密器
Cipher cipher = Cipher.getInstance(AES_ECB);
SecretKeySpec secretKeySpec = getSecretKeySpec(key);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
// 加密字节数组
byte[] encryptedBytes = cipher.doFinal(Objects.requireNonNull(getBytes(text)));
// 将密文转换为 Base64 编码字符串
return Base64.getEncoder().encodeToString(encryptedBytes);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 解密 - 模式 ECB
*
* @param text 需要解密的文本内容
* @param key 解密的密钥 key
*/
public static String decrypt(String text, String key) {
if (isEmpty(text) || isEmpty(key)) {
return null;
}
// 将密文转换为16字节的字节数组
byte[] textBytes = Base64.getDecoder().decode(text);
try {
// 创建AES加密器
Cipher cipher = Cipher.getInstance(AES_ECB);
SecretKeySpec secretKeySpec = getSecretKeySpec(key);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
// 解密字节数组
byte[] decryptedBytes = cipher.doFinal(textBytes);
// 将明文转换为字符串
return new String(decryptedBytes, StandardCharsets.UTF_8);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 加密 - 自定义加密模式
*
* @param text 需要加密的文本内容
* @param key 加密的密钥 key
* @param iv 初始化向量
* @param mode 加密模式
*/
public static String encrypt(String text, String key, String iv, String mode) {
if (isEmpty(text) || isEmpty(key) || isEmpty(iv)) {
return null;
}
try {
// 创建AES加密器
Cipher cipher = Cipher.getInstance(mode);
SecretKeySpec secretKeySpec = getSecretKeySpec(key);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(Objects.requireNonNull(getBytes(iv))));
// 加密字节数组
byte[] encryptedBytes = cipher.doFinal(Objects.requireNonNull(getBytes(text)));
// 将密文转换为 Base64 编码字符串
return Base64.getEncoder().encodeToString(encryptedBytes);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 加密
*
* @param content 待加密内容
* @param password 加密密钥
* @return 加密后的内容
*/
public static String AesEncode(String content, String password) {
try {
byte[] encryptResult = encryptByte(content, password);
return Base64Util.encode(encryptResult);
} catch (Exception e) {
log.error("加密出现问题!", e);
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
String s = "{\"accumulationFund\":1,\"age\":18,\"car\":1,\"career\":1,\"city\":\"重庆\",\"cityCode\":1000,\"creditCard\":1,\"education\":1,\"guarantee\":1,\"hourse\":1,\"idCardMd5\":\"331d17d1ca8a091410e3238fab16a863\",\"monthlyIncome\":5000,\"nameMd5\":\"331d17d1ca8a091410e3238fab16a863\",\"phoneMd5\":\"331d17d1ca8a091410e3238fab16a863\",\"sex\":0,\"socialSecurity\":1,\"zhiMa\":600}";
String s1 = "{\"accumulationFund\":1,\"age\":18,\"car\":1,\"career\":1,\"city\":\"重庆\",\"cityCode\":1000,\"creditCard\":1,\"education\":1,\"guarantee\":1,\"hourse\":1,\"idCard\":\"341202199306023511\",\"idCardMd5\":\"331d17d1ca8a091410e3238fab16a863\",\"monthlyIncome\":5000,\"name\":\"朱三\",\"nameMd5\":\"331d17d1ca8a091410e3238fab16a863\",\"phone\":\"15205600635\",\"phoneMd5\":\"331d17d1ca8a091410e3238fab16a863\",\"sex\":0,\"socialSecurity\":1,\"zhiMa\":600}";
String s3 = "{\n" +
" \"orderNo\":\"111111\",\n" +
" \"md5\":\"aaaaaa\",\n" +
" \"price\":100.00,\n" +
" \"orderStatus\":\"2\"\n" +
"}";
System.out.println(AesEncode(s1,"g5N8XTYaOEwEmBgg"));
}
/**
* 解密
*
* @param content 待解密内容
* @param password 解密密钥
* @return 解密后的内容
*/
public static String AesDecode(String content, String password) {
try {
byte[] decryptResult = decryptByte(Base64Util.decodeToByteArray(content), password);
return new String(decryptResult, StandardCharsets.UTF_8);
} catch (Exception e) {
log.error("解密出现问题!", e);
return null;
}
}
/**
* 加密 - 模式 CBC
*
* @param text 需要加密的文本内容
* @param key 加密的密钥 key
* @param iv 初始化向量
* @return 加密后的内容
*/
public static String encryptCbc(String text, String key, String iv) {
return encrypt(text, key, iv, AES_CBC);
}
/**
* 解密 - 自定义加密模式
*
* @param text 需要解密的文本内容
* @param key 解密的密钥 key
* @param iv 初始化向量
* @param mode 加密模式
*/
public static String decrypt(String text, String key, String iv, String mode) {
if (isEmpty(text) || isEmpty(key) || isEmpty(iv)) {
return null;
}
// 将密文转换为16字节的字节数组
byte[] textBytes = Base64.getDecoder().decode(text);
try {
// 创建AES加密器
Cipher cipher = Cipher.getInstance(mode);
SecretKeySpec secretKeySpec = getSecretKeySpec(key);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(Objects.requireNonNull(getBytes(iv))));
// 解密字节数组
byte[] decryptedBytes = cipher.doFinal(textBytes);
// 将明文转换为字符串
return new String(decryptedBytes, StandardCharsets.UTF_8);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 解密
*
* @param content 待解密内容
* @param password 解密密钥
* @return 解密后的内容
*/
private static byte[] decryptByte(byte[] content, String password)
throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(password.getBytes());
keyGenerator.init(128, secureRandom);
SecretKey secretKey = keyGenerator.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
return cipher.doFinal(content);
}
/**
* 加密
*
* @param content 需要加密的内容
* @param password 加密密码
* @return 加密后的字节数组
*/
private static byte[] encryptByte(String content, String password)
throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(password.getBytes());
keyGenerator.init(128, secureRandom);
SecretKey secretKey = keyGenerator.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Cipher cipher = Cipher.getInstance("AES");// 创建密码器
byte[] byteContent = content.getBytes(StandardCharsets.UTF_8);
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(byteContent);
}
/**
* 解密 - 模式 CBC
*
* @param text 需要加密的文本内容
* @param key 加密的密钥 key
* @param iv 初始化向量
* @return 加密后的内容
*/
public static String decryptCbc(String text, String key, String iv) {
return decrypt(text, key, iv, AES_CBC);
}
}
/**
* Base64加解密
*/
public static class Base64Util {
/**
* 编码字符串为Base64
*
* @param input 需要编码的字符串
* @return 编码后的Base64字符串
*/
public static String encode(String input) {
return Base64.getEncoder().encodeToString(input.getBytes());
}
/**
* 从Base64编码解码为字符串
*
* @param input Base64编码的字符串
* @return 解码后的字符串
*/
public static String decode(String input) {
byte[] decodedBytes = Base64.getDecoder().decode(input);
return new String(decodedBytes);
}
/**
* 编码字节数组为Base64字符串
*
* @param input 需要编码的字节数组
* @return 编码后的Base64字符串
*/
public static String encode(byte[] input) {
return Base64.getEncoder().encodeToString(input);
}
/**
* 解码Base64字符串为字节数组
*
* @param input Base64编码的字符串
* @return 解码后的字节数组
*/
public static byte[] decodeToByteArray(String input) {
return Base64.getDecoder().decode(input);
}
/**
* 判断是否为Base64编码
*
* @param str 字符串
* @return 结果
*/
public static boolean isBase64(String str) {
String base64Pattern = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$";
return Pattern.matches(base64Pattern, str);
}
}
public static void main(String[] args) {
}
}

View File

@@ -0,0 +1,456 @@
package com.ruoyi.common.core.utils.match;
import com.ruoyi.common.core.domain.http.Customer;
import com.ruoyi.common.core.domain.http.Merchant;
import lombok.extern.slf4j.Slf4j;
import java.util.Objects;
@Slf4j
public class MatchQualification {
/**
* 是否可以匹配上产品
* @param customer 用户信息
* @param merchant 产品前筛
* openInfoFilter 开启资质筛选 0:不筛选, 1:满足1, 2:满足全部
*
* @return 结构
*/
public static Boolean doesItMatchProduct(Customer customer, Merchant merchant) {
// if (Objects.isNull(merchant)){
// return true;
// }
//
// if (Objects.isNull(merchant.getCustomerInfoFilterType()) || merchant.getCustomerInfoFilterType() == 0){
// return true;
// }
//
// //满足1个
// boolean openOne = merchant.getCustomerInfoFilterType() == 1;
// //满足所有
// boolean openAll = merchant.getCustomerInfoFilterType() == 2;
// //结果
// boolean result = false;
//
// String userInfo = customer.getId() + "-" + customer.getChannelId() + "-" + merchant.getId();
//
// //社保
// if (merchant.getSocialSecurityHigh() || merchant.getSocialSecurityNo() ||merchant.getSocialSecurityLow()) {
// if (openAll && Objects.isNull(customer.getSocialSecurity())){
// log.info("资质匹配筛选, 配置[满足所有]-社保为空, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userInfo);
// return false;
// }
//
// Integer infoByCode = customer.getSocialSecurity();
// if (Objects.nonNull(customer.getSocialSecurity())) {
// if (merchant.getSocialSecurityNo()) {
// if (customer.getSocialSecurity()==merchant.getSocialSecurityNo())) {
// result = true;
// }
// }
//
// if (merchant.getSocialSecurityLow()) {
// if (customer.getSocialSecurity().equals(CustomerSocialSecurityType.GREAT_SOCIAL_SECURITY.getCode())) {
// result = true;
// }
// }
//
// //条件为 满足一个即可, 恰巧现在就有满足的, 则返回true通过
// if (openOne && result) {
//// log.info("资质匹配筛选, 配置[满足其一]-社保:{}, 匹配通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userDetailsDTO.getSocialSecurity() + "-" + infoByCode, userInfo);
// return result;
// }
// }
//
// //条件为 满足全部, 恰巧现在这个不满足, 则返回false(不通过)
// if (openAll && !result) {
// log.info("资质匹配筛选, 配置[满足所有]-社保:{}, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userDetailsDTO.getSocialSecurity() + "-" + infoByCode, userInfo);
// return false;
// }
// }
//
// //公积金
// if (productLimit.getSmallProvidentFund() || productLimit.getGreatProvidentFund()) {
// if (openAll && Objects.isNull(userDetailsDTO.getProvidentFund())){
// log.info("资质匹配筛选, 配置[满足所有]-公积金为空, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userInfo);
// return false;
// }
//
// //判断结果置默认
// result = false;
// String infoByCode = CustomerProvidentFundType.getInfoByCode(userDetailsDTO.getProvidentFund());
// if (Objects.nonNull(userDetailsDTO.getProvidentFund())) {
// if (productLimit.getSmallProvidentFund()) {
// if (userDetailsDTO.getProvidentFund().equals(CustomerProvidentFundType.SMALL_PROVIDENT_FUND.getCode())) {
// result = true;
// }
// }
//
// if (productLimit.getGreatProvidentFund()) {
// if (userDetailsDTO.getProvidentFund().equals(CustomerProvidentFundType.GREAT_PROVIDENT_FUND.getCode())) {
// result = true;
// }
// }
//
// //条件为 满足一个即可, 恰巧现在就有满足的, 则返回true通过
// if (openOne && result) {
//// log.info("资质匹配筛选, 配置[满足其一]-公积金:{}, 匹配通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userDetailsDTO.getProvidentFund() + "-" + infoByCode, userInfo);
// return result;
// }
// }
//
// //条件为 满足全部, 恰巧现在这个不满足, 则返回false(不通过)
// if (openAll && !result) {
//// log.info("资质匹配筛选, 配置[满足所有]-公积金:{}, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userDetailsDTO.getProvidentFund() + "-" + infoByCode, userInfo);
// return false;
// }
// }
//
// //车产
// if (productLimit.getHavaCar()) {
// if (openAll && Objects.isNull(userDetailsDTO.getCarProduction())){
// log.info("资质匹配筛选, 配置[满足所有]-车产为空, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userInfo);
// return false;
// }
//
// //判断结果置默认
// result = false;
// String infoByCode = CustomerCarProductionType.getInfoByCode(userDetailsDTO.getCarProduction());
// if (Objects.nonNull(userDetailsDTO.getCarProduction())) {
// if (userDetailsDTO.getCarProduction().equals(CustomerCarProductionType.HAVE_CAR.getCode())) {
// result = true;
// }
//
// //条件为 满足一个即可, 恰巧现在就有满足的, 则返回true通过
// if (openOne && result) {
// log.info("资质匹配筛选, 配置[满足其一]-车产:{}, 匹配通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userDetailsDTO.getCarProduction() + "-" + infoByCode, userInfo);
// return result;
// }
// }
//
// //条件为 满足全部, 恰巧现在这个不满足, 则返回false(不通过)
// if (openAll && !result) {
// log.info("资质匹配筛选, 配置[满足所有]-车产:{}, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userDetailsDTO.getCarProduction() + "-" + infoByCode, userInfo);
// return false;
// }
// }
//
// //房产
// if (productLimit.getHaveMortgageRoom() || productLimit.getHaveFullRoom()) {
// if (openAll && Objects.isNull(userDetailsDTO.getEstate())){
// log.info("资质匹配筛选, 配置[满足所有]-房产为空, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userInfo);
// return false;
// }
//
// //判断结果置默认
// result = false;
// String infoByCode = CustomerEstateType.getInfoByCode(userDetailsDTO.getEstate());
// if (Objects.nonNull(userDetailsDTO.getEstate())) {
// if (productLimit.getHaveMortgageRoom()){
// if (userDetailsDTO.getEstate().equals(CustomerEstateType.HAVE_PROPERTY.getCode())){
// result = true;
// }
// }
//
// if (productLimit.getHaveFullRoom()){
// if (userDetailsDTO.getEstate().equals(CustomerEstateType.FULL_PAYMENT_FOR_HOUSING.getCode())){
// result = true;
// }
// }
//
// //条件为 满足一个即可, 恰巧现在就有满足的, 则返回true通过
// if (openOne && result) {
//// log.info("资质匹配筛选, 配置[满足其一]-房产:{}, 匹配通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userDetailsDTO.getEstate() + "-" + infoByCode, userInfo);
// return result;
// }
// }
//
// //条件为 满足全部, 恰巧现在这个不满足, 则返回false(不通过)
// if (openAll && !result) {
// log.info("资质匹配筛选, 配置[满足所有]-房产:{}, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userDetailsDTO.getEstate() + "-" + infoByCode, userInfo);
// return false;
// }
// }
//
// //保单
// if (productLimit.getPolicyLessThanOneYear() || productLimit.getPolicyPaymentForOneYear() || productLimit.getPolicyPaymentForTwoYear()) {
// if (openAll && Objects.isNull(userDetailsDTO.getPersonalInsurance())){
// log.info("资质匹配筛选, 配置[满足所有]-保单为空, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userInfo);
// return false;
// }
//
// //判断结果置默认
// result = false;
// String infoByCode = CustomerInsurancePolicyType.getInfoByCode(userDetailsDTO.getPersonalInsurance());
// if (Objects.nonNull(userDetailsDTO.getPersonalInsurance())) {
// if (productLimit.getPolicyLessThanOneYear()) {
// if (userDetailsDTO.getPersonalInsurance().equals(CustomerInsurancePolicyType.POLICY_LESS_THAN_ONE_YEAR.getCode())) {
// result = true;
// }
// }
//
// if (productLimit.getPolicyPaymentForOneYear()) {
// if (userDetailsDTO.getPersonalInsurance().equals(CustomerInsurancePolicyType.POLICY_PAYMENT_FOR_ONE_YEAR.getCode())) {
// result = true;
// }
// }
//
// if (productLimit.getPolicyPaymentForTwoYear()) {
// if (userDetailsDTO.getPersonalInsurance().equals(CustomerInsurancePolicyType.POLICY_PAYMENT_FOR_TWO_YEAR.getCode())) {
// result = true;
// }
// }
//
// //条件为 满足一个即可, 恰巧现在就有满足的, 则返回true通过
// if (openOne && result) {
// log.info("资质匹配筛选, 配置[满足其一]-保单:{}, 匹配通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userDetailsDTO.getPersonalInsurance() + "-" + infoByCode, userInfo);
// return result;
// }
// }
//
// //条件为 满足全部, 恰巧现在这个不满足, 则返回false(不通过)
// if (openAll && !result) {
// log.info("资质匹配筛选, 配置[满足所有]-保单:{}, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userDetailsDTO.getPersonalInsurance() + "-" + infoByCode, userInfo);
// return false;
// }
// }
//
// //芝麻分
// if (Objects.nonNull(productLimit.getSesame())){
// if (openAll && Objects.isNull(userDetailsDTO.getSesame())){
// log.info("资质匹配筛选, 配置[满足所有]-芝麻分为空, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userInfo);
// return false;
// }
//
// //判断结果置默认
// result = false;
// if (Objects.nonNull(userDetailsDTO.getSesame())) {
// if (userDetailsDTO.getSesame() >= productLimit.getSesame()){
// result = true;
// }
//
// //条件为 满足一个即可, 恰巧现在就有满足的, 则返回true通过
// if (openOne && result) {
// log.info("资质匹配筛选, 配置[满足其一]-芝麻分:{}, 匹配通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userDetailsDTO.getSesame(), userInfo);
// return result;
// }
// }
//
// //条件为 满足全部, 恰巧现在这个不满足, 则返回false(不通过)
// if (openAll && !result) {
// log.info("资质匹配筛选, 配置[满足所有]-芝麻分:{}, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userDetailsDTO.getSesame(), userInfo);
// return false;
// }
// }
//
// //职业
// if (productLimit.getOfficeWorker() ||
// productLimit.getCivilServant() ||
// productLimit.getPrivateOwners() ||
// productLimit.getSmallPrivateBusiness() ||
// productLimit.getOtherOccupations()) {
//
// if (openAll && Objects.isNull(userDetailsDTO.getProfessionalIdentity())){
// log.info("资质匹配筛选, 配置[满足所有]-职业为空, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userInfo);
// return false;
// }
//
// //判断结果置默认
// result = false;
// String infoByCode = CustomerProfessionalIdentityType.getInfoByCode(userDetailsDTO.getProfessionalIdentity());
// if (Objects.nonNull(userDetailsDTO.getProfessionalIdentity())) {
// if (productLimit.getOfficeWorker()){
// if (userDetailsDTO.getProfessionalIdentity().equals(CustomerProfessionalIdentityType.OFFICE_WORKER.getCode())) {
// result = true;
// }
// }
//
// if (productLimit.getCivilServant()){
// if (userDetailsDTO.getProfessionalIdentity().equals(CustomerProfessionalIdentityType.CIVIL_SERVANT.getCode())) {
// result = true;
// }
// }
//
// if (productLimit.getPrivateOwners()){
// if (userDetailsDTO.getProfessionalIdentity().equals(CustomerProfessionalIdentityType.PRIVATE_OWNERS.getCode())) {
// result = true;
// }
// }
//
// if (productLimit.getSmallPrivateBusiness()){
// if (userDetailsDTO.getProfessionalIdentity().equals(CustomerProfessionalIdentityType.SMALL_PRIVATE_BUSINESS.getCode())) {
// result = true;
// }
// }
//
// if (productLimit.getOtherOccupations()){
// if (userDetailsDTO.getProfessionalIdentity().equals(CustomerProfessionalIdentityType.OTHER_OCCUPATIONS.getCode())) {
// result = true;
// }
// }
//
// //条件为 满足一个即可, 恰巧现在就有满足的, 则返回true通过
// if (openOne && result) {
// log.info("资质匹配筛选, 配置[满足其一]-职业:{}, 匹配通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userDetailsDTO.getProfessionalIdentity() + "-" + infoByCode, userInfo);
// return result;
// }
// }
//
// //条件为 满足全部, 恰巧现在这个不满足, 则返回false(不通过)
// if (openAll && !result) {
// log.info("资质匹配筛选, 配置[满足所有]-职业:{}, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userDetailsDTO.getProfessionalIdentity() + "-" + infoByCode, userInfo);
// return false;
// }
// }
//
// //学历 字典映射 1: "初中及以下,2: "高中",3: "中专",4: "大专",5: "本科",6: "研究生及以上"
// if (productLimit.getJuniorMiddleSchool() ||
// productLimit.getSeniorMiddleSchool() ||
// productLimit.getMiddleSchool() ||
// productLimit.getCollege() ||
// productLimit.getUndergraduate() ||
// productLimit.getPostgraduate()) {
//
// if (openAll && Objects.isNull(userDetailsDTO.getEducation())){
// log.info("资质匹配筛选, 配置[满足所有]-学历为空, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userInfo);
// return false;
// }
//
// //判断结果置默认
// result = false;
// String infoByCode = getEducationByCode(userDetailsDTO.getEducation());
// if (Objects.nonNull(userDetailsDTO.getEducation())) {
// if (productLimit.getJuniorMiddleSchool() && userDetailsDTO.getEducation() == 1) { //初中
// result = true;
// }
//
// if (productLimit.getSeniorMiddleSchool() && userDetailsDTO.getEducation() == 2) { //高中
// result = true;
// }
//
// if (productLimit.getMiddleSchool() && userDetailsDTO.getEducation() == 3) { //中专
// result = true;
// }
//
// if (productLimit.getCollege() && userDetailsDTO.getEducation() == 4) { //大专
// result = true;
// }
//
// if (productLimit.getUndergraduate() && userDetailsDTO.getEducation() == 5) { //本科
// result = true;
// }
//
// if (productLimit.getPostgraduate() && userDetailsDTO.getEducation() == 6) { //研究生
// result = true;
// }
//
// //条件为 满足一个即可, 恰巧现在就有满足的, 则返回true通过
// if (openOne && result) {
// log.info("资质匹配筛选, 配置[满足其一]-学历:{}, 匹配通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userDetailsDTO.getEducation() + "-" + infoByCode, userInfo);
// return result;
// }
// }
//
// //条件为 满足全部, 恰巧现在这个不满足, 则返回false(不通过)
// if (openAll && !result) {
// log.info("资质匹配筛选, 配置[满足所有]-学历:{}, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userDetailsDTO.getEducation() + "-" + infoByCode, userInfo);
// return false;
// }
// }
//
// //白条可用额度 字典映射 1: 无额度,2: 2000以下,3: 2000-10000,4: 大于10000
// if (productLimit.getBaiTiaoLevelOne() ||
// productLimit.getBaiTiaoLevelTwo() ||
// productLimit.getBaiTiaoLevelThree()) {
//
// if (openAll && Objects.isNull(userDetailsDTO.getBaiTiaoQuota())){
// log.info("资质匹配筛选, 配置[满足所有]-白条为空, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userInfo);
// return false;
// }
//
// //判断结果置默认
// result = false;
// String infoByCode = getBaiTiaoByCode(userDetailsDTO.getBaiTiaoQuota());
// if (Objects.nonNull(userDetailsDTO.getBaiTiaoQuota())) {
// if (productLimit.getBaiTiaoLevelOne() && userDetailsDTO.getBaiTiaoQuota() == 2) { //2000以下
// result = true;
// }
//
// if (productLimit.getBaiTiaoLevelTwo() && userDetailsDTO.getBaiTiaoQuota() == 3) { //2000-10000
// result = true;
// }
//
// if (productLimit.getBaiTiaoLevelThree() && userDetailsDTO.getBaiTiaoQuota() == 4) { //大于10000
// result = true;
// }
//
// //条件为 满足一个即可, 恰巧现在就有满足的, 则返回true通过
// if (openOne && result) {
// log.info("资质匹配筛选, 配置[满足其一]-白条:{}, 匹配通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userDetailsDTO.getBaiTiaoQuota() + "-" + infoByCode, userInfo);
// return result;
// }
// }
//
// //条件为 满足全部, 恰巧现在这个不满足, 则返回false(不通过)
// if (openAll && !result) {
// log.info("资质匹配筛选, 配置[满足所有]-白条:{}, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userDetailsDTO.getBaiTiaoQuota() + "-" + infoByCode, userInfo);
// return false;
// }
// }
//
// //花呗可用额度 字典映射 1: 无额度,2: 2000以下,3: 2000-10000,4: 大于10000
// if (productLimit.getHuaBeiLevelOne() ||
// productLimit.getHuaBeiLevelTwo() ||
// productLimit.getHuaBeiLevelThree()) {
//
// if (openAll && Objects.isNull(userDetailsDTO.getHuaBeiQuota())){
// log.info("资质匹配筛选, 配置[满足所有]-花呗为空, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userInfo);
// return false;
// }
//
// //判断结果置默认
// result = false;
// String infoByCode = getBaiTiaoByCode(userDetailsDTO.getHuaBeiQuota());
// if (Objects.nonNull(userDetailsDTO.getHuaBeiQuota())) {
// if (productLimit.getHuaBeiLevelOne() && userDetailsDTO.getHuaBeiQuota() == 2) { //2000以下
// result = true;
// }
//
// if (productLimit.getHuaBeiLevelTwo() && userDetailsDTO.getHuaBeiQuota() == 3) { //2000-10000
// result = true;
// }
//
// if (productLimit.getHuaBeiLevelThree() && userDetailsDTO.getHuaBeiQuota() == 4) { //大于10000
// result = true;
// }
//
// //条件为 满足一个即可, 恰巧现在就有满足的, 则返回true通过
// if (openOne && result) {
// log.info("资质匹配筛选, 配置[满足其一]-花呗:{}, 匹配通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userDetailsDTO.getHuaBeiQuota() + "-" + infoByCode, userInfo);
// return result;
// }
// }
//
// //条件为 满足全部, 恰巧现在这个不满足, 则返回false(不通过)
// if (openAll && !result) {
// log.info("资质匹配筛选, 配置[满足所有]-花呗:{}, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userDetailsDTO.getHuaBeiQuota() + "-" + infoByCode, userInfo);
// return false;
// }
// }
//
// //满足其一, 但结果为false, 则不通过
// if (openOne && !result){
//// log.info("资质匹配筛选, 配置[满足其一]-未匹配成功, 匹配不通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userInfo);
// return result;
// }
//
// if (openAll && result){
// log.info("资质匹配筛选, 配置[满足所有]-匹配成功, 匹配通过, 结束匹配, 用户id-渠道id-渠道名称-产品id:{}", userInfo);
// return result;
// }
//
// log.info("资质匹配筛选, 此行日志我觉得不会输出, 用户id-渠道id-渠道名称-产品id:{}", userInfo);
return true;
}
}

View File

@@ -129,6 +129,17 @@ public class BaseController
return rows > 0 ? AjaxResult.success() : AjaxResult.error(); return rows > 0 ? AjaxResult.success() : AjaxResult.error();
} }
/**
* 响应返回结果
*
* @param rows 影响行数
* @return 操作结果
*/
protected AjaxResult toAjax(Long rows)
{
return rows > 0 ? AjaxResult.success() : AjaxResult.error();
}
/** /**
* 响应返回结果 * 响应返回结果
* *

View File

@@ -4,6 +4,8 @@ import java.io.Serializable;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
@@ -19,9 +21,11 @@ public class BaseEntity implements Serializable
/** 搜索值 */ /** 搜索值 */
@JsonIgnore @JsonIgnore
@TableField(exist = false)
private String searchValue; private String searchValue;
/** 创建者 */ /** 创建者 */
@TableField(exist = false)
private String createBy; private String createBy;
/** 创建时间 */ /** 创建时间 */
@@ -29,6 +33,7 @@ public class BaseEntity implements Serializable
private Date createTime; private Date createTime;
/** 更新者 */ /** 更新者 */
@TableField(exist = false)
private String updateBy; private String updateBy;
/** 更新时间 */ /** 更新时间 */
@@ -40,6 +45,7 @@ public class BaseEntity implements Serializable
/** 请求参数 */ /** 请求参数 */
@JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonInclude(JsonInclude.Include.NON_EMPTY)
@TableField(exist = false)
private Map<String, Object> params; private Map<String, Object> params;
public String getSearchValue() public String getSearchValue()

View File

@@ -0,0 +1,391 @@
package com.ruoyi.common.redis.service;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.core.constant.RedisConstant;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* Created with IntelliJ IDEA.
*
* @Author:
* @Date: 18点29分
* @Description: 用户token管理
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class CustomerTokenService {
private final RedisService redisService;
/**
* token过期时间
*/
private static final Long EXPIRE_TIME = 30 * 24 * 60 * 60L;
/**
* 随机生成128位的token包含数字、大小写字母
*
* @param customerId 用户id
* @param phone 手机号
* @param deviceType 设备类型
* @param channelId 渠道id
* @return token
*/
public String generateToken(Long customerId, String phone, String deviceType, Long channelId) {
//获取到老的token
String oldToken = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_KEY + customerId);
if (StringUtils.hasText(oldToken)) {
//删除老的token
this.refreshToken(oldToken);
}
String newToken = null;
boolean exit = true;
while (exit) {
newToken = RandomUtil.randomString(128);
if (!redisService.hasKey(RedisConstant.APP_CUSTOMER_USERNAME_KEY + newToken)) {
exit = false;
}
}
redisService.setCacheObject(RedisConstant.APP_CUSTOMER_USERNAME_KEY + newToken, phone, EXPIRE_TIME, TimeUnit.SECONDS);
redisService.setCacheObject(RedisConstant.APP_CUSTOMER_KEY + customerId, newToken, EXPIRE_TIME, TimeUnit.SECONDS);
redisService.setCacheObject(RedisConstant.APP_CUSTOMER_CHANNEL_KEY + newToken, channelId, EXPIRE_TIME, TimeUnit.SECONDS);
redisService.setCacheObject(RedisConstant.APP_CUSTOMER_TOKEN_KEY + newToken, customerId, EXPIRE_TIME, TimeUnit.SECONDS);
redisService.setCacheObject(RedisConstant.APP_DEVICE_IDENTIFICATION + newToken, deviceType.toString(), EXPIRE_TIME, TimeUnit.SECONDS);
return newToken;
}
/**
* 判断token是否过期
*
* @param token token
* @return true过期false未过期
*/
public boolean isExpire(String token) {
String customerId = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_TOKEN_KEY + token) + StrUtil.EMPTY;
String originalToken = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_KEY + customerId);
String username = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_USERNAME_KEY + token) + StrUtil.EMPTY;
return StringUtils.isEmpty(customerId) || StringUtils.isEmpty(originalToken) || !originalToken.equals(token) || !StringUtils.hasText(username);
}
/**
* 刷新token有效期
*
* @param token token
* @param booleans 是否需要退出登录
*/
public void refreshToken(String token, Boolean... booleans) {
boolean logOut = isLogOut(booleans);
Long customerId = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_TOKEN_KEY + token);
if (Objects.isNull(customerId) && logOut) {
new Exception("登录已过期,请重新登录");
}
redisService.expire(RedisConstant.APP_CUSTOMER_USERNAME_KEY + token, EXPIRE_TIME, TimeUnit.SECONDS);
redisService.expire(RedisConstant.APP_CUSTOMER_KEY + customerId, EXPIRE_TIME, TimeUnit.SECONDS);
redisService.expire(RedisConstant.APP_CUSTOMER_CHANNEL_KEY + token, EXPIRE_TIME, TimeUnit.SECONDS);
redisService.expire(RedisConstant.APP_CUSTOMER_TOKEN_KEY + token, EXPIRE_TIME, TimeUnit.SECONDS);
redisService.expire(RedisConstant.APP_DEVICE_IDENTIFICATION + token, EXPIRE_TIME, TimeUnit.SECONDS);
}
/**
* 根据用户id刷新token有效期
*
* @param customerId 用户id
* @param booleans 是否需要退出登录
* @return token
*/
public String refreshToken(Long customerId, Boolean... booleans) {
boolean logOut = isLogOut(booleans);
String token = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_KEY + customerId);
if (StringUtils.isEmpty(token) && logOut) {
new Exception("登录已过期,请重新登录");
}
this.refreshToken(token);
return token;
}
/**
* 刷新token有效期
*
* @param request 请求
*/
public void refreshToken(HttpServletRequest request) {
String token = getToken(request);
this.refreshToken(token);
}
/**
* 移除token
*
* @param token token
* @param booleans 是否需要退出登录
*/
public void removeToken(String token, Boolean... booleans) {
boolean logOut = isLogOut(booleans);
Long customerId = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_TOKEN_KEY + token);
if (Objects.isNull(customerId) && logOut) {
new Exception("登录已过期,请重新登录");
}
redisService.deleteObject(RedisConstant.APP_CUSTOMER_KEY + customerId);
redisService.deleteObject(RedisConstant.APP_CUSTOMER_TOKEN_KEY + token);
redisService.deleteObject(RedisConstant.APP_CUSTOMER_USERNAME_KEY + token);
redisService.deleteObject(RedisConstant.APP_CUSTOMER_CHANNEL_KEY + token);
redisService.deleteObject(RedisConstant.APP_DEVICE_IDENTIFICATION + token);
}
/**
* 根据用户id移除token
*
* @param customerId 用户id
*/
public void removeToken(Long customerId) {
String token = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_KEY + customerId);
this.removeToken(token);
}
/**
* 根据HttpServletRequest获取token
*
* @param request HttpServletRequest
* @param booleans 是否需要退出登录
* @return token
*/
public String getToken(HttpServletRequest request, Boolean... booleans) {
boolean logOut = isLogOut(booleans);
String token = request.getHeader("Authorization");
if (StringUtils.isEmpty(token) && logOut) {
String requestURI = request.getRequestURI();
log.info("登录过期重新登录, requestURI:{}, logOut:{}, token:{}", requestURI, logOut, token);
new Exception("登录已过期,请重新登录");
}
return token;
}
/**
* 根据用户id获取到token
*
* @param customerId 用户id
* @return token
*/
public String getToken(Long customerId) {
String token = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_KEY + customerId);
if (StringUtils.isEmpty(token)) {
return null;
}
return token;
}
/**
* 通过token获取到用户的ID
*
* @param token token
* @param logOut 是否需要退出登录
* @return 用户ID
*/
public Long getCustomerId(String token, Boolean logOut) {
Long customerId = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_TOKEN_KEY + token);
if (Objects.isNull(customerId) && logOut) {
new Exception("登录已过期,请重新登录");
}
return customerId;
}
/**
* 根据HttpServletRequest获取到用户的ID
*
* @param request HttpServletRequest
* @param booleans 是否需要退出登录
* @return 用户ID
*/
public Long getCustomerId(HttpServletRequest request, Boolean... booleans) {
boolean logOut = isLogOut(booleans);
String token = getToken(request, logOut);
if (StringUtils.isEmpty(token)) {
return null;
}
return getCustomerId(token, logOut);
}
/**
* 根据token获取到用户的手机号 未解密
*
* @param token token
* @param booleans 是否需要退出登录
* @return 手机号
*/
public String getPhone(String token, Boolean... booleans) {
boolean logOut = isLogOut(booleans);
String phone = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_USERNAME_KEY + token);
if (Objects.isNull(phone) && logOut) {
new Exception("登录已过期,请重新登录");
}
return phone;
}
/**
* 根据用户ID获取手机号码
*
* @param customerId 用户ID
* @param booleans 是否需要退出登录
* @return 手机号
*/
public String getPhone(Long customerId, Boolean... booleans) {
String token = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_KEY + customerId);
if (Objects.isNull(token) && isLogOut(booleans)) {
new Exception("登录已过期,请重新登录");
}
String phone = getPhone(token);
// try {
// phone = EncryptUtil.AESdecode(phone, redisService.getAppEncrypted());
// }catch (Exception e) {
// return phone;
// }
return phone;
}
/**
* 根据HttpServletRequest获取到用户的手机号
*
* @param request HttpServletRequest
* @return 手机号
*/
public String getPhone(HttpServletRequest request) {
String token = getToken(request);
return getPhone(token);
}
/**
* 根据token获取到用户的渠道ID
*
* @param token token
* @param booleans 是否需要退出登录
* @return 渠道ID
*/
public Long getChannelId(String token, Boolean... booleans) {
Long channelId = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_CHANNEL_KEY + token);
if (Objects.isNull(channelId) && isLogOut(booleans)) {
new Exception("登录已过期,请重新登录");
}
return channelId;
}
/**
* 根据HttpServletRequest获取到用户的渠道ID
*
* @param request HttpServletRequest
* @return 渠道ID
*/
public Long getChannelId(HttpServletRequest request, Boolean... booleans) {
String token = getToken(request,booleans);
return getChannelId(token,booleans);
}
/**
* 根据用户ID获取渠道ID
*
* @param customerId 用户ID
* @param booleans 是否需要退出登录
* @return 渠道ID
*/
public Long getChannelId(Long customerId, Boolean... booleans) {
String token = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_KEY + customerId);
if (Objects.isNull(token) && isLogOut(booleans)) {
new Exception("登录已过期,请重新登录");
}
Long channelId = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_CHANNEL_KEY + token);
if (Objects.isNull(channelId) && isLogOut(booleans)) {
new Exception("登录已过期,请重新登录");
}
return channelId;
}
/**
* 更新渠道
* @param customerId 用户ID
* @param channelId 渠道ID
*/
public void setChannelId(Long customerId,Long channelId) {
String token = getToken(customerId);
redisService.setCacheObject(RedisConstant.APP_CUSTOMER_CHANNEL_KEY + token, channelId, EXPIRE_TIME, TimeUnit.SECONDS);
}
/**
* 根据token获取设备类型
*
* @param token token
* @param booleans 是否需要退出登录
* @return 设备类型
*/
public String getDeviceType(String token, Boolean... booleans) {
String deviceType = redisService.getCacheObject(RedisConstant.APP_DEVICE_IDENTIFICATION + token);
if (Objects.isNull(deviceType) && isLogOut(booleans)) {
new Exception("登录已过期,请重新登录");
}
return deviceType;
}
/**
* 根据HttpServletRequest获取设备类型
*
* @param request HttpServletRequest
* @return 设备类型
*/
public String getDeviceType(HttpServletRequest request,Boolean... booleans) {
String token = getToken(request,booleans);
return getDeviceType(token,booleans);
}
/**
* 根据HttpServletRequest获取设备类型
*
* @param request HttpServletRequest
* @return 设备类型
*/
public String getDeviceTypeStr(HttpServletRequest request) {
String token = getToken(request);
return getDeviceType(token);
}
/**
* 根据用户ID获取设备类型
*
* @param customerId 用户ID
* @param booleans 是否需要退出登录
* @return 设备类型
*/
public String getDeviceType(Long customerId, Boolean... booleans) {
String token = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_KEY + customerId);
if (Objects.isNull(token) && isLogOut(booleans)) {
new Exception("登录已过期,请重新登录");
}
String deviceType = redisService.getCacheObject(RedisConstant.APP_DEVICE_IDENTIFICATION + token);
if (!StringUtils.hasText(deviceType)) {
deviceType = "ANDROID";
}
return deviceType;
}
/**
* 是否需要退出登录
*
* @param booleans 参数值
* @return 是否需要退出登录
*/
public Boolean isLogOut(Boolean... booleans) {
if (booleans == null || booleans.length == 0) {
return true;
}
return booleans[0];
}
}

View File

@@ -1,2 +1,3 @@
com.ruoyi.common.redis.configure.RedisConfig com.ruoyi.common.redis.configure.RedisConfig
com.ruoyi.common.redis.service.RedisService com.ruoyi.common.redis.service.RedisService
com.ruoyi.common.redis.service.CustomerTokenService

View File

@@ -4,6 +4,8 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import com.ruoyi.common.core.constant.RedisConstant;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -42,6 +44,11 @@ public class TokenService
private final static Long MILLIS_MINUTE_TEN = CacheConstants.REFRESH_TIME * MILLIS_MINUTE; private final static Long MILLIS_MINUTE_TEN = CacheConstants.REFRESH_TIME * MILLIS_MINUTE;
/**
* token过期时间
*/
private static final Long EXPIRE_TIME = 30 * 24 * 60 * 60L;
/** /**
* 创建令牌 * 创建令牌
*/ */
@@ -69,6 +76,40 @@ public class TokenService
return rspMap; return rspMap;
} }
/**
* 创建令牌
*/
public String createTokenApp(Long customerId,Long channelId)
{
String token = IdUtils.fastUUID();
// Long userId = loginUser.getSysUser().getUserId();
// String userName = loginUser.getSysUser().getUserName();
// loginUser.setToken(token);
// loginUser.setUserid(userId);
// loginUser.setUsername(userName);
// loginUser.setIpaddr(IpUtils.getIpAddr());
// refreshToken(loginUser);
// Jwt存储信息
Map<String, Object> claimsMap = new HashMap<String, Object>();
claimsMap.put(SecurityConstants.USER_KEY, token);
claimsMap.put(SecurityConstants.DETAILS_USER_ID, customerId);
claimsMap.put(SecurityConstants.DETAILS_USERNAME, "userName");
// 接口返回信息
Map<String, Object> rspMap = new HashMap<String, Object>();
String token1 = JwtUtils.createToken(claimsMap);
rspMap.put("access_token", token1);
rspMap.put("expires_in", expireTime);
redisService.setCacheObject(RedisConstant.APP_CUSTOMER_USERNAME_KEY + token1, customerId, EXPIRE_TIME, TimeUnit.SECONDS);
redisService.setCacheObject(RedisConstant.APP_CUSTOMER_KEY + customerId, token1, EXPIRE_TIME, TimeUnit.SECONDS);
redisService.setCacheObject(RedisConstant.APP_CUSTOMER_CHANNEL_KEY + token1, channelId, EXPIRE_TIME, TimeUnit.SECONDS);
redisService.setCacheObject(RedisConstant.APP_CUSTOMER_TOKEN_KEY + token1, customerId, EXPIRE_TIME, TimeUnit.SECONDS);
redisService.setCacheObject( CacheConstants.LOGIN_TOKEN_KEY+token,customerId,EXPIRE_TIME,TimeUnit.SECONDS);
return token1;
}
/** /**
* 获取用户身份信息 * 获取用户身份信息
* *

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
<version>3.6.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-common-sms</artifactId>
<description>
ruoyi-common-sms 短信模块
</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.7.0</version> <!-- 或其他兼容版本 -->
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,24 @@
package com.ruoyi.common.sms;
import com.ruoyi.common.sms.component.SmsComponent;
import com.ruoyi.common.sms.properties.XunDaYunXinProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
@EnableConfigurationProperties(XunDaYunXinProperties.class)
public class XunDaYunXinAutoConfiguration {
@Bean
public SmsComponent smsComponent() {
return new SmsComponent();
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

View File

@@ -0,0 +1,145 @@
package com.ruoyi.common.sms.component;
import com.ruoyi.common.sms.entity.response.SmsEntity;
import com.ruoyi.common.sms.entity.response.SmsResponse;
import com.ruoyi.common.sms.properties.XunDaYunXinProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import java.util.*;
@Slf4j
public class SmsComponent {
@Autowired
private XunDaYunXinProperties properties;
@Autowired
private RestTemplate restTemplate;
/**
* 点对点
*
* @param mobileContentKvp 号码内容键值对 示例 {"15100000000":"【测试】test1","15100000001":"【测试】test2"}
* @return SmsResponse<SmsEntity>
*/
public SmsResponse sendP2PMsg(Map<String, String> mobileContentKvp) {
Map<String, Object> extraParams = new HashMap<>();
for (Map.Entry<String, String> entry : mobileContentKvp.entrySet()) {
String oldValue = entry.getValue();
String newValue = replaceCode(properties.getTemplate(), oldValue);
entry.setValue(newValue);
}
extraParams.put("mobileContentKvp", mobileContentKvp);
return sendSmsRequest("p2p", extraParams, new ParameterizedTypeReference<SmsResponse>() {
});
}
/**
* 发送群发信息
*
* @param mobile 电话号码按照,分割 示例 "15100000000,15100000001"
* @param content 内容 一般为验证码
* @return SmsResponse<SmsEntity>
*/
public SmsResponse<SmsEntity> sendGroupMsg(String mobile, String content) {
Map<String, Object> extraParams = new HashMap<>();
extraParams.put("mobile", removeDuplicates(mobile));
extraParams.put("content", replaceCode(properties.getTemplate(), content));
return sendSmsRequest("send", extraParams, new ParameterizedTypeReference<SmsResponse<SmsEntity>>() {
});
}
public SmsResponse<?> checkBalance() {
String url = properties.getBaseUrl() + "/smsv2";
Map<String, Object> params = new HashMap<>();
params.put("action", "balance");
params.put("account", properties.getAccount());
params.put("password", properties.getPassword());
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(params);
ResponseEntity<SmsResponse<?>> responseEntity = restTemplate.exchange(
url,
HttpMethod.POST,
requestEntity,
new ParameterizedTypeReference<SmsResponse<?>>() {
}
);
return responseEntity.getBody();
}
/**
* 发送短信请求的通用方法,适用于不同的短信操作。
*
* @param action 短信操作的类型,例如 "p2p"、"send" "balance"。
* @param extraParams 附加的请求参数,具体取决于短信操作的需求。可以为 null。
* @param responseType 返回值的泛型类型,用于指定响应的具体类型。
* @param <T> 响应体中泛型的类型参数。
* @return 包含响应结果的 SmsResponse 对象,响应体中可能包含不同类型的数据。
*/
private <T> T sendSmsRequest(String action, Map<String, Object> extraParams, ParameterizedTypeReference<T> responseType) {
// 拼接请求的 URL 地址
String url = properties.getBaseUrl() + "/smsv2";
// 创建请求参数 Map并填充必需的账户信息和操作类型
Map<String, Object> params = new HashMap<>();
params.put("action", action); // 设置请求的操作类型,如发送短信或查询余额
params.put("account", properties.getAccount()); // 设置账户名
params.put("password", properties.getPassword()); // 设置密码
params.put("extno", properties.getExtno()); // 虚拟接入码
// 如果有额外的参数,则将它们添加到请求参数中
if (extraParams != null) {
params.putAll(extraParams);
}
// 构建 HttpEntity 实体,包含请求参数
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(params);
// 使用 RestTemplate 的 exchange 方法发送 POST 请求,并指定返回的泛型类型
ResponseEntity<T> responseEntity = restTemplate.exchange(
url, // 请求 URL
HttpMethod.POST, // HTTP 方法类型为 POST
requestEntity, // 请求体包含请求参数
responseType // 指定返回类型的泛型引用,用于保留泛型信息
);
// 返回响应体(根据调用方法传入的类型)
return responseEntity.getBody();
}
/**
* 相同号码去重
*
* @param input 字符串电话号码 逗号分隔符分割
* @return String 去重之后的手机电话号码
*/
private String removeDuplicates(String input) {
// 使用 LinkedHashSet 保持插入顺序并去重
Set<String> uniqueSet = new LinkedHashSet<>(Arrays.asList(input.split(",")));
if (uniqueSet.size() >= 1000) {
throw new IllegalArgumentException("群发不建议超过1000个电话号码");
}
// 将去重后的集合转换回字符串
return String.join(",", uniqueSet);
}
/**
* 模板替换占位符
*
* @param template 模板
* @param code 实际值
* @return 替换之后的模板
*/
public String replaceCode(String template, String code) {
return template.replace("{code}", code);
}
}

View File

@@ -0,0 +1 @@
package com.ruoyi.common.sms.entity;

View File

@@ -0,0 +1 @@
package com.ruoyi.common.sms.entity.request;

View File

@@ -0,0 +1,32 @@
package com.ruoyi.common.sms.entity.response;
public class SmsEntity {
private String mid;
private String mobile;
private int result;
// Getters and Setters
public String getMid() {
return mid;
}
public void setMid(String mid) {
this.mid = mid;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public int getResult() {
return result;
}
public void setResult(int result) {
this.result = result;
}
}

View File

@@ -0,0 +1,12 @@
package com.ruoyi.common.sms.entity.response;
import lombok.Data;
import java.util.List;
@Data
public class SmsResponse<T> {
private Integer status;
private Integer balance;
private List<T> list;
}

View File

@@ -0,0 +1,40 @@
package com.ruoyi.common.sms.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 迅达云信短信 配置类
*/
@Data
@ConfigurationProperties(prefix = "xundayunxin")
public class XunDaYunXinProperties {
/**
* 请求地址
*/
private String baseUrl = "http://47.96.236.136:7862/";
/**
* 账号
*/
private String account = "932425";
/**
* 密码
*/
private String password = "alDE77Gmo";
/**
* 虚拟接入码
*/
private String extno = "10690367";
/**
* 是否启用手机号加密
*/
private boolean encryptionEnabled;
/**
* 短信模板
*/
private String template = "【信用秒租】验证码为:{code}您正在登录信用秒租请在3分钟内完成验证如非本人操作请忽略本短信。";
}

View File

@@ -0,0 +1,2 @@
com.ruoyi.common.sms.XunDaYunXinAutoConfiguration
com.ruoyi.common.sms.component.SmsComponent

View File

@@ -15,15 +15,6 @@ public class RuoYiGatewayApplication
public static void main(String[] args) public static void main(String[] args)
{ {
SpringApplication.run(RuoYiGatewayApplication.class, args); SpringApplication.run(RuoYiGatewayApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 若依网关启动成功 ლ(´ڡ`ლ)゙ \n" + System.out.println("(♥◠‿◠)ノ゙ 租研舍网关启动成功 ლ(´ڡ`ლ)゙ \n");
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
} }
} }

View File

@@ -14,10 +14,12 @@ spring:
nacos: nacos:
discovery: discovery:
# 服务注册地址 # 服务注册地址
server-addr: 127.0.0.1:8848 server-addr: 47.109.135.151:8848
namespace: b8ad3fd2-18ea-4cdf-a82c-4ce483392b1a
config: config:
# 配置中心地址 # 配置中心地址
server-addr: 127.0.0.1:8848 server-addr: 47.109.135.151:8848
namespace: b8ad3fd2-18ea-4cdf-a82c-4ce483392b1a
# 配置文件格式 # 配置文件格式
file-extension: yml file-extension: yml
# 共享配置 # 共享配置
@@ -28,12 +30,12 @@ spring:
eager: true eager: true
transport: transport:
# 控制台地址 # 控制台地址
dashboard: 127.0.0.1:8718 dashboard: 47.109.135.151:8718
# nacos配置持久化 # nacos配置持久化
datasource: datasource:
ds1: ds1:
nacos: nacos:
server-addr: 127.0.0.1:8848 server-addr: 47.109.135.151:8848
dataId: sentinel-ruoyi-gateway dataId: sentinel-ruoyi-gateway
groupId: DEFAULT_GROUP groupId: DEFAULT_GROUP
data-type: json data-type: json

View File

@@ -13,6 +13,7 @@
<module>ruoyi-gen</module> <module>ruoyi-gen</module>
<module>ruoyi-job</module> <module>ruoyi-job</module>
<module>ruoyi-file</module> <module>ruoyi-file</module>
<module>ruoyi-btc</module>
</modules> </modules>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>

View File

@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId>
<version>3.6.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-modules-btc</artifactId>
<description>
ruoyi-modules-btc三方业务服务
</description>
<dependencies>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- SpringBoot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- RuoYi Api System -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-api-system</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-redis</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-security</artifactId>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,22 @@
package com.ruoyi.btc;
import com.ruoyi.common.security.annotation.EnableRyFeignClients;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
/**
* 三方调用服务
*
* @author ruoyi
*/
@EnableRyFeignClients
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class RuoYiBtcApplication
{
public static void main(String[] args)
{
SpringApplication.run(RuoYiBtcApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 三方业务服务模块启动成功 ლ(´ڡ`ლ)゙ \n");
}
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.btc.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "system")
@Data
public class Config {
/**
* 加密密钥
*/
private String AESkey;
}

View File

@@ -0,0 +1,43 @@
package com.ruoyi.btc.controller;
import com.ruoyi.btc.domain.ComPublicHalfDto;
import com.ruoyi.btc.service.ISysPublicAllService;
import com.ruoyi.btc.service.ISysPublicHalfService;
import com.ruoyi.common.core.web.domain.AjaxResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
/**
* 半流程API接口写这里
*
* @author z
*/
@RestController
@Slf4j
@RequestMapping("/all/api")
@RequiredArgsConstructor
public class PublicAllController {
private final ISysPublicAllService sysPublicAllService;
/**
* 通用半流程撞库
*/
@PostMapping("check")
public AjaxResult upload(@RequestBody ComPublicHalfDto comPublicHalfDto)
{
sysPublicAllService.check(comPublicHalfDto);
return null;
}
/**
* 通用半流程撞库
*/
@PostMapping("input")
public AjaxResult input(@RequestBody ComPublicHalfDto comPublicHalfDto)
{
sysPublicAllService.input(comPublicHalfDto);
return null;
}
}

View File

@@ -0,0 +1,50 @@
package com.ruoyi.btc.controller;
import com.ruoyi.btc.domain.ComPublicHalfDto;
import com.ruoyi.btc.service.ISysPublicHalfService;
import com.ruoyi.common.core.web.domain.AjaxResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
/**
* 半流程API接口写这里
*
* @author z
*/
@RestController
@Slf4j
@RequestMapping("/half/api")
@RequiredArgsConstructor
public class PublicHalfController{
private final ISysPublicHalfService sysPublicHalfService;
/**
* 通用半流程撞库
*/
@PostMapping("/check")
public AjaxResult upload(@RequestBody ComPublicHalfDto comPublicHalfDto)
{
return sysPublicHalfService.check(comPublicHalfDto);
}
/**
* 通用半流程撞库
*/
@PostMapping("/input")
public AjaxResult input(@RequestBody ComPublicHalfDto comPublicHalfDto)
{
return sysPublicHalfService.input(comPublicHalfDto);
}
/**
* 通用半流程撞库
*/
@GetMapping("/checkOrder")
public AjaxResult checkOrder(String phoneMd5,String channelSign)
{
return sysPublicHalfService.checkOrder(phoneMd5,channelSign);
}
}

View File

@@ -0,0 +1,13 @@
package com.ruoyi.btc.domain;
import lombok.Data;
@Data
public class ComPublicHalfDto {
//参数实体类
private String data;
//渠道标识
private String channelSignature;
}

View File

@@ -0,0 +1,51 @@
package com.ruoyi.btc.domain;
import lombok.Data;
@Data
public class CustomerInfoDto {
//手机号码Md5
private String phoneMd5;
//手机号
private String phone;
//性别 0 男 1 女
private Integer sex;
//手机号码Md5
private String nameMd5;
//姓名
private String name;
//年龄
private Integer age;
//手身份证md5
private String idCardMd5;
//身份证好
private String idCard;
//所在城市
private String city;
//所在城市代码
private Integer cityCode;
//本地社保
private Integer socialSecurity;
//本地公积金
private Integer accumulationFund;
//名下车产
private Integer car;
//名下房产
private Integer hourse;
//个人保险
private Integer guarantee;
//芝麻分
private Integer zhiMa;
//职业身份
private Integer career;
//信用卡1无 2有
private Integer creditCard;
//学历
private Integer education;
//月收入
private Integer monthlyIncome;
//ip地址
private String ip;
//渠道标识
private String channelSignature;
}

View File

@@ -0,0 +1,27 @@
package com.ruoyi.btc.service;
import com.ruoyi.btc.domain.ComPublicHalfDto;
import com.ruoyi.common.core.web.domain.AjaxResult;
/**
* 文件上传接口
*
* @author ruoyi
*/
public interface ISysPublicAllService
{
/**
* 半流程通用撞库接口
* @param comPublicHalfDto
*/
AjaxResult check(ComPublicHalfDto comPublicHalfDto);
/**
* 半流程通用进件
* @param comPublicHalfDto
*/
AjaxResult input(ComPublicHalfDto comPublicHalfDto);
}

View File

@@ -0,0 +1,33 @@
package com.ruoyi.btc.service;
import com.ruoyi.btc.domain.ComPublicHalfDto;
import com.ruoyi.common.core.web.domain.AjaxResult;
import org.springframework.web.bind.annotation.RequestParam;
/**
* 文件上传接口
*
* @author ruoyi
*/
public interface ISysPublicHalfService
{
/**
* 半流程通用撞库接口
* @param comPublicHalfDto
*/
AjaxResult check(ComPublicHalfDto comPublicHalfDto);
/**
* 半流程通用进件
* @param comPublicHalfDto
*/
AjaxResult input(ComPublicHalfDto comPublicHalfDto);
/**
* 渠道查询订单是否成功
* @param
*/
AjaxResult checkOrder(String phoneMd5, String channelSign);
}

View File

@@ -0,0 +1,251 @@
package com.ruoyi.btc.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.btc.domain.ComPublicHalfDto;
import com.ruoyi.btc.domain.CustomerInfoDto;
import com.ruoyi.btc.service.ISysPublicAllService;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.domain.GetSumDto;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.http.Channel;
import com.ruoyi.common.core.domain.http.Customer;
import com.ruoyi.common.core.domain.http.CustomerApplyLog;
import com.ruoyi.common.core.domain.http.Merchant;
import com.ruoyi.common.core.utils.SecureUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.system.api.RemoteCustomerApplyLogService;
import com.ruoyi.system.api.RemoteCustomerService;
import com.ruoyi.system.api.RemoteMerchantService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
/**
* 本地文件存储
*
* @author ruoyi
*/
@Service
@RequiredArgsConstructor
public class SysPublicAllServiceImpl implements ISysPublicAllService
{
private final RemoteCustomerService remoteCustomerService;
private final RemoteMerchantService remoteMerchantService;
private final RemoteCustomerApplyLogService remoteCustomerApplyLogService;
private final RedisService redisService;
/**
* 半流程通用撞库
* @param comPublicHalfDto
*/
@Override
public AjaxResult check(ComPublicHalfDto comPublicHalfDto) {
//校验 IP地址是否正常 渠道标识是否存在 数据是否为空
if (StringUtils.isEmpty(comPublicHalfDto.getChannelSignature())){
return AjaxResult.error("渠道标识不能未空");
}
Channel channel = redisService.getCacheObject(CacheConstants.CHANNEL_SIGN + comPublicHalfDto.getChannelSignature());
if (channel==null||channel.getId()==null){
return AjaxResult.error("渠道不存在");
}
if (StringUtils.isEmpty(comPublicHalfDto.getData())){
return AjaxResult.error("加密数据不能为空");
}
//解密为customerInfoDto
String s = SecureUtils.AesUtil.AesDecode(comPublicHalfDto.getData(), comPublicHalfDto.getChannelSignature());
if (s==null){
return AjaxResult.error("解密异常");
}
CustomerInfoDto customerInfoDto = JSONObject.parseObject(s, CustomerInfoDto.class);
//校验数据必传参数是否未传
String checkData = checkData(customerInfoDto);
if (checkData!=null){
return AjaxResult.error(checkData);
}
//转化字段未数据库中资质字段 并保存 用户未实名状态 一并保存用户申请记录 未申请状态
Customer customer = new Customer();
BeanUtil.copyProperties(customerInfoDto,customer);
customer.setChannelId(channel.getId());
customer.setActurlName(customerInfoDto.getNameMd5());
customer.setFirstLoginTime(new Date());
customer.setLastLoginTime(new Date());
customer.setIsAuth(false);
customer.setStatus(2);
R<Customer> customerInfoByPhoneMd5 = remoteCustomerService.getCustomerInfoByPhoneMd5(customerInfoDto.getPhoneMd5(), SecurityConstants.INNER);
if (customerInfoByPhoneMd5.getCode()==200){
remoteCustomerService.updateByPhoneMd5(customer,SecurityConstants.INNER);
}else {
remoteCustomerService.add(customer,SecurityConstants.INNER);
}
//TODO 暂时不做 目前下游暂时不需要 匹配资质 造轮子 返回多个符合的商户
List<Merchant> merchants = matchMerchant(customer);
//结束返回上游结果
Map<String,Boolean> re = new HashMap<>();
if (merchants.size()>0){
re.put("data",true);
return AjaxResult.success(re);
}
re.put("data",false);
return AjaxResult.success(re);
}
/**
* 获取前筛符合的商户
* @param customer
*/
private List<Merchant> matchMerchant(Customer customer) {
R<List<Merchant>> listR = remoteMerchantService.merchantList(SecurityConstants.INNER);
if (listR.getCode()!=200){
return new ArrayList<>();
}
List<Merchant> merchants = new ArrayList<>();
for (Merchant merchant:listR.getData()) {
//限量判定
GetSumDto dto = new GetSumDto();
dto.setMerchantId(merchant.getId());
R<Integer> sum = remoteCustomerApplyLogService.sum(dto, SecurityConstants.INNER);
if (merchant.getLimitType()==1&&merchant.getLimitNum()<=sum.getData()){
continue;
}
if (customer.getAge()<merchant.getAgeLimitStart()||customer.getAge()>merchant.getAgeLimitEnd()){
continue;
}
if (merchant.getChannelLimitType()==1||merchant.getChannelLimitType()==2){
List<Long> list = Arrays.asList(merchant.getChannelLimit().split(",")).stream().map(val->Long.parseLong(val)).collect(Collectors.toList());
if (merchant.getChannelLimitType()==1&& !list.contains(customer.getChannelId())){
continue;
}
if (merchant.getChannelLimitType()==2&& list.contains(customer.getChannelId())){
continue;
}
}
merchants.add(merchant);
}
return merchants;
}
/**
* 校验参数
* @param customerInfoDto
*/
private String checkData(CustomerInfoDto customerInfoDto) {
if (customerInfoDto.getAge()==null){
return "年龄不能为空";
}
if (StringUtils.isEmpty(customerInfoDto.getPhoneMd5())){
return "手机号MD5不能为空";
}
if (StringUtils.isEmpty(customerInfoDto.getCity())){
return "城市不能为空";
}
if (customerInfoDto.getCityCode()==null){
return "城市编码不能为空";
}
if (customerInfoDto.getSocialSecurity()==null){
return "本地社保不能为空";
}
if (customerInfoDto.getAccumulationFund()==null){
return "本地公积金不能为空";
}
if (customerInfoDto.getCar()==null){
return "车产不能为空";
}
if (customerInfoDto.getHourse()==null){
return "房产不能为空";
}
if (customerInfoDto.getGuarantee()==null){
return "房产不能为空";
}
if (customerInfoDto.getZhiMa()==null){
return "芝麻分不能为空";
}
if (customerInfoDto.getCareer()==null){
return "职业不能为空";
}
if (customerInfoDto.getCreditCard()==null){
return "信用卡不能为空";
}
if (customerInfoDto.getEducation()==null){
return "学历不能为空";
}
if (customerInfoDto.getMonthlyIncome()==null){
return "月收入不能为空";
}
return null;
}
/**
* 半流程通用进件
* @param comPublicHalfDto
*/
@Override
public AjaxResult input(ComPublicHalfDto comPublicHalfDto) {
//校验 IP地址是否正常 渠道标识是否存在 数据是否为空
if (StringUtils.isEmpty(comPublicHalfDto.getChannelSignature())){
return AjaxResult.error("渠道标识不能未空");
}
Channel channel = redisService.getCacheObject(CacheConstants.CHANNEL_SIGN + comPublicHalfDto.getChannelSignature());
if (channel==null||channel.getId()==null){
return AjaxResult.error("渠道不存在");
}
if (StringUtils.isEmpty(comPublicHalfDto.getData())){
return AjaxResult.error("加密数据不能为空");
}
//解密为customerInfoDto
String s = SecureUtils.AesUtil.AesDecode(comPublicHalfDto.getData(), comPublicHalfDto.getChannelSignature());
if (s==null){
return AjaxResult.error("解密异常");
}
CustomerInfoDto customerInfoDto = JSONObject.parseObject(s, CustomerInfoDto.class);
//校验数据必传参数是否未传
String checkData = checkData(customerInfoDto);
//转化字段未数据库中资质字段 更新 用户实名状态 一并保存用户申请记录 已申请
if (checkData!=null){
return AjaxResult.error(checkData);
}
//转化字段未数据库中资质字段 并保存 用户未实名状态 一并保存用户申请记录 未申请状态
Customer customer = new Customer();
BeanUtil.copyProperties(customerInfoDto,customer);
customer.setChannelId(channel.getId());
customer.setActurlName(customerInfoDto.getName());
customer.setFirstLoginTime(new Date());
customer.setLastLoginTime(new Date());
customer.setIsAuth(true);
customer.setStatus(1);
R<Customer> customerInfoByPhoneMd5 = remoteCustomerService.getCustomerInfoByPhoneMd5(customerInfoDto.getPhoneMd5(), SecurityConstants.INNER);
if (customerInfoByPhoneMd5.getCode()==200){
remoteCustomerService.updateByPhoneMd5(customer,SecurityConstants.INNER);
}else {
return AjaxResult.error("今日未撞库");
}
//匹配资质 造轮子 返回多个符合的商户
List<Merchant> merchants = matchMerchant(customer);
//TODO 取排序第一的
//返回渠道绑定的注册页拼接token
Map<String,Object> result = new HashMap<>();
Map<String,Object> map = new HashMap<>();
//TODO 下游是H5承接不了上游全流程 暂时不做
CustomerApplyLog customerApplyLog = new CustomerApplyLog();
customerApplyLog.setCustomerId(customerInfoByPhoneMd5.getData().getId());
customerApplyLog.setChannelId(channel.getId());
customerApplyLog.setMerchantId(merchants.get(0).getId());
customerApplyLog.setOrderStatus(0l);
remoteCustomerApplyLogService.add(customerApplyLog);
//返回上游信息
return AjaxResult.success(result);
}
}

View File

@@ -0,0 +1,328 @@
package com.ruoyi.btc.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.btc.config.Config;
import com.ruoyi.btc.domain.ComPublicHalfDto;
import com.ruoyi.btc.domain.CustomerInfoDto;
import com.ruoyi.btc.service.ISysPublicHalfService;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.constant.RedisConstant;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.domain.GetSumDto;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.http.Channel;
import com.ruoyi.common.core.domain.http.Customer;
import com.ruoyi.common.core.domain.http.Merchant;
import com.ruoyi.common.core.utils.EncryptUtil;
import com.ruoyi.common.core.utils.ProbitUtil;
import com.ruoyi.common.core.utils.SecureUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.system.api.RemoteCustomerApplyLogService;
import com.ruoyi.system.api.RemoteCustomerService;
import com.ruoyi.system.api.RemoteMerchantService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* 本地文件存储
*
* @author ruoyi
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class SysPublicHalfServiceImpl implements ISysPublicHalfService
{
private final RemoteCustomerService remoteCustomerService;
private final RemoteMerchantService remoteMerchantService;
private final RemoteCustomerApplyLogService remoteCustomerApplyLogService;
private final RedisService redisService;
private final Config config;
/**
* 半流程通用撞库
* @param comPublicHalfDto
*/
@Override
public AjaxResult check(ComPublicHalfDto comPublicHalfDto) {
//校验 IP地址是否正常 渠道标识是否存在 数据是否为空
if (StringUtils.isEmpty(comPublicHalfDto.getChannelSignature())){
return AjaxResult.error("渠道标识不能未空");
}
Channel channel = redisService.getCacheObject(CacheConstants.CHANNEL_SIGN + comPublicHalfDto.getChannelSignature());
if (channel==null||channel.getId()==null){
return AjaxResult.error("渠道不存在");
}
if (StringUtils.isEmpty(comPublicHalfDto.getData())){
return AjaxResult.error("加密数据不能为空");
}
//解密为customerInfoDto
String s = SecureUtils.AesUtil.AesDecode(comPublicHalfDto.getData(), comPublicHalfDto.getChannelSignature());
if (s==null){
return AjaxResult.error("解密异常");
}
CustomerInfoDto customerInfoDto = JSONObject.parseObject(s, CustomerInfoDto.class);
//撞库幂等性校验 暂时不加
// Boolean aBoolean = redisService.hasKey(RedisConstant.HIT_CHECK_CACHE+customerInfoDto.getPhoneMd5()+":"+comPublicHalfDto.getChannelSignature());
// if (aBoolean){
// return AjaxResult.error("手机号:"+customerInfoDto.getPhoneMd5()+"请勿重复撞库");
// }
// redisService.setCacheObject(RedisConstant.HIT_CHECK_CACHE+customerInfoDto.getPhoneMd5(),1,60*3l, TimeUnit.SECONDS);
log.info("渠道:{},撞库手机号:{}",channel.getChannelName(),customerInfoDto.getPhoneMd5());
//校验数据必传参数是否未传
String checkData = checkData(customerInfoDto);
if (checkData!=null){
return AjaxResult.error(checkData);
}
//转化字段未数据库中资质字段 并保存 用户未实名状态 一并保存用户申请记录 未申请状态
Customer customer = new Customer();
BeanUtil.copyProperties(customerInfoDto,customer);
customer.setChannelId(channel.getId());
customer.setActurlName(customerInfoDto.getNameMd5());
customer.setFirstLoginTime(new Date());
customer.setLastLoginTime(new Date());
customer.setIsAuth(false);
customer.setStatus(2);
customer.setPhoneMd5(customerInfoDto.getPhoneMd5());
R<Customer> customerInfoByPhoneMd5 = remoteCustomerService.getCustomerInfoByPhoneMd5(customerInfoDto.getPhoneMd5(), SecurityConstants.INNER);
log.info("渠道:{},是否查询到用户:{}",channel.getChannelName(),customerInfoByPhoneMd5.getCode());
if (customerInfoByPhoneMd5.getCode()==200){
remoteCustomerService.updateByPhoneMd5(customer,SecurityConstants.INNER);
}else {
remoteCustomerService.add(customer,SecurityConstants.INNER);
}
//TODO 暂时不做 目前下游暂时不需要 匹配资质 造轮子 返回多个符合的商户
List<Merchant> merchants = matchMerchant(customer);
//结束返回上游结果
Map<String,Boolean> re = new HashMap<>();
if (merchants.size()>0){
re.put("data",true);
return AjaxResult.success(re);
}
re.put("data",false);
return AjaxResult.success(re);
}
/**
* 获取前筛符合的商户
* @param customer
*/
private List<Merchant> matchMerchant(Customer customer) {
R<List<Merchant>> listR = remoteMerchantService.merchantList(SecurityConstants.INNER);
if (listR.getCode()!=200){
return new ArrayList<>();
}
List<Merchant> merchants = new ArrayList<>();
for (Merchant merchant:listR.getData()) {
//限量判定
GetSumDto dto = new GetSumDto();
dto.setMerchantId(merchant.getId());
R<Integer> sum = remoteCustomerApplyLogService.sum(dto, SecurityConstants.INNER);
if (merchant.getLimitType()==1&&merchant.getLimitNum()<=sum.getData()){
continue;
}
if (customer.getAge()<merchant.getAgeLimitStart()||customer.getAge()>merchant.getAgeLimitEnd()){
continue;
}
if (merchant.getChannelLimitType()==1||merchant.getChannelLimitType()==2){
List<Long> list = Arrays.asList(merchant.getChannelLimit().split(",")).stream().map(val->Long.parseLong(val)).collect(Collectors.toList());
if (merchant.getChannelLimitType()==1&& !list.contains(customer.getChannelId())){
continue;
}
if (merchant.getChannelLimitType()==2&& list.contains(customer.getChannelId())){
continue;
}
}
merchants.add(merchant);
}
return merchants;
}
/**
* 校验参数
* @param customerInfoDto
*/
private String checkData(CustomerInfoDto customerInfoDto) {
if (customerInfoDto.getAge()==null){
return "年龄不能为空";
}
if (StringUtils.isEmpty(customerInfoDto.getPhoneMd5())){
return "手机号MD5不能为空";
}
if (StringUtils.isEmpty(customerInfoDto.getCity())){
return "城市不能为空";
}
if (customerInfoDto.getCityCode()==null){
return "城市编码不能为空";
}
if (customerInfoDto.getSocialSecurity()==null){
return "本地社保不能为空";
}
if (customerInfoDto.getAccumulationFund()==null){
return "本地公积金不能为空";
}
if (customerInfoDto.getCar()==null){
return "车产不能为空";
}
if (customerInfoDto.getHourse()==null){
return "房产不能为空";
}
if (customerInfoDto.getGuarantee()==null){
return "房产不能为空";
}
if (customerInfoDto.getZhiMa()==null){
return "芝麻分不能为空";
}
if (customerInfoDto.getCareer()==null){
return "职业不能为空";
}
if (customerInfoDto.getCreditCard()==null){
return "信用卡不能为空";
}
if (customerInfoDto.getEducation()==null){
return "学历不能为空";
}
if (customerInfoDto.getMonthlyIncome()==null){
return "月收入不能为空";
}
return null;
}
/**
* 半流程通用进件
* @param comPublicHalfDto
*/
@Override
public AjaxResult input(ComPublicHalfDto comPublicHalfDto) {
//校验 IP地址是否正常 渠道标识是否存在 数据是否为空
if (StringUtils.isEmpty(comPublicHalfDto.getChannelSignature())){
return AjaxResult.error("渠道标识不能未空");
}
Channel channel = redisService.getCacheObject(CacheConstants.CHANNEL_SIGN + comPublicHalfDto.getChannelSignature());
if (channel==null||channel.getId()==null){
return AjaxResult.error("渠道不存在");
}
if (StringUtils.isEmpty(comPublicHalfDto.getData())){
return AjaxResult.error("加密数据不能为空");
}
//解密为customerInfoDto
String s = SecureUtils.AesUtil.AesDecode(comPublicHalfDto.getData(), comPublicHalfDto.getChannelSignature());
if (s==null){
return AjaxResult.error("解密异常");
}
CustomerInfoDto customerInfoDto = JSONObject.parseObject(s, CustomerInfoDto.class);
log.info("渠道:{},进件手机号:{}",channel.getChannelName(),customerInfoDto.getPhone());
//校验数据必传参数是否未传
String checkData = checkData(customerInfoDto);
//转化字段未数据库中资质字段 更新 用户实名状态 一并保存用户申请记录 已申请
if (checkData!=null){
return AjaxResult.error(checkData);
}
//转化字段未数据库中资质字段 并保存 用户未实名状态 一并保存用户申请记录 未申请状态
Customer customer = new Customer();
BeanUtil.copyProperties(customerInfoDto,customer);
customer.setChannelId(channel.getId());
customer.setActurlName(customerInfoDto.getName());
customer.setFirstLoginTime(new Date());
customer.setLastLoginTime(new Date());
customer.setIsAuth(true);
customer.setStatus(1);
R<Customer> customerInfoByPhoneMd5 = remoteCustomerService.getCustomerInfoByPhoneMd5(customerInfoDto.getPhoneMd5(), SecurityConstants.INNER);
if (customerInfoByPhoneMd5.getCode()==200){
customer.setPhone(EncryptUtil.AESencode(customer.getPhone(), config.getAESkey()));
customer.setIdCard(EncryptUtil.AESencode(customer.getIdCard(),config.getAESkey()));
customer.setActurlName(EncryptUtil.AESencode(customer.getActurlName(),config.getAESkey()));
remoteCustomerService.updateByPhoneMd5(customer,SecurityConstants.INNER);
}else {
remoteCustomerService.add(customer,SecurityConstants.INNER);
}
//匹配资质 造轮子 返回多个符合的商户
List<Merchant> merchants = matchMerchant(customer);
//TODO 取排序第一的
//返回渠道绑定的注册页拼接token
Map<String,Object> result = new HashMap<>();
Map<String,Object> map = new HashMap<>();
if (CollectionUtil.isEmpty(merchants)){
map.put("url","");
map.put("regist",false);
result.put("data",map);
return AjaxResult.success(result);
}
String url = channel.getHtmlLocation()+"?sign="+channel.getChannelSign() + "&token="+remoteCustomerService.getCustomerToken(customer.getPhone(),channel.getId() );
map.put("url",url);
map.put("regist",true);
result.put("data",map);
//CustomerApplyLog customerApplyLog = new CustomerApplyLog();
// customerApplyLog.setCustomerId(customerInfoByPhoneMd5.getData().getId());
// customerApplyLog.setChannelId(channel.getId());
// customerApplyLog.setOrderStatus(0l);
//+"&orderNo="+ LocalDateTimeUtils.getStringFromLocalDateTime()
//remoteCustomerApplyLogService.add(customerApplyLog);
//返回上游信息
return AjaxResult.success(result);
}
/**
* 渠道查询订单是否成功
* @param comPublicHalfDto
*/
@Override
public AjaxResult checkOrder(String phoneMd5, String channelSign) {
//根据手机号MD5渠道标识 查询是否成功
R<Customer> customerInfoByPhoneMd5 = remoteCustomerService.getCustomerInfoByPhoneMd5(phoneMd5, SecurityConstants.INNER);
Channel channel = redisService.getCacheObject(CacheConstants.CHANNEL_ID + customerInfoByPhoneMd5.getData().getChannelId());
R<Boolean> booleanR = remoteCustomerApplyLogService.customerApply(customerInfoByPhoneMd5.getData().getId(), SecurityConstants.INNER);
//失败直接失败
if (!booleanR.getData()){
return AjaxResult.success("用户未申请","false");
}
//成功抽奖 按扣量比抽
//成功数
double succ = channel.getScore()*0.01;
//扣量数
double socre = 1-(channel.getScore()*0.01);
List<Double> drow = new ArrayList<>();
drow.add(succ);
drow.add(socre);
int draw = ProbitUtil.draw(drow);
//返回是否成功
return draw==0?AjaxResult.success("用户已申请",true):AjaxResult.success("用户未申请","false");
}
public static void main(String[] args) {
CustomerInfoDto customerInfoDto = new CustomerInfoDto();
customerInfoDto.setPhoneMd5("331d17d1ca8a091410e3238fab16a863");
customerInfoDto.setPhone("15205600635");
customerInfoDto.setSex(0);
customerInfoDto.setNameMd5("331d17d1ca8a091410e3238fab16a863");
customerInfoDto.setName("朱三");
customerInfoDto.setAge(18);
customerInfoDto.setIdCardMd5("331d17d1ca8a091410e3238fab16a863");
customerInfoDto.setIdCard("341202199306023511");
customerInfoDto.setCity("重庆");
customerInfoDto.setCityCode(1000);
customerInfoDto.setSocialSecurity(1);
customerInfoDto.setAccumulationFund(1);
customerInfoDto.setCar(1);
customerInfoDto.setHourse(1);
customerInfoDto.setGuarantee(1);
customerInfoDto.setZhiMa(600);
customerInfoDto.setCareer(1);
customerInfoDto.setCreditCard(1);
customerInfoDto.setEducation(1);
customerInfoDto.setMonthlyIncome(5000);
System.out.println(JSONObject.toJSONString(customerInfoDto));
}
}

View File

@@ -0,0 +1,10 @@
Spring Boot Version: ${spring-boot.version}
Spring Application Name: ${spring.application.name}
_ __ _ _
(_) / _|(_)| |
_ __ _ _ ___ _ _ _ ______ | |_ _ | | ___
| '__|| | | | / _ \ | | | || ||______|| _|| || | / _ \
| | | |_| || (_) || |_| || | | | | || || __/
|_| \__,_| \___/ \__, ||_| |_| |_||_| \___|
__/ |
|___/

View File

@@ -0,0 +1,27 @@
# Tomcat
server:
port: 9301
# Spring
spring:
application:
# 应用名称
name: ruoyi-btc
profiles:
# 环境配置
active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 47.109.135.151:8848
namespace: b8ad3fd2-18ea-4cdf-a82c-4ce483392b1a
config:
# 配置中心地址
server-addr: 47.109.135.151:8848
namespace: b8ad3fd2-18ea-4cdf-a82c-4ce483392b1a
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 -->
<property name="log.path" value="logs/ruoyi-file" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.ruoyi" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
</configuration>

View File

@@ -15,15 +15,6 @@ public class RuoYiFileApplication
public static void main(String[] args) public static void main(String[] args)
{ {
SpringApplication.run(RuoYiFileApplication.class, args); SpringApplication.run(RuoYiFileApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 文件服务模块启动成功 ლ(´ڡ`ლ)゙ \n" + System.out.println("(♥◠‿◠)ノ゙ 文件服务模块启动成功 ლ(´ڡ`ლ)゙ \n");
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
} }
} }

View File

@@ -1,5 +1,6 @@
package com.ruoyi.file.service; package com.ruoyi.file.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -13,6 +14,7 @@ import com.ruoyi.file.utils.FileUploadUtils;
*/ */
@Primary @Primary
@Service @Service
@Slf4j
public class LocalSysFileServiceImpl implements ISysFileService public class LocalSysFileServiceImpl implements ISysFileService
{ {
/** /**
@@ -45,6 +47,7 @@ public class LocalSysFileServiceImpl implements ISysFileService
{ {
String name = FileUploadUtils.upload(localFilePath, file); String name = FileUploadUtils.upload(localFilePath, file);
String url = domain + localFilePrefix + name; String url = domain + localFilePrefix + name;
return url; return url;
} }
} }

View File

@@ -14,10 +14,12 @@ spring:
nacos: nacos:
discovery: discovery:
# 服务注册地址 # 服务注册地址
server-addr: 127.0.0.1:8848 server-addr: 47.109.135.151:8848
namespace: b8ad3fd2-18ea-4cdf-a82c-4ce483392b1a
config: config:
# 配置中心地址 # 配置中心地址
server-addr: 127.0.0.1:8848 server-addr: 47.109.135.151:8848
namespace: b8ad3fd2-18ea-4cdf-a82c-4ce483392b1a
# 配置文件格式 # 配置文件格式
file-extension: yml file-extension: yml
# 共享配置 # 共享配置

View File

@@ -18,15 +18,6 @@ public class RuoYiGenApplication
public static void main(String[] args) public static void main(String[] args)
{ {
SpringApplication.run(RuoYiGenApplication.class, args); SpringApplication.run(RuoYiGenApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 代码生成模块启动成功 ლ(´ڡ`ლ)゙ \n" + System.out.println("(♥◠‿◠)ノ゙ 代码生成模块启动成功 ლ(´ڡ`ლ)゙ \n");
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
} }
} }

View File

@@ -215,7 +215,7 @@ public class GenUtils
*/ */
public static String replaceText(String text) public static String replaceText(String text)
{ {
return RegExUtils.replaceAll(text, "(?:表|若依)", ""); return RegExUtils.replaceAll(text, "(?:表|租研舍)", "");
} }
/** /**

View File

@@ -14,10 +14,12 @@ spring:
nacos: nacos:
discovery: discovery:
# 服务注册地址 # 服务注册地址
server-addr: 127.0.0.1:8848 server-addr: 47.109.135.151:8848
namespace: b8ad3fd2-18ea-4cdf-a82c-4ce483392b1a
config: config:
# 配置中心地址 # 配置中心地址
server-addr: 127.0.0.1:8848 server-addr: 47.109.135.151:8848
namespace: b8ad3fd2-18ea-4cdf-a82c-4ce483392b1a
# 配置文件格式 # 配置文件格式
file-extension: yml file-extension: yml
# 共享配置 # 共享配置

View File

@@ -18,15 +18,6 @@ public class RuoYiJobApplication
public static void main(String[] args) public static void main(String[] args)
{ {
SpringApplication.run(RuoYiJobApplication.class, args); SpringApplication.run(RuoYiJobApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 定时任务模块启动成功 ლ(´ڡ`ლ)゙ \n" + System.out.println("(♥◠‿◠)ノ゙ 定时任务模块启动成功 ლ(´ڡ`ლ)゙ \n");
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
} }
} }

View File

@@ -14,10 +14,12 @@ spring:
nacos: nacos:
discovery: discovery:
# 服务注册地址 # 服务注册地址
server-addr: 127.0.0.1:8848 server-addr: 47.109.135.151:8848
namespace: b8ad3fd2-18ea-4cdf-a82c-4ce483392b1a
config: config:
# 配置中心地址 # 配置中心地址
server-addr: 127.0.0.1:8848 server-addr: 47.109.135.151:8848
namespace: b8ad3fd2-18ea-4cdf-a82c-4ce483392b1a
# 配置文件格式 # 配置文件格式
file-extension: yml file-extension: yml
# 共享配置 # 共享配置

View File

@@ -71,6 +71,22 @@
<artifactId>ruoyi-common-swagger</artifactId> <artifactId>ruoyi-common-swagger</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-sms</artifactId>
<version>3.6.4</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@@ -1,9 +1,14 @@
package com.ruoyi.system; package com.ruoyi.system;
import org.apache.tomcat.util.http.LegacyCookieProcessor;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.ruoyi.common.security.annotation.EnableCustomConfig; import com.ruoyi.common.security.annotation.EnableCustomConfig;
import com.ruoyi.common.security.annotation.EnableRyFeignClients; import com.ruoyi.common.security.annotation.EnableRyFeignClients;
import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
/** /**
* 系统模块 * 系统模块
@@ -18,15 +23,14 @@ public class RuoYiSystemApplication
public static void main(String[] args) public static void main(String[] args)
{ {
SpringApplication.run(RuoYiSystemApplication.class, args); SpringApplication.run(RuoYiSystemApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 系统模块启动成功 ლ(´ڡ`ლ)゙ \n" + System.out.println("(♥◠‿◠)ノ゙ 系统模块启动成功 ლ(´ڡ`ლ)゙ \n");
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
} }
@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> cookieProcessorCustomizer() {
return tomcatServletWebServerFactory -> tomcatServletWebServerFactory.addContextCustomizers((TomcatContextCustomizer) context -> {
context.setCookieProcessor(new LegacyCookieProcessor());
});
}
} }

View File

@@ -0,0 +1,23 @@
package com.ruoyi.system.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Minio 配置信息
*
* @author ruoyi
*/
@Configuration
@ConfigurationProperties(prefix = "system")
@Data
public class SystemConfig
{
/**
* 加密密钥
*/
private String AESkey;
}

View File

@@ -0,0 +1,109 @@
package com.ruoyi.system.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.common.core.domain.http.Channel;
import com.ruoyi.system.service.IChannelService;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.page.TableDataInfo;
/**
* 渠道配置Controller
*
* @author ruoyi
* @date 2024-09-15
*/
@RestController
@RequestMapping("/channel")
public class ChannelController extends BaseController
{
@Autowired
private IChannelService channelService;
/**
* 查询渠道配置列表
*/
@RequiresPermissions("system:channel:list")
@GetMapping("/list")
public TableDataInfo list(Channel channel)
{
startPage();
List<Channel> list = channelService.selectChannelList(channel);
return getDataTable(list);
}
/**
* 导出渠道配置列表
*/
@RequiresPermissions("system:channel:export")
@Log(title = "渠道配置", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, Channel channel)
{
List<Channel> list = channelService.selectChannelList(channel);
ExcelUtil<Channel> util = new ExcelUtil<Channel>(Channel.class);
util.exportExcel(response, list, "渠道配置数据");
}
/**
* 获取渠道配置详细信息
*/
@RequiresPermissions("system:channel:query")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(channelService.selectChannelById(id));
}
/**
* 新增渠道配置
*/
@RequiresPermissions("system:channel:add")
@Log(title = "渠道配置", businessType = BusinessType.INSERT)
@RequestMapping(value = "/add", method = RequestMethod.POST)
public AjaxResult add(@RequestBody Channel channel)
{
return toAjax(channelService.insertChannel(channel));
}
/**
* 修改渠道配置
*/
@RequiresPermissions("system:channel:edit")
@Log(title = "渠道配置", businessType = BusinessType.UPDATE)
@RequestMapping(value = "/edit", method = RequestMethod.POST)
public AjaxResult edit(@RequestBody Channel channel)
{
return toAjax(channelService.updateChannel(channel));
}
/**
* 删除渠道配置
*/
@RequiresPermissions("system:channel:remove")
@Log(title = "渠道配置", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(channelService.deleteChannelByIds(ids));
}
/**
* 根据渠道标识获取渠道类型
* @param sign
* @return
*/
@GetMapping("/getChannelBySign")
public AjaxResult getChannelBySign(@RequestParam("sign")String sign){
return channelService.getChannelBySign(sign);
}
}

Some files were not shown because too many files have changed in this diff Show More