Pre Merge pull request !380 from 鲸落/master_zhp

pull/380/MERGE
鲸落 11 months ago committed by Gitee
commit 47b9563ddf
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F

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

@ -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.

@ -11,7 +11,7 @@
## 平台简介
若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
租研舍是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
* 采用前后端分离的模式,微服务版本前端(基于 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue))。
* 后端采用Spring Boot、Spring Cloud & Alibaba。
@ -22,7 +22,7 @@
* 阿里云折扣场:[点我进入](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)  
#### 友情链接 [若依/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>
## 若依微服务交流群
## 租研舍微服务交流群
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) 点击按钮入群。

@ -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

@ -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

@ -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"

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

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

@ -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

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

@ -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;
}
}
}

@ -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

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

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

@ -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

@ -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"]

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

@ -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"]

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

@ -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"]

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

@ -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"]

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

@ -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"]

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

@ -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"]

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

@ -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"]

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

@ -10,7 +10,7 @@
<name>ruoyi</name>
<url>http://www.ruoyi.vip</url>
<description>若依微服务系统</description>
<description>租研舍微服务系统</description>
<properties>
<ruoyi.version>3.6.4</ruoyi.version>
@ -35,6 +35,9 @@
<poi.version>4.1.2</poi.version>
<springdoc.version>1.6.9</springdoc.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>
<!-- 依赖声明 -->
@ -216,6 +219,21 @@
<artifactId>ruoyi-api-system</artifactId>
<version>${ruoyi.version}</version>
</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>
</dependencyManagement>

@ -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
{
}

@ -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);
}

@ -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);
}

@ -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);
}

@ -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()
{
};
}
}

@ -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;
}
};
}
}

@ -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;
}
};
}
}

@ -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());
}
};
}
}

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

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

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

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

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

@ -106,7 +106,21 @@
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</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>
</project>

@ -56,4 +56,20 @@ public class CacheConstants
* IP cache key
*/
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:";
}

@ -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:";
}

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

@ -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;
}

@ -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;
}

@ -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;
}

@ -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;
}

@ -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;
}

@ -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;
}
/**
* 使KeyGeneratorDES/AES216
*
* @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"));
}
/***
* ApacheSHA-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;
}
}
}

@ -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"));
}
/**
* DateLocalDateTime
*
* @param date
* @return
*/
public static LocalDateTime getLocalDateTimeFromDate(Date date) {
LocalDateTime localDateTime = date.toInstant().atOffset(ZoneOffset.of("+8")).toLocalDateTime();
return localDateTime;
}
/**
* LocalDateTimeDate
*
* @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();
}
}

@ -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);
// }
}

@ -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 20240520 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) {
}
}

@ -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;
}
}

@ -129,6 +129,17 @@ public class BaseController
return rows > 0 ? AjaxResult.success() : AjaxResult.error();
}
/**
*
*
* @param rows
* @return
*/
protected AjaxResult toAjax(Long rows)
{
return rows > 0 ? AjaxResult.success() : AjaxResult.error();
}
/**
*
*

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

@ -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: 1829
* @Description: token
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class CustomerTokenService {
private final RedisService redisService;
/**
* token
*/
private static final Long EXPIRE_TIME = 30 * 24 * 60 * 60L;
/**
* 128token
*
* @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 truefalse
*/
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);
}
/**
* idtoken
*
* @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);
}
/**
* idtoken
*
* @param customerId id
*/
public void removeToken(Long customerId) {
String token = redisService.getCacheObject(RedisConstant.APP_CUSTOMER_KEY + customerId);
this.removeToken(token);
}
/**
* HttpServletRequesttoken
*
* @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;
}
/**
* idtoken
*
* @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;
}
/**
* tokenID
*
* @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;
}
/**
* HttpServletRequestID
*
* @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);
}
/**
* tokenID
*
* @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;
}
/**
* HttpServletRequestID
*
* @param request HttpServletRequest
* @return ID
*/
public Long getChannelId(HttpServletRequest request, Boolean... booleans) {
String token = getToken(request,booleans);
return getChannelId(token,booleans);
}
/**
* IDID
*
* @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];
}
}

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

@ -4,6 +4,8 @@ import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import com.ruoyi.common.core.constant.RedisConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
/**
* token
*/
private static final Long EXPIRE_TIME = 30 * 24 * 60 * 60L;
/**
*
*/
@ -69,6 +76,40 @@ public class TokenService
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;
}
/**
*
*

@ -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>

@ -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();
}
}

@ -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);
}
}

@ -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;
}
}

@ -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;
}

@ -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分钟内完成验证如非本人操作请忽略本短信。";
}

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

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

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

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

@ -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>

@ -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");
}
}

@ -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;
}

@ -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;
}
}

@ -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);
}
}

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

@ -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;
}

@ -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);
}

@ -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);
}

@ -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);
}
}

@ -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));
}
}

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

@ -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}

@ -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>

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

@ -1,82 +1,82 @@
package com.ruoyi.file.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.minio.MinioClient;
/**
* Minio
*
* @author ruoyi
*/
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig
{
/**
*
*/
private String url;
/**
*
*/
private String accessKey;
/**
*
*/
private String secretKey;
/**
*
*/
private String bucketName;
public String getUrl()
{
return url;
}
public void setUrl(String url)
{
this.url = url;
}
public String getAccessKey()
{
return accessKey;
}
public void setAccessKey(String accessKey)
{
this.accessKey = accessKey;
}
public String getSecretKey()
{
return secretKey;
}
public void setSecretKey(String secretKey)
{
this.secretKey = secretKey;
}
public String getBucketName()
{
return bucketName;
}
public void setBucketName(String bucketName)
{
this.bucketName = bucketName;
}
@Bean
public MinioClient getMinioClient()
{
return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();
}
}
package com.ruoyi.file.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.minio.MinioClient;
/**
* Minio
*
* @author ruoyi
*/
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig
{
/**
*
*/
private String url;
/**
*
*/
private String accessKey;
/**
*
*/
private String secretKey;
/**
*
*/
private String bucketName;
public String getUrl()
{
return url;
}
public void setUrl(String url)
{
this.url = url;
}
public String getAccessKey()
{
return accessKey;
}
public void setAccessKey(String accessKey)
{
this.accessKey = accessKey;
}
public String getSecretKey()
{
return secretKey;
}
public void setSecretKey(String secretKey)
{
this.secretKey = secretKey;
}
public String getBucketName()
{
return bucketName;
}
public void setBucketName(String bucketName)
{
this.bucketName = bucketName;
}
@Bean
public MinioClient getMinioClient()
{
return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();
}
}

@ -1,50 +1,50 @@
package com.ruoyi.file.config;
import java.io.File;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
*
*
* @author ruoyi
*/
@Configuration
public class ResourcesConfig implements WebMvcConfigurer
{
/**
*
*/
@Value("${file.path}")
private String localFilePath;
/**
*
*/
@Value("${file.prefix}")
public String localFilePrefix;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
/** 本地文件上传路径 */
registry.addResourceHandler(localFilePrefix + "/**")
.addResourceLocations("file:" + localFilePath + File.separator);
}
/**
*
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
// 设置允许跨域的路由
registry.addMapping(localFilePrefix + "/**")
// 设置允许跨域请求的域名
.allowedOrigins("*")
// 设置允许的方法
.allowedMethods("GET");
}
package com.ruoyi.file.config;
import java.io.File;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
*
*
* @author ruoyi
*/
@Configuration
public class ResourcesConfig implements WebMvcConfigurer
{
/**
*
*/
@Value("${file.path}")
private String localFilePath;
/**
*
*/
@Value("${file.prefix}")
public String localFilePrefix;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
/** 本地文件上传路径 */
registry.addResourceHandler(localFilePrefix + "/**")
.addResourceLocations("file:" + localFilePath + File.separator);
}
/**
*
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
// 设置允许跨域的路由
registry.addMapping(localFilePrefix + "/**")
// 设置允许跨域请求的域名
.allowedOrigins("*")
// 设置允许的方法
.allowedMethods("GET");
}
}

@ -1,48 +1,48 @@
package com.ruoyi.file.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.file.FileUtils;
import com.ruoyi.file.service.ISysFileService;
import com.ruoyi.system.api.domain.SysFile;
/**
*
*
* @author ruoyi
*/
@RestController
public class SysFileController
{
private static final Logger log = LoggerFactory.getLogger(SysFileController.class);
@Autowired
private ISysFileService sysFileService;
/**
*
*/
@PostMapping("upload")
public R<SysFile> upload(MultipartFile file)
{
try
{
// 上传并返回访问地址
String url = sysFileService.uploadFile(file);
SysFile sysFile = new SysFile();
sysFile.setName(FileUtils.getName(url));
sysFile.setUrl(url);
return R.ok(sysFile);
}
catch (Exception e)
{
log.error("上传文件失败", e);
return R.fail(e.getMessage());
}
}
package com.ruoyi.file.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.file.FileUtils;
import com.ruoyi.file.service.ISysFileService;
import com.ruoyi.system.api.domain.SysFile;
/**
*
*
* @author ruoyi
*/
@RestController
public class SysFileController
{
private static final Logger log = LoggerFactory.getLogger(SysFileController.class);
@Autowired
private ISysFileService sysFileService;
/**
*
*/
@PostMapping("upload")
public R<SysFile> upload(MultipartFile file)
{
try
{
// 上传并返回访问地址
String url = sysFileService.uploadFile(file);
SysFile sysFile = new SysFile();
sysFile.setName(FileUtils.getName(url));
sysFile.setUrl(url);
return R.ok(sysFile);
}
catch (Exception e)
{
log.error("上传文件失败", e);
return R.fail(e.getMessage());
}
}
}

@ -1,46 +1,46 @@
package com.ruoyi.file.service;
import java.io.InputStream;
import com.alibaba.nacos.common.utils.IoUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.ruoyi.common.core.utils.file.FileTypeUtils;
/**
* FastDFS
*
* @author ruoyi
*/
@Service
public class FastDfsSysFileServiceImpl implements ISysFileService
{
/**
* 访
*/
@Value("${fdfs.domain}")
public String domain;
@Autowired
private FastFileStorageClient storageClient;
/**
* FastDfs
*
* @param file
* @return 访
* @throws Exception
*/
@Override
public String uploadFile(MultipartFile file) throws Exception
{
InputStream inputStream = file.getInputStream();
StorePath storePath = storageClient.uploadFile(inputStream, file.getSize(),
FileTypeUtils.getExtension(file), null);
IoUtils.closeQuietly(inputStream);
return domain + "/" + storePath.getFullPath();
}
}
package com.ruoyi.file.service;
import java.io.InputStream;
import com.alibaba.nacos.common.utils.IoUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.ruoyi.common.core.utils.file.FileTypeUtils;
/**
* FastDFS
*
* @author ruoyi
*/
@Service
public class FastDfsSysFileServiceImpl implements ISysFileService
{
/**
* 访
*/
@Value("${fdfs.domain}")
public String domain;
@Autowired
private FastFileStorageClient storageClient;
/**
* FastDfs
*
* @param file
* @return 访
* @throws Exception
*/
@Override
public String uploadFile(MultipartFile file) throws Exception
{
InputStream inputStream = file.getInputStream();
StorePath storePath = storageClient.uploadFile(inputStream, file.getSize(),
FileTypeUtils.getExtension(file), null);
IoUtils.closeQuietly(inputStream);
return domain + "/" + storePath.getFullPath();
}
}

@ -1,20 +1,20 @@
package com.ruoyi.file.service;
import org.springframework.web.multipart.MultipartFile;
/**
*
*
* @author ruoyi
*/
public interface ISysFileService
{
/**
*
*
* @param file
* @return 访
* @throws Exception
*/
public String uploadFile(MultipartFile file) throws Exception;
}
package com.ruoyi.file.service;
import org.springframework.web.multipart.MultipartFile;
/**
*
*
* @author ruoyi
*/
public interface ISysFileService
{
/**
*
*
* @param file
* @return 访
* @throws Exception
*/
public String uploadFile(MultipartFile file) throws Exception;
}

@ -1,50 +1,53 @@
package com.ruoyi.file.service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.file.utils.FileUploadUtils;
/**
*
*
* @author ruoyi
*/
@Primary
@Service
public class LocalSysFileServiceImpl implements ISysFileService
{
/**
*
*/
@Value("${file.prefix}")
public String localFilePrefix;
/**
* 访
*/
@Value("${file.domain}")
public String domain;
/**
*
*/
@Value("${file.path}")
private String localFilePath;
/**
*
*
* @param file
* @return 访
* @throws Exception
*/
@Override
public String uploadFile(MultipartFile file) throws Exception
{
String name = FileUploadUtils.upload(localFilePath, file);
String url = domain + localFilePrefix + name;
return url;
}
}
package com.ruoyi.file.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.file.utils.FileUploadUtils;
/**
*
*
* @author ruoyi
*/
@Primary
@Service
@Slf4j
public class LocalSysFileServiceImpl implements ISysFileService
{
/**
*
*/
@Value("${file.prefix}")
public String localFilePrefix;
/**
* 访
*/
@Value("${file.domain}")
public String domain;
/**
*
*/
@Value("${file.path}")
private String localFilePath;
/**
*
*
* @param file
* @return 访
* @throws Exception
*/
@Override
public String uploadFile(MultipartFile file) throws Exception
{
String name = FileUploadUtils.upload(localFilePath, file);
String url = domain + localFilePrefix + name;
return url;
}
}

@ -1,49 +1,49 @@
package com.ruoyi.file.service;
import java.io.InputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.alibaba.nacos.common.utils.IoUtils;
import com.ruoyi.file.config.MinioConfig;
import com.ruoyi.file.utils.FileUploadUtils;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
/**
* Minio
*
* @author ruoyi
*/
@Service
public class MinioSysFileServiceImpl implements ISysFileService
{
@Autowired
private MinioConfig minioConfig;
@Autowired
private MinioClient client;
/**
* Minio
*
* @param file
* @return 访
* @throws Exception
*/
@Override
public String uploadFile(MultipartFile file) throws Exception
{
String fileName = FileUploadUtils.extractFilename(file);
InputStream inputStream = file.getInputStream();
PutObjectArgs args = PutObjectArgs.builder()
.bucket(minioConfig.getBucketName())
.object(fileName)
.stream(inputStream, file.getSize(), -1)
.contentType(file.getContentType())
.build();
client.putObject(args);
IoUtils.closeQuietly(inputStream);
return minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + fileName;
}
}
package com.ruoyi.file.service;
import java.io.InputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.alibaba.nacos.common.utils.IoUtils;
import com.ruoyi.file.config.MinioConfig;
import com.ruoyi.file.utils.FileUploadUtils;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
/**
* Minio
*
* @author ruoyi
*/
@Service
public class MinioSysFileServiceImpl implements ISysFileService
{
@Autowired
private MinioConfig minioConfig;
@Autowired
private MinioClient client;
/**
* Minio
*
* @param file
* @return 访
* @throws Exception
*/
@Override
public String uploadFile(MultipartFile file) throws Exception
{
String fileName = FileUploadUtils.extractFilename(file);
InputStream inputStream = file.getInputStream();
PutObjectArgs args = PutObjectArgs.builder()
.bucket(minioConfig.getBucketName())
.object(fileName)
.stream(inputStream, file.getSize(), -1)
.contentType(file.getContentType())
.build();
client.putObject(args);
IoUtils.closeQuietly(inputStream);
return minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + fileName;
}
}

@ -1,185 +1,185 @@
package com.ruoyi.file.utils;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Objects;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.exception.file.FileException;
import com.ruoyi.common.core.exception.file.FileNameLengthLimitExceededException;
import com.ruoyi.common.core.exception.file.FileSizeLimitExceededException;
import com.ruoyi.common.core.exception.file.InvalidExtensionException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.file.FileTypeUtils;
import com.ruoyi.common.core.utils.file.MimeTypeUtils;
import com.ruoyi.common.core.utils.uuid.Seq;
/**
*
*
* @author ruoyi
*/
public class FileUploadUtils
{
/**
* 50M
*/
public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024L;
/**
* 100
*/
public static final int DEFAULT_FILE_NAME_LENGTH = 100;
/**
*
*
* @param baseDir
* @param file
* @return
* @throws IOException
*/
public static final String upload(String baseDir, MultipartFile file) throws IOException
{
try
{
return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
}
catch (FileException fe)
{
throw new IOException(fe.getDefaultMessage(), fe);
}
catch (Exception e)
{
throw new IOException(e.getMessage(), e);
}
}
/**
*
*
* @param baseDir
* @param file
* @param allowedExtension
* @return
* @throws FileSizeLimitExceededException
* @throws FileNameLengthLimitExceededException
* @throws IOException
* @throws InvalidExtensionException
*/
public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException
{
int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
{
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
assertAllowed(file, allowedExtension);
String fileName = extractFilename(file);
String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
file.transferTo(Paths.get(absPath));
return getPathFileName(fileName);
}
/**
*
*/
public static final String extractFilename(MultipartFile file)
{
return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), FileTypeUtils.getExtension(file));
}
private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
{
File desc = new File(uploadDir + File.separator + fileName);
if (!desc.exists())
{
if (!desc.getParentFile().exists())
{
desc.getParentFile().mkdirs();
}
}
return desc.isAbsolute() ? desc : desc.getAbsoluteFile();
}
private static final String getPathFileName(String fileName) throws IOException
{
String pathFileName = "/" + fileName;
return pathFileName;
}
/**
*
*
* @param file
* @throws FileSizeLimitExceededException
* @throws InvalidExtensionException
*/
public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, InvalidExtensionException
{
long size = file.getSize();
if (size > DEFAULT_MAX_SIZE)
{
throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
}
String fileName = file.getOriginalFilename();
String extension = FileTypeUtils.getExtension(file);
if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
{
if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
{
throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
{
throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
{
throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
{
throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
fileName);
}
else
{
throw new InvalidExtensionException(allowedExtension, extension, fileName);
}
}
}
/**
* MIMEMIME
*
* @param extension
* @param allowedExtension
* @return true/false
*/
public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
{
for (String str : allowedExtension)
{
if (str.equalsIgnoreCase(extension))
{
return true;
}
}
return false;
}
package com.ruoyi.file.utils;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Objects;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.exception.file.FileException;
import com.ruoyi.common.core.exception.file.FileNameLengthLimitExceededException;
import com.ruoyi.common.core.exception.file.FileSizeLimitExceededException;
import com.ruoyi.common.core.exception.file.InvalidExtensionException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.file.FileTypeUtils;
import com.ruoyi.common.core.utils.file.MimeTypeUtils;
import com.ruoyi.common.core.utils.uuid.Seq;
/**
*
*
* @author ruoyi
*/
public class FileUploadUtils
{
/**
* 50M
*/
public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024L;
/**
* 100
*/
public static final int DEFAULT_FILE_NAME_LENGTH = 100;
/**
*
*
* @param baseDir
* @param file
* @return
* @throws IOException
*/
public static final String upload(String baseDir, MultipartFile file) throws IOException
{
try
{
return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
}
catch (FileException fe)
{
throw new IOException(fe.getDefaultMessage(), fe);
}
catch (Exception e)
{
throw new IOException(e.getMessage(), e);
}
}
/**
*
*
* @param baseDir
* @param file
* @param allowedExtension
* @return
* @throws FileSizeLimitExceededException
* @throws FileNameLengthLimitExceededException
* @throws IOException
* @throws InvalidExtensionException
*/
public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException
{
int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
{
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
assertAllowed(file, allowedExtension);
String fileName = extractFilename(file);
String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
file.transferTo(Paths.get(absPath));
return getPathFileName(fileName);
}
/**
*
*/
public static final String extractFilename(MultipartFile file)
{
return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), FileTypeUtils.getExtension(file));
}
private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
{
File desc = new File(uploadDir + File.separator + fileName);
if (!desc.exists())
{
if (!desc.getParentFile().exists())
{
desc.getParentFile().mkdirs();
}
}
return desc.isAbsolute() ? desc : desc.getAbsoluteFile();
}
private static final String getPathFileName(String fileName) throws IOException
{
String pathFileName = "/" + fileName;
return pathFileName;
}
/**
*
*
* @param file
* @throws FileSizeLimitExceededException
* @throws InvalidExtensionException
*/
public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, InvalidExtensionException
{
long size = file.getSize();
if (size > DEFAULT_MAX_SIZE)
{
throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
}
String fileName = file.getOriginalFilename();
String extension = FileTypeUtils.getExtension(file);
if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
{
if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
{
throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
{
throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
{
throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
{
throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
fileName);
}
else
{
throw new InvalidExtensionException(allowedExtension, extension, fileName);
}
}
}
/**
* MIMEMIME
*
* @param extension
* @param allowedExtension
* @return true/false
*/
public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
{
for (String str : allowedExtension)
{
if (str.equalsIgnoreCase(extension))
{
return true;
}
}
return false;
}
}

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

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

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

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

Loading…
Cancel
Save