初始化Jeepay项目

This commit is contained in:
dingzhiwei 2021-06-09 16:05:40 +08:00
parent 40dcaf4ab6
commit de3de82dc8
897 changed files with 28154 additions and 69214 deletions

178
LICENSE
View File

@ -1,21 +1,165 @@
MIT License
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (c) 2017 https://github.com/jmdhappy/xxpay-master
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
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.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
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.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

140
README.md
View File

@ -1,16 +1,120 @@
### 郑重声明
<p align="center">
<a href="https://www.jeepay.vip"><img src="https://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/jeepay_logo.svg"></a>
</p>
<p align="center">
<strong>适合互联网企业使用的开源支付系统</strong>
</p>
<p align="center">
👉 <a href="https://www.jeepay.vip">https://www.jeepay.vip</a> 👈
</p>
<p align="center">
<a target="_blank" href="https://spring.io/projects/spring-boot">
<img src="https://img.shields.io/badge/spring%20boot-2.4.5-yellowgreen" />
</a>
<a target="_blank" href="https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html">
<img src="https://img.shields.io/badge/JDK-8+-green.svg" />
</a>
<a target="_blank" href="http://www.gnu.org/licenses/lgpl.html">
<img src="https://img.shields.io/badge/license-LGPL--3.0-blue" />
</a>
<a href='https://gitee.com/jeequan/jeepay/stargazers' target="_blank">
<img src='https://gitee.com/jeequan/jeepay/badge/star.svg?theme=gvp' alt='star'></img>
</a>
<a target="_blank" href='https://github.com/jeequan/jeepay'>
<img src="https://img.shields.io/github/stars/jeequan/jeepay.svg?style=social" alt="github star"/>
</a>
</p>
<br/>
<p align="center">
<a href="https://jq.qq.com/?_wv=1027&k=94WnXmdL">
<img src="https://img.shields.io/badge/qq%E7%BE%A4%E2%91%A0-635647058-critical"/>
</a>
</p>
-------------------------------------------------------------------------------
## 📚 项目介绍
Jeepay是一套适合互联网企业使用的开源支付系统支持多渠道服务商和普通商户模式。已对接`微信支付``支付宝``云闪付`官方接口,支持聚合码支付。
Jeepay使用`Spring Boot`和`Ant Design Vue`开发,集成`Spring Security`实现权限管理功能是一套非常实用的web开发框架。
### 🎁 名称的由来
Jeepay = Jee + pay是由原XxPay支付系统作者带领团队开发“Jee”是公司计全科技名称的表示pay表示支付。中文名称为计全支付释为计出万全、支付安全让支付更加方便安全。
### 🍟 项目体验
- Jeepay支付流程体验[https://www.jeequan.com/demo/jeepay_cashier.html](https://www.jeequan.com/demo/jeepay_cashier.html "Jeepay支付体验")
- Jeepay运营平台和商户系统演体验[https://www.jeequan.com/doc/detail_84.html](https://www.jeequan.com/doc/detail_84.html "Jeepay支付系统体验")
- Jeepay项目文档[https://www.jeepay.vip](https://www.jeepay.vip "Jeepay项目文档")
### 🍎 项目特点
* 支持多渠道对接,支付网关自动路由
* 已对接`微信`服务商和普通商户接口,支持`V2`和`V3`接口
* 已对接`支付宝`服务商和普通商户接口支持RSA和RSA2签名
* 已对接`云闪付`服务商接口,可选择多家支付机构
* 提供http形式接口提供各语言的`sdk`实现,方便对接
* 接口请求和响应数据采用签名机制,保证交易安全可靠
* 系统安全,支持`分布式`部署,`高并发`
* 管理端包括`运营平台`和`商户系统`
* 管理平台操作界面简洁、易用
* 支付平台到商户系统的订单通知使用MQ实现保证了高可用消息可达
* 支付渠道的接口参数配置界面自动化生成
* 使用`spring security`实现权限管理
* 前后端分离架构,方便二次开发
* 由原`XxPay`团队开发,有着多年支付系统开发经验
## 🥞 系统架构
> Jeepay计全支付系统架构图
![Jeepay系统架构图](https://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/jeepay_framework.png "Jeepay系统架构图")
> 原`XxPay聚合支付`项目已更名为Jeepay由原XxPay团队开发维护。目前`Jeepay`开发已经进入收尾阶段最晚6月初会发布源码到Github和码云上。
> 核心技术栈
> 新版Jeepay支付系统使用SpringBoot + Ant Vue开发适合互联网企业搭建内部支付系统。支持普通商户和服务商模式已对接微信、支付宝、云闪付官方通道。统一的下单接口实现主扫/被扫(聚合)。
| 软件名称 | 描述 | 版本
|---|---|---
|Jdk | Java环境 | 1.8
|Spring Boot | 开发框架 | 2.4.5
|Redis | 分布式缓存 | 3.2.8 或 高版本
|MySQL | 数据库 | 5.7.X
|ActiveMQ | 消息中间件 | 5.15.8 或 高版本
|[Ant Design Vue](https://www.antdv.com/docs/vue/introduce-cn/) | Ant Design的Vue实现前端开发使用 | 2.1.2
|[MyBatis-Plus](https://mp.baomidou.com/) | MyBatis增强工具 | 3.4.2
|[WxJava](https://gitee.com/binary/weixin-java-tools) | 微新开发Java SDK | 4.0.0
|[Hutool](https://www.hutool.cn/) | Java工具类库 | 5.6.6
> 请关注官方网站[www.jeequan.com](https://www.jeequan.com "计全科技官网")或官方公众号微信搜索计全科技获取Jeepay最新发布消息如果您喜欢该项目不妨随手Star下。
> 项目结构
> 待发布源码时会更公布官方qq或微信技术交流群同时会发布使用文档及演示地址。
```lua
jeepay-ui -- https://gitee.com/jeequan/jeepay-ui
### 功能列表
jeepay
├── conf -- 存放系统部署使用的.yml文件
└── docs -- 存放项目相关文档说明
├── script -- 项目启动shell脚本
└── sql -- 初始化sql文件
├── jeepay-core -- 核心依赖包
├── jeepay-manager -- 运营平台服务端[9217]
├── jeepay-merchant -- 商户系统服务端[9218]
├── jeepay-payment -- 支付网关[9216]
├── jeepay-service -- 业务层代码
└── jeepay-z-codegen -- mybatis代码生成
```
> 开发部署
- 系统开发:[https://www.jeepay.vip/#/develop/dev_serv](https://www.jeepay.vip/#/develop/dev_serv)
- 通道对接:[https://www.jeepay.vip/#/develop/dev_channel](https://www.jeepay.vip/#/develop/dev_channel)
- 线上部署:[https://www.jeepay.vip/#/develop/deploy](https://www.jeepay.vip/#/develop/deploy)
- 接口文档:[https://www.jeepay.vip/#/interface/payment_api](https://www.jeepay.vip/#/interface/payment_api)
## 🍿 功能模块
> Jeepay运营平台功能
@ -20,7 +124,7 @@
![Jeepay商户系统功能](https://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/jeepay_mch.png "Jeepay商户系统功能")
### 功能预览
## 🍯 系统截图
`以下截图是从实际已完成功能界面截取,截图时间为2021-05-29 02:05`
@ -28,18 +132,10 @@
![Jeepay演示界面](http://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/yanshi/002.png "Jeepay演示界面")
![Jeepay演示界面](http://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/yanshi/003.png "Jeepay演示界面")
![Jeepay演示界面](http://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/yanshi/004.png "Jeepay演示界面")
![Jeepay演示界面](http://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/yanshi/005.png "Jeepay演示界面")
![Jeepay演示界面](http://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/yanshi/006.png "Jeepay演示界面")
![Jeepay演示界面](http://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/yanshi/007.png "Jeepay演示界面")
![Jeepay演示界面](http://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/yanshi/008.png "Jeepay演示界面")
![Jeepay演示界面](http://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/yanshi/009.png "Jeepay演示界面")
![Jeepay演示界面](http://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/yanshi/010.png "Jeepay演示界面")
@ -54,21 +150,9 @@
![Jeepay演示界面](http://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/yanshi/015.png "Jeepay演示界面")
![Jeepay演示界面](http://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/yanshi/016.png "Jeepay演示界面")
![Jeepay演示界面](http://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/yanshi/017.png "Jeepay演示界面")
![Jeepay演示界面](http://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/yanshi/018.png "Jeepay演示界面")
![Jeepay演示界面](http://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/yanshi/019.png "Jeepay演示界面")
![Jeepay演示界面](http://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/yanshi/020.png "Jeepay演示界面")
![Jeepay演示界面](http://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/yanshi/021.png "Jeepay演示界面")
![Jeepay演示界面](http://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/yanshi/022.png "Jeepay演示界面")
### 关于我们
## 🥪 关于我们
***
微信扫描下面二维码,关注官方公众号:计全科技,获取更多精彩内容。

View File

@ -0,0 +1,45 @@
#################################
# spring boot支持外部application.yml 读取优先级为:
# 1、file:./config/当前目录下的config文件夹
# 2、file:./(当前目录)
# 3、classpath:/config/classpath下的config目录
# 4、classpath:/classpath根目录
# 建议: 如果是jar则放置到与jar相同的目录下 如果解压文件放置到classpath: config目录下。 (需要将文件重命名为 application.yml )
#
# 该yml文件只配置与环境相关的参数 其他配置读取项目下的配置项
#
#################################
server:
port: 9217 #设置端口为 9217
spring:
datasource:
# yml填写url连接串 无需将&符号进行转义
url: jdbc:mysql://127.0.0.1:3306/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false
username: jeepay
password: 123456
redis:
host: 127.0.0.1
port: 6379
password:
#activeMQ配置
activemq:
broker-url: tcp://localhost:61616 #连接地址
#日志配置参数。
# 当存在logback-spring.xml文件时 该配置将引进到logback配置 springboot配置不生效。
# 不存在logback-spring.xml 文件时, 使用springboot的配置 同样可用。
logging:
level:
root: info #主日志级别
com.jeequan.jeepay: debug #该项目日志级别当需要打印sql时请开启为debug
path: ./logs #日志存放地址
#系统业务参数
isys:
allow-cors: false #是否允许跨域请求 [生产环境建议关闭, 若api与前端项目没有在同一个域名下时应开启此配置或在nginx统一配置允许跨域]
jwt-secret: t7w3P8X6472qWc3u #生成jwt的秘钥。 要求每个系统有单独的秘钥管理机制。
# 文件系统配置项系统内oss 并非云oss
oss-file:
root-path: /home/jeepay/upload #存储根路径 ( 无需以‘/’结尾 )

View File

@ -0,0 +1,45 @@
#################################
# spring boot支持外部application.yml 读取优先级为:
# 1、file:./config/当前目录下的config文件夹
# 2、file:./(当前目录)
# 3、classpath:/config/classpath下的config目录
# 4、classpath:/classpath根目录
# 建议: 如果是jar则放置到与jar相同的目录下 如果解压文件放置到classpath: config目录下。 (需要将文件重命名为 application.yml )
#
# 该yml文件只配置与环境相关的参数 其他配置读取项目下的配置项
#
#################################
server:
port: 9218 # 设置端口为 9218
spring:
datasource:
# yml填写url连接串 无需将&符号进行转义
url: jdbc:mysql://127.0.0.1:3306/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false
username: jeepay
password: 123456
redis:
host: 127.0.0.1
port: 6379
password:
#activeMQ配置
activemq:
broker-url: tcp://localhost:61616 #连接地址
#日志配置参数。
# 当存在logback-spring.xml文件时 该配置将引进到logback配置 springboot配置不生效。
# 不存在logback-spring.xml 文件时, 使用springboot的配置 同样可用。
logging:
level:
root: info #主日志级别
com.jeequan.jeepay: debug #该项目日志级别当需要打印sql时请开启为debug
path: ./logs #日志存放地址
#系统业务参数
isys:
allow-cors: false #是否允许跨域请求 [生产环境建议关闭, 若api与前端项目没有在同一个域名下时应开启此配置或在nginx统一配置允许跨域]
jwt-secret: ARNXp4MzjOOQqxtv #生成jwt的秘钥。 要求每个系统有单独的秘钥管理机制。
# 文件系统配置项系统内oss 并非云oss
oss-file:
root-path: /home/jeepay/upload #存储根路径 ( 无需以‘/’结尾 )

View File

@ -0,0 +1,44 @@
#################################
# spring boot支持外部application.yml 读取优先级为:
# 1、file:./config/当前目录下的config文件夹
# 2、file:./(当前目录)
# 3、classpath:/config/classpath下的config目录
# 4、classpath:/classpath根目录
# 建议: 如果是jar则放置到与jar相同的目录下 如果解压文件放置到classpath: config目录下。 (需要将文件重命名为 application.yml )
#
# 该yml文件只配置与环境相关的参数 其他配置读取项目下的配置项
#
#################################
server:
port: 9216 #设置端口为 9216
spring:
datasource:
# yml填写url连接串 无需将&符号进行转义
url: jdbc:mysql://127.0.0.1:3306/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false
username: jeepay
password: 123456
redis:
host: 127.0.0.1
port: 6379
password:
#activeMQ配置
activemq:
broker-url: tcp://localhost:61616 #连接地址
#日志配置参数。
# 当存在logback-spring.xml文件时 该配置将引进到logback配置 springboot配置不生效。
# 不存在logback-spring.xml 文件时, 使用springboot的配置 同样可用。
logging:
level:
root: info #主日志级别
com.jeequan.jeepay: debug #该项目日志级别当需要打印sql时请开启为debug
path: ./logs #日志存放地址
#系统业务参数
isys:
allow-cors: false #是否允许跨域请求 [生产环境建议关闭, 若api与前端项目没有在同一个域名下时应开启此配置或在nginx统一配置允许跨域]
# 文件系统配置项系统内oss 并非云oss
oss-file:
root-path: /home/jeepay/upload #存储根路径 ( 无需以‘/’结尾 )

135
docs/script/app.sh Normal file
View File

@ -0,0 +1,135 @@
#!/bin/sh
#功能简介:启动 xxx.jar 文件
#请先cd到项目下执行
#注意在sh文件中=赋值,左右两侧不能有空格
# .Power by terrfly
#当前所在目录
PROJECT_PATH=$(cd `dirname $0`; pwd)
#当前所在文件夹名
PROJECT_NAME="${PROJECT_PATH##*/}"
#jar名称
APP_NAME='jeepay-'$PROJECT_NAME'.jar'
#=======================================================================
#当前应用进行的变量标识
APP_PID=''
# 重新获取APPID
function refAppPID(){
APP_PID=`ps -ef|grep $APP_NAME|grep -v grep|grep -v kill|awk '{print $2}'`
}
# 获取运行程序的pid 进程号
function getAppPID(){
if [ ! $APP_PID ]; then #未获取过
refAppPID
fi
}
# 启动
function start(){
refAppPID #获取进程PID, 需重新获取, 避免restart时无法正确启动。
if [ $APP_PID ]; then
echo " [$APP_NAME] App is running. this start fail. "
return 0
fi
nohup java -jar $APP_NAME >/dev/null 2>start.log &
# tail -200f start.log
echo " [$APP_NAME] App starting ... "
}
# 停止
function stop(){
getAppPID #获取进程PID
if [ ! $APP_PID ]; then
echo " [$APP_NAME] App is NOT running. "
return 0
fi
echo " [$APP_NAME] [pid=$APP_PID] [kill -15] stop process... "
kill -15 $APP_PID # kill-15 :正常退出程序
sleep 5 #等待5s
# 重新获取PID
refAppPID
#仍然存在 需要kill -9
if [ $APP_PID ]; then
forcekill
fi
echo " [$APP_NAME] Stop Success! "
}
# 检查
function check(){
getAppPID #获取进程PID
if [ $APP_PID ]; then
echo " [$APP_NAME] App is running. PID[$APP_PID] "
else
echo " [$APP_NAME] App is NOT running. "
fi
}
# 强制kill进程
function forcekill(){
getAppPID #获取进程PID
if [ $APP_PID ]; then
echo " [$APP_NAME] [pid=$APP_PID] [kill -9] Kill ing ... "
kill -9 $APP_PID
echo " [$APP_NAME] [pid=$APP_PID] [kill -9] Kill Success! "
else
echo " [$APP_NAME] App is NOT running. "
fi
}
echo ''
command=$1
if [ "${command}" == "start" ]; then
start
elif [ "${command}" == "stop" ]; then
stop
elif [ "${command}" == "restart" ]; then
stop
start
elif [ "${command}" == "check" ]; then
check
elif [ "${command}" == "kill" ]; then
forcekill
else
echo "Usage: $0 {start|stop|restart|check|kill|}"
fi
echo ''

567
docs/sql/init.sql Normal file
View File

@ -0,0 +1,567 @@
#
# * Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
# * <p>
# * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
# * you may not use this file except in compliance with the License.
# * You may obtain a copy of the License at
# * <p>
# * http://www.gnu.org/licenses/lgpl.html
# * <p>
# * Unless required by applicable law or agreed to in writing, software
# * distributed under the License is distributed on an "AS IS" BASIS,
# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# * See the License for the specific language governing permissions and
# * limitations under the License.
#
##### ↓↓↓↓↓↓↓↓↓↓ 表结构DDL ↓↓↓↓↓↓↓↓↓↓ #####
-- RBAC设计思路 [用户] 1<->N [角色] 1<->N [权限]
-- 权限表
DROP TABLE IF EXISTS `t_sys_entitlement`;
CREATE TABLE `t_sys_entitlement` (
`ent_id` VARCHAR(32) NOT NULL COMMENT '权限ID[ENT_功能模块_子模块_操作], eg: ENT_ROLE_LIST_ADD',
`ent_name` VARCHAR(32) NOT NULL COMMENT '权限名称',
`menu_icon` VARCHAR(32) COMMENT '菜单图标',
`menu_uri` VARCHAR(128) COMMENT '菜单uri/路由地址',
`component_name` VARCHAR(32) COMMENT '组件Name前后端分离使用',
`ent_type` CHAR(2) NOT NULL COMMENT '权限类型 ML-左侧显示菜单, MO-其他菜单, PB-页面/按钮',
`quick_jump` TINYINT(6) NOT NULL DEFAULT 0 COMMENT '快速开始菜单 0-否, 1-是',
`state` TINYINT(6) NOT NULL DEFAULT 1 COMMENT '状态 0-停用, 1-启用',
`pid` VARCHAR(32) NOT NULL COMMENT '父ID',
`ent_sort` INT(11) NOT NULL DEFAULT 0 COMMENT '排序字段, 规则:正序',
`system` VARCHAR(8) NOT NULL COMMENT '所属系统: MGR-运营平台, MCH-商户中心',
`created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
PRIMARY KEY (`ent_id`, `system`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统权限表';
-- 角色表
DROP TABLE IF EXISTS `t_sys_role`;
CREATE TABLE `t_sys_role` (
`role_id` VARCHAR(32) NOT NULL COMMENT '角色ID, ROLE_开头',
`role_name` VARCHAR(32) NOT NULL COMMENT '角色名称',
`system` VARCHAR(8) NOT NULL COMMENT '所属系统: MGR-运营平台, MCH-商户中心',
`belong_info_id` VARCHAR(64) NOT NULL DEFAULT '0' COMMENT '所属商户ID / 0(平台)',
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
PRIMARY KEY (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统角色表';
-- 角色<->权限 关联表
DROP TABLE IF EXISTS `t_sys_role_ent_rela`;
CREATE TABLE `t_sys_role_ent_rela` (
`role_id` VARCHAR(32) NOT NULL COMMENT '角色ID',
`ent_id` VARCHAR(32) NOT NULL COMMENT '权限ID' ,
PRIMARY KEY (`role_id`, `ent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统角色权限关联表';
-- 系统用户表
DROP TABLE IF EXISTS `t_sys_user`;
CREATE TABLE `t_sys_user` (
`sys_user_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '系统用户ID',
`login_username` VARCHAR(32) NOT NULL COMMENT '登录用户名',
`realname` VARCHAR(32) NOT NULL COMMENT '真实姓名',
`telphone` VARCHAR(32) NOT NULL COMMENT '手机号',
`sex` TINYINT(6) NOT NULL DEFAULT 0 COMMENT '性别 0-未知, 1-男, 2-女',
`avatar_url` VARCHAR(128) COMMENT '头像地址',
`user_no` VARCHAR(32) COMMENT '员工编号',
`is_admin` TINYINT(6) NOT NULL DEFAULT 0 COMMENT '是否超管(超管拥有全部权限) 0-否 1-是',
`state` TINYINT(6) NOT NULL DEFAULT 0 COMMENT '状态 0-停用 1-启用',
`system` VARCHAR(8) NOT NULL COMMENT '所属系统: MGR-运营平台, MCH-商户中心',
`belong_info_id` VARCHAR(64) NOT NULL DEFAULT '0' COMMENT '所属商户ID / 0(平台)',
`created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
PRIMARY KEY (`sys_user_id`),
UNIQUE KEY(`system`,`login_username`),
UNIQUE KEY(`system`,`telphone`),
UNIQUE KEY(`system`, `user_no`)
) ENGINE=InnoDB AUTO_INCREMENT=100001 DEFAULT CHARSET=utf8mb4 COMMENT='系统用户表';
-- 系统用户认证表
DROP TABLE IF EXISTS `t_sys_user_auth`;
CREATE TABLE `t_sys_user_auth` (
`auth_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`user_id` BIGINT(20) NOT NULL COMMENT 'user_id',
`identity_type` TINYINT(6) NOT NULL DEFAULT '0' COMMENT '登录类型 1-登录账号 2-手机号 3-邮箱 10-微信 11-QQ 12-支付宝 13-微博',
`identifier` VARCHAR(128) NOT NULL COMMENT '认证标识 ( 用户名 | open_id )',
`credential` VARCHAR(128) NOT NULL COMMENT '密码凭证',
`salt` VARCHAR(128) NOT NULL COMMENT 'salt',
`system` VARCHAR(8) NOT NULL COMMENT '所属系统: MGR-运营平台, MCH-商户中心',
PRIMARY KEY (`auth_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8mb4 COMMENT='系统用户认证表';
-- 操作员<->角色 关联表
DROP TABLE IF EXISTS `t_sys_user_role_rela`;
CREATE TABLE `t_sys_user_role_rela` (
`user_id` BIGINT(20) NOT NULL COMMENT '用户ID',
`role_id`VARCHAR(32) NOT NULL COMMENT '角色ID',
PRIMARY KEY (`user_id`, `role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='操作员<->角色 关联表';
-- 系统配置表
DROP TABLE IF EXISTS `t_sys_config`;
CREATE TABLE `t_sys_config` (
`config_key` VARCHAR(50) NOT NULL COMMENT '配置KEY',
`config_name` VARCHAR(50) NOT NULL COMMENT '配置名称',
`config_desc` VARCHAR(200) NOT NULL COMMENT '描述信息',
`group_key` VARCHAR(50) NOT NULL COMMENT '分组key',
`group_name` VARCHAR(50) NOT NULL COMMENT '分组名称',
`config_val` TEXT NOT NULL COMMENT '配置内容项',
`type` VARCHAR(20) NOT NULL DEFAULT 'text' COMMENT '类型: text-输入框, textarea-多行文本, uploadImg-上传图片, switch-开关',
`sort_num` BIGINT(20) NOT NULL DEFAULT 0 COMMENT '显示顺序',
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
PRIMARY KEY (`config_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统配置表';
-- 系统操作日志表
DROP TABLE IF EXISTS `t_sys_log`;
CREATE TABLE `t_sys_log` (
`sys_log_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`user_id` bigint(20) DEFAULT NULL COMMENT '系统用户ID',
`user_name` varchar(32) DEFAULT NULL COMMENT '用户姓名',
`user_ip` varchar(128) NOT NULL DEFAULT '' COMMENT '用户IP',
`system` varchar(8) NOT NULL COMMENT '所属系统: MGR-运营平台, MCH-商户中心',
`method_name` varchar(128) NOT NULL DEFAULT '' COMMENT '方法名',
`method_remark` varchar(128) NOT NULL DEFAULT '' COMMENT '方法描述',
`req_url` varchar(256) NOT NULL DEFAULT '' COMMENT '请求地址',
`opt_req_param` varchar(2048) NOT NULL DEFAULT '' COMMENT '操作请求参数',
`opt_res_info` varchar(2048) NOT NULL DEFAULT '' COMMENT '操作响应结果',
`created_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
PRIMARY KEY (`sys_log_id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4 COMMENT = '系统操作日志表';
-- 1.商户信息表
DROP TABLE IF EXISTS t_mch_info;
CREATE TABLE `t_mch_info` (
`mch_no` VARCHAR(64) NOT NULL COMMENT '商户号',
`mch_name` VARCHAR(64) NOT NULL COMMENT '商户名称',
`mch_short_name` VARCHAR(32) NOT NULL COMMENT '商户简称',
`type` TINYINT(6) NOT NULL DEFAULT 1 COMMENT '类型: 1-普通商户, 2-特约商户(服务商模式)',
`isv_no` VARCHAR(64) COMMENT '服务商号',
`contact_name` VARCHAR(32) COMMENT '联系人姓名',
`contact_tel` VARCHAR(32) COMMENT '联系人手机号',
`contact_email` VARCHAR(32) COMMENT '联系人邮箱',
`private_key` VARCHAR(128) COMMENT '私钥',
`state` TINYINT(6) NOT NULL DEFAULT 1 COMMENT '商户状态: 0-停用, 1-正常',
`remark` VARCHAR(128) COMMENT '商户备注',
`init_user_id` BIGINT(20) DEFAULT NULL COMMENT '初始用户ID创建商户时允许商户登录的用户',
`created_uid` BIGINT(20) COMMENT '创建者用户ID',
`created_by` VARCHAR(64) COMMENT '创建者姓名',
`created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
PRIMARY KEY (`mch_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商户信息表';
-- 2.服务商信息表
DROP TABLE IF EXISTS t_isv_info;
CREATE TABLE `t_isv_info` (
`isv_no` VARCHAR(64) NOT NULL COMMENT '服务商号',
`isv_name` VARCHAR(64) NOT NULL COMMENT '服务商名称',
`isv_short_name` VARCHAR(32) NOT NULL COMMENT '服务商简称',
`contact_name` VARCHAR(32) COMMENT '联系人姓名',
`contact_tel` VARCHAR(32) COMMENT '联系人手机号',
`contact_email` VARCHAR(32) COMMENT '联系人邮箱',
`state` TINYINT(6) NOT NULL DEFAULT 1 COMMENT '状态: 0-停用, 1-正常',
`remark` VARCHAR(128) DEFAULT NULL COMMENT '备注',
`created_uid` BIGINT(20) COMMENT '创建者用户ID',
`created_by` VARCHAR(64) COMMENT '创建者姓名',
`created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
PRIMARY KEY (`isv_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='服务商信息表';
-- 3.支付方式表 pay_way
DROP TABLE IF EXISTS t_pay_way;
CREATE TABLE `t_pay_way` (
`way_code` VARCHAR(20) NOT NULL COMMENT '支付方式代码 例如: wxpay_jsapi',
`way_name` VARCHAR(20) NOT NULL COMMENT '支付方式名称',
`created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
PRIMARY KEY (`way_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支付方式表';
-- 4.支付接口定义表
DROP TABLE IF EXISTS t_pay_interface_define;
CREATE TABLE `t_pay_interface_define` (
`if_code` VARCHAR(20) NOT NULL COMMENT '接口代码 全小写 wxpay alipay ',
`if_name` VARCHAR(20) NOT NULL COMMENT '接口名称',
`is_mch_mode` TINYINT(6) NOT NULL DEFAULT 1 COMMENT '是否支持普通商户模式: 0-不支持, 1-支持',
`is_isv_mode` TINYINT(6) NOT NULL DEFAULT 1 COMMENT '是否支持服务商子商户模式: 0-不支持, 1-支持',
`isv_params` VARCHAR(4096) DEFAULT NULL COMMENT 'ISV接口配置定义描述,json字符串',
`isvsub_mch_params` VARCHAR(4096) DEFAULT NULL COMMENT '特约商户接口配置定义描述,json字符串',
`normal_mch_params` VARCHAR(4096) DEFAULT NULL COMMENT '普通商户接口配置定义描述,json字符串',
`way_codes` JSON NOT NULL COMMENT '支持的支付方式 ["wxpay_jsapi", "wxpay_bar"]',
`icon` VARCHAR(256) DEFAULT NULL COMMENT '页面展示:卡片-图标',
`bg_color` VARCHAR(20) DEFAULT NULL COMMENT '页面展示:卡片-背景色',
`state` TINYINT(6) NOT NULL DEFAULT 1 COMMENT '状态: 0-停用, 1-启用',
`remark` VARCHAR(128) DEFAULT NULL COMMENT '备注',
`created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
PRIMARY KEY (`if_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支付接口定义表';
-- 5.支付接口配置参数表
DROP TABLE IF EXISTS t_pay_interface_config;
CREATE TABLE `t_pay_interface_config` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`info_type` TINYINT(6) NOT NULL COMMENT '账号类型:1-服务商 2-商户',
`info_id` VARCHAR(64) NOT NULL COMMENT '服务商或商户No',
`if_code` VARCHAR(20) NOT NULL COMMENT '支付接口代码',
`if_params` VARCHAR(4096) NOT NULL COMMENT '接口配置参数,json字符串',
`if_rate` DECIMAL(20,6) DEFAULT NULL COMMENT '支付接口费率',
`state` TINYINT(6) NOT NULL default 1 COMMENT '状态: 0-停用, 1-启用',
`remark` VARCHAR(128) DEFAULT NULL COMMENT '备注',
`created_uid` BIGINT(20) COMMENT '创建者用户ID',
`created_by` VARCHAR(64) COMMENT '创建者姓名',
`created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
`updated_uid` BIGINT(20) COMMENT '更新者用户ID',
`updated_by` VARCHAR(64) COMMENT '更新者姓名',
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `Uni_InfoType_InfoId_IfCode` (`info_type`, `info_id`, `if_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支付接口配置参数表';
-- 6.商户支付通道表 (允许商户 支付方式 对应多个支付接口的配置)
DROP TABLE IF EXISTS t_mch_pay_passage;
CREATE TABLE `t_mch_pay_passage` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`mch_no` VARCHAR(64) NOT NULL COMMENT '商户号',
`if_code` VARCHAR(20) NOT NULL COMMENT '支付接口',
`way_code` VARCHAR(20) NOT NULL COMMENT '支付方式',
`rate` DECIMAL(20,6) NOT NULL COMMENT '支付方式费率',
`risk_config` JSON DEFAULT NULL COMMENT '风控数据',
`state` TINYINT(6) NOT NULL COMMENT '状态: 0-停用, 1-启用',
`created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `Uni_MchNo_WayCode` (`mch_no`,`if_code`, `way_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商户支付通道表';
-- 轮询表
-- mch_no, way_code, 轮询策略。
-- 7.支付订单表
DROP TABLE IF EXISTS t_pay_order;
CREATE TABLE `t_pay_order` (
`pay_order_id` VARCHAR(30) NOT NULL COMMENT '支付订单号',
`mch_no` VARCHAR(64) NOT NULL COMMENT '商户号',
`isv_no` VARCHAR(64) DEFAULT NULL COMMENT '服务商号',
`mch_name` VARCHAR(30) NOT NULL COMMENT '商户名称',
`mch_type` TINYINT(6) NOT NULL COMMENT '类型: 1-普通商户, 2-特约商户(服务商模式)',
`mch_order_no` VARCHAR(64) NOT NULL COMMENT '商户订单号',
`if_code` VARCHAR(20) COMMENT '支付接口代码',
`way_code` VARCHAR(20) NOT NULL COMMENT '支付方式代码',
`amount` BIGINT(20) NOT NULL COMMENT '支付金额,单位分',
`currency` VARCHAR(3) NOT NULL DEFAULT 'cny' COMMENT '三位货币代码,人民币:cny',
`state` TINYINT(6) NOT NULL DEFAULT '0' COMMENT '支付状态: 0-订单生成, 1-支付中, 2-支付成功, 3-支付失败, 4-已撤销, 5-已退款, 6-订单关闭',
`notify_state` TINYINT(6) NOT NULL DEFAULT '0' COMMENT '向下游回调状态, 0-未发送, 1-已发送',
`client_ip` VARCHAR(32) DEFAULT NULL COMMENT '客户端IP',
`subject` VARCHAR(64) NOT NULL COMMENT '商品标题',
`body` VARCHAR(256) NOT NULL COMMENT '商品描述信息',
`channel_extra` VARCHAR(512) DEFAULT NULL COMMENT '特定渠道发起额外参数',
`channel_user` VARCHAR(64) DEFAULT NULL COMMENT '渠道用户标识,如微信openId,支付宝账号',
`channel_order_no` VARCHAR(64) DEFAULT NULL COMMENT '渠道订单号',
`refund_times` INT NOT NULL DEFAULT 0 COMMENT '退款次数',
`refund_amount` BIGINT(20) NOT NULL DEFAULT 0 COMMENT '退款总金额,单位分',
`division_flag` TINYINT(6) DEFAULT 0 COMMENT '订单分账标志0-否 1-是',
`division_time` DATETIME COMMENT '预计分账发起时间',
`err_code` VARCHAR(64) DEFAULT NULL COMMENT '渠道支付错误码',
`err_msg` VARCHAR(128) DEFAULT NULL COMMENT '渠道支付错误描述',
`ext_param` VARCHAR(128) DEFAULT NULL COMMENT '商户扩展参数',
`notify_url` VARCHAR(128) NOT NULL default '' COMMENT '异步通知地址',
`return_url` VARCHAR(128) DEFAULT '' COMMENT '页面跳转地址',
`expired_time` DATETIME DEFAULT NULL COMMENT '订单失效时间',
`success_time` DATETIME DEFAULT NULL COMMENT '订单支付成功时间',
`created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
PRIMARY KEY (`pay_order_id`),
UNIQUE KEY `Uni_MchNo_MchOrderNo` (`mch_no`, `mch_order_no`),
INDEX(`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支付订单表';
-- 8.商户通知记录表
DROP TABLE IF EXISTS t_mch_notify_record;
CREATE TABLE `t_mch_notify_record` (
`notify_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '商户通知记录ID',
`order_id` VARCHAR(64) NOT NULL COMMENT '订单ID',
`order_type` TINYINT(6) NOT NULL COMMENT '订单类型:1-支付,2-退款',
`mch_order_no` VARCHAR(64) NOT NULL COMMENT '商户订单号',
`mch_no` VARCHAR(64) NOT NULL COMMENT '商户号',
`isv_no` VARCHAR(64) COMMENT '服务商号',
`notify_url` TEXT NOT NULL COMMENT '通知地址',
`res_result` TEXT DEFAULT NULL COMMENT '通知响应结果',
`notify_count` INT(11) NOT NULL DEFAULT '0' COMMENT '通知次数',
`state` TINYINT(6) NOT NULL DEFAULT '1' COMMENT '通知状态,1-通知中,2-通知成功,3-通知失败',
`last_notify_time` DATETIME DEFAULT NULL COMMENT '最后一次通知时间',
`created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
PRIMARY KEY (`notify_id`),
UNIQUE KEY `Uni_OrderId_Type` (`order_id`, `order_type`)
) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8mb4 COMMENT='商户通知记录表';
-- 9.订单接口数据快照(加密存储)
DROP TABLE IF EXISTS `t_order_snapshot`;
CREATE TABLE `t_order_snapshot` (
`order_id` VARCHAR(64) NOT NULL COMMENT '订单ID',
`order_type` TINYINT(6) NOT NULL COMMENT '订单类型: 1-支付, 2-退款',
`mch_req_data` TEXT DEFAULT NULL COMMENT '下游请求数据',
`mch_req_time` DATETIME DEFAULT NULL COMMENT '下游请求时间',
`mch_resp_data` TEXT DEFAULT NULL COMMENT '向下游响应数据',
`mch_resp_time` DATETIME DEFAULT NULL COMMENT '向下游响应时间',
`channel_req_data` TEXT DEFAULT NULL COMMENT '向上游请求数据',
`channel_req_time` DATETIME DEFAULT NULL COMMENT '向上游请求时间',
`channel_resp_data` TEXT DEFAULT NULL COMMENT '上游响应数据',
`channel_resp_time` DATETIME DEFAULT NULL COMMENT '上游响应时间',
`created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
PRIMARY KEY (`order_id`, `order_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单接口数据快照';
-- 10.退款订单表
DROP TABLE IF EXISTS t_refund_order;
CREATE TABLE `t_refund_order` (
`refund_order_id` VARCHAR(30) NOT NULL COMMENT '退款订单号',
`pay_order_id` VARCHAR(30) NOT NULL COMMENT '支付订单号',
`channel_pay_order_no` VARCHAR(64) DEFAULT NULL COMMENT '渠道支付单号',
`mch_no` VARCHAR(64) NOT NULL COMMENT '商户号',
`mch_type` TINYINT(6) NOT NULL COMMENT '类型: 1-普通商户, 2-特约商户(服务商模式)',
`mch_refund_no` VARCHAR(64) NOT NULL COMMENT '商户退款单号',
`isv_no` VARCHAR(64) DEFAULT NULL COMMENT '服务商号',
`way_code` VARCHAR(20) NOT NULL COMMENT '支付方式代码',
`if_code` VARCHAR(20) NOT NULL COMMENT '支付接口代码',
`pay_amount` BIGINT(20) NOT NULL COMMENT '支付金额,单位分',
`refund_amount` BIGINT(20) NOT NULL COMMENT '退款金额,单位分',
`currency` VARCHAR(3) NOT NULL DEFAULT 'cny' COMMENT '三位货币代码,人民币:cny',
`state` TINYINT(6) NOT NULL DEFAULT '0' COMMENT '退款状态:0-订单生成,1-退款中,2-退款成功,3-退款失败',
`result` TINYINT(6) NOT NULL DEFAULT '0' COMMENT '退款结果:0-不确认结果,1-等待手动处理,2-确认成功,3-确认失败',
`client_ip` VARCHAR(32) DEFAULT NULL COMMENT '客户端IP',
`remark` VARCHAR(256) DEFAULT NULL COMMENT '备注',
`channel_order_no` VARCHAR(32) DEFAULT NULL COMMENT '渠道订单号',
`channel_err_code` VARCHAR(128) DEFAULT NULL COMMENT '渠道错误码',
`channel_err_msg` VARCHAR(128) DEFAULT NULL COMMENT '渠道错误描述',
`channel_extra` VARCHAR(512) DEFAULT NULL COMMENT '特定渠道发起时额外参数',
`notify_url` VARCHAR(128) DEFAULT NULL COMMENT '通知地址',
`ext_param` VARCHAR(64) DEFAULT NULL COMMENT '扩展参数',
`success_time` DATETIME DEFAULT NULL COMMENT '订单退款成功时间',
`created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
`updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
PRIMARY KEY (`refund_order_id`),
UNIQUE KEY `Uni_MchNo_MchRefundNo` (`mch_no`, `mch_refund_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='退款订单表';
##### ↑↑↑↑↑↑↑↑↑↑ 表结构DDL ↑↑↑↑↑↑↑↑↑↑ #####
##### ↓↓↓↓↓↓↓↓↓↓ 初始化DML ↓↓↓↓↓↓↓↓↓↓ #####
-- 权限表数据 不包含根目录
insert into t_sys_entitlement values('ENT_COMMONS', '系统通用菜单', 'no-icon', '', 'RouteView', 'MO', 0, 1, 'ROOT', '-1', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_C_USERINFO', '个人中心', 'no-icon', '/current/userinfo', 'CurrentUserInfo', 'MO', 0, 1, 'ENT_COMMONS', '-1', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_C_MAIN', '主页', 'home', '/main', 'MainPage', 'ML', 0, 1, 'ROOT', '1', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_C_MAIN_PAY_AMOUNT_WEEK', '主页周支付统计', 'no-icon', '', '', 'PB', 0, 1, 'ENT_C_MAIN', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_C_MAIN_NUMBER_COUNT', '主页数量总统计', 'no-icon', '', '', 'PB', 0, 1, 'ENT_C_MAIN', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_C_MAIN_PAY_COUNT', '主页交易统计', 'no-icon', '', '', 'PB', 0, 1, 'ENT_C_MAIN', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_C_MAIN_PAY_TYPE_COUNT', '主页交易方式统计', 'no-icon', '', '', 'PB', 0, 1, 'ENT_C_MAIN', '0', 'MGR', now(), now());
-- 商户管理
insert into t_sys_entitlement values('ENT_MCH_INFO', '商户管理', 'shop', '', 'RouteView', 'ML', 0, 1, 'ROOT', '30', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_MCH_INFO_LIST', '商户列表', 'profile', '/mch', 'MchListPage', 'ML', 0, 1, 'ENT_MCH_INFO', '10', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_MCH_INFO_ADD', '按钮:新增', 'no-icon', '', '', 'PB', 0, 1, 'ENT_MCH_INFO_LIST', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_MCH_INFO_EDIT', '按钮:编辑', 'no-icon', '', '', 'PB', 0, 1, 'ENT_MCH_INFO_LIST', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_MCH_INFO_VIEW', '按钮:详情', 'no-icon', '', '', 'PB', 0, 1, 'ENT_MCH_INFO_LIST', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_MCH_INFO_DEL', '按钮:删除', 'no-icon', '', '', 'PB', 0, 1, 'ENT_MCH_INFO_LIST', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_MCH_PAY_CONFIG_LIST', '商户支付参数配置列表', 'no-icon', '', '', 'PB', 0, 1, 'ENT_MCH_INFO_LIST', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_MCH_PAY_CONFIG_ADD', '商户支付参数配置', 'no-icon', '', '', 'PB', 0, 1, 'ENT_MCH_PAY_CONFIG_LIST', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_MCH_PAY_CONFIG_VIEW', '商户支付参数配置详情', 'no-icon', '', '', 'PB', 0, 1, 'ENT_MCH_PAY_CONFIG_LIST', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_MCH_PAY_PASSAGE_LIST', '商户支付通道配置列表', 'no-icon', '', '', 'PB', 0, 1, 'ENT_MCH_INFO_LIST', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_MCH_PAY_PASSAGE_CONFIG', '商户支付通道配置入口', 'no-icon', '', '', 'PB', 0, 1, 'ENT_MCH_PAY_PASSAGE_LIST', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_MCH_PAY_PASSAGE_ADD', '商户支付通道配置保存', 'no-icon', '', '', 'PB', 0, 1, 'ENT_MCH_PAY_PASSAGE_LIST', '0', 'MGR', now(), now());
-- 服务商管理
insert into t_sys_entitlement values('ENT_ISV_INFO', '服务商管理', 'block', '', 'RouteView', 'ML', 0, 1, 'ROOT', '40', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_ISV_INFO_LIST', '服务商列表', 'profile', '/isv', 'IsvListPage', 'ML', 0, 1, 'ENT_ISV_INFO', '10', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_ISV_INFO_ADD', '按钮:新增', 'no-icon', '', '', 'PB', 0, 1, 'ENT_ISV_INFO_LIST', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_ISV_INFO_EDIT', '按钮:编辑', 'no-icon', '', '', 'PB', 0, 1, 'ENT_ISV_INFO_LIST', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_ISV_INFO_VIEW', '按钮:详情', 'no-icon', '', '', 'PB', 0, 1, 'ENT_ISV_INFO_LIST', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_ISV_INFO_DEL', '按钮:删除', 'no-icon', '', '', 'PB', 0, 1, 'ENT_ISV_INFO_LIST', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_ISV_PAY_CONFIG_LIST', '服务商支付参数配置列表', 'no-icon', '', '', 'PB', 0, 1, 'ENT_ISV_INFO_LIST', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_ISV_PAY_CONFIG_ADD', '服务商支付参数配置', 'no-icon', '', '', 'PB', 0, 1, 'ENT_ISV_PAY_CONFIG_LIST', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_ISV_PAY_CONFIG_VIEW', '服务商支付参数配置详情', 'no-icon', '', '', 'PB', 0, 1, 'ENT_ISV_PAY_CONFIG_LIST', '0', 'MGR', now(), now());
-- 订单管理
insert into t_sys_entitlement values('ENT_ORDER', '订单管理', 'transaction', '', 'RouteView', 'ML', 0, 1, 'ROOT', '50', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_PAY_ORDER_LIST', '支付订单', 'account-book', '/pay', 'PayOrderListPage', 'ML', 0, 1, 'ENT_ORDER', '10', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_PAY_ORDER_VIEW', '按钮:详情', 'no-icon', '', '', 'PB', 0, 1, 'ENT_PAY_ORDER_LIST', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_REFUND_ORDER_LIST', '退款订单', 'exception', '/refund', 'RefundOrderListPage', 'ML', 0, 1, 'ENT_ORDER', '20', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_REFUND_ORDER_VIEW', '按钮:详情', 'no-icon', '', '', 'PB', 0, 1, 'ENT_REFUND_ORDER_LIST', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_MCH_NOTIFY_LIST', '商户通知', 'notification', '/notify', 'MchNotifyListPage', 'ML', 0, 1, 'ENT_ORDER', '30', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_MCH_NOTIFY_VIEW', '按钮:详情', 'no-icon', '', '', 'PB', 0, 1, 'ENT_MCH_NOTIFY_LIST', '0', 'MGR', now(), now());
-- 支付配置菜单
insert into t_sys_entitlement values('ENT_PC', '支付配置', 'file-done', '', 'RouteView', 'ML', 0, 1, 'ROOT', '60', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_PC_IF_DEFINE', '支付接口', 'interaction', '/ifdefines', 'IfDefinePage', 'ML', 0, 1, 'ENT_PC', '10', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_PC_IF_DEFINE_LIST', '页面:支付接口定义列表', 'no-icon', '', '', 'PB', 0, 1, 'ENT_PC_IF_DEFINE', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_PC_IF_DEFINE_SEARCH', '页面:搜索', 'no-icon', '', '', 'PB', 0, 1, 'ENT_PC_IF_DEFINE', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_PC_IF_DEFINE_VIEW', '按钮:详情', 'no-icon', '', '', 'PB', 0, 1, 'ENT_PC_IF_DEFINE', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_PC_IF_DEFINE_ADD', '按钮:新增', 'no-icon', '', '', 'PB', 0, 1, 'ENT_PC_IF_DEFINE', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_PC_IF_DEFINE_EDIT', '按钮:修改', 'no-icon', '', '', 'PB', 0, 1, 'ENT_PC_IF_DEFINE', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_PC_IF_DEFINE_DEL', '按钮:删除', 'no-icon', '', '', 'PB', 0, 1, 'ENT_PC_IF_DEFINE', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_PC_WAY', '支付方式', 'appstore', '/payways', 'PayWayPage', 'ML', 0, 1, 'ENT_PC', '20', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_PC_WAY_LIST', '页面:支付方式列表', 'no-icon', '', '', 'PB', 0, 1, 'ENT_PC_WAY', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_PC_WAY_SEARCH', '页面:搜索', 'no-icon', '', '', 'PB', 0, 1, 'ENT_PC_WAY', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_PC_WAY_VIEW', '按钮:详情', 'no-icon', '', '', 'PB', 0, 1, 'ENT_PC_WAY', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_PC_WAY_ADD', '按钮:新增', 'no-icon', '', '', 'PB', 0, 1, 'ENT_PC_WAY', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_PC_WAY_EDIT', '按钮:修改', 'no-icon', '', '', 'PB', 0, 1, 'ENT_PC_WAY', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_PC_WAY_DEL', '按钮:删除', 'no-icon', '', '', 'PB', 0, 1, 'ENT_PC_WAY', '0', 'MGR', now(), now());
-- 系统管理
insert into t_sys_entitlement values('ENT_SYS_CONFIG', '系统管理', 'setting', '', 'RouteView', 'ML', 0, 1, 'ROOT', '200', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_UR', '用户角色管理', 'team', '', 'RouteView', 'ML', 0, 1, 'ENT_SYS_CONFIG', '10', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_UR_USER', '操作员管理', 'contacts', '/users', 'SysUserPage', 'ML', 0, 1, 'ENT_UR', '10', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_UR_USER_LIST', '页面:操作员列表', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_USER', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_UR_USER_SEARCH', '按钮:搜索', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_USER', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_UR_USER_ADD', '按钮:添加操作员', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_USER', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_UR_USER_VIEW', '按钮: 详情', '', 'no-icon', '', 'PB', 0, 1, 'ENT_UR_USER', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_UR_USER_EDIT', '按钮: 修改基本信息', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_USER', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_UR_USER_UPD_ROLE', '按钮: 角色分配', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_USER', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_UR_ROLE', '角色管理', 'user', '/roles', 'RolePage', 'ML', 0, 1, 'ENT_UR', '20', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_UR_ROLE_LIST', '页面:角色列表', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_ROLE', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_UR_ROLE_SEARCH', '页面:搜索', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_ROLE', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_UR_ROLE_ADD', '按钮:添加角色', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_ROLE', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_UR_ROLE_DIST', '按钮: 分配权限', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_ROLE', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_UR_ROLE_EDIT', '按钮: 修改基本信息', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_ROLE', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_UR_ROLE_DEL', '按钮: 删除', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_ROLE', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_UR_ROLE_ENT', '权限管理', 'apartment', '/ents', 'EntPage', 'ML', 0, 1, 'ENT_UR', '30', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_UR_ROLE_ENT_LIST', '页面: 权限列表', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_ROLE_ENT', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_UR_ROLE_ENT_EDIT', '按钮: 权限变更', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_ROLE_ENT', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_SYS_CONFIG_INFO', '系统配置', 'setting', '/config', 'SysConfigPage', 'ML', 0, 1, 'ENT_SYS_CONFIG', '15', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_SYS_CONFIG_EDIT', '按钮: 修改', 'no-icon', '', '', 'PB', 0, 1, 'ENT_SYS_CONFIG_INFO', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_SYS_LOG_LIST', '系统日志', 'file-text', '/log', 'SysLogPage', 'ML', 0, 1, 'ENT_SYS_CONFIG', '20', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_SYS_LOG_VIEW', '按钮:详情', 'no-icon', '', '', 'PB', 0, 1, 'ENT_SYS_LOG_LIST', '0', 'MGR', now(), now());
insert into t_sys_entitlement values('ENT_SYS_LOG_DEL', '按钮:删除', 'no-icon', '', '', 'PB', 0, 1, 'ENT_SYS_LOG_LIST', '0', 'MGR', now(), now());
-- 【商户系统】 主页
insert into t_sys_entitlement values('ENT_COMMONS', '系统通用菜单', 'no-icon', '', 'RouteView', 'MO', 0, 1, 'ROOT', '-1', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_C_USERINFO', '个人中心', 'no-icon', '/current/userinfo', 'CurrentUserInfo', 'MO', 0, 1, 'ENT_COMMONS', '-1', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_MCH_MAIN', '主页', 'home', '/main', 'MainPage', 'ML', 0, 1, 'ROOT', '1', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_MCH_MAIN_PAY_AMOUNT_WEEK', '主页周支付统计', 'no-icon', '', '', 'PB', 0, 1, 'ENT_MCH_MAIN', '0', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_MCH_MAIN_NUMBER_COUNT', '主页数量总统计', 'no-icon', '', '', 'PB', 0, 1, 'ENT_MCH_MAIN', '0', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_MCH_MAIN_PAY_COUNT', '主页交易统计', 'no-icon', '', '', 'PB', 0, 1, 'ENT_MCH_MAIN', '0', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_MCH_MAIN_PAY_TYPE_COUNT', '主页交易方式统计', 'no-icon', '', '', 'PB', 0, 1, 'ENT_MCH_MAIN', '0', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_MCH_MAIN_USER_INFO', '主页用户信息', 'no-icon', '', '', 'PB', 0, 1, 'ENT_MCH_MAIN', '0', 'MCH', now(), now());
-- 【商户系统】 商户中心
-- insert into t_sys_entitlement values('ENT_MCH_CENTER', '商户中心', 'team', '', 'RouteView', 'ML', 0, 'ROOT', '10', 'MCH', now(), now());
-- insert into t_sys_entitlement values('ENT_MCH_INFO', '商户信息', 'user', '/mch', 'MchInfoPage', 'ML', 0, 'ENT_MCH_CENTER', '10', 'MCH', now(), now());
-- insert into t_sys_entitlement values('ENT_MCH_INFO_EDIT', '按钮:修改商户信息', 'no-icon', '', '', 'PB', 0, 'ENT_MCH_INFO', '0', 'MCH', now(), now());
-- 【商户系统】 订单管理
insert into t_sys_entitlement values('ENT_ORDER', '订单中心', 'transaction', '', 'RouteView', 'ML', 0, 1, 'ROOT', '20', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_PAY_ORDER_LIST', '订单管理', 'account-book', '/pay', 'PayOrderListPage', 'ML', 0, 1, 'ENT_ORDER', '10', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_PAY_ORDER_VIEW', '按钮:详情', 'no-icon', '', '', 'PB', 0, 1, 'ENT_PAY_ORDER_LIST', '0', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_REFUND_ORDER_LIST', '退款记录', 'exception', '/refund', 'RefundOrderListPage', 'ML', 0, 1, 'ENT_ORDER', '20', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_REFUND_ORDER_VIEW', '按钮:详情', 'no-icon', '', '', 'PB', 0, 1, 'ENT_REFUND_ORDER_LIST', '0', 'MCH', now(), now());
-- 【商户系统】 支付配置
insert into t_sys_entitlement values('ENT_MCH_PC', '支付配置', 'file-done', '', 'RouteView', 'ML', 0, 1, 'ROOT', '30', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_MCH_PAY_CONFIG_LIST', '支付参数', 'interaction', '/pay/config', 'PayConfigPage', 'ML', 0, 1, 'ENT_MCH_PC', '10', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_MCH_PAY_CONFIG_ADD', '商户支付参数配置', 'no-icon', '', '', 'PB', 0, 1, 'ENT_MCH_PAY_CONFIG_LIST', '0', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_MCH_PAY_CONFIG_VIEW', '商户支付参数配置详情', 'no-icon', '', '', 'PB', 0, 1, 'ENT_MCH_PAY_CONFIG_LIST', '0', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_MCH_PAY_PASSAGE_LIST', '支付通道', 'appstore', '/pay/passage', 'PayPassagePage', 'ML', 0, 1, 'ENT_MCH_PC', '20', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_MCH_PAY_PASSAGE_CONFIG', '商户支付通道配置入口', 'no-icon', '', '', 'PB', 0, 1, 'ENT_MCH_PAY_PASSAGE_LIST', '0', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_MCH_PAY_PASSAGE_ADD', '商户支付通道配置保存', 'no-icon', '', '', 'PB', 0, 1, 'ENT_MCH_PAY_PASSAGE_LIST', '0', 'MCH', now(), now());
-- 【商户系统】 系统管理
insert into t_sys_entitlement values('ENT_SYS_CONFIG', '系统管理', 'setting', '', 'RouteView', 'ML', 0, 1, 'ROOT', '200', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_UR', '用户角色管理', 'team', '', 'RouteView', 'ML', 0, 1, 'ENT_SYS_CONFIG', '10', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_UR_USER', '操作员管理', 'contacts', '/users', 'SysUserPage', 'ML', 0, 1, 'ENT_UR', '10', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_UR_USER_LIST', '页面:操作员列表', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_USER', '0', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_UR_USER_SEARCH', '按钮:搜索', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_USER', '0', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_UR_USER_ADD', '按钮:添加操作员', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_USER', '0', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_UR_USER_VIEW', '按钮: 详情', '', 'no-icon', '', 'PB', 0, 1, 'ENT_UR_USER', '0', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_UR_USER_EDIT', '按钮: 修改基本信息', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_USER', '0', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_UR_USER_UPD_ROLE', '按钮: 角色分配', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_USER', '0', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_UR_ROLE', '角色管理', 'user', '/roles', 'RolePage', 'ML', 0, 1, 'ENT_UR', '20', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_UR_ROLE_LIST', '页面:角色列表', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_ROLE', '0', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_UR_ROLE_SEARCH', '页面:搜索', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_ROLE', '0', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_UR_ROLE_ADD', '按钮:添加角色', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_ROLE', '0', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_UR_ROLE_DIST', '按钮: 分配权限', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_ROLE', '0', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_UR_ROLE_EDIT', '按钮: 修改名称', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_ROLE', '0', 'MCH', now(), now());
insert into t_sys_entitlement values('ENT_UR_ROLE_DEL', '按钮: 删除', 'no-icon', '', '', 'PB', 0, 1, 'ENT_UR_ROLE', '0', 'MCH', now(), now());
-- 默认角色
insert into t_sys_role values ('ROLE_ADMIN', '系统管理员', 'MGR', '0', '2021-05-01');
insert into t_sys_role values ('ROLE_OP', '普通操作员', 'MGR', '0', '2021-05-01');
-- 角色权限关联, [超管]用户 拥有所有权限
-- insert into t_sys_role_ent_rela select '801', ent_id from t_sys_entitlement;
-- 超管用户: jeepay / jeepay123
insert into t_sys_user values (801, 'jeepay', '超管', '13000000001', '1', 'https://edu-system.oss-cn-beijing.aliyuncs.com/1/img/z/avatar_1.jpg', 'D0001', 1, 1, 'MGR', '0', '2020-06-13', '2020-06-13');
insert into t_sys_user_auth values (801, '801', '1', 'jeepay', '$2a$10$WKuPJKE1XhX15ibqDM745eOCaZZVUiRitUjEyX6zVNd9k.cQXfzGa', 'testkey', 'MGR');
-- insert into t_sys_user_role_rela values (801, 801);
INSERT INTO `t_sys_config` VALUES ('mgrSiteUrl', '运营平台网址(不包含结尾/)', '运营平台网址(不包含结尾/)', 'applicationConfig', '系统应用配置', 'http://127.0.0.1:9217', 'text', 0, '2021-5-18 14:46:10');
INSERT INTO `t_sys_config` VALUES ('mchSiteUrl', '商户平台网址(不包含结尾/)', '商户平台网址(不包含结尾/)', 'applicationConfig', '系统应用配置', 'http://127.0.0.1:9218', 'text', 0, '2021-5-18 14:46:10');
INSERT INTO `t_sys_config` VALUES ('paySiteUrl', '支付网关地址(不包含结尾/)', '支付网关地址(不包含结尾/)', 'applicationConfig', '系统应用配置', 'http://127.0.0.1:9216', 'text', 0, '2021-5-18 14:46:10');
INSERT INTO `t_sys_config` VALUES ('ossPublicSiteUrl', '公共oss访问地址(不包含结尾/)', '公共oss访问地址(不包含结尾/)', 'applicationConfig', '系统应用配置', 'http://127.0.0.1:9217/api/anon/localOssFiles', 'text', 0, '2021-5-18 14:46:10');
-- 初始化支付方式
INSERT INTO t_pay_way (way_code, way_name) VALUES ('ALI_BAR', '支付宝条码');
INSERT INTO t_pay_way (way_code, way_name) VALUES ('ALI_JSAPI', '支付宝生活号');
INSERT INTO t_pay_way (way_code, way_name) VALUES ('ALI_APP', '支付宝APP');
INSERT INTO t_pay_way (way_code, way_name) VALUES ('ALI_WAP', '支付宝WAP');
INSERT INTO t_pay_way (way_code, way_name) VALUES ('ALI_PC', '支付宝PC网站');
INSERT INTO t_pay_way (way_code, way_name) VALUES ('ALI_QR', '支付宝二维码');
INSERT INTO t_pay_way (way_code, way_name) VALUES ('WX_BAR', '微信条码');
INSERT INTO t_pay_way (way_code, way_name) VALUES ('WX_JSAPI', '微信公众号');
INSERT INTO t_pay_way (way_code, way_name) VALUES ('WX_APP', '微信APP');
INSERT INTO t_pay_way (way_code, way_name) VALUES ('WX_H5', '微信H5');
INSERT INTO t_pay_way (way_code, way_name) VALUES ('WX_NATIVE', '微信扫码');
INSERT INTO t_pay_way (way_code, way_name) VALUES ('WX_LITE', '微信小程序');
INSERT INTO t_pay_way (way_code, way_name) VALUES ('YSF_BAR', '云闪付条码');
INSERT INTO t_pay_way (way_code, way_name) VALUES ('YSF_JSAPI', '云闪付jsapi');
-- 初始化支付接口定义
INSERT INTO t_pay_interface_define (if_code, if_name, is_mch_mode, is_isv_mode, isv_params, isvsub_mch_params, normal_mch_params, way_codes, icon, bg_color, state, remark)
VALUES ('alipay', '支付宝官方', 1, 1,
'[{"name":"sandbox","desc":"环境配置","type":"radio","verify":"","values":"1,0","titles":"沙箱环境,生产环境","verify":"required"},{"name":"pid","desc":"合作伙伴身份PID","type":"text","verify":"required"},{"name":"appId","desc":"应用App ID","type":"text","verify":"required"},{"name":"privateKey", "desc":"应用私钥", "type": "textarea","verify":"required"},{"name":"alipayPublicKey", "desc":"支付宝公钥(不使用证书时必填)", "type": "textarea"},{"name":"signType","desc":"接口签名方式(推荐使用RSA2)","type":"radio","verify":"","values":"RSA,RSA2","titles":"RSA,RSA2","verify":"required"},{"name":"useCert","desc":"公钥证书","type":"radio","verify":"","values":"1,0","titles":"使用证书请使用RSA2私钥,不使用证书"},{"name":"appPublicCert","desc":"应用公钥证书(.crt格式","type":"file","verify":""},{"name":"alipayPublicCert","desc":"支付宝公钥证书(.crt格式","type":"file","verify":""},{"name":"alipayRootCert","desc":"支付宝根证书(.crt格式","type":"file","verify":""}]',
'[{"name":"appAuthToken", "desc":"子商户app_auth_token", "type": "text","readonly":"readonly"},{"name":"refreshToken", "desc":"子商户刷新token", "type": "hidden","readonly":"readonly"},{"name":"expireTimestamp", "desc":"authToken有效期13位时间戳", "type": "hidden","readonly":"readonly"}]',
'[{"name":"sandbox","desc":"环境配置","type":"radio","verify":"","values":"1,0","titles":"沙箱环境,生产环境","verify":"required"},{"name":"appId","desc":"应用App ID","type":"text","verify":"required"},{"name":"privateKey", "desc":"应用私钥", "type": "textarea","verify":"required"},{"name":"alipayPublicKey", "desc":"支付宝公钥(不使用证书时必填)", "type": "textarea"},{"name":"signType","desc":"接口签名方式(推荐使用RSA2)","type":"radio","verify":"","values":"RSA,RSA2","titles":"RSA,RSA2","verify":"required"},{"name":"useCert","desc":"公钥证书","type":"radio","verify":"","values":"1,0","titles":"使用证书请使用RSA2私钥,不使用证书"},{"name":"appPublicCert","desc":"应用公钥证书(.crt格式","type":"file","verify":""},{"name":"alipayPublicCert","desc":"支付宝公钥证书(.crt格式","type":"file","verify":""},{"name":"alipayRootCert","desc":"支付宝根证书(.crt格式","type":"file","verify":""}]',
'[{"wayCode": "ALI_JSAPI"}, {"wayCode": "ALI_WAP"}, {"wayCode": "ALI_BAR"}, {"wayCode": "ALI_APP"}, {"wayCode": "ALI_PC"}, {"wayCode": "ALI_QR"}]',
'http://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/alipay.png', '#1779FF', 1, '支付宝官方通道');
INSERT INTO t_pay_interface_define (if_code, if_name, is_mch_mode, is_isv_mode, isv_params, isvsub_mch_params, normal_mch_params, way_codes, icon, bg_color, state, remark)
VALUES ('wxpay', '微信支付官方', 1, 1,
'[{"name":"mchId", "desc":"微信支付商户号", "type": "text","verify":"required"},{"name":"appId","desc":"应用App ID","type":"text","verify":"required"},{"name":"appSecret","desc":"应用AppSecret","type":"text","verify":"required"},{"name":"oauth2Url", "desc":"oauth2地址置空将使用官方", "type": "text"},{"name":"key", "desc":"API密钥", "type": "textarea","verify":"required"},{"name":"apiVersion", "desc":"微信支付API版本", "type": "radio","values":"V2,V3","titles":"V2,V3","verify":"required"},{"name":"apiV3Key", "desc":"API V3秘钥V3接口必填", "type": "textarea","verify":""},{"name":"serialNo", "desc":"序列号V3接口必填", "type": "textarea","verify":""},{"name":"cert", "desc":"API证书(.p12格式)", "type": "file","verify":""},{"name":"apiClientKey", "desc":"私钥文件(.pem格式)", "type": "file","verify":""}]',
'[{"name":"subMchId","desc":"子商户ID","type":"text","verify":"required"},{"name":"subMchAppId","desc":"子账户appID(线上支付必填)","type":"text","verify":""}]',
'[{"name":"mchId", "desc":"微信支付商户号", "type": "text","verify":"required"},{"name":"appId","desc":"应用App ID","type":"text","verify":"required"},{"name":"appSecret","desc":"应用AppSecret","type":"text","verify":"required"},{"name":"oauth2Url", "desc":"oauth2地址置空将使用官方", "type": "text"},{"name":"key", "desc":"API密钥", "type": "textarea","verify":"required"},{"name":"apiVersion", "desc":"微信支付API版本", "type": "radio","values":"V2,V3","titles":"V2,V3","verify":"required"},{"name":"apiV3Key", "desc":"API V3秘钥V3接口必填", "type": "textarea","verify":""},{"name":"serialNo", "desc":"序列号V3接口必填", "type": "textarea","verify":""},{"name":"cert", "desc":"API证书(.p12格式)", "type": "file","verify":""},{"name":"apiClientKey", "desc":"私钥文件(.pem格式)", "type": "file","verify":""}]',
'[{"wayCode": "WX_APP"}, {"wayCode": "WX_H5"}, {"wayCode": "WX_NATIVE"}, {"wayCode": "WX_JSAPI"}, {"wayCode": "WX_BAR"}, {"wayCode": "WX_LITE"}]',
'http://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/wxpay.png', '#04BE02', 1, '微信官方通道');
INSERT INTO t_pay_interface_define (if_code, if_name, is_mch_mode, is_isv_mode, isv_params, isvsub_mch_params, normal_mch_params, way_codes, icon, bg_color, state, remark)
VALUES ('ysfpay', '云闪付官方', 0, 1,
'[{"name":"sandbox","desc":"环境配置","type":"radio","verify":"","values":"1,0","titles":"沙箱环境,生产环境","verify":"required"},{"name":"serProvId","desc":"服务商开发ID[serProvId]","type":"text","verify":"required"},{"name":"isvPrivateCertFile","desc":"服务商私钥文件(.pfx格式","type":"file","verify":"required"},{"name":"isvPrivateCertPwd","desc":"服务商私钥文件密码","type":"text","verify":"required"},{"name":"ysfpayPublicKey","desc":"云闪付开发公钥(证书管理页面可查询)","type":"textarea","verify":"required"},{"name":"acqOrgCode","desc":"可用支付机构编号","type":"text","verify":"required"}]',
'[{"name":"merId","desc":"商户编号","type":"text","verify":"required"}]',
NULL,
'[{"wayCode": "YSF_BAR"}, {"wayCode": "ALI_JSAPI"}, {"wayCode": "WX_JSAPI"}, {"wayCode": "ALI_BAR"}, {"wayCode": "WX_BAR"}]',
'http://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/ysfpay.png', 'red', 1, '云闪付官方通道');

View File

@ -1,169 +0,0 @@
/* 支付中心相关表结构 */
CREATE TABLE `t_mch_info` (
`MchId` varchar(30) NOT NULL COMMENT '商户ID',
`Name` varchar(30) NOT NULL COMMENT '名称',
`Type` varchar(24) NOT NULL COMMENT '类型',
`ReqKey` varchar(128) NOT NULL COMMENT '请求私钥',
`ResKey` varchar(128) NOT NULL COMMENT '响应私钥',
`State` tinyint(6) NOT NULL DEFAULT '1' COMMENT '商户状态,0-停止使用,1-使用中',
`CreateTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`MchId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商户信息表';
CREATE TABLE `t_pay_channel` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '渠道主键ID',
`ChannelId` varchar(24) NOT NULL COMMENT '渠道ID',
`ChannelName` varchar(30) NOT NULL COMMENT '渠道名称,如:alipay,wechat',
`ChannelMchId` varchar(32) NOT NULL COMMENT '渠道商户ID',
`MchId` varchar(30) NOT NULL COMMENT '商户ID',
`State` tinyint(6) NOT NULL DEFAULT '1' COMMENT '渠道状态,0-停止使用,1-使用中',
`Param` varchar(4096) NOT NULL COMMENT '配置参数,json字符串',
`Remark` varchar(128) DEFAULT NULL COMMENT '备注',
`CreateTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`ID`),
UNIQUE KEY `IDX_MchId_MchOrderNo` (`ChannelId`, `MchId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支付渠道表';
CREATE TABLE `t_pay_order` (
`PayOrderId` varchar(30) NOT NULL COMMENT '支付订单号',
`MchId` varchar(30) NOT NULL COMMENT '商户ID',
`MchOrderNo` varchar(30) NOT NULL COMMENT '商户订单号',
`ChannelId` varchar(24) NOT NULL COMMENT '渠道ID',
`Amount` bigint(20) NOT NULL COMMENT '支付金额,单位分',
`Currency` varchar(3) NOT NULL DEFAULT 'cny' COMMENT '三位货币代码,人民币:cny',
`Status` tinyint(6) NOT NULL DEFAULT '0' COMMENT '支付状态,0-订单生成,1-支付中(目前未使用),2-支付成功,3-业务处理完成',
`ClientIp` varchar(32) DEFAULT NULL COMMENT '客户端IP',
`Device` varchar(64) DEFAULT NULL COMMENT '设备',
`Subject` varchar(64) NOT NULL COMMENT '商品标题',
`Body` varchar(256) NOT NULL COMMENT '商品描述信息',
`Extra` varchar(512) DEFAULT NULL COMMENT '特定渠道发起时额外参数',
`ChannelMchId` varchar(32) NOT NULL COMMENT '渠道商户ID',
`ChannelOrderNo` varchar(64) DEFAULT NULL COMMENT '渠道订单号',
`ErrCode` varchar(64) DEFAULT NULL COMMENT '渠道支付错误码',
`ErrMsg` varchar(128) DEFAULT NULL COMMENT '渠道支付错误描述',
`Param1` varchar(64) DEFAULT NULL COMMENT '扩展参数1',
`Param2` varchar(64) DEFAULT NULL COMMENT '扩展参数2',
`NotifyUrl` varchar(128) NOT NULL COMMENT '通知地址',
`NotifyCount` tinyint(6) NOT NULL DEFAULT 0 COMMENT '通知次数',
`LastNotifyTime` bigint(20) DEFAULT NULL COMMENT '最后一次通知时间',
`ExpireTime` bigint(20) DEFAULT NULL COMMENT '订单失效时间',
`PaySuccTime` bigint(20) DEFAULT NULL COMMENT '订单支付成功时间',
`CreateTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`PayOrderId`),
UNIQUE KEY `IDX_MchId_MchOrderNo` (`MchId`, MchOrderNo)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支付订单表';
CREATE TABLE `t_iap_receipt` (
`PayOrderId` varchar(30) NOT NULL COMMENT '支付订单号',
`MchId` varchar(30) NOT NULL COMMENT '商户ID',
`TransactionId` varchar(24) NOT NULL COMMENT 'IAP业务号',
`ReceiptData` TEXT NOT NULL COMMENT '渠道ID',
`Status` tinyint(6) NOT NULL DEFAULT '0' COMMENT '处理状态:0-未处理,1-处理成功,-1-处理失败',
`HandleCount` tinyint(6) NOT NULL DEFAULT 0 COMMENT '处理次数',
`CreateTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`PayOrderId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='苹果支付凭据表';
CREATE TABLE `t_trans_order` (
`TransOrderId` varchar(30) NOT NULL COMMENT '转账订单号',
`MchId` varchar(30) NOT NULL COMMENT '商户ID',
`MchTransNo` varchar(30) NOT NULL COMMENT '商户转账单号',
`ChannelId` varchar(24) NOT NULL COMMENT '渠道ID',
`Amount` bigint(20) NOT NULL COMMENT '转账金额,单位分',
`Currency` varchar(3) NOT NULL DEFAULT 'cny' COMMENT '三位货币代码,人民币:cny',
`Status` tinyint(6) NOT NULL DEFAULT '0' COMMENT '转账状态:0-订单生成,1-转账中,2-转账成功,3-转账失败,4-业务处理完成',
`Result` tinyint(6) NOT NULL DEFAULT '0' COMMENT '转账结果:0-不确认结果,1-等待手动处理,2-确认成功,3-确认失败',
`ClientIp` varchar(32) DEFAULT NULL COMMENT '客户端IP',
`Device` varchar(64) DEFAULT NULL COMMENT '设备',
`RemarkInfo` varchar(256) DEFAULT NULL COMMENT '备注',
`ChannelUser` varchar(32) DEFAULT NULL COMMENT '渠道用户标识,如微信openId,支付宝账号',
`UserName` varchar(24) DEFAULT NULL COMMENT '用户姓名',
`ChannelMchId` varchar(32) NOT NULL COMMENT '渠道商户ID',
`ChannelOrderNo` varchar(32) DEFAULT NULL COMMENT '渠道订单号',
`ChannelErrCode` varchar(128) DEFAULT NULL COMMENT '渠道错误码',
`ChannelErrMsg` varchar(128) DEFAULT NULL COMMENT '渠道错误描述',
`Extra` varchar(512) DEFAULT NULL COMMENT '特定渠道发起时额外参数',
`NotifyUrl` varchar(128) NOT NULL COMMENT '通知地址',
`Param1` varchar(64) DEFAULT NULL COMMENT '扩展参数1',
`Param2` varchar(64) DEFAULT NULL COMMENT '扩展参数2',
`ExpireTime` datetime DEFAULT NULL COMMENT '订单失效时间',
`TransSuccTime` datetime DEFAULT NULL COMMENT '订单转账成功时间',
`CreateTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`TransOrderId`),
UNIQUE KEY `IDX_MchId_MchOrderNo` (`MchId`, MchTransNo)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='转账订单表';
CREATE TABLE `t_refund_order` (
`RefundOrderId` varchar(30) NOT NULL COMMENT '退款订单号',
`PayOrderId` varchar(30) NOT NULL COMMENT '支付订单号',
`ChannelPayOrderNo` varchar(64) DEFAULT NULL COMMENT '渠道支付单号',
`MchId` varchar(30) NOT NULL COMMENT '商户ID',
`MchRefundNo` varchar(30) NOT NULL COMMENT '商户退款单号',
`ChannelId` varchar(24) NOT NULL COMMENT '渠道ID',
`PayAmount` bigint(20) NOT NULL COMMENT '支付金额,单位分',
`RefundAmount` bigint(20) NOT NULL COMMENT '退款金额,单位分',
`Currency` varchar(3) NOT NULL DEFAULT 'cny' COMMENT '三位货币代码,人民币:cny',
`Status` tinyint(6) NOT NULL DEFAULT '0' COMMENT '退款状态:0-订单生成,1-退款中,2-退款成功,3-退款失败,4-业务处理完成',
`Result` tinyint(6) NOT NULL DEFAULT '0' COMMENT '退款结果:0-不确认结果,1-等待手动处理,2-确认成功,3-确认失败',
`ClientIp` varchar(32) DEFAULT NULL COMMENT '客户端IP',
`Device` varchar(64) DEFAULT NULL COMMENT '设备',
`RemarkInfo` varchar(256) DEFAULT NULL COMMENT '备注',
`ChannelUser` varchar(32) DEFAULT NULL COMMENT '渠道用户标识,如微信openId,支付宝账号',
`UserName` varchar(24) DEFAULT NULL COMMENT '用户姓名',
`ChannelMchId` varchar(32) NOT NULL COMMENT '渠道商户ID',
`ChannelOrderNo` varchar(32) DEFAULT NULL COMMENT '渠道订单号',
`ChannelErrCode` varchar(128) DEFAULT NULL COMMENT '渠道错误码',
`ChannelErrMsg` varchar(128) DEFAULT NULL COMMENT '渠道错误描述',
`Extra` varchar(512) DEFAULT NULL COMMENT '特定渠道发起时额外参数',
`NotifyUrl` varchar(128) NOT NULL COMMENT '通知地址',
`Param1` varchar(64) DEFAULT NULL COMMENT '扩展参数1',
`Param2` varchar(64) DEFAULT NULL COMMENT '扩展参数2',
`ExpireTime` datetime DEFAULT NULL COMMENT '订单失效时间',
`RefundSuccTime` datetime DEFAULT NULL COMMENT '订单退款成功时间',
`CreateTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`RefundOrderId`),
UNIQUE KEY `IDX_MchId_MchOrderNo` (`MchId`, MchRefundNo)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='退款订单表';
CREATE TABLE `t_mch_notify` (
`OrderId` varchar(24) NOT NULL COMMENT '订单ID',
`MchId` varchar(30) NOT NULL COMMENT '商户ID',
`MchOrderNo` varchar(30) NOT NULL COMMENT '商户订单号',
`OrderType` varchar(8) NOT NULL COMMENT '订单类型:1-支付,2-转账,3-退款',
`NotifyUrl` varchar(2048) NOT NULL COMMENT '通知地址',
`NotifyCount` tinyint(6) NOT NULL DEFAULT 0 COMMENT '通知次数',
`Result` varchar(2048) DEFAULT NULL COMMENT '通知响应结果',
`Status` tinyint(6) NOT NULL DEFAULT '1' COMMENT '通知状态,1-通知中,2-通知成功,3-通知失败',
`LastNotifyTime` datetime DEFAULT NULL COMMENT '最后一次通知时间',
`CreateTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`OrderId`),
UNIQUE KEY `IDX_MchId_OrderType_MchOrderNo` (`MchId`, `OrderType`, `MchOrderNo`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商户通知表';
/* 支付演示商城相关表 */
CREATE TABLE `t_goods_order` (
`GoodsOrderId` varchar(30) NOT NULL COMMENT '商品订单ID',
`GoodsId` varchar(30) NOT NULL COMMENT '商品ID',
`GoodsName` varchar(64) NOT NULL DEFAULT '' COMMENT '商品名称',
`Amount` bigint(20) NOT NULL COMMENT '金额,单位分',
`UserId` varchar(30) NOT NULL COMMENT '用户ID',
`Status` tinyint(6) NOT NULL DEFAULT '0' COMMENT '订单状态,订单生成(0),支付成功(1),处理完成(2),处理失败(-1)',
`PayOrderId` varchar(30) DEFAULT NULL COMMENT '支付订单号',
`ChannelId` varchar(24) DEFAULT NULL COMMENT '渠道ID',
`ChannelUserId` varchar(64) DEFAULT NULL COMMENT '支付渠道用户ID(微信openID或支付宝账号等第三方支付账号)',
`CreateTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`UpdateTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`GoodsOrderId`),
UNIQUE KEY `IDX_PayOrderId` (PayOrderId)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品订单表';

98
jeepay-core/pom.xml Normal file
View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <!-- POM模型版本 -->
<groupId>com.jeequan</groupId> <!-- 组织名, 类似于包名 -->
<artifactId>jeepay-core</artifactId> <!-- 项目名称 -->
<packaging>jar</packaging> <!-- 项目的最终打包类型/发布形式, 可选[jar, war, pom, maven-plugin]等 -->
<version>${isys.version}</version> <!-- 项目当前版本号 -->
<description>Jeepay计全支付系统 [jeepay-core]</description> <!-- 项目描述 -->
<url>https://www.jeequan.com</url>
<parent>
<groupId>com.jeequan</groupId>
<artifactId>jeepay</artifactId>
<version>1.0.0</version>
</parent>
<!-- 项目依赖声明 -->
<dependencies>
<!-- 依赖 [spring-context] 基础包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<scope>provided</scope>
</dependency>
<!-- 可选依赖 [spring-redis] -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<scope>provided</scope>
</dependency>
<!-- 添加 spring-webmvc 基础依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<scope>provided</scope> <!-- 仅编译依赖该jar 运行时存在 -->
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope> <!-- 仅编译依赖该jar 运行时存在 -->
</dependency>
<!-- mybatis plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis.plus.starter.version}</version>
<scope>provided</scope>
</dependency>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<scope>provided</scope>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<scope>provided</scope>
</dependency>
<!-- alibaba FastJSON -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<!-- commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/java</directory>
<includes><include>**/*.xml</include></includes><!-- maven可以将mapper.xml进行打包处理否则仅对java文件处理 -->
</resource>
</resources>
</build>
</project>

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.aop;
import java.lang.annotation.*;
/*
* 方法级日志切面注解
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 18:00
*/
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MethodLog {
String remark() default "";
}

View File

@ -0,0 +1,170 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.beans;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import javax.servlet.http.HttpServletRequest;
import java.util.Iterator;
import java.util.Map;
/*
* 基于spring的 req 工具类
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/7 12:16
*/
@Slf4j
@Component
public class RequestKitBean {
@Autowired(required = false)
protected HttpServletRequest request; //自动注入request
/** reqContext对象中的key: 转换好的json对象 */
private static final String REQ_CONTEXT_KEY_PARAMJSON = "REQ_CONTEXT_KEY_PARAMJSON";
/**request.getParameter 获取参数 并转换为JSON格式 **/
public JSONObject reqParam2JSON() {
JSONObject returnObject = new JSONObject();
if(isConvertJSON()){
String body = "";
try {
String str;
while((str = request.getReader().readLine()) != null){
body += str;
}
if(StringUtils.isEmpty(body)) return returnObject;
return JSONObject.parseObject(body);
} catch (Exception e) {
log.error("请求参数转换异常! params=[{}]", body);
throw new BizException(ApiCodeEnum.PARAMS_ERROR, "转换异常");
}
}
// 参数Map
Map properties = request.getParameterMap();
// 返回值Map
Iterator entries = properties.entrySet().iterator();
Map.Entry entry;
String name;
String value = "";
while (entries.hasNext()) {
entry = (Map.Entry) entries.next();
name = (String) entry.getKey();
Object valueObj = entry.getValue();
if(null == valueObj){
value = "";
}else if(valueObj instanceof String[]){
String[] values = (String[])valueObj;
for(int i=0;i<values.length;i++){
value = values[i] + ",";
}
value = value.substring(0, value.length()-1);
}else{
value = valueObj.toString();
}
if(!name.contains("[")){
returnObject.put(name, value);
continue;
}
//添加对json对象解析的支持 example: {ps[abc] : 1}
String mainKey = name.substring(0, name.indexOf("["));
String subKey = name.substring(name.indexOf("[") + 1 , name.indexOf("]"));
JSONObject subJson = new JSONObject();
if(returnObject.get(mainKey) != null) {
subJson = (JSONObject)returnObject.get(mainKey);
}
subJson.put(subKey, value);
returnObject.put(mainKey, subJson);
}
return returnObject;
}
/** 获取json格式的请求参数 **/
public JSONObject getReqParamJSON(){
//将转换好的reqParam JSON格式的对象保存在当前请求上下文对象中进行保存
// 注意1 springMVC的CTRL默认单例模式 不可使用局部变量保存会出现线程安全问题
// 注意2 springMVC的请求模式为线程池如果采用ThreadLocal保存对象信息可能会出现不清空或者被覆盖的问题
Object reqParamObject = RequestContextHolder.getRequestAttributes().getAttribute(REQ_CONTEXT_KEY_PARAMJSON, RequestAttributes.SCOPE_REQUEST);
if(reqParamObject == null){
JSONObject reqParam = reqParam2JSON();
RequestContextHolder.getRequestAttributes().setAttribute(REQ_CONTEXT_KEY_PARAMJSON, reqParam, RequestAttributes.SCOPE_REQUEST);
return reqParam;
}
return (JSONObject) reqParamObject;
}
/** 判断请求参数是否转换为json格式 */
private boolean isConvertJSON(){
String contentType = request.getContentType();
//有contentType && json格式 get请求不转换
if(contentType != null
&& contentType.toLowerCase().indexOf("application/json") >= 0
&& !request.getMethod().equalsIgnoreCase("GET")
){ //application/json 需要转换为json格式
return true;
}
return false;
}
/** 获取客户端ip地址 **/
public String getClientIp() {
String ipAddress = null;
ipAddress = request.getHeader("x-forwarded-for");
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getRemoteAddr();
}
// 对于通过多个代理的情况第一个IP为客户端真实IP,多个IP按照','分割
if (ipAddress != null && ipAddress.length() > 15) {
if (ipAddress.indexOf(",") > 0) {
ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
}
}
return ipAddress;
}
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.cache;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.model.security.JeeUserDetails;
/*
* token service
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/5/24 09:06
*/
public class ITokenService {
/** 处理token信息
* 1. 如果不允许多用户则踢掉之前的所有用户信息
* 2. 更新token 缓存时间信息
* 3. 更新用户token列表
* **/
public static void processTokenCache(JeeUserDetails userDetail, String cacheKey){
userDetail.setCacheKey(cacheKey); //设置cacheKey
//当前用户的所有登录token 集合
// if(!PropKit.isAllowMultiUser()){ //不允许多用户登录
//
// List<String> allTokenList = new ArrayList<>();
// for (String token : allTokenList) {
// if(!cacheKey.equalsIgnoreCase(token)){
// RedisUtil.del(token);
// }
// }
// }
//保存token
RedisUtil.set(cacheKey, userDetail, CS.TOKEN_TIME); //缓存时间2小时, 保存具体信息而只是uid, 因为很多场景需要得到信息 例如验证接口权限 每次请求都需要获取 将信息封装在一起减少磁盘请求次数 如果放置多个key会增加非顺序读取
}
/** 退出时清除token信息 */
public static void removeIToken(String iToken, Long currentUID){
//1. 清除token的信息
RedisUtil.del(iToken);
}
/**
* 刷新数据
* **/
public static void refData(JeeUserDetails currentUserInfo){
//保存token tokenList信息
RedisUtil.set(currentUserInfo.getCacheKey(), currentUserInfo, CS.TOKEN_TIME); //缓存时间2小时, 保存具体信息而只是uid, 因为很多场景需要得到信息 例如验证接口权限 每次请求都需要获取 将信息封装在一起减少磁盘请求次数 如果放置多个key会增加非顺序读取
}
}

View File

@ -0,0 +1,135 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.cache;
import com.alibaba.fastjson.JSON;
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.CollectionUtils;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
/*
* Redis工具类
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/5/24 17:58
*/
public class RedisUtil {
private static StringRedisTemplate stringRedisTemplate = null;
/** 获取RedisTemplate对象, 默认使用 StringRedisTemplate, 客户端可查询 **/
private static final RedisTemplate getStringRedisTemplate(){
if(stringRedisTemplate == null){
if(SpringBeansUtil.getApplicationContext().containsBean("defaultStringRedisTemplate")){
stringRedisTemplate = SpringBeansUtil.getBean("defaultStringRedisTemplate", StringRedisTemplate.class);
}else{
stringRedisTemplate = SpringBeansUtil.getBean(StringRedisTemplate.class);
}
}
return stringRedisTemplate;
}
/** 获取缓存数据, String类型 */
public static String getString(String key) {
if(key == null) return null;
return (String)getStringRedisTemplate().opsForValue().get(key);
}
/** 获取缓存数据对象 */
public static <T> T getObject(String key, Class<T> cls) {
String val = getString(key);
return JSON.parseObject(val, cls);
}
/** 放置缓存对象 */
public static void setString(String key, String value) {
getStringRedisTemplate().opsForValue().set(key, value);
}
/** 普通缓存放入并设置时间, 默认单位:秒 */
public static void setString(String key, String value, long time) {
getStringRedisTemplate().opsForValue().set(key, value, time, TimeUnit.SECONDS);
}
/** 普通缓存放入并设置时间 */
public static void setString(String key, String value, long time, TimeUnit timeUnit) {
getStringRedisTemplate().opsForValue().set(key, value, time, timeUnit);
}
/** 放置缓存对象 */
public static void set(String key, Object value) {
setString(key, JSON.toJSONString(value));
}
/** 普通缓存放入并设置时间, 默认单位:秒 */
public static void set(String key, Object value, long time) {
setString(key, JSON.toJSONString(value), time);
}
/** 普通缓存放入并设置时间 */
public static void set(String key, Object value, long time, TimeUnit timeUnit) {
setString(key, JSON.toJSONString(value), time, timeUnit);
}
/** 指定缓存失效时间 */
public static void expire(String key, long time) {
getStringRedisTemplate().expire(key, time, TimeUnit.SECONDS);
}
/** 指定缓存失效时间 */
public static void expire(String key, long time, TimeUnit timeUnit) {
getStringRedisTemplate().expire(key, time, timeUnit);
}
/**
* 根据key 获取过期时间
* @param key 不能为null
* @return 时间() 返回0代表为永久有效
*/
public static long getExpire(String key) {
return getStringRedisTemplate().getExpire(key, TimeUnit.SECONDS);
}
/** 判断key是否存在 */
public static boolean hasKey(String key) {
return getStringRedisTemplate().hasKey(key);
}
/** 删除缓存 **/
public static void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
getStringRedisTemplate().delete(key[0]);
} else {
getStringRedisTemplate().delete(CollectionUtils.arrayToList(key));
}
}
}
/** 查询keys */
public static Collection<String> keys(String pattern) {
return getStringRedisTemplate().keys(pattern);
}
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.constants;
/*
* 接口返回码
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/5/24 17:07
*/
public enum ApiCodeEnum{
SUCCESS(0, "SUCCESS"), //请求成功
CUSTOM_FAIL(9999, "自定义业务异常"), //自定义业务异常
SYSTEM_ERROR(10, "系统异常[%s]"),
PARAMS_ERROR(11, "参数有误[%s]"),
DB_ERROR(12, "数据库服务异常"),
SYS_OPERATION_FAIL_CREATE(5000, "新增失败"),
SYS_OPERATION_FAIL_DELETE(5001, "删除失败"),
SYS_OPERATION_FAIL_UPDATE(5002, "修改失败"),
SYS_OPERATION_FAIL_SELETE(5003, "记录不存在"),
SYS_PERMISSION_ERROR(5004, "权限错误,当前用户不支持此操作");
private int code;
private String msg;
ApiCodeEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
public int getCode(){
return this.code;
}
public String getMsg() {
return this.msg;
}
}

View File

@ -0,0 +1,212 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.constants;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @Author terrfly
* @Date 2019/11/16 15:09
* @Description Constants 常量对象
**/
public class CS {
/** 系统类型定义 **/
public interface SYS_TYPE{
String MCH = "MCH";
String MGR = "MGR";
Map<String, String> SYS_TYPE_MAP = new HashMap<>();
}
static {
SYS_TYPE.SYS_TYPE_MAP.put(SYS_TYPE.MCH, "商户系统");
SYS_TYPE.SYS_TYPE_MAP.put(SYS_TYPE.MGR, "运营平台");
}
/** yes or no **/
public static final byte NO = 0;
public static final byte YES = 1;
/** 通用 可用 / 禁用 **/
public static final int PUB_USABLE = 1;
public static final int PUB_DISABLE = 0;
public static final Map<Integer, String> PUB_USABLE_MAP = new HashMap<>();
static {
PUB_USABLE_MAP.put(PUB_USABLE, "正常");
PUB_USABLE_MAP.put(PUB_DISABLE, "停用");
}
/**
* 账号类型:1-服务商 2-商户
*/
public static final byte INFO_TYPE_ISV = 1;
public static final byte INFO_TYPE_MCH = 2;
/**
* 商户类型:1-普通商户 2-特约商户
*/
public static final byte MCH_TYPE_NORMAL = 1;
public static final byte MCH_TYPE_ISVSUB = 2;
/**
* 性别 1- 2-
*/
public static final byte SEX_UNKNOWN = 0;
public static final byte SEX_MALE = 1;
public static final byte SEX_FEMALE = 2;
/** 默认密码 */
public static final String DEFAULT_PWD = "jeepay666";
/**
* 允许上传的的图片文件格式需要与 WebSecurityConfig对应
*/
public static final Set<String> ALLOW_UPLOAD_IMG_SUFFIX = new HashSet<>();
static{
ALLOW_UPLOAD_IMG_SUFFIX.add("jpg");
ALLOW_UPLOAD_IMG_SUFFIX.add("png");
ALLOW_UPLOAD_IMG_SUFFIX.add("jpeg");
ALLOW_UPLOAD_IMG_SUFFIX.add("gif");
ALLOW_UPLOAD_IMG_SUFFIX.add("mp4");
}
public static final long TOKEN_TIME = 60 * 60 * 2; //单位s, 两小时
//access_token 名称
public static final String ACCESS_TOKEN_NAME = "iToken";
/** 不同系统请放置不同的redis库 **/
/** 缓存key: 当前用户所有用户的token集合 example: TOKEN_1001_HcNheNDqHzhTIrT0lUXikm7xU5XY4Q */
public static final String CACHE_KEY_TOKEN = "TOKEN_%s_%s";
public static String getCacheKeyToken(Long sysUserId, String uuid){
return String.format(CACHE_KEY_TOKEN, sysUserId, uuid);
}
/** 图片验证码 缓存key **/
public static final String CACHE_KEY_IMG_CODE = "img_code_%s";
public static String getCacheKeyImgCode(String imgToken){
return String.format(CACHE_KEY_IMG_CODE, imgToken);
}
/** 登录认证类型 **/
public interface AUTH_TYPE{
byte LOGIN_USER_NAME = 1; //登录用户名
byte TELPHONE = 2; //手机号
byte EMAIL = 3; //邮箱
byte WX_UNION_ID = 10; //微信unionId
byte WX_MINI = 11; //微信小程序
byte WX_MP = 12; //微信公众号
byte QQ = 20; //QQ
}
public interface MQ{
/** 更新配置的通知消息 **/
String TOPIC_MODIFY_SYS_CONFIG = "topic.modify.sys.config";
/** 更新商户配置信息 **/
String TOPIC_MODIFY_MCH_INFO = "topic.modify.mch.info";
/** 更新服务商配置信息 **/
String TOPIC_MODIFY_ISV_INFO = "topic.modify.isv.info";
/** 支付订单 商户通知MQ **/
String QUEUE_PAYORDER_MCH_NOTIFY = "queue.payorder.mch.notify";
/** 轮询查单 MQ **/
String QUEUE_CHANNEL_ORDER_QUERY = "queue.channel.order.query";
/** 清除商户登录用户信息 **/
String QUEUE_MODIFY_MCH_USER_REMOVE = "queue.modify.mch.user.remove";
}
//菜单类型
public interface ENT_TYPE{
String MENU_LEFT = "ML"; //左侧显示菜单
String MENU_OTHER = "MO"; //其他菜单
String PAGE_OR_BTN = "PB"; //页面 or 按钮
}
//接口类型
public interface IF_CODE{
String ALIPAY = "alipay"; //支付宝官方支付
String WXPAY = "wxpay"; //微信官方支付
String YSFPAY = "ysfpay"; //云闪付开放平台
}
//支付方式代码
public interface PAY_WAY_CODE{
// 特殊支付方式
String QR_CASHIER = "QR_CASHIER"; // ( 通过二维码跳转到收银台完成支付 已集成获取用户ID的实现 )
String AUTO_BAR = "AUTO_BAR"; // 条码聚合支付自动分类条码类型
String ALI_BAR = "ALI_BAR"; //支付宝条码支付
String ALI_JSAPI = "ALI_JSAPI"; //支付宝服务窗支付
String ALI_APP = "ALI_APP"; //支付宝 app支付
String ALI_PC = "ALI_PC"; //支付宝 电脑网站支付
String ALI_WAP = "ALI_WAP"; //支付宝 wap支付
String ALI_QR = "ALI_QR"; //支付宝 二维码付款
String YSF_BAR = "YSF_BAR"; //云闪付条码支付
String YSF_JSAPI = "YSF_JSAPI"; //云闪付服务窗支付
String WX_JSAPI = "WX_JSAPI"; //微信jsapi支付
String WX_LITE = "WX_LITE"; //微信小程序支付
String WX_BAR = "WX_BAR"; //微信条码支付
String WX_H5 = "WX_H5"; //微信H5支付
String WX_NATIVE = "WX_NATIVE"; //微信扫码支付
}
//支付数据包 类型
public interface PAY_DATA_TYPE {
String PAY_URL = "payurl"; //跳转链接的方式 redirectUrl
String FORM = "form"; //表单提交
String WX_APP = "wxapp"; //微信app参数
String ALI_APP = "aliapp"; //支付宝app参数
String YSF_APP = "ysfapp"; //云闪付app参数
String CODE_URL = "codeUrl"; //二维码URL
String CODE_IMG_URL = "codeImgUrl"; //二维码图片显示URL
String NONE = "none"; //无参数
// String QR_CONTENT = "qrContent"; //二维码实际内容
}
//接口版本
public interface PAY_IF_VERSION{
String WX_V2 = "V2"; //微信接口版本V2
String WX_V3 = "V3"; //微信接口版本V3
}
}

View File

@ -0,0 +1,304 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.ctrls;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.beans.RequestKitBean;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.BaseModel;
import com.jeequan.jeepay.core.utils.DateKit;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/*
* 抽象公共Ctrl
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2020/02/18 17:28
*/
public abstract class AbstractCtrl {
protected static final Logger logger = LoggerFactory.getLogger(AbstractCtrl.class);
private static final String PAGE_INDEX_PARAM_NAME = "pageNumber"; //分页页码 参数名
private static final String PAGE_SIZE_PARAM_NAME = "pageSize"; //分页条数 参数名
private static final int DEFAULT_PAGE_INDEX = 1; // 默认页码 第一页
private static final int DEFAULT_PAGE_SIZE = 20; // 默认条数 20
private static final String SORT_FIELD_PARAM_NAME = "sortField"; //排序字段
private static final String SORT_ORDER_FLAG_PARAM_NAME = "sortOrder"; // 排序正序 倒序标志
@Autowired
protected HttpServletRequest request; //自动注入request
@Autowired
protected HttpServletResponse response; //自动注入response
@Autowired
protected RequestKitBean requestKitBean;
/** 获取json格式的请求参数 **/
protected JSONObject getReqParamJSON(){
return requestKitBean.getReqParamJSON();
}
/** 获取页码 **/
protected int getPageIndex() {
Integer pageIndex = getReqParamJSON().getInteger(PAGE_INDEX_PARAM_NAME);
if(pageIndex == null) return DEFAULT_PAGE_INDEX;
return pageIndex;
}
/** 获取条数, 默认不允许查询全部数据 **/
protected int getPageSize() {
return getPageSize(false);
}
/** 获取条数, 加入条件:是否允许获取全部数据 **/
protected int getPageSize(boolean allowQueryAll) {
Integer pageSize = getReqParamJSON().getInteger(PAGE_SIZE_PARAM_NAME);
if(allowQueryAll && pageSize != null && pageSize == -1) return Integer.MAX_VALUE; // -1代表获取全部数据查询int最大值的数据
if(pageSize == null || pageSize < 0) return DEFAULT_PAGE_SIZE;
return pageSize;
}
/** 获取Ipage分页信息, 默认不允许获取全部数据 **/
protected IPage getIPage(){
return new Page(getPageIndex(), getPageSize());
}
/** 获取Ipage分页信息, 加入条件:是否允许获取全部数据 **/
protected IPage getIPage(boolean allowQueryAll){
return new Page(getPageIndex(), getPageSize(allowQueryAll));
}
/** 获取排序字段 MutablePair<是否正序, 排序字段> **/
protected MutablePair<Boolean, String> getSortInfo() {
String sortField = getReqParamJSON().getString(SORT_FIELD_PARAM_NAME);
String sortOrderFlag = getReqParamJSON().getString(SORT_ORDER_FLAG_PARAM_NAME);
if(StringUtils.isAllEmpty(sortField, sortField)){
return null;
}
return MutablePair.of("ascend".equalsIgnoreCase(sortOrderFlag), StrUtil.toUnderlineCase(sortField).toLowerCase());
}
/** 获取请求参数值 [ T 类型 ], [ 非必填 ] **/
protected <T> T getVal(String key, Class<T> cls) {
return getReqParamJSON().getObject(key, cls);
}
/** 获取请求参数值 [ T 类型 ], [ 必填 ] **/
protected <T> T getValRequired(String key, Class<T> cls) {
T value = getVal(key, cls);
if(ObjectUtils.isEmpty(value)) {
throw new BizException(ApiCodeEnum.PARAMS_ERROR, genParamRequiredMsg(key));
}
return value;
}
/** 获取请求参数值 [ T 类型 ], [ 如为null返回默认值 ] **/
protected <T> T getValDefault(String key, T defaultValue, Class<T> cls) {
T value = getVal(key, cls);
if(value == null) return defaultValue;
return value;
}
/** 获取请求参数值 String 类型相关函数 **/
protected String getValString(String key) {
return getVal(key, String.class);
}
protected String getValStringRequired(String key) {
return getValRequired(key, String.class);
}
protected String getValStringDefault(String key, String defaultValue) {
return getValDefault(key, defaultValue, String.class);
}
/** 获取请求参数值 Byte 类型相关函数 **/
protected Byte getValByte(String key) {
return getVal(key, Byte.class);
}
protected Byte getValByteRequired(String key) {
return getValRequired(key, Byte.class);
}
protected Byte getValByteDefault(String key, Byte defaultValue) {
return getValDefault(key, defaultValue, Byte.class);
}
/** 获取请求参数值 Integer 类型相关函数 **/
protected Integer getValInteger(String key) {
return getVal(key, Integer.class);
}
protected Integer getValIntegerRequired(String key) {
return getValRequired(key, Integer.class);
}
protected Integer getValIntegerDefault(String key, Integer defaultValue) {
return getValDefault(key, defaultValue, Integer.class);
}
/** 获取请求参数值 Long 类型相关函数 **/
protected Long getValLong(String key) {
return getVal(key, Long.class);
}
protected Long getValLongRequired(String key) {
return getValRequired(key, Long.class);
}
protected Long getValLongDefault(String key, Long defaultValue) {
return getValDefault(key, defaultValue, Long.class);
}
/** 获取请求参数值 BigDecimal 类型相关函数 **/
protected BigDecimal getValBigDecimal(String key) {
return getVal(key, BigDecimal.class);
}
protected BigDecimal getValBigDecimalRequired(String key) {
return getValRequired(key, BigDecimal.class);
}
protected BigDecimal getValBigDecimalDefault(String key, BigDecimal defaultValue) {
return getValDefault(key, defaultValue, BigDecimal.class);
}
/** 获取对象类型 **/
protected <T> T getObject(Class<T> clazz) {
JSONObject params = getReqParamJSON();
T result = params.toJavaObject(clazz);
if(result instanceof BaseModel){ //如果属于BaseModel, 处理apiExtVal
JSONObject resultTemp = (JSONObject) JSON.toJSON(result);
for (String key : params.keySet()) { //遍历原始参数
if(!resultTemp.containsKey(key)){
((BaseModel) result).addExt(key, params.get(key));
}
}
}
return result;
}
/** 生成参数必填错误信息 **/
private String genParamRequiredMsg(String key) {
return "参数" + key + "必填";
}
/** 校验参数值不能为空 */
protected void checkRequired(String... keys) {
for(String key : keys) {
String value = getReqParamJSON().getString(key);
if(StringUtils.isEmpty(value)) throw new BizException(ApiCodeEnum.PARAMS_ERROR, genParamRequiredMsg(key));
}
}
/** 得到前端传入的金额元,转换成长整型分 **/
public Long getRequiredAmountL(String name) {
String amountStr = getValStringRequired(name); // 前端填写的为元,可以为小数点2位
Long amountL = new BigDecimal(amountStr.trim()).multiply(new BigDecimal(100)).longValue(); // // 转成分
return amountL;
}
/** 得到前端传入的金额元,转换成长整型分 (非必填) **/
public Long getAmountL(String name) {
String amountStr = getValString(name); // 前端填写的为元,可以为小数点2位
if(StringUtils.isEmpty(amountStr)) return null;
Long amountL = new BigDecimal(amountStr.trim()).multiply(new BigDecimal(100)).longValue(); // // 转成分
return amountL;
}
/**
* 处理参数中的金额(将前端传入金额元转成分)
* modify: 20181206 添加JSON对象中的对象属性转换为分 格式[xxx.xxx]
* @param names
*/
public void handleParamAmount(String... names) {
for(String name : names) {
String amountStr = getValString(name); // 前端填写的为元,可以为小数点2位
if(StringUtils.isNotBlank(amountStr)) {
Long amountL = new BigDecimal(amountStr.trim()).multiply(new BigDecimal(100)).longValue(); // // 转成分
if(name.indexOf(".") < 0 ){
getReqParamJSON().put(name, amountL);
continue;
}
getReqParamJSON().getJSONObject(name.substring(0, name.indexOf("."))).put(name.substring(name.indexOf(".")+1), amountL);
}
}
}
/**
* 获取查询的时间范围
* @return
*/
protected Date[] getQueryDateRange(){
return DateKit.getQueryDateRange(getReqParamJSON().getString("queryDateRange")); //默认参数为 queryDateRange
}
/** 请求参数转换为map格式 **/
public Map<String, Object> request2payResponseMap(HttpServletRequest request, String[] paramArray) {
Map<String, Object> responseMap = new HashMap<>();
for (int i = 0;i < paramArray.length; i++) {
String key = paramArray[i];
String v = request.getParameter(key);
if (v != null) {
responseMap.put(key, v);
}
}
return responseMap;
}
/** 将上传的文件进行保存 - 公共函数 **/
protected void saveFile(MultipartFile file, String savePath) throws Exception {
File saveFile = new File(savePath);
//如果文件夹不存在则创建文件夹
File dir = saveFile.getParentFile();
if(!dir.exists()) dir.mkdirs();
file.transferTo(saveFile);
}
/** 获取客户端ip地址 **/
public String getClientIp() {
return requestKitBean.getClientIp();
}
public String getUserAgent(){
String userAgent = request.getHeader("User-Agent");
return StringUtils.isNotEmpty(userAgent) ? userAgent: "未知";
}
}

View File

@ -0,0 +1,113 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jeequan.jeepay.core.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 服务商信息表
* </p>
*
* @author [mybatis plus generator]
* @since 2021-04-27
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_isv_info")
public class IsvInfo extends BaseModel implements Serializable {
//gw
public static final LambdaQueryWrapper<IsvInfo> gw(){
return new LambdaQueryWrapper<>();
}
private static final long serialVersionUID=1L;
/**
* 服务商号
*/
@TableId(value = "isv_no", type = IdType.INPUT)
private String isvNo;
/**
* 服务商名称
*/
private String isvName;
/**
* 服务商简称
*/
private String isvShortName;
/**
* 联系人姓名
*/
private String contactName;
/**
* 联系人手机号
*/
private String contactTel;
/**
* 联系人邮箱
*/
private String contactEmail;
/**
* 状态: 0-停用, 1-正常
*/
private Byte state;
/**
* 备注
*/
private String remark;
/**
* 创建者用户ID
*/
private Long createdUid;
/**
* 创建者姓名
*/
private String createdBy;
/**
* 创建时间
*/
private Date createdAt;
/**
* 更新时间
*/
private Date updatedAt;
}

View File

@ -0,0 +1,137 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jeequan.jeepay.core.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 商户信息表
* </p>
*
* @author [mybatis plus generator]
* @since 2021-04-27
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_mch_info")
public class MchInfo extends BaseModel implements Serializable {
//gw
public static final LambdaQueryWrapper<MchInfo> gw(){
return new LambdaQueryWrapper<>();
}
private static final long serialVersionUID=1L;
public static final byte TYPE_NORMAL = 1; //商户类型 1-普通商户
public static final byte TYPE_ISVSUB = 2; //商户类型 2-特约商户
/**
* 商户号
*/
@TableId(value = "mch_no", type = IdType.INPUT)
private String mchNo;
/**
* 商户名称
*/
private String mchName;
/**
* 商户简称
*/
private String mchShortName;
/**
* 类型: 1-普通商户, 2-特约商户(服务商模式)
*/
private Byte type;
/**
* 服务商号
*/
private String isvNo;
/**
* 联系人姓名
*/
private String contactName;
/**
* 联系人手机号
*/
private String contactTel;
/**
* 联系人邮箱
*/
private String contactEmail;
/**
* 私钥
*/
private String privateKey;
/**
* 商户状态: 0-停用, 1-正常
*/
private Byte state;
/**
* 商户备注
*/
private String remark;
/**
* 初始用户ID创建商户时允许商户登录的用户
*/
private Long initUserId;
/**
* 创建者用户ID
*/
private Long createdUid;
/**
* 创建者姓名
*/
private String createdBy;
/**
* 创建时间
*/
private Date createdAt;
/**
* 更新时间
*/
private Date updatedAt;
}

View File

@ -0,0 +1,127 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jeequan.jeepay.core.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 商户通知记录表
* </p>
*
* @author [mybatis plus generator]
* @since 2021-04-27
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_mch_notify_record")
public class MchNotifyRecord extends BaseModel implements Serializable {
//订单类型:1-支付,2-退款
public static final Byte TYPE_PAY_ORDER = 1;
public static final Byte TYPE_REFUND_ORDER = 2;
//通知状态
public static final Byte STATE_ING = 1;
public static final Byte STATE_SUCCESS = 2;
public static final Byte STATE_FAIL = 3;
//gw
public static final LambdaQueryWrapper<MchNotifyRecord> gw(){
return new LambdaQueryWrapper<>();
}
private static final long serialVersionUID=1L;
/**
* 商户通知记录ID
*/
@TableId(value = "notify_id", type = IdType.AUTO)
private Long notifyId;
/**
* 订单ID
*/
private String orderId;
/**
* 订单类型:1-支付,2-退款
*/
private Byte orderType;
/**
* 商户订单号
*/
private String mchOrderNo;
/**
* 商户号
*/
private String mchNo;
/**
* 服务商号
*/
private String isvNo;
/**
* 通知地址
*/
private String notifyUrl;
/**
* 通知响应结果
*/
private String resResult;
/**
* 通知次数
*/
private Integer notifyCount;
/**
* 通知状态,1-通知中,2-通知成功,3-通知失败
*/
private Byte state;
/**
* 最后一次通知时间
*/
private Date lastNotifyTime;
/**
* 创建时间
*/
private Date createdAt;
/**
* 更新时间
*/
private Date updatedAt;
}

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jeequan.jeepay.core.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* <p>
* 商户支付通道表
* </p>
*
* @author [mybatis plus generator]
* @since 2021-04-27
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_mch_pay_passage")
public class MchPayPassage extends BaseModel implements Serializable {
public static final LambdaQueryWrapper<MchPayPassage> gw(){
return new LambdaQueryWrapper<>();
}
private static final long serialVersionUID=1L;
/**
* ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 商户号
*/
private String mchNo;
/**
* 支付接口
*/
private String ifCode;
/**
* 支付方式
*/
private String wayCode;
/**
* 支付方式费率
*/
private BigDecimal rate;
/**
* 风控数据
*/
private String riskConfig;
/**
* 状态: 0-停用, 1-启用
*/
private Byte state;
/**
* 创建时间
*/
private Date createdAt;
/**
* 更新时间
*/
private Date updatedAt;
}

View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jeequan.jeepay.core.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* <p>
* 支付接口配置参数表
* </p>
*
* @author [mybatis plus generator]
* @since 2021-04-27
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_pay_interface_config")
public class PayInterfaceConfig extends BaseModel implements Serializable {
public static final LambdaQueryWrapper<PayInterfaceConfig> gw(){
return new LambdaQueryWrapper<>();
}
private static final long serialVersionUID=1L;
/**
* ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 账号类型:1-服务商 2-商户
*/
private Byte infoType;
/**
* 服务商或商户No
*/
private String infoId;
/**
* 支付接口代码
*/
private String ifCode;
/**
* 接口配置参数,json字符串
*/
private String ifParams;
/**
* 支付接口费率
*/
private BigDecimal ifRate;
/**
* 状态: 0-停用, 1-启用
*/
private Byte state;
/**
* 备注
*/
private String remark;
/**
* 创建者用户ID
*/
private Long createdUid;
/**
* 创建者姓名
*/
private String createdBy;
/**
* 创建时间
*/
private Date createdAt;
/**
* 更新者用户ID
*/
private Long updatedUid;
/**
* 更新者姓名
*/
private String updatedBy;
/**
* 更新时间
*/
private Date updatedAt;
}

View File

@ -0,0 +1,125 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.entity;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
import com.jeequan.jeepay.core.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 支付接口定义表
* </p>
*
* @author [mybatis plus generator]
* @since 2021-04-27
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName(value = "t_pay_interface_define", autoResultMap = true)
public class PayInterfaceDefine extends BaseModel implements Serializable {
public static final LambdaQueryWrapper<PayInterfaceDefine> gw(){
return new LambdaQueryWrapper<>();
}
private static final long serialVersionUID=1L;
/**
* 接口代码 全小写 wxpay alipay
*/
@TableId
private String ifCode;
/**
* 接口名称
*/
private String ifName;
/**
* 是否支持普通商户模式: 0-不支持, 1-支持
*/
private Byte isMchMode;
/**
* 是否支持服务商子商户模式: 0-不支持, 1-支持
*/
private Byte isIsvMode;
/**
* ISV接口配置定义描述,json字符串
*/
private String isvParams;
/**
* 特约商户接口配置定义描述,json字符串
*/
private String isvsubMchParams;
/**
* 普通商户接口配置定义描述,json字符串
*/
private String normalMchParams;
/**
* 支持的支付方式 ["wxpay_jsapi", "wxpay_bar"]
*/
@TableField(typeHandler = FastjsonTypeHandler.class)
private JSONArray wayCodes;
/**
* 页面展示卡片-图标
*/
private String icon;
/**
* 页面展示卡片-背景色
*/
private String bgColor;
/**
* 状态: 0-停用, 1-启用
*/
private Byte state;
/**
* 备注
*/
private String remark;
/**
* 创建时间
*/
private Date createdAt;
/**
* 更新时间
*/
private Date updatedAt;
}

View File

@ -0,0 +1,216 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jeequan.jeepay.core.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 支付订单表
* </p>
*
* @author [mybatis plus generator]
* @since 2021-04-27
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_pay_order")
public class PayOrder extends BaseModel implements Serializable {
public static final LambdaQueryWrapper<PayOrder> gw(){
return new LambdaQueryWrapper<>();
}
private static final long serialVersionUID=1L;
public static final byte STATE_INIT = 0; //订单生成
public static final byte STATE_ING = 1; //支付中
public static final byte STATE_SUCCESS = 2; //支付成功
public static final byte STATE_FAIL = 3; //支付失败
public static final byte STATE_CANCEL = 4; //已撤销
public static final byte STATE_REFUND = 5; //已退款
public static final byte STATE_CLOSED = 6; //订单关闭
/**
* 支付订单号
*/
@TableId
private String payOrderId;
/**
* 商户号
*/
private String mchNo;
/**
* 服务商号
*/
private String isvNo;
/**
* 商户名称
*/
private String mchName;
/**
* 类型: 1-普通商户, 2-特约商户(服务商模式)
*/
private Byte mchType;
/**
* 商户订单号
*/
private String mchOrderNo;
/**
* 支付接口代码
*/
private String ifCode;
/**
* 支付方式代码
*/
private String wayCode;
/**
* 支付金额,单位分
*/
private Long amount;
/**
* 三位货币代码,人民币:cny
*/
private String currency;
/**
* 支付状态: 0-订单生成, 1-支付中, 2-支付成功, 3-支付失败, 4-已撤销, 5-已退款, 6-订单关闭
*/
private Byte state;
/**
* 向下游回调状态, 0-未发送, 1-已发送
*/
private Byte notifyState;
/**
* 客户端IP
*/
private String clientIp;
/**
* 商品标题
*/
private String subject;
/**
* 商品描述信息
*/
private String body;
/**
* 特定渠道发起额外参数
*/
private String channelExtra;
/**
* 渠道用户标识,如微信openId,支付宝账号
*/
private String channelUser;
/**
* 渠道订单号
*/
private String channelOrderNo;
/**
* 退款次数
*/
private Integer refundTimes;
/**
* 退款总金额,单位分
*/
private Long refundAmount;
/**
* 订单分账标志0- 1-
*/
private Byte divisionFlag;
/**
* 预计分账发起时间
*/
private Date divisionTime;
/**
* 渠道支付错误码
*/
private String errCode;
/**
* 渠道支付错误描述
*/
private String errMsg;
/**
* 商户扩展参数
*/
private String extParam;
/**
* 异步通知地址
*/
private String notifyUrl;
/**
* 页面跳转地址
*/
private String returnUrl;
/**
* 订单失效时间
*/
private Date expiredTime;
/**
* 订单支付成功时间
*/
private Date successTime;
/**
* 创建时间
*/
private Date createdAt;
/**
* 更新时间
*/
private Date updatedAt;
}

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jeequan.jeepay.core.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 支付方式表
* </p>
*
* @author [mybatis plus generator]
* @since 2021-04-27
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_pay_way")
public class PayWay extends BaseModel implements Serializable {
public static final LambdaQueryWrapper<PayWay> gw(){
return new LambdaQueryWrapper<>();
}
private static final long serialVersionUID=1L;
/**
* 支付方式代码 例如 wxpay_jsapi
*/
@TableId
private String wayCode;
/**
* 支付方式名称
*/
private String wayName;
/**
* 创建时间
*/
private Date createdAt;
/**
* 更新时间
*/
private Date updatedAt;
}

View File

@ -0,0 +1,176 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jeequan.jeepay.core.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 退款订单表
* </p>
*
* @author [mybatis plus generator]
* @since 2021-04-27
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_refund_order")
public class RefundOrder extends BaseModel implements Serializable {
public static final LambdaQueryWrapper<RefundOrder> gw(){
return new LambdaQueryWrapper<>();
}
private static final long serialVersionUID=1L;
/**
* 退款订单号
*/
@TableId
private String refundOrderId;
/**
* 支付订单号
*/
private String payOrderId;
/**
* 渠道支付单号
*/
private String channelPayOrderNo;
/**
* 商户号
*/
private String mchNo;
/**
* 类型: 1-普通商户, 2-特约商户(服务商模式)
*/
private Byte mchType;
/**
* 商户退款单号
*/
private String mchRefundNo;
/**
* 服务商号
*/
private String isvNo;
/**
* 支付方式代码
*/
private String wayCode;
/**
* 支付接口代码
*/
private String ifCode;
/**
* 支付金额,单位分
*/
private Long payAmount;
/**
* 退款金额,单位分
*/
private Long refundAmount;
/**
* 三位货币代码,人民币:cny
*/
private String currency;
/**
* 退款状态:0-订单生成,1-退款中,2-退款成功,3-退款失败
*/
private Byte state;
/**
* 退款结果:0-不确认结果,1-等待手动处理,2-确认成功,3-确认失败
*/
private Byte result;
/**
* 客户端IP
*/
private String clientIp;
/**
* 备注
*/
private String remark;
/**
* 渠道订单号
*/
private String channelOrderNo;
/**
* 渠道错误码
*/
private String channelErrCode;
/**
* 渠道错误描述
*/
private String channelErrMsg;
/**
* 特定渠道发起时额外参数
*/
private String channelExtra;
/**
* 通知地址
*/
private String notifyUrl;
/**
* 扩展参数
*/
private String extParam;
/**
* 订单退款成功时间
*/
private Date successTime;
/**
* 创建时间
*/
private Date createdAt;
/**
* 更新时间
*/
private Date updatedAt;
}

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jeequan.jeepay.core.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 系统配置表
* </p>
*
* @author [mybatis plus generator]
* @since 2021-04-23
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_sys_config")
public class SysConfig extends BaseModel implements Serializable {
//gw
public static final LambdaQueryWrapper<SysConfig> gw(){
return new LambdaQueryWrapper<>();
}
private static final long serialVersionUID=1L;
/**
* 配置KEY
*/
@TableId(value = "config_key", type = IdType.INPUT)
private String configKey;
/**
* 配置名称
*/
private String configName;
/**
* 描述信息
*/
private String configDesc;
/**
* 分组key
*/
private String groupKey;
/**
* 分组名称
*/
private String groupName;
/**
* 配置内容项
*/
private String configVal;
/**
* 类型: text-输入框, textarea-多行文本, uploadImg-上传图片, switch-开关
*/
private String type;
/**
* 显示顺序
*/
private Long sortNum;
/**
* 更新时间
*/
private Date updatedAt;
}

View File

@ -0,0 +1,116 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jeequan.jeepay.core.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.util.Date;
/**
* <p>
* 系统权限表
* </p>
*
* @author [mybatis plus generator]
* @since 2021-04-23
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_sys_entitlement")
public class SysEntitlement extends BaseModel {
//gw
public static final LambdaQueryWrapper<SysEntitlement> gw(){
return new LambdaQueryWrapper<>();
}
private static final long serialVersionUID=1L;
/**
* 权限ID[ENT_功能模块_子模块_操作], eg: ENT_ROLE_LIST_ADD
*/
@TableId
private String entId;
/**
* 权限名称
*/
private String entName;
/**
* 菜单图标
*/
private String menuIcon;
/**
* 菜单uri/路由地址
*/
private String menuUri;
/**
* 组件Name前后端分离使用
*/
private String componentName;
/**
* 权限类型 ML-左侧显示菜单, MO-其他菜单, PB-页面/按钮
*/
private String entType;
/**
* 快速开始菜单 0-, 1-
*/
private Byte quickJump;
/**
* 状态 0-停用, 1-启用
*/
private Byte state;
/**
* 父ID
*/
private String pid;
/**
* 排序字段, 规则正序
*/
private Integer entSort;
/**
* 所属系统 MGR-运营平台, MCH-商户中心
*/
private String system;
/**
* 创建时间
*/
private Date createdAt;
/**
* 更新时间
*/
private Date updatedAt;
}

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 系统操作日志表
* </p>
*
* @author [mybatis plus generator]
* @since 2021-04-27
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_sys_log")
public class SysLog implements Serializable {
public static final LambdaQueryWrapper<SysLog> gw(){
return new LambdaQueryWrapper<>();
}
private static final long serialVersionUID=1L;
/**
* id
*/
@TableId(value = "sys_log_id", type = IdType.AUTO)
private Integer sysLogId;
/**
* 系统用户ID
*/
private Long userId;
/**
* 用户姓名
*/
private String userName;
/**
* 用户IP
*/
private String userIp;
/**
* 所属系统 MGR-运营平台, MCH-商户中心
*/
private String system;
/**
* 方法名
*/
private String methodName;
/**
* 方法描述
*/
private String methodRemark;
/**
* 请求地址
*/
private String reqUrl;
/**
* 操作请求参数
*/
private String optReqParam;
/**
* 操作响应结果
*/
private String optResInfo;
/**
* 创建时间
*/
private Date createdAt;
}

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 系统角色表
* </p>
*
* @author [mybatis plus generator]
* @since 2021-04-23
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_sys_role")
public class SysRole implements Serializable {
//gw
public static final LambdaQueryWrapper<SysRole> gw(){
return new LambdaQueryWrapper<>();
}
private static final long serialVersionUID=1L;
/**
* 角色ID, ROLE_开头
*/
@TableId
private String roleId;
/**
* 角色名称
*/
private String roleName;
/**
* 所属系统 MGR-运营平台, MCH-商户中心
*/
private String system;
/**
* 所属商户ID / 0(平台)
*/
private String belongInfoId;
/**
* 更新时间
*/
private Date updatedAt;
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* <p>
* 系统角色权限关联表
* </p>
*
* @author [mybatis plus generator]
* @since 2021-04-23
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_sys_role_ent_rela")
public class SysRoleEntRela implements Serializable {
//gw
public static final LambdaQueryWrapper<SysRoleEntRela> gw(){
return new LambdaQueryWrapper<>();
}
private static final long serialVersionUID=1L;
/**
* 角色ID
*/
private String roleId;
/**
* 权限ID
*/
private String entId;
}

View File

@ -0,0 +1,117 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jeequan.jeepay.core.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.util.Date;
/**
* <p>
* 系统用户表
* </p>
*
* @author [mybatis plus generator]
* @since 2021-04-23
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_sys_user")
public class SysUser extends BaseModel {
//gw
public static final LambdaQueryWrapper<SysUser> gw(){
return new LambdaQueryWrapper<>();
}
private static final long serialVersionUID=1L;
/**
* 系统用户ID
*/
@TableId(value = "sys_user_id", type = IdType.AUTO)
private Long sysUserId;
/**
* 登录用户名
*/
private String loginUsername;
/**
* 真实姓名
*/
private String realname;
/**
* 手机号
*/
private String telphone;
/**
* 性别 0-未知, 1-, 2-
*/
private Byte sex;
/**
* 头像地址
*/
private String avatarUrl;
/**
* 员工编号
*/
private String userNo;
/**
* 是否超管超管拥有全部权限 0- 1-
*/
private Byte isAdmin;
/**
* 状态 0-停用 1-启用
*/
private Byte state;
/**
* 所属系统 MGR-运营平台, MCH-商户中心
*/
private String system;
/**
* 所属商户ID / 0(平台)
*/
private String belongInfoId;
/**
* 创建时间
*/
private Date createdAt;
/**
* 更新时间
*/
private Date updatedAt;
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* <p>
* 系统用户认证表
* </p>
*
* @author [mybatis plus generator]
* @since 2021-04-23
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_sys_user_auth")
public class SysUserAuth implements Serializable {
//gw
public static final LambdaQueryWrapper<SysUserAuth> gw(){
return new LambdaQueryWrapper<>();
}
private static final long serialVersionUID=1L;
/**
* ID
*/
@TableId(value = "auth_id", type = IdType.AUTO)
private Long authId;
/**
* user_id
*/
private Long userId;
/**
* 登录类型 1-昵称 2-手机号 3-邮箱 10-微信 11-QQ 12-支付宝 13-微博
*/
private Byte identityType;
/**
* 认证标识 ( 用户名 | open_id )
*/
private String identifier;
/**
* 密码凭证
*/
private String credential;
/**
* salt
*/
private String salt;
/**
* 所属系统 MGR-运营平台, MCH-商户中心
*/
private String system;
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* <p>
* 操作员<->角色 关联表
* </p>
*
* @author [mybatis plus generator]
* @since 2021-04-23
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_sys_user_role_rela")
public class SysUserRoleRela implements Serializable {
//gw
public static final LambdaQueryWrapper<SysUserRoleRela> gw(){
return new LambdaQueryWrapper<>();
}
private static final long serialVersionUID=1L;
/**
* 用户ID
*/
private Long userId;
/**
* 角色ID
*/
private String roleId;
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.exception;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.model.ApiRes;
import lombok.Getter;
/*
* 自定义业务异常
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:33
*/
@Getter
public class BizException extends RuntimeException{
private static final long serialVersionUID = 1L;
private ApiRes apiRes;
/** 业务自定义异常 **/
public BizException(String msg) {
super(msg);
this.apiRes = ApiRes.customFail(msg);
}
public BizException(ApiCodeEnum apiCodeEnum, String... params) {
super();
apiRes = ApiRes.fail(apiCodeEnum, params);
}
public BizException(ApiRes apiRes) {
super(apiRes.getMsg());
this.apiRes = apiRes;
}
}

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.exception;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.model.ApiRes;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.DataAccessException;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
* 异常信息自定义返回数据
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:30
*/
@Configuration
public class BizExceptionResolver implements HandlerExceptionResolver {
private Logger logger = LogManager.getLogger(BizExceptionResolver.class);
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) {
// 是否包含ss框架
boolean hasSpringSecurity = false;
try {
hasSpringSecurity = Class.forName("org.springframework.security.access.AccessDeniedException") != null;
} catch (Exception e) {
}
String outPutJson;
//业务异常
if(ex instanceof BizException) {
logger.error("公共捕捉[Biz]异常:{}",ex.getMessage());
outPutJson = ((BizException) ex).getApiRes().toJSONString();
}else if(ex instanceof DataAccessException){
logger.error("公共捕捉[DataAccessException]异常:",ex);
outPutJson = ApiRes.fail(ApiCodeEnum.DB_ERROR).toJSONString();
}else if(hasSpringSecurity && ex instanceof org.springframework.security.access.AccessDeniedException) {
logger.error("公共捕捉[AccessDeniedException]异常:", ex);
outPutJson = ApiRes.fail(ApiCodeEnum.SYS_PERMISSION_ERROR, ex.getMessage()).toJSONString();
}else{
logger.error("公共捕捉[Exception]异常:",ex);
outPutJson = ApiRes.fail(ApiCodeEnum.SYSTEM_ERROR, ex.getMessage()).toJSONString();
}
try {
this.outPutJson(response, outPutJson);
} catch (IOException e) {
logger.error("输出错误信息异常:", e);
}
return new ModelAndView();
}
public void outPutJson(HttpServletResponse res, String jsonStr) throws IOException {
res.setContentType("text/json;charset=utf-8");
res.getWriter().write(jsonStr);
res.getWriter().flush();
res.getWriter().close();
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.exception;
import lombok.Getter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
/*
* 响应异常 一般用于支付接口回调函数
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:31
*/
@Getter
public class ResponseException extends RuntimeException{
private static final long serialVersionUID = 1L;
private ResponseEntity responseEntity;
/** 业务自定义异常 **/
public ResponseException(ResponseEntity resp) {
super();
this.responseEntity = resp;
}
/** 生成文本类型的响应 **/
public static ResponseException buildText(String text){
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.TEXT_HTML);
ResponseEntity entity = new ResponseEntity(text, httpHeaders, HttpStatus.OK);
return new ResponseException(entity);
}
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.jwt;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.model.security.JeeUserDetails;
import lombok.Data;
import java.util.Map;
/*
* JWT payload 载体
* 格式
{
"sysUserId": "10001",
"created": "1568250147846",
"cacheKey": "KEYKEYKEYKEY",
}
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 18:01
*/
@Data
public class JWTPayload {
private Long sysUserId; //登录用户ID
private Long created; //创建时间, 格式13位时间戳
private String cacheKey; //redis保存的key
protected JWTPayload(){}
public JWTPayload(JeeUserDetails jeeUserDetails){
this.setSysUserId(jeeUserDetails.getSysUser().getSysUserId());
this.setCreated(System.currentTimeMillis());
this.setCacheKey(jeeUserDetails.getCacheKey());
}
/** toMap **/
public Map<String, Object> toMap(){
JSONObject json = (JSONObject)JSONObject.toJSON(this);
return json.toJavaObject(Map.class);
}
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.jwt;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
/*
* JWT工具包
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:32
*/
public class JWTUtils {
/** 生成token **/
public static String generateToken(JWTPayload jwtPayload, String jwtSecret) {
return Jwts.builder()
.setClaims(jwtPayload.toMap())
//过期时间 = 当前时间 + 设置过期时间[单位 s ] token放置redis 过期时间无意义
//.setExpiration(new Date(System.currentTimeMillis() + (jwtExpiration * 1000) ))
.signWith(SignatureAlgorithm.HS512, jwtSecret)
.compact();
}
/** 根据token与秘钥 解析token并转换为 JWTPayload **/
public static JWTPayload parseToken(String token, String secret){
try {
Claims claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
JWTPayload result = new JWTPayload();
result.setSysUserId(claims.get("sysUserId", Long.class));
result.setCreated(claims.get("created", Long.class));
result.setCacheKey(claims.get("cacheKey", String.class));
return result;
} catch (Exception e) {
return null; //解析失败
}
}
}

View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.model;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.utils.JeepayKit;
import com.jeequan.jeepay.core.utils.JsonKit;
import lombok.AllArgsConstructor;
import lombok.Data;
/*
* 接口返回对象
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:35
*/
@Data
@AllArgsConstructor
public class ApiRes {
/** 业务响应码 **/
private Integer code;
/** 业务响应信息 **/
private String msg;
/** 数据对象 **/
private Object data;
/** 签名值 **/
private String sign;
/** 输出json格式字符串 **/
public String toJSONString(){
return JSON.toJSONString(this);
}
/** 业务处理成功 **/
public static ApiRes ok(){
return ok(null);
}
/** 业务处理成功 **/
public static ApiRes ok(Object data){
return new ApiRes(ApiCodeEnum.SUCCESS.getCode(), ApiCodeEnum.SUCCESS.getMsg(), data, null);
}
/** 业务处理成功, 自动签名 **/
public static ApiRes okWithSign(Object data, String mchKey){
if(data == null){
return new ApiRes(ApiCodeEnum.SUCCESS.getCode(), ApiCodeEnum.SUCCESS.getMsg(), null, null);
}
JSONObject jsonObject = (JSONObject)JSONObject.toJSON(data);
String sign = JeepayKit.getSign(jsonObject, mchKey);
return new ApiRes(ApiCodeEnum.SUCCESS.getCode(), ApiCodeEnum.SUCCESS.getMsg(), data, sign);
}
/** 业务处理成功, 返回简单json格式 **/
public static ApiRes ok4newJson(String key, Object val){
return ok(JsonKit.newJson(key, val));
}
/** 业务处理成功, 封装分页数据, 仅返回必要参数 **/
public static ApiRes page(IPage iPage){
JSONObject result = new JSONObject();
result.put("records", iPage.getRecords()); //记录明细
result.put("total", iPage.getTotal()); //总条数
result.put("current", iPage.getCurrent()); //当前页码
result.put("hasNext", iPage.getPages() > iPage.getCurrent() ); //是否有下一页
return ok(result);
}
/** 业务处理失败 **/
public static ApiRes fail(ApiCodeEnum apiCodeEnum, String... params){
if(params == null || params.length <= 0){
return new ApiRes(apiCodeEnum.getCode(), apiCodeEnum.getMsg(), null, null);
}
return new ApiRes(apiCodeEnum.getCode(), String.format(apiCodeEnum.getMsg(), params), null, null);
}
/** 自定义错误信息, 原封不用的返回输入的错误信息 **/
public static ApiRes customFail(String customMsg){
return new ApiRes(ApiCodeEnum.CUSTOM_FAIL.getCode(), customMsg, null, null);
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.model;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
/*
* BaseModel 封装公共处理函数
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:49
*/
public class BaseModel<T> implements Serializable{
private static final long serialVersionUID = 1L;
/** ext参数, 用作扩展参数, 会在转换为api数据时自动将ext全部属性放置在对象的主属性上, 并且不包含ext属性 **/
/** api接口扩展字段 当包含该字段时 将自动填充到实体对象属性中如{id:1, ext:{abc:222}} 则自动转换为 {id:1, abc:222}
* 需配合ResponseBodyAdvice使用
* **/
@TableField(exist = false)
private JSONObject ext;
//获取的时候设置默认值
public JSONObject getExt() {
return ext;
}
//设置扩展字段
public BaseModel addExt(String key, Object val) {
if(ext == null) ext = new JSONObject();
ext.put(key,val);
return this;
}
/** get ext value 可直接使用JSONObject对象的函数 **/
public JSONObject extv() {
return ext == null ? new JSONObject() : ext;
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.model;
import cn.hutool.core.util.URLUtil;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.utils.JeepayKit;
import lombok.Data;
import java.io.Serializable;
/*
* 系统应用配置项定义Bean
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:35
*/
@Data
public class DBApplicationConfig implements Serializable {
/** 运营系统地址 **/
private String mgrSiteUrl;
/** 商户系统地址 **/
private String mchSiteUrl;
/** 支付网关地址 **/
private String paySiteUrl;
/** oss公共读文件地址 **/
private String ossPublicSiteUrl;
/** 生成 【jsapi统一收银台跳转地址】 **/
public String genUniJsapiPayUrl(String payOrderId){
return getPaySiteUrl() + "/cashier/index.html#/hub/" + JeepayKit.aesEncode(payOrderId);
}
/** 生成 【jsapi统一收银台】oauth2获取用户ID回调地址 **/
public String genOauth2RedirectUrlEncode(String payOrderId){
return URLUtil.encode(getPaySiteUrl() + "/cashier/index.html#/oauth2Callback/" + JeepayKit.aesEncode(payOrderId));
}
/** 生成 【商户获取渠道用户ID接口】oauth2获取用户ID回调地址 **/
public String genMchChannelUserIdApiOauth2RedirectUrlEncode(JSONObject param){
return URLUtil.encode(getPaySiteUrl() + "/api/channelUserId/oauth2Callback/" + JeepayKit.aesEncode(param.toJSONString()));
}
/** 生成 【jsapi统一收银台二维码图片地址】 **/
public String genScanImgUrl(String url){
return getPaySiteUrl() + "/api/scan/imgs/" + JeepayKit.aesEncode(url) + ".png";
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.model;
import lombok.AllArgsConstructor;
import lombok.Data;
/*
* 返回原始数据
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:37
*/
@Data
@AllArgsConstructor
public class OriginalRes {
/** 返回数据 **/
private Object data;
public static OriginalRes ok(Object data){
return new OriginalRes(data);
}
}

View File

@ -0,0 +1,96 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import java.util.*;
/*
* 定义文件上传的配置信息
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:38
*/
@Data
@AllArgsConstructor
public class OssFileConfig {
/** 用户头像 **/
interface BIZ_TYPE {
String AVATAR = "avatar"; /** 用户头像 **/
String IF_BG = "ifBG"; /** 接口类型卡片背景图片 **/
String CERT = "cert"; /** 接口参数 **/
}
/** 图片类型后缀格式 **/
public static final Set IMG_SUFFIX = new HashSet(Arrays.asList("jpg", "png", "jpeg", "gif"));
/** 全部后缀格式的文件标识符 **/
public static final String ALL_SUFFIX_FLAG = "*";
/** 不校验文件大小标识符 **/
public static final Long ALL_MAX_SIZE = -1L;
/** 允许上传的最大文件大小的默认值 **/
public static final Long DEFAULT_MAX_SIZE = 5 * 1024 * 1024L;
private static final Map<String, OssFileConfig> ALL_BIZ_TYPE_MAP = new HashMap<>();
static{
ALL_BIZ_TYPE_MAP.put(BIZ_TYPE.AVATAR, new OssFileConfig(true, IMG_SUFFIX, DEFAULT_MAX_SIZE) );
ALL_BIZ_TYPE_MAP.put(BIZ_TYPE.IF_BG, new OssFileConfig(true, IMG_SUFFIX, DEFAULT_MAX_SIZE) );
ALL_BIZ_TYPE_MAP.put(BIZ_TYPE.CERT, new OssFileConfig(false, new HashSet<>(Arrays.asList(ALL_SUFFIX_FLAG)), DEFAULT_MAX_SIZE) );
}
/** 是否允许公共读 **/
private boolean allowPublicRead = false;
/** 允许的文件后缀, 默认全部类型 **/
private Set<String> allowFileSuffix = new HashSet<>(Arrays.asList(ALL_SUFFIX_FLAG));
/** 允许的文件大小, 单位: Byte **/
private Long maxSize = DEFAULT_MAX_SIZE;
/** 是否在允许的文件类型后缀内 **/
public boolean isAllowFileSuffix(String fixSuffix){
if(this.allowFileSuffix.contains(ALL_SUFFIX_FLAG)){ //允许全部
return true;
}
return this.allowFileSuffix.contains(StringUtils.defaultIfEmpty(fixSuffix, "").toLowerCase());
}
/** 是否在允许的大小范围内 **/
public boolean isMaxSizeLimit(Long fileSize){
if(ALL_MAX_SIZE.equals(this.maxSize)){ //允许全部大小
return true;
}
return this.maxSize >= ( fileSize == null ? 0L : fileSize);
}
public static OssFileConfig getOssFileConfigByBizType(String bizType){
return ALL_BIZ_TYPE_MAP.get(bizType);
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.model.params;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.model.params.alipay.AlipayIsvParams;
import com.jeequan.jeepay.core.model.params.wxpay.WxpayIsvParams;
import com.jeequan.jeepay.core.model.params.ysf.YsfpayIsvParams;
/*
* 抽象类 isv参数定义
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:33
*/
public abstract class IsvParams {
public static IsvParams factory(String ifCode, String paramsStr){
if(CS.IF_CODE.WXPAY.equals(ifCode)){
return JSONObject.parseObject(paramsStr, WxpayIsvParams.class);
}else if(CS.IF_CODE.ALIPAY.equals(ifCode)){
return JSONObject.parseObject(paramsStr, AlipayIsvParams.class);
}else if(CS.IF_CODE.YSFPAY.equals(ifCode)){
return JSONObject.parseObject(paramsStr, YsfpayIsvParams.class);
}
return null;
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.model.params;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.model.params.alipay.AlipayIsvsubMchParams;
import com.jeequan.jeepay.core.model.params.wxpay.WxpayIsvsubMchParams;
import com.jeequan.jeepay.core.model.params.ysf.YsfpayIsvsubMchParams;
/*
* 抽象类 特约商户参数定义
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:33
*/
public abstract class IsvsubMchParams {
public static IsvsubMchParams factory(String ifCode, String paramsStr){
if(CS.IF_CODE.WXPAY.equals(ifCode)){
return JSONObject.parseObject(paramsStr, WxpayIsvsubMchParams.class);
}else if(CS.IF_CODE.ALIPAY.equals(ifCode)){
return JSONObject.parseObject(paramsStr, AlipayIsvsubMchParams.class);
}else if(CS.IF_CODE.YSFPAY.equals(ifCode)){
return JSONObject.parseObject(paramsStr, YsfpayIsvsubMchParams.class);
}
return null;
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.model.params;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.model.params.alipay.AlipayNormalMchParams;
import com.jeequan.jeepay.core.model.params.wxpay.WxpayNormalMchParams;
/*
* 抽象类 普通商户参数定义
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:33
*/
public abstract class NormalMchParams {
public static NormalMchParams factory(String ifCode, String paramsStr){
if(CS.IF_CODE.WXPAY.equals(ifCode)){
return JSONObject.parseObject(paramsStr, WxpayNormalMchParams.class);
}else if(CS.IF_CODE.ALIPAY.equals(ifCode)){
return JSONObject.parseObject(paramsStr, AlipayNormalMchParams.class);
}
return null;
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.model.params.alipay;
import lombok.Data;
/*
* 支付宝 通用配置信息
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:32
*/
@Data
public class AlipayConfig{
public static final String SIGN_TYPE_RSA = "RSA";
public static final String SIGN_TYPE_RSA2 = "RSA2";
/** 网关地址 */
public static String PROD_SERVER_URL = "https://openapi.alipay.com/gateway.do";
public static String SANDBOX_SERVER_URL = "https://openapi.alipaydev.com/gateway.do";
public static String PROD_OAUTH_URL = "https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id=%s&scope=auth_base&state=&redirect_uri=%s";
public static String SANDBOX_OAUTH_URL = "https://openauth.alipaydev.com/oauth2/publicAppAuthorize.htm?app_id=%s&scope=auth_base&state=&redirect_uri=%s";
public static String FORMAT = "json";
public static String CHARSET = "UTF-8";
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.model.params.alipay;
import com.jeequan.jeepay.core.model.params.IsvParams;
import lombok.Data;
/*
* 支付宝 isv参数定义
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:34
*/
@Data
public class AlipayIsvParams extends IsvParams {
/** 是否沙箱环境 */
private Byte sandbox;
/** pid */
private String pid;
/** appId */
private String appId;
/** privateKey */
private String privateKey;
/** alipayPublicKey */
private String alipayPublicKey;
/** 签名方式 **/
private String signType;
/** 是否使用证书方式 **/
private Byte useCert;
/** app 证书 **/
private String appPublicCert;
/** 支付宝公钥证书(.crt格式 **/
private String alipayPublicCert;
/** 支付宝根证书 **/
private String alipayRootCert;
}

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.model.params.alipay;
import com.jeequan.jeepay.core.model.params.IsvsubMchParams;
import lombok.Data;
/*
* 支付宝 特约商户参数定义
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:33
*/
@Data
public class AlipayIsvsubMchParams extends IsvsubMchParams {
private String appAuthToken;
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.model.params.alipay;
import com.jeequan.jeepay.core.model.params.NormalMchParams;
import lombok.Data;
/*
* 支付宝 普通商户参数定义
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:33
*/
@Data
public class AlipayNormalMchParams extends NormalMchParams {
/** 是否沙箱环境 */
private Byte sandbox;
/** appId */
private String appId;
/** privateKey */
private String privateKey;
/** alipayPublicKey */
private String alipayPublicKey;
/** 签名方式 **/
private String signType;
/** 是否使用证书方式 **/
private Byte useCert;
/** app 证书 **/
private String appPublicCert;
/** 支付宝公钥证书(.crt格式 **/
private String alipayPublicCert;
/** 支付宝根证书 **/
private String alipayRootCert;
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.model.params.wxpay;
import com.jeequan.jeepay.core.model.params.IsvParams;
import lombok.Data;
/*
* 微信官方支付 配置参数
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021/6/8 18:02
*/
@Data
public class WxpayIsvParams extends IsvParams {
/** 应用App ID */
private String appId;
/** 应用AppSecret */
private String appSecret;
/** 微信支付商户号 */
private String mchId;
/** oauth2地址 */
private String oauth2Url;
/** API密钥 */
private String key;
/** 签名方式 **/
private String signType;
/** 微信支付API版本 **/
private String apiVersion;
/** API V3秘钥 **/
private String apiV3Key;
/** 序列号 **/
private String serialNo;
/** API证书(.p12格式)**/
private String cert;
/** 私钥文件(.pem格式) **/
private String apiClientKey;
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.model.params.wxpay;
import com.jeequan.jeepay.core.model.params.IsvsubMchParams;
import lombok.Data;
/*
* 微信官方支付 配置参数
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021/6/8 18:02
*/
@Data
public class WxpayIsvsubMchParams extends IsvsubMchParams {
/** 子商户ID **/
private String subMchId;
/** 子账户appID **/
private String subMchAppId;
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.model.params.wxpay;
import com.jeequan.jeepay.core.model.params.NormalMchParams;
import lombok.Data;
/*
* 微信官方支付 配置参数
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021/6/8 18:02
*/
@Data
public class WxpayNormalMchParams extends NormalMchParams {
/** 应用App ID */
private String appId;
/** 应用AppSecret */
private String appSecret;
/** 微信支付商户号 */
private String mchId;
/** oauth2地址 */
private String oauth2Url;
/** API密钥 */
private String key;
/** 微信支付API版本 **/
private String apiVersion;
/** API V3秘钥 **/
private String apiV3Key;
/** 序列号 **/
private String serialNo;
/** API证书(.p12格式)**/
private String cert;
/** 私钥文件(.pem格式) **/
private String apiClientKey;
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.model.params.ysf;
import lombok.Data;
/*
* 云闪付 通用配置信息
*
* @author pangxiaoyu
* @site https://www.jeepay.vip
* @date 2021/6/8 18:02
*/
@Data
public class YsfpayConfig {
/** 网关地址 */
public static String PROD_SERVER_URL = "https://partner.95516.com";
public static String SANDBOX_SERVER_URL = "http://ysf.bcbip.cn:10240";
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.model.params.ysf;
import com.jeequan.jeepay.core.model.params.IsvParams;
import lombok.Data;
/*
* 云闪付 配置信息
*
* @author pangxiaoyu
* @site https://www.jeepay.vip
* @date 2021/6/8 18:02
*/
@Data
public class YsfpayIsvParams extends IsvParams {
/** 是否沙箱环境 */
private Byte sandbox;
/** serProvId **/
private String serProvId;
/** isvPrivateCertFile 证书 **/
private String isvPrivateCertFile;
/** isvPrivateCertPwd **/
private String isvPrivateCertPwd;
/** ysfpayPublicKey **/
private String ysfpayPublicKey;
/** acqOrgCodeList 支付机构号 **/
private String acqOrgCode;
}

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.model.params.ysf;
import com.jeequan.jeepay.core.model.params.IsvsubMchParams;
import lombok.Data;
/*
* 云闪付 配置信息
*
* @author pangxiaoyu
* @site https://www.jeepay.vip
* @date 2021/6/8 18:02
*/
@Data
public class YsfpayIsvsubMchParams extends IsvsubMchParams {
private String merId; // 商户编号
}

View File

@ -0,0 +1,122 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.model.security;
import com.jeequan.jeepay.core.entity.SysUser;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.ArrayList;
import java.util.Collection;
/*
* 实现Spring Security的UserDetails接口
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:34
*/
@Slf4j
@Data
public class JeeUserDetails implements UserDetails {
/** 系统用户信息 **/
private SysUser sysUser;
/** 密码 **/
private String credential;
/** 角色+权限 集合 (角色必须以: ROLE_ 开头) **/
private Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
/** 缓存标志 **/
private String cacheKey;
/** 登录IP **/
private String loginIp;
//此处的无参构造为json反序列化提供
public JeeUserDetails() {
}
public JeeUserDetails(SysUser sysUser, String credential) {
this.setSysUser(sysUser);
this.setCredential(credential);
//TODO ....
//做一些初始化操作
}
/** spring-security 需要验证的密码 **/
@Override
public String getPassword() {
return getCredential();
}
/** spring-security 登录名 **/
@Override
public String getUsername() {
return getSysUser().getSysUserId() + "";
}
/** 账户是否过期 **/
@Override
public boolean isAccountNonExpired() {
return true;
}
/** 账户是否已解锁 **/
@Override
public boolean isAccountNonLocked() {
return true;
}
/** 密码是否过期 **/
@Override
public boolean isCredentialsNonExpired() {
return true;
}
/** 账户是否开启 **/
@Override
public boolean isEnabled() {
return true;
}
/** 获取权限集合 **/
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
public static JeeUserDetails getCurrentUserDetails() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) return null;
try {
return (JeeUserDetails) authentication.getPrincipal();
}catch (Exception e) {
return null;
}
}
}

View File

@ -1,7 +1,25 @@
package org.xxpay.common.util;
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.utils;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @Description: 金额工具类
@ -68,6 +86,18 @@ public class AmountUtil {
+ "." + s.substring(s.length() - 2)));
}
/**
* 将Long ""转换成""长格式100分被转换为1.00元
* @param s
* @return
*/
public static String convertCent2Dollar(Long s){
if(s == null) return "";
return new BigDecimal(s).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 将字符串""转换成""短格式100分被转换为1元
* @param s
@ -84,4 +114,16 @@ public class AmountUtil {
return ss;
}
/**
* 判断金额为2位小数
* @param str
* @return
*/
public static boolean isAmount(String str){
if(str == null) return false;
Pattern pattern = Pattern.compile("^(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d){0,2})?$"); // 判断小数点后2位的数字的正则表达式
Matcher match = pattern.matcher(str);
return match.matches();
}
}

View File

@ -0,0 +1,113 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.model.OriginalRes;
import com.jeequan.jeepay.core.model.ApiRes;
import org.springframework.core.io.InputStreamResource;
import java.util.Collection;
/*
* 自定义springMVC的controller的返回值
* 功能
* 1. 自动添加ApiRes.ok();
* 2. 处理model的扩展字段 (只需要在model中设置[ext]参数 可以实现json自动转换为外层字段 )
* 比如 model为 {id:1, ext:{abc:222}} 则自动转换为 {id:1, abc:222}
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:49
*/
public class ApiResBodyAdviceKit {
/** 扩展字段的key名称 **/
private static final String API_EXTEND_FIELD_NAME = "ext";
public static Object beforeBodyWrite(Object body) {
//空的情况 不处理
if(body == null ) return null;
if(body instanceof OriginalRes){
return ((OriginalRes) body).getData();
}
//返回文件流不处理
if(body instanceof InputStreamResource){
return body;
}
//返回二进制文件不处理
if(body instanceof byte[]){
return body;
}
//如果为ApiRes类型则仅处理扩展字段
if(body instanceof ApiRes) {
return procAndConvertJSON(body);
}else{
//ctrl返回其他非[ApiRes]认为处理成功 先转换为成功状态 在处理字段
return procAndConvertJSON(ApiRes.ok(body));
}
}
/** 处理扩展字段 and 转换为json格式 **/
private static Object procAndConvertJSON(Object object){
Object json = JSON.toJSON(object); //转换为JSON格式
if(json instanceof JSONObject){ //对象类型
processExtFieldByJSONObject((JSONObject) json);
return json;
}
if(json instanceof Collection){ //数组类型
JSONArray result = new JSONArray();
for (Object itemObj : (Collection) json) {
result.add(procAndConvertJSON(itemObj));
}
return result;
}
return json;
}
/** 处理jsonObject格式 **/
private static void processExtFieldByJSONObject(JSONObject jsonObject){
//如果包含字段 则赋值到外层然后删除该字段
if(jsonObject.containsKey(API_EXTEND_FIELD_NAME)){
JSONObject exFieldMap = jsonObject.getJSONObject(API_EXTEND_FIELD_NAME);
if(exFieldMap != null){ //包含字段
for (String s : exFieldMap.keySet()) { //遍历赋值到外层
jsonObject.put(s, exFieldMap.get(s));
}
}
jsonObject.remove(API_EXTEND_FIELD_NAME); //删除字段
}
//处理所有值
for (String key : jsonObject.keySet()) {
jsonObject.put(key, procAndConvertJSON(jsonObject.get(key)));
}
}
}

View File

@ -0,0 +1,122 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.utils;
import cn.hutool.core.date.DateUtil;
import com.jeequan.jeepay.core.exception.BizException;
import org.apache.commons.lang3.StringUtils;
import java.util.Date;
/*
* 时间工具类
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:58
*/
public class DateKit {
/** 获取参数时间当天的开始时间 **/
public static Date getBegin(Date date){
if(date == null) return null;
return DateUtil.beginOfDay(date).toJdkDate();
}
/** 获取参数时间当天的结束时间 **/
public static Date getEnd(Date date){
if(date == null) return null;
return DateUtil.endOfDay(date).toJdkDate();
}
/**
* 获取自定义查询时间
* today|0 -- 今天
* yesterday|0 -- 昨天
* near2now|7 -- 近xx天 到今天
* near2yesterday|30 -- 近xx天 到昨天
* customDate|2020-01-01,N -- 自定义日期格式 N表示为空 占位使用
* customDateTime|2020-01-01 23:00:00,2020-01-01 23:00:00 -- 自定义日期时间格式
*
* @return
*/
public static Date[] getQueryDateRange(String queryParamVal){
//查询全部
if(StringUtils.isEmpty(queryParamVal)){
return new Date[]{null, null};
}
//根据 | 分割
String[] valArray = queryParamVal.split("\\|");
if(valArray.length != 2){ //参数有误
throw new BizException("查询时间参数有误");
}
String dateType = valArray[0]; //时间类型
String dateVal = valArray[1]; //搜索时间值
Date nowDateTime = new Date(); //当前时间
if("today".equals(dateType)){ //今天
return new Date[]{getBegin(nowDateTime), getEnd(nowDateTime)};
}else if("yesterday".equals(dateType)){ //昨天
Date yesterdayDateTime = DateUtil.offsetDay(nowDateTime, -1).toJdkDate(); //昨天
return new Date[]{getBegin(yesterdayDateTime), getEnd(yesterdayDateTime)};
}else if("near2now".equals(dateType)){ //近xx天 xx天之前 ~ 当前时间
Integer offsetDay = 1 - Integer.parseInt(dateVal); //获取时间偏移量
Date offsetDayDate = DateUtil.offsetDay(nowDateTime, offsetDay).toJdkDate();
return new Date[]{getBegin(offsetDayDate), getEnd(nowDateTime)};
}else if("near2yesterday".equals(dateType)){ //近xx天 xx天之前 ~ 昨天
Date yesterdayDateTime = DateUtil.offsetDay(nowDateTime, -1).toJdkDate(); //昨天
Integer offsetDay = 1 - Integer.parseInt(dateVal); //获取时间偏移量
Date offsetDayDate = DateUtil.offsetDay(yesterdayDateTime, offsetDay).toJdkDate();
return new Date[]{getBegin(offsetDayDate), getEnd(yesterdayDateTime)};
}else if("customDate".equals(dateType) || "customDateTime".equals(dateType)){ //自定义格式
String[] timeArray = dateVal.split(","); //以逗号分割
if(timeArray.length != 2) throw new BizException("查询自定义时间参数有误");
String timeStr1 = "N".equalsIgnoreCase(timeArray[0]) ? null : timeArray[0] ; //开始时间
String timeStr2 = "N".equalsIgnoreCase(timeArray[1]) ? null : timeArray[1]; //结束时间 N表示为空 占位使用
Date time1 = null;
Date time2 = null;
if(StringUtils.isNotEmpty(timeStr1)){
time1 = DateUtil.parseDateTime("customDate".equals(dateType) ? (timeStr1 + " 00:00:00" ) : timeStr1);
}
if(StringUtils.isNotEmpty(timeStr2)){
time2 = DateUtil.parseDateTime("customDate".equals(dateType) ? (timeStr2 + " 23:59:59" ) : timeStr2);
}
return new Date[]{time1, time2};
}else{
throw new BizException("查询时间参数有误");
}
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.utils;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
/*
* 文件工具类
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:50
*/
public class FileKit {
/**
* 获取文件的后缀名
* @param appendDot 是否拼接.
* @return
*/
public static String getFileSuffix(String fullFileName, boolean appendDot){
if(fullFileName == null || fullFileName.indexOf(".") < 0 || fullFileName.length() <= 1) return "";
return (appendDot? "." : "") + fullFileName.substring(fullFileName.lastIndexOf(".") + 1);
}
/** 获取有效的图片格式, 返回null 不支持的图片类型 **/
public static String getImgSuffix(String filePath){
String suffix = getFileSuffix(filePath, false).toLowerCase();
if(CS.ALLOW_UPLOAD_IMG_SUFFIX.contains(suffix)){
return suffix;
}
throw new BizException("不支持的图片类型");
}
}

View File

@ -0,0 +1,172 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.utils;
import cn.hutool.crypto.SecureUtil;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import sun.misc.BASE64Decoder;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
/*
* jeepay工具类
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:50
*/
@Slf4j
public class JeepayKit {
public static byte[] AES_KEY = null;
static{
try {
AES_KEY = new BASE64Decoder().decodeBuffer("4ChT08phkz59hquD795X7w==");
} catch (IOException e) {
}
}
/** 加密 **/
public static String aesEncode(String str){
return SecureUtil.aes(JeepayKit.AES_KEY).encryptHex(str);
}
public static String aesDecode(String str){
return SecureUtil.aes(JeepayKit.AES_KEY).decryptStr(str);
}
private static String encodingCharset = "UTF-8";
/**
* <p><b>Description: </b>计算签名摘要
* <p>2018年9月30日 上午11:32:46
* @param map 参数Map
* @param key 商户秘钥
* @return
*/
public static String getSign(Map<String,Object> map, String key){
ArrayList<String> list = new ArrayList<String>();
for(Map.Entry<String,Object> entry:map.entrySet()){
if(null != entry.getValue() && !"".equals(entry.getValue())){
list.add(entry.getKey() + "=" + entry.getValue() + "&");
}
}
int size = list.size();
String [] arrayToSort = list.toArray(new String[size]);
Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
StringBuilder sb = new StringBuilder();
for(int i = 0; i < size; i ++) {
sb.append(arrayToSort[i]);
}
String result = sb.toString();
result += "key=" + key;
log.info("signStr:{}", result);
result = md5(result, encodingCharset).toUpperCase();
log.info("sign:{}", result);
return result;
}
/**
* <p><b>Description: </b>MD5
* <p>2018年9月30日 上午11:33:19
* @param value
* @param charset
* @return
*/
public static String md5(String value, String charset) {
MessageDigest md = null;
try {
byte[] data = value.getBytes(charset);
md = MessageDigest.getInstance("MD5");
byte[] digestData = md.digest(data);
return toHex(digestData);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
public static String toHex(byte input[]) {
if (input == null)
return null;
StringBuffer output = new StringBuffer(input.length * 2);
for (int i = 0; i < input.length; i++) {
int current = input[i] & 0xff;
if (current < 16)
output.append("0");
output.append(Integer.toString(current, 16));
}
return output.toString();
}
/** map 转换为 url参数 **/
public static String genUrlParams(Map<String, Object> paraMap) {
if(paraMap == null || paraMap.isEmpty()) return "";
StringBuffer urlParam = new StringBuffer();
Set<String> keySet = paraMap.keySet();
int i = 0;
for(String key:keySet) {
urlParam.append(key).append("=").append( paraMap.get(key) == null ? "" : paraMap.get(key) );
if(++i == keySet.size()) break;
urlParam.append("&");
}
return urlParam.toString();
}
/** 校验微信/支付宝二维码是否符合规范, 并根据支付类型返回对应的支付方式 **/
public static String getPayWayCodeByBarCode(String barCode){
if(StringUtils.isEmpty(barCode)) throw new BizException("条码为空");
//微信 用户付款码条形码规则18位纯数字以101112131415开头
//文档 https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=5_1
if(barCode.length() == 18 && Pattern.matches("^(10|11|12|13|14|15)(.*)", barCode)){
return CS.PAY_WAY_CODE.WX_BAR;
}
//支付宝 25~30开头的长度为16~24位的数字
//文档 https://docs.open.alipay.com/api_1/alipay.trade.pay/
else if(barCode.length() >= 16 && barCode.length() <= 24 && Pattern.matches("^(25|26|27|28|29|30)(.*)", barCode)){
return CS.PAY_WAY_CODE.ALI_BAR;
}
//云闪付 二维码标准 19位 + 62开头
//文档https://wenku.baidu.com/view/b2eddcd09a89680203d8ce2f0066f5335a8167fa.html
else if(barCode.length() == 19 && Pattern.matches("^(62)(.*)", barCode)){
return CS.PAY_WAY_CODE.YSF_BAR;
}
else{ //暂时不支持的条码类型
throw new BizException("不支持的条码");
}
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.utils;
import com.alibaba.fastjson.JSONObject;
/*
* json工具类
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:51
*/
public class JsonKit {
public static JSONObject newJson(String key, Object val){
JSONObject result = new JSONObject();
result.put(key, val);
return result;
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.utils;
/*
*
* 正则验证kit
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:56
*/
public class RegKit {
public static final String REG_MOBILE = "^1\\d{10}$"; //判断是否是手机号
public static boolean isMobile(String str){
return match(str, REG_MOBILE);
}
/** 正则验证 */
public static boolean match(String text, String reg){
if(text == null) return false;
return text.matches(reg);
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.utils;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import java.util.Date;
import java.util.concurrent.atomic.AtomicLong;
/*
* 序列号生成 工具类
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:56
*/
public class SeqKit {
private static final AtomicLong BUY_ORDER_SEQ = new AtomicLong(0L);
private static final String BUY_ORDER_SEQ_PREFIX = "P";
/** 生成购买订单ID **/
public static String genPayOrderId() {
return String.format("%s%s%04d",BUY_ORDER_SEQ_PREFIX,
DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN),
(int) BUY_ORDER_SEQ.getAndIncrement() % 10000);
}
}

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.utils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* @description: Spring 框架下, 获取Beans静态函数方法
* @Author terrfly
* @Date 2019/12/31 13:57
*/
@Component
public class SpringBeansUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(SpringBeansUtil.applicationContext == null){
SpringBeansUtil.applicationContext = applicationContext;
}
}
/** 获取applicationContext */
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/** 通过name获取 Bean. */
public static Object getBean(String name){
if(!getApplicationContext().containsBean(name)){
return null;
}
return getApplicationContext().getBean(name);
}
/** 通过class获取Bean. */
public static <T> T getBean(Class<T> clazz){
try {
return getApplicationContext().getBean(clazz);
} catch (BeansException e) {
return null;
}
}
/** 通过name,以及Clazz返回指定的Bean */
public static <T> T getBean(String name, Class<T> clazz){
if(!getApplicationContext().containsBean(name)){
return null;
}
return getApplicationContext().getBean(name, clazz);
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.utils;
import java.util.UUID;
/*
* String 工具类
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 16:58
*/
public class StringKit {
public static String getUUID(){
return UUID.randomUUID().toString().replace("-", "") + Thread.currentThread().getId();
}
public static String getUUID(int endAt){
return getUUID().substring(0, endAt);
}
}

View File

@ -0,0 +1,183 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.utils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/*
* [ 通用树状结构构造器 ]
* 解决 将数据库查询到的多行List 转换为层级关系的树状结构
* 使用方式
* 1. 先将查询的到对象List转换为JSONObject List
* 在转换过程中JSONObject中必须包含 [id, pid](字段名称可自定义) 必须是String类型
* 2. 使用构造函数创建对象参数为转换好的对象 如果自定义字段key 则将字段名称一并传入
* 3. 使用buildTreeString() 或者 buildTreeObject() 生成所需对象
*
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2019/12/8 06:37
*/
public class TreeDataBuilder {
/** 私有构造器 + 指定参数构造器 **/
private TreeDataBuilder(){}
public TreeDataBuilder(Collection nodes) {
super();
this.nodes = nodes;
}
public TreeDataBuilder(Collection nodes, String idName, String pidName, String childrenName) {
super();
this.nodes = nodes;
this.idName = idName;
this.sortName = idName; //排序字段按照idName
this.pidName = pidName;
this.childrenName = childrenName;
}
/** 自定义字段 + 排序标志 **/
public TreeDataBuilder(Collection nodes, String idName, String pidName, String childrenName, String sortName, boolean isAscSort) {
super();
this.nodes = nodes;
this.idName = idName;
this.pidName = pidName;
this.childrenName = childrenName;
this.sortName = sortName;
this.isAscSort = isAscSort;
}
/** 所有数据集合 **/
private Collection<JSONObject> nodes;
/** 默认数据中的主键key */
private String idName = "id";
/** 默认数据中的父级id的key */
private String pidName = "pid";
/** 默认数据中的子类对象key */
private String childrenName = "children";
/** 排序字段, 默认按照ID排序 **/
private String sortName = idName;
/** 默认按照升序排序 **/
private boolean isAscSort = true;
// 构建JSON树形结构
public String buildTreeString() {
List<JSONObject> nodeTree = buildTreeObject();
JSONArray jsonArray = new JSONArray();
nodeTree.stream().forEach(item -> jsonArray.add(item));
return jsonArray.toString();
}
// 构建树形结构
public List<JSONObject> buildTreeObject() {
//定义待返回的对象
List<JSONObject> resultNodes = new ArrayList<>();
//获取所有的根节点 考虑根节点有多个的情况 将根节点单独处理
List<JSONObject> rootNodes = getRootNodes();
listSort(rootNodes); //排序
//遍历根节点对象
for (JSONObject rootNode : rootNodes) {
buildChildNodes(rootNode); //递归查找子节点并设置
resultNodes.add(rootNode); //添加到对象信息
}
return resultNodes;
}
/** 递归查找并赋值子节点 **/
private void buildChildNodes(JSONObject node) {
List<JSONObject> children = getChildNodes(node);
if (!children.isEmpty()) {
for (JSONObject child : children) {
buildChildNodes(child);
}
listSort(children); //排序
node.put(childrenName, children);
}
}
/** 查找当前节点的子节点 */
private List<JSONObject> getChildNodes(JSONObject currentNode) {
List<JSONObject> childNodes = new ArrayList<>();
for (JSONObject n : nodes) {
if (currentNode.getString(idName).equals(n.getString(pidName))) {
childNodes.add(n);
}
}
return childNodes;
}
/** 判断是否为根节点 */
private boolean isRootNode(JSONObject node) {
boolean isRootNode = true;
for (JSONObject n : nodes) {
if (node.getString(pidName) != null && node.getString(pidName).equals(n.getString(idName))) {
isRootNode = false;
break;
}
}
return isRootNode;
}
/** 获取集合中所有的根节点 */
private List<JSONObject> getRootNodes() {
List<JSONObject> rootNodes = new ArrayList<>();
for (JSONObject n : nodes) {
if (isRootNode(n)) {
rootNodes.add(n);
}
}
return rootNodes;
}
/** 将list进行排序 */
private void listSort(List<JSONObject> list){
Collections.sort(list, (o1, o2) -> {
int result;
if(o1.get(sortName) instanceof Integer){
result = o1.getInteger(sortName).compareTo(o2.getInteger(sortName));
}else{
result = o1.get(sortName).toString().compareTo(o2.get(sortName).toString());
}
if(!isAscSort){ //倒序 取反数
return -result;
}
return result;
});
}
}

View File

View File

112
jeepay-manager/pom.xml Normal file
View File

@ -0,0 +1,112 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <!-- POM模型版本 -->
<groupId>com.jeequan</groupId> <!-- 组织名, 类似于包名 -->
<artifactId>jeepay-manager</artifactId> <!-- 项目名称 -->
<packaging>jar</packaging> <!-- 项目的最终打包类型/发布形式, 可选[jar, war, pom, maven-plugin]等 -->
<version>${isys.version}</version> <!-- 项目当前版本号 -->
<description>Jeepay计全支付系统 [运营后台管理端]</description> <!-- 项目描述 -->
<url>https://www.jeequan.com</url>
<parent>
<groupId>com.jeequan</groupId>
<artifactId>jeepay</artifactId>
<version>1.0.0</version>
</parent>
<!-- 项目依赖声明 -->
<dependencies>
<!-- 依赖[ service ]包, 会自动传递依赖[ core ]包。 -->
<dependency>
<groupId>com.jeequan</groupId>
<artifactId>jeepay-service</artifactId>
<version>${isys.version}</version>
</dependency>
<!-- 依赖 sping-boot-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion> <!-- 删除spring boot默认json映射器 Jackson 引入fastJSON -->
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
</exclusion>
<exclusion> <!-- hibernate.validator插件一般不使用 -->
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- spring-security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<!-- spring-aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- freemarker -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- 添加redis支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 添加对activeMQ的支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
</dependencies>
<!-- 作为可执行jar -->
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,164 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.aop;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.beans.RequestKitBean;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.SysLog;
import com.jeequan.jeepay.core.model.security.JeeUserDetails;
import com.jeequan.jeepay.service.impl.SysLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
/**
* 方法级日志切面组件
*
* @author terrfly
* @modify pangxiaoyu
* @site https://www.jeepay.vip
* @date 2021-06-07 07:15
*/
@Component
@Aspect
public class MethodLogAop {
private static final Logger logger = LoggerFactory.getLogger(MethodLogAop.class);
@Autowired
private SysLogService sysLogService;
@Autowired private RequestKitBean requestKitBean;
/**
* 异步处理线程池
*/
private final static ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10);
/**
* 切点
*/
@Pointcut("@annotation(com.jeequan.jeepay.core.aop.MethodLog)")
public void methodCachePointcut() { }
/**
* 切面
* @param point
* @return
* @throws Throwable
*/
@Around("methodCachePointcut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
final SysLog sysLog = new SysLog();
// 基础日志信息
setBaseLogInfo(point, sysLog);
//处理切面任务 发生异常将向外抛出 不记录日志
Object result = point.proceed();
try {
sysLog.setUserId(JeeUserDetails.getCurrentUserDetails().getSysUser().getSysUserId());
sysLog.setUserName(JeeUserDetails.getCurrentUserDetails().getSysUser().getRealname());
sysLog.setSystem(JeeUserDetails.getCurrentUserDetails().getSysUser().getSystem());
sysLog.setOptResInfo(JSONObject.toJSON(result).toString());
scheduledThreadPool.execute(() -> sysLogService.save(sysLog));
} catch (Exception e) {
logger.error("methodLogError", e);
}
return result;
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 14:04
* @describe: 记录异常操作请求信息
*/
@AfterThrowing(pointcut = "methodCachePointcut()", throwing="e")
public void doException(JoinPoint joinPoint, Throwable e) throws Exception{
final SysLog sysLog = new SysLog();
// 基础日志信息
setBaseLogInfo(joinPoint, sysLog);
sysLog.setOptResInfo("请求异常");
scheduledThreadPool.execute(() -> sysLogService.save(sysLog));
}
/**
* 获取方法中的中文备注
* @param joinPoint
* @return
* @throws Exception
*/
public static String getAnnotationRemark(JoinPoint joinPoint) throws Exception {
Signature sig = joinPoint.getSignature();
Method m = joinPoint.getTarget().getClass().getMethod(joinPoint.getSignature().getName(), ((MethodSignature) sig).getParameterTypes());
MethodLog methodCache = m.getAnnotation(MethodLog.class);
if (methodCache != null) {
return methodCache.remark();
}
return "";
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 14:12
* @describe: 日志基本信息 公共方法
*/
private void setBaseLogInfo(JoinPoint joinPoint, SysLog sysLog) throws Exception {
// 使用point.getArgs()可获取request仅限于spring MVC参数包含request改为通过contextHolder获取
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//请求参数
sysLog.setOptReqParam( requestKitBean.getReqParamJSON().toJSONString() );
//注解备注
sysLog.setMethodRemark(getAnnotationRemark(joinPoint));
//包名 方法名
String methodName = joinPoint.getSignature().getName();
String packageName = joinPoint.getThis().getClass().getName();
if (packageName.indexOf("$$EnhancerByCGLIB$$") > -1 || packageName.indexOf("$$EnhancerBySpringCGLIB$$") > -1) { // 如果是CGLIB动态生成的类
packageName = packageName.substring(0, packageName.indexOf("$$"));
}
sysLog.setMethodName(packageName + "." + methodName);
sysLog.setReqUrl(request.getRequestURL().toString());
sysLog.setUserIp(requestKitBean.getClientIp());
sysLog.setCreatedAt(new Date());
sysLog.setSystem(CS.SYS_TYPE.MGR);
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.bootstrap;
import cn.hutool.core.date.DatePattern;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.Date;
/*
* 项目初始化操作
* 比如初始化配置文件 读取基础数据 资源初始化等 避免在Main函数中写业务代码
* CommandLineRunner / ApplicationRunner都可以达到要求 只是调用参数有所不同
*
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:04
*/
@Component
public class InitRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
//初始化处理fastjson格式
SerializeConfig serializeConfig = SerializeConfig.getGlobalInstance();
serializeConfig.put(Date.class, new SimpleDateFormatSerializer(DatePattern.NORM_DATETIME_PATTERN));
//解决json 序列化时候的 $ref问题
JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();
}
}

View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.bootstrap;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.EnableScheduling;
import java.util.Arrays;
/*
* spring-boot 主启动程序
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2019/11/7 15:19
*/
@SpringBootApplication
@EnableScheduling
@MapperScan("com.jeequan.jeepay.service.mapper") //Mybatis mapper接口路径
@ComponentScan(basePackages = "com.jeequan.jeepay.*") //由于MainApplication没有在项目根目录 需要配置basePackages属性使得成功扫描所有Spring组件
@Configuration
public class JeepayMgrApplication {
/** main启动函数 **/
public static void main(String[] args) {
//启动项目
SpringApplication.run(JeepayMgrApplication.class, args);
}
/** fastJson 配置信息 **/
@Bean
public HttpMessageConverters fastJsonConfig(){
//新建fast-json转换器
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
//fast-json 配置信息
FastJsonConfig config = new FastJsonConfig();
config.setDateFormat("yyyy-MM-dd HH:mm:ss");
converter.setFastJsonConfig(config);
//设置响应的 Content-Type
converter.setSupportedMediaTypes(Arrays.asList(new MediaType[]{MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON_UTF8}));
return new HttpMessageConverters(converter);
}
/** Mybatis plus 分页插件 **/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// 设置请求的页面大于最大页后操作 true调回到首页false 继续请求 默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量默认 500 -1 不受限制
// paginationInterceptor.setLimit(500);
return paginationInterceptor;
}
}

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.config;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
/*
* Redis配置类
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:05
*/
@Configuration
public class RedisConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private Integer port;
@Value("${spring.redis.timeout}")
private Integer timeout;
@Value("${spring.redis.database}")
private Integer defaultDatabase;
@Value("${spring.redis.password}")
private String password;
/** 当前系统的redis缓存操作对象 (主对象) **/
@Primary
@Bean(name = "defaultStringRedisTemplate")
public StringRedisTemplate sysStringRedisTemplate() {
StringRedisTemplate template = new StringRedisTemplate();
LettuceConnectionFactory jedisConnectionFactory = new LettuceConnectionFactory();
jedisConnectionFactory.setHostName(host);
jedisConnectionFactory.setPort(port);
jedisConnectionFactory.setTimeout(timeout);
if (!StringUtils.isEmpty(password)) {
jedisConnectionFactory.setPassword(password);
}
if (defaultDatabase != 0) {
jedisConnectionFactory.setDatabase(defaultDatabase);
}
jedisConnectionFactory.afterPropertiesSet();
template.setConnectionFactory(jedisConnectionFactory);
return template;
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.stereotype.Component;
/**
* 系统Yml配置参数定义Bean
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021-04-27 15:50
*/
@Data
@Component
@ConfigurationProperties(prefix="isys")
public class SystemYmlConfig {
/** 是否允许跨域请求 [生产环境建议关闭, 若api与前端项目没有在同一个域名下时应开启此配置或在nginx统一配置允许跨域] **/
private Boolean allowCors;
/** 生成jwt的秘钥。 要求每个系统有单独的秘钥管理机制。 **/
private String jwtSecret;
@NestedConfigurationProperty //指定该属性为嵌套值, 否则默认为简单值导致对象为空外部类不存在该问题 内部static需明确指定
private OssFile ossFile;
/** 系统oss配置信息 **/
@Data
public static class OssFile{
/** 存储根路径 **/
private String rootPath;
/** 公共读取块 **/
private String publicPath;
/** 私有读取块 **/
private String privatePath;
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl;
import com.jeequan.jeepay.core.ctrls.AbstractCtrl;
import com.jeequan.jeepay.core.model.security.JeeUserDetails;
import com.jeequan.jeepay.mgr.config.SystemYmlConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
/*
* 定义通用CommonCtrl
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:09
*/
public abstract class CommonCtrl extends AbstractCtrl {
@Autowired
protected SystemYmlConfig mainConfig;
/** 获取当前用户ID */
protected JeeUserDetails getCurrentUser(){
return (JeeUserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
}
/**
* 获取当前用户登录IP
* @return
*/
protected String getIp() {
return getClientIp();
}
}

View File

@ -0,0 +1,151 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.cache.ITokenService;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.SysEntitlement;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.utils.TreeDataBuilder;
import com.jeequan.jeepay.core.model.security.JeeUserDetails;
import com.jeequan.jeepay.service.impl.SysEntitlementService;
import com.jeequan.jeepay.service.impl.SysUserAuthService;
import com.jeequan.jeepay.service.impl.SysUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
/*
* 当前登录者的信息相关接口
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:10
*/
@RestController
@RequestMapping("api/current")
public class CurrentUserController extends CommonCtrl{
@Autowired private SysEntitlementService sysEntitlementService;
@Autowired private SysUserService sysUserService;
@Autowired private SysUserAuthService sysUserAuthService;
@RequestMapping(value="/user", method = RequestMethod.GET)
public ApiRes currentUserInfo() {
///当前用户信息
JeeUserDetails jeeUserDetails = getCurrentUser();
SysUser user = jeeUserDetails.getSysUser();
//1. 当前用户所有权限ID集合
List<String> entIdList = new ArrayList<>();
jeeUserDetails.getAuthorities().stream().forEach(r->entIdList.add(r.getAuthority()));
List<SysEntitlement> allMenuList = new ArrayList<>(); //所有菜单集合
//2. 查询出用户所有菜单集合 (包含左侧显示菜单 其他类型菜单 )
if(entIdList != null && !entIdList.isEmpty()){
allMenuList = sysEntitlementService.list(SysEntitlement.gw()
.in(SysEntitlement::getEntId, entIdList)
.in(SysEntitlement::getEntType, Arrays.asList(CS.ENT_TYPE.MENU_LEFT, CS.ENT_TYPE.MENU_OTHER))
.eq(SysEntitlement::getSystem, CS.SYS_TYPE.MGR)
.eq(SysEntitlement::getState, CS.PUB_USABLE));
}
//4. 转换为json树状结构
JSONArray jsonArray = (JSONArray) JSONArray.toJSON(allMenuList);
List<JSONObject> allMenuRouteTree = new TreeDataBuilder(jsonArray,
"entId", "pid", "children", "entSort", true)
.buildTreeObject();
//1. 所有权限ID集合
user.addExt("entIdList", entIdList);
user.addExt("allMenuRouteTree", allMenuRouteTree);
return ApiRes.ok(getCurrentUser().getSysUser());
}
/** 修改个人信息 */
@RequestMapping(value="/user", method = RequestMethod.PUT)
@MethodLog(remark = "修改信息")
public ApiRes modifyCurrentUserInfo() {
//修改头像
String avatarUrl = getValString("avatarUrl");
String realname = getValString("realname");
Byte sex = getValByte("sex");
SysUser updateRecord = new SysUser();
updateRecord.setSysUserId(getCurrentUser().getSysUser().getSysUserId());
if (StringUtils.isNotEmpty(avatarUrl)) updateRecord.setAvatarUrl(avatarUrl);
if (StringUtils.isNotEmpty(realname)) updateRecord.setRealname(realname);
if (sex != null) updateRecord.setSex(sex);
sysUserService.updateById(updateRecord);
//保存redis最新数据
JeeUserDetails currentUser = getCurrentUser();
currentUser.setSysUser(sysUserService.getById(getCurrentUser().getSysUser().getSysUserId()));
ITokenService.refData(currentUser);
return ApiRes.ok();
}
/** 修改密码 */
@RequestMapping(value="modifyPwd", method = RequestMethod.PUT)
@MethodLog(remark = "修改密码")
public ApiRes modifyPwd() throws BizException{
//更改密码 验证当前用户信息
String currentUserPwd = getValStringRequired("originalPwd"); //当前用户登录密码
//验证当前密码是否正确
if(!sysUserAuthService.validateCurrentUserPwd(currentUserPwd)){
throw new BizException("原密码验证失败!");
}
String opUserPwd = getValStringRequired("confirmPwd");
// 验证原密码与新密码是否相同
if (opUserPwd.equals(currentUserPwd)) {
throw new BizException("新密码与原密码不能相同!");
}
sysUserAuthService.resetAuthInfo(getCurrentUser().getSysUser().getSysUserId(), null, null, opUserPwd, CS.SYS_TYPE.MGR);
//调用登出接口
return logout();
}
// /** 登出 */
// @RequestMapping(value="logout", method = RequestMethod.POST)
// @MethodLog(remark = "登出")
public ApiRes logout() throws BizException{
ITokenService.removeIToken(getCurrentUser().getCacheKey(), getCurrentUser().getSysUser().getSysUserId());
return ApiRes.ok();
}
}

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.anon;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.cache.RedisUtil;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.mgr.service.AuthService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/*
* 认证接口
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:09
*/
@RestController
@RequestMapping("/api/anon/auth")
public class AuthController extends CommonCtrl {
@Autowired private AuthService authService;
/** 用户信息认证 获取iToken **/
@RequestMapping(value = "/validate", method = RequestMethod.POST)
@MethodLog(remark = "登录认证")
public ApiRes validate() throws BizException {
String account = Base64.decodeStr(getValStringRequired("ia")); //用户名 i account, 已做base64处理
String ipassport = Base64.decodeStr(getValStringRequired("ip")); //密码 i passport, 已做base64处理
String vercode = Base64.decodeStr(getValStringRequired("vc")); //验证码 vercode, 已做base64处理
String vercodeToken = Base64.decodeStr(getValStringRequired("vt")); //验证码token, vercode token , 已做base64处理
String cacheCode = RedisUtil.getString(CS.getCacheKeyImgCode(vercodeToken));
if(StringUtils.isEmpty(cacheCode) || !cacheCode.equalsIgnoreCase(vercode)){
throw new BizException("验证码有误!");
}
// 返回前端 accessToken
String accessToken = authService.auth(account, ipassport);
// 删除图形验证码缓存数据
RedisUtil.del(CS.getCacheKeyImgCode(vercodeToken));
return ApiRes.ok4newJson(CS.ACCESS_TOKEN_NAME, accessToken);
}
/** 图片验证码 **/
@RequestMapping(value = "/vercode", method = RequestMethod.GET)
public ApiRes vercode() throws BizException {
//定义图形验证码的长和宽 // 4位验证码
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(137, 40, 4, 80);
lineCaptcha.createCode(); //生成code
//redis
String vercodeToken = UUID.fastUUID().toString();
RedisUtil.setString(CS.getCacheKeyImgCode(vercodeToken), lineCaptcha.getCode(), 60 ); //图片验证码缓存时间: 1分钟
JSONObject result = new JSONObject();
result.put("imageBase64Data", lineCaptcha.getImageBase64Data());
result.put("vercodeToken", vercodeToken);
return ApiRes.ok(result);
}
}

View File

@ -0,0 +1,111 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.common;
import cn.hutool.core.lang.UUID;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.OssFileConfig;
import com.jeequan.jeepay.core.utils.FileKit;
import com.jeequan.jeepay.mgr.config.SystemYmlConfig;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.SysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
/*
* 统一文件上传接口ossFile
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:07
*/
@RestController
@RequestMapping("/api/ossFiles")
public class OssFileController extends CommonCtrl {
@Autowired private SystemYmlConfig systemYmlConfig;
@Autowired private SysConfigService sysConfigService;
/** 上传文件 (单文件上传) */
@PostMapping("/{bizType}")
public ApiRes singleFileUpload(@RequestParam("file") MultipartFile file, @PathVariable("bizType") String bizType) {
if( file == null ) return ApiRes.fail(ApiCodeEnum.SYSTEM_ERROR, "选择文件不存在");
try {
OssFileConfig ossFileConfig = OssFileConfig.getOssFileConfigByBizType(bizType);
//1. 判断bizType 是否可用
if(ossFileConfig == null){
throw new BizException("类型有误");
}
// 2. 判断文件是否支持
String fileSuffix = FileKit.getFileSuffix(file.getOriginalFilename(), false);
if( !ossFileConfig.isAllowFileSuffix(fileSuffix) ){
throw new BizException("上传文件格式不支持!");
}
// 3. 判断文件大小是否超限
if( !ossFileConfig.isMaxSizeLimit(file.getSize()) ){
throw new BizException("上传大小请限制在["+ossFileConfig.getMaxSize() / 1024 / 1024 +"M]以内!");
}
boolean isAllowPublicRead = ossFileConfig.isAllowPublicRead(); //是否允许公共读 true公共读 false私有文件
//公共读 & 是否上传到oss
boolean isYunOss = false; //TODO 暂时不支持云oss方式
if(isAllowPublicRead && isYunOss){
return null;
}
//以下为文件上传到本地
// 新文件地址
String newFileName = UUID.fastUUID() + "." + fileSuffix;
// 保存的文件夹名称
String saveFilePath = isAllowPublicRead ? systemYmlConfig.getOssFile().getPublicPath() : systemYmlConfig.getOssFile().getPrivatePath();
saveFilePath = saveFilePath + File.separator + bizType + File.separator + newFileName;
//保存文件
saveFile(file, saveFilePath);
//返回响应结果
String resultUrl = bizType + "/" + newFileName;
if(isAllowPublicRead){ //允许公共读取
resultUrl = sysConfigService.getDBApplicationConfig().getOssPublicSiteUrl() + "/" + resultUrl;
}
return ApiRes.ok(resultUrl);
} catch (BizException biz) {
throw biz;
} catch (Exception e) {
logger.error("upload error, fileName = {}", file == null ? null :file.getOriginalFilename(), e);
throw new BizException(ApiCodeEnum.SYSTEM_ERROR);
}
}
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.common;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
/*
* 静态文件下载/预览 ctrl
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:08
*/
@Controller
public class StaticController extends CommonCtrl {
/** 图片预览 **/
@GetMapping("/api/anon/localOssFiles/**/*.*")
public ResponseEntity<?> imgView() {
try {
//查找图片文件
File imgFile = new File(mainConfig.getOssFile().getPublicPath() + File.separator + request.getRequestURI().substring(24));
if(!imgFile.isFile() || !imgFile.exists()) return new ResponseEntity<>(HttpStatus.NOT_FOUND);
//输出文件流图片格式
HttpHeaders httpHeaders = new HttpHeaders();
// httpHeaders.setContentType(MediaType.IMAGE_JPEG); //图片格式
InputStream inputStream = new FileInputStream(imgFile);
return new ResponseEntity<>(new InputStreamResource(inputStream), httpHeaders, HttpStatus.OK);
} catch (FileNotFoundException e) {
logger.error("static file error", e);
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}

View File

@ -0,0 +1,104 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.config;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.PayOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 首页统计类
*
* @author pangxiaoyu
* @site https://www.jeepay.vip
* @date 2021-06-07 07:15
*/
@Slf4j
@RestController
@RequestMapping("api/mainChart")
public class MainChartController extends CommonCtrl {
@Autowired private PayOrderService payOrderService;
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:18
* @describe: 周交易总金额
*/
@PreAuthorize("hasAuthority('ENT_C_MAIN_PAY_AMOUNT_WEEK')")
@RequestMapping(value="/payAmountWeek", method = RequestMethod.GET)
public ApiRes payAmountWeek() {
return ApiRes.ok(payOrderService.mainPageWeekCount(null));
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:18
* @describe: 商户总数量服务商总数量总交易金额总交易笔数
*/
@PreAuthorize("hasAuthority('ENT_C_MAIN_NUMBER_COUNT')")
@RequestMapping(value="/numCount", method = RequestMethod.GET)
public ApiRes numCount() {
JSONObject json = payOrderService.mainPageNumCount(null);
//返回数据
return ApiRes.ok(json);
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:18
* @describe: 交易统计
*/
@PreAuthorize("hasAuthority('ENT_C_MAIN_PAY_COUNT')")
@RequestMapping(value="/payCount", method = RequestMethod.GET)
public ApiRes payCount() {
// 获取传入参数
JSONObject paramJSON = getReqParamJSON();
String createdStart = paramJSON.getString("createdStart");
String createdEnd = paramJSON.getString("createdEnd");
List<Map> mapList = payOrderService.mainPagePayCount(null, createdStart, createdEnd);
//返回数据
return ApiRes.ok(mapList);
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:18
* @describe: 支付方式统计
*/
@PreAuthorize("hasAuthority('ENT_C_MAIN_PAY_TYPE_COUNT')")
@RequestMapping(value="/payTypeCount", method = RequestMethod.GET)
public ApiRes payWayCount() {
JSONObject paramJSON = getReqParamJSON();
// 开始结束时间
String createdStart = paramJSON.getString("createdStart");
String createdEnd = paramJSON.getString("createdEnd");
ArrayList arrayResult = payOrderService.mainPagePayTypeCount(null, createdStart, createdEnd);
return ApiRes.ok(arrayResult);
}
}

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.config;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.entity.SysConfig;
import com.jeequan.jeepay.core.utils.StringKit;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.mgr.mq.topic.MqTopic4ModifySysConfig;
import com.jeequan.jeepay.service.impl.SysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 系统配置信息类
*
* @author pangxiaoyu
* @site https://www.jeepay.vip
* @date 2021-06-07 07:15
*/
@Slf4j
@RestController
@RequestMapping("api/sysConfigs")
public class SysConfigController extends CommonCtrl {
@Autowired private SysConfigService sysConfigService;
@Autowired private MqTopic4ModifySysConfig mqTopic4ModifySysConfig;
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:19
* @describe: 分组下的配置
*/
@PreAuthorize("hasAuthority('ENT_SYS_CONFIG_INFO')")
@RequestMapping(value="/{groupKey}", method = RequestMethod.GET)
public ApiRes getConfigs(@PathVariable("groupKey") String groupKey) {
LambdaQueryWrapper<SysConfig> condition = SysConfig.gw();
condition.orderByAsc(SysConfig::getSortNum);
if(StringUtils.isNotEmpty(groupKey)){
condition.eq(SysConfig::getGroupKey, groupKey);
}
List<SysConfig> configList = sysConfigService.list(condition);
//返回数据
return ApiRes.ok(configList);
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:19
* @describe: 系统配置修改
*/
@PreAuthorize("hasAuthority('ENT_SYS_CONFIG_EDIT')")
@MethodLog(remark = "系统配置修改")
@RequestMapping(value="/{groupKey}", method = RequestMethod.PUT)
public ApiRes update(@PathVariable("groupKey") String groupKey) {
JSONObject paramJSON = getReqParamJSON();
Map<String, String> updateMap = JSONObject.toJavaObject(paramJSON, Map.class);
int update = sysConfigService.updateByConfigKey(updateMap);
if(update <= 0) return ApiRes.fail(ApiCodeEnum.SYSTEM_ERROR, "更新失败");
mqTopic4ModifySysConfig.push(groupKey);
return ApiRes.ok();
}
}

View File

@ -0,0 +1,131 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.isv;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.entity.IsvInfo;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.mgr.mq.topic.MqTopic4ModifyIsvInfo;
import com.jeequan.jeepay.service.impl.IsvInfoService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* 服务商管理类
*
* @author pangxiaoyu
* @site https://www.jeepay.vip
* @date 2021-06-07 07:15
*/
@RestController
@RequestMapping("/api/isvInfo")
public class IsvInfoController extends CommonCtrl {
@Autowired private IsvInfoService isvInfoService;
@Autowired private MqTopic4ModifyIsvInfo mqTopic4ModifyIsvInfo;
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:12
* @describe: 查询服务商信息列表
*/
@PreAuthorize("hasAuthority('ENT_ISV_INFO_LIST')")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes list() {
IsvInfo isvInfo = getObject(IsvInfo.class);
LambdaQueryWrapper<IsvInfo> wrapper = IsvInfo.gw();
if (StringUtils.isNotEmpty(isvInfo.getIsvNo())) wrapper.eq(IsvInfo::getIsvNo, isvInfo.getIsvNo());
if (StringUtils.isNotEmpty(isvInfo.getIsvName())) wrapper.eq(IsvInfo::getIsvName, isvInfo.getIsvName());
if (isvInfo.getState() != null) wrapper.eq(IsvInfo::getState, isvInfo.getState());
wrapper.orderByDesc(IsvInfo::getCreatedAt);
IPage<IsvInfo> pages = isvInfoService.page(getIPage(true), wrapper);
return ApiRes.page(pages);
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:13
* @describe: 新增服务商信息
*/
@PreAuthorize("hasAuthority('ENT_ISV_INFO_ADD')")
@MethodLog(remark = "新增服务商")
@RequestMapping(value="", method = RequestMethod.POST)
public ApiRes add() {
IsvInfo isvInfo = getObject(IsvInfo.class);
String isvNo = "V" + DateUtil.currentSeconds();
isvInfo.setIsvNo(isvNo);
isvInfo.setCreatedUid(getCurrentUser().getSysUser().getSysUserId());
isvInfo.setCreatedBy(getCurrentUser().getSysUser().getRealname());
boolean result = isvInfoService.save(isvInfo);
if (!result) return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE);
return ApiRes.ok();
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:13
* @describe: 删除服务商信息
*/
@PreAuthorize("hasAuthority('ENT_ISV_INFO_DEL')")
@MethodLog(remark = "删除服务商")
@RequestMapping(value="/{isvNo}", method = RequestMethod.DELETE)
public ApiRes delete(@PathVariable("isvNo") String isvNo) {
isvInfoService.removeByIsvNo(isvNo);
mqTopic4ModifyIsvInfo.push(isvNo); // 推送mq到目前节点进行更新数据
return ApiRes.ok();
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:13
* @describe: 更新服务商信息
*/
@PreAuthorize("hasAuthority('ENT_ISV_INFO_EDIT')")
@MethodLog(remark = "更新服务商信息")
@RequestMapping(value="/{isvNo}", method = RequestMethod.PUT)
public ApiRes update(@PathVariable("isvNo") String isvNo) {
IsvInfo isvInfo = getObject(IsvInfo.class);
isvInfo.setIsvNo(isvNo);
boolean result = isvInfoService.updateById(isvInfo);
mqTopic4ModifyIsvInfo.push(isvNo); // 推送mq到目前节点进行更新数据
if (!result) return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
return ApiRes.ok();
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:13
* @describe: 查看服务商信息
*/
@PreAuthorize("hasAnyAuthority('ENT_ISV_INFO_VIEW', 'ENT_ISV_INFO_EDIT')")
@RequestMapping(value="/{isvNo}", method = RequestMethod.GET)
public ApiRes detail(@PathVariable("isvNo") String isvNo) {
IsvInfo isvInfo = isvInfoService.getById(isvNo);
if (isvInfo == null) return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SELETE);
return ApiRes.ok(isvInfo);
}
}

View File

@ -0,0 +1,121 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.isv;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayInterfaceConfig;
import com.jeequan.jeepay.core.entity.PayInterfaceDefine;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.mgr.mq.topic.MqTopic4ModifyIsvInfo;
import com.jeequan.jeepay.service.impl.PayInterfaceConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.List;
/**
* 服务商支付接口管理类
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021-04-27 15:50
*/
@RestController
@RequestMapping("/api/isv/payConfigs")
public class IsvPayInterfaceConfigController extends CommonCtrl {
@Autowired private PayInterfaceConfigService payInterfaceConfigService;
@Autowired private MqTopic4ModifyIsvInfo mqTopic4ModifyIsvInfo;
/**
* @Author: ZhuXiao
* @Description: 查询服务商支付接口配置列表
* @Date: 16:45 2021/4/27
*/
@PreAuthorize("hasAuthority('ENT_ISV_PAY_CONFIG_LIST')")
@GetMapping
public ApiRes list() {
List<PayInterfaceDefine> list = payInterfaceConfigService.selectAllPayIfConfigListByInfoId(CS.INFO_TYPE_ISV, getValStringRequired("isvNo"));
return ApiRes.ok(list);
}
/**
* @Author: ZhuXiao
* @Description: 根据 服务商号接口类型 获取商户参数配置
* @Date: 17:03 2021/4/27
*/
@PreAuthorize("hasAuthority('ENT_ISV_PAY_CONFIG_VIEW')")
@GetMapping("/{isvNo}/{ifCode}")
public ApiRes getByMchNo(@PathVariable(value = "isvNo") String isvNo, @PathVariable(value = "ifCode") String ifCode) {
PayInterfaceConfig payInterfaceConfig = payInterfaceConfigService.getByInfoIdAndIfCode(CS.INFO_TYPE_ISV, isvNo, ifCode);
if (payInterfaceConfig != null && payInterfaceConfig.getIfRate() != null) {
payInterfaceConfig.setIfRate(payInterfaceConfig.getIfRate().multiply(new BigDecimal("100")));
}
return ApiRes.ok(payInterfaceConfig);
}
/**
* @Author: ZhuXiao
* @Description: 服务商支付接口参数配置
* @Date: 16:45 2021/4/27
*/
@PreAuthorize("hasAuthority('ENT_ISV_PAY_CONFIG_ADD')")
@PostMapping
@MethodLog(remark = "更新服务商支付参数")
public ApiRes saveOrUpdate() {
String infoId = getValStringRequired("infoId");
String ifCode = getValStringRequired("ifCode");
PayInterfaceConfig payInterfaceConfig = getObject(PayInterfaceConfig.class);
payInterfaceConfig.setInfoType(CS.INFO_TYPE_ISV);
// 存入真实费率
if (payInterfaceConfig.getIfRate() != null) {
payInterfaceConfig.setIfRate(payInterfaceConfig.getIfRate().divide(new BigDecimal("100"), 6, BigDecimal.ROUND_HALF_UP));
}
//添加更新者信息
Long userId = getCurrentUser().getSysUser().getSysUserId();
String realName = getCurrentUser().getSysUser().getRealname();
payInterfaceConfig.setUpdatedUid(userId);
payInterfaceConfig.setUpdatedBy(realName);
//根据 服务商号接口类型 获取商户参数配置
PayInterfaceConfig dbRecoed = payInterfaceConfigService.getByInfoIdAndIfCode(CS.INFO_TYPE_ISV, infoId, ifCode);
//若配置存在为saveOrUpdate添加ID第一次配置添加创建者
if (dbRecoed != null) {
payInterfaceConfig.setId(dbRecoed.getId());
}else {
payInterfaceConfig.setCreatedUid(userId);
payInterfaceConfig.setCreatedBy(realName);
}
boolean result = payInterfaceConfigService.saveOrUpdate(payInterfaceConfig);
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYSTEM_ERROR, "配置失败");
}
mqTopic4ModifyIsvInfo.push(infoId); // 推送mq到目前节点进行更新数据
return ApiRes.ok();
}
}

View File

@ -0,0 +1,177 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.merchant;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.MchInfo;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.mgr.mq.queue.MqQueue4ModifyMchUserRemove;
import com.jeequan.jeepay.mgr.mq.topic.MqTopic4ModifyMchInfo;
import com.jeequan.jeepay.service.impl.MchInfoService;
import com.jeequan.jeepay.service.impl.SysUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/**
* 商户管理类
*
* @author pangxiaoyu
* @site https://www.jeepay.vip
* @date 2021-06-07 07:15
*/
@RestController
@RequestMapping("/api/mchInfo")
public class MchInfoController extends CommonCtrl {
@Autowired private MchInfoService mchInfoService;
@Autowired private SysUserService sysUserService;
@Autowired private MqTopic4ModifyMchInfo mqTopic4ModifyMchInfo;
@Autowired private MqQueue4ModifyMchUserRemove mqQueue4ModifyMchUserRemove;
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:14
* @describe: 商户信息列表
*/
@PreAuthorize("hasAuthority('ENT_MCH_INFO_LIST')")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes list() {
MchInfo mchInfo = getObject(MchInfo.class);
LambdaQueryWrapper<MchInfo> wrapper = MchInfo.gw();
if (StringUtils.isNotEmpty(mchInfo.getMchNo())) wrapper.eq(MchInfo::getMchNo, mchInfo.getMchNo());
if (StringUtils.isNotEmpty(mchInfo.getIsvNo())) wrapper.eq(MchInfo::getIsvNo, mchInfo.getIsvNo());
if (StringUtils.isNotEmpty(mchInfo.getMchName())) wrapper.eq(MchInfo::getMchName, mchInfo.getMchName());
if (mchInfo.getType() != null) wrapper.eq(MchInfo::getType, mchInfo.getType());
if (mchInfo.getState() != null) wrapper.eq(MchInfo::getState, mchInfo.getState());
wrapper.orderByDesc(MchInfo::getCreatedAt);
IPage<MchInfo> pages = mchInfoService.page(getIPage(), wrapper);
return ApiRes.page(pages);
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:14
* @describe: 新增商户信息
*/
@PreAuthorize("hasAuthority('ENT_MCH_INFO_ADD')")
@MethodLog(remark = "新增商户")
@RequestMapping(value="", method = RequestMethod.POST)
public ApiRes add() {
MchInfo mchInfo = getObject(MchInfo.class);
// 获取传入的商户登录名
String loginUserName = getValStringRequired("loginUserName");
mchInfo.setMchNo("M" + DateUtil.currentSeconds());
// 当前登录用户信息
SysUser sysUser = getCurrentUser().getSysUser();
mchInfo.setCreatedUid(sysUser.getSysUserId());
mchInfo.setCreatedBy(sysUser.getRealname());
mchInfoService.addMch(mchInfo, loginUserName);
return ApiRes.ok();
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:14
* @describe: 删除商户信息
*/
@PreAuthorize("hasAuthority('ENT_MCH_INFO_DEL')")
@MethodLog(remark = "删除商户")
@RequestMapping(value="/{mchNo}", method = RequestMethod.DELETE)
public ApiRes delete(@PathVariable("mchNo") String mchNo) {
List<Long> userIdList = mchInfoService.removeByMchNo(mchNo);
// 推送mq删除redis用户缓存
mqQueue4ModifyMchUserRemove.push(StringUtils.join(userIdList, ","));
// 推送mq到目前节点进行更新数据
mqTopic4ModifyMchInfo.push(mchNo);
return ApiRes.ok();
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:14
* @describe: 更新商户信息
*/
@PreAuthorize("hasAuthority('ENT_MCH_INFO_EDIT')")
@MethodLog(remark = "更新商户信息")
@RequestMapping(value="/{mchNo}", method = RequestMethod.PUT)
public ApiRes update(@PathVariable("mchNo") String mchNo) {
MchInfo mchInfo = getObject(MchInfo.class);
mchInfo.setMchNo(mchNo);
// 校验该商户是否为特邀商户
MchInfo dbMchInfo = mchInfoService.getById(mchNo);
if (dbMchInfo == null) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SELETE);
}
// 如果为特邀商户则不允许修改服务商及商户类型
if (dbMchInfo.getType() == CS.MCH_TYPE_ISVSUB) {
mchInfo.setType(dbMchInfo.getType());
mchInfo.setIsvNo(dbMchInfo.getIsvNo());
}
// 如果商户状态为禁用状态清除该商户用户登录信息
if (mchInfo.getState() == CS.NO) {
List<Long> userIdList = new ArrayList<>();
List<SysUser> userList = sysUserService.list(SysUser.gw()
.eq(SysUser::getBelongInfoId, mchNo)
.eq(SysUser::getSystem, CS.SYS_TYPE.MCH)
);
if (userList.size() > 0) {
for (SysUser user:userList) {
userIdList.add(user.getSysUserId());
}
}
// 推送mq删除redis用户缓存
mqQueue4ModifyMchUserRemove.push(StringUtils.join(userIdList, ","));
}
boolean result = mchInfoService.updateById(mchInfo);
mqTopic4ModifyMchInfo.push(mchNo); // 推送mq到目前节点进行更新数据
if (!result) return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
return ApiRes.ok();
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:14
* @describe: 查询商户信息
*/
@PreAuthorize("hasAnyAuthority('ENT_MCH_INFO_VIEW', 'ENT_MCH_INFO_EDIT')")
@RequestMapping(value="/{mchNo}", method = RequestMethod.GET)
public ApiRes detail(@PathVariable("mchNo") String mchNo) {
MchInfo mchInfo = mchInfoService.getById(mchNo);
if (mchInfo == null) return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SELETE);
SysUser sysUser = sysUserService.getById(mchInfo.getInitUserId());
if (sysUser != null) mchInfo.addExt("loginUserName", sysUser.getLoginUsername());
return ApiRes.ok(mchInfo);
}
}

View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.merchant;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayInterfaceConfig;
import com.jeequan.jeepay.core.entity.PayInterfaceDefine;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.mgr.mq.topic.MqTopic4ModifyMchInfo;
import com.jeequan.jeepay.service.impl.PayInterfaceConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.List;
/**
* 商户支付接口管理类
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021-04-27 15:50
*/
@RestController
@RequestMapping("/api/mch/payConfigs")
public class MchPayInterfaceConfigController extends CommonCtrl {
@Autowired private PayInterfaceConfigService payInterfaceConfigService;
@Autowired private MqTopic4ModifyMchInfo mqTopic4ModifyMchInfo;
/**
* @Author: ZhuXiao
* @Description: 查询商户支付接口配置列表
* @Date: 15:50 2021/4/27
*/
@PreAuthorize("hasAuthority('ENT_MCH_PAY_CONFIG_LIST')")
@GetMapping
public ApiRes list() {
List<PayInterfaceDefine> list = payInterfaceConfigService.selectAllPayIfConfigListByInfoId(CS.INFO_TYPE_MCH, getValStringRequired("mchNo"));
return ApiRes.ok(list);
}
/**
* @Author: ZhuXiao
* @Description: 根据 商户号接口类型 获取商户参数配置
* @Date: 17:03 2021/4/27
*/
@PreAuthorize("hasAuthority('ENT_MCH_PAY_CONFIG_VIEW')")
@GetMapping("/{mchNo}/{ifCode}")
public ApiRes getByMchNo(@PathVariable(value = "mchNo") String mchNo, @PathVariable(value = "ifCode") String ifCode) {
PayInterfaceConfig payInterfaceConfig = payInterfaceConfigService.getByInfoIdAndIfCode(CS.INFO_TYPE_MCH, mchNo, ifCode);
if (payInterfaceConfig != null && payInterfaceConfig.getIfRate() != null) {
payInterfaceConfig.setIfRate(payInterfaceConfig.getIfRate().multiply(new BigDecimal("100")));
}
return ApiRes.ok(payInterfaceConfig);
}
/**
* @Author: ZhuXiao
* @Description: 商户支付接口配置
* @Date: 16:13 2021/4/27
*/
@PreAuthorize("hasAuthority('ENT_MCH_PAY_CONFIG_ADD')")
@PostMapping
@MethodLog(remark = "更新商户支付参数")
public ApiRes saveOrUpdate() {
String infoId = getValStringRequired("infoId");
String ifCode = getValStringRequired("ifCode");
PayInterfaceConfig payInterfaceConfig = getObject(PayInterfaceConfig.class);
payInterfaceConfig.setInfoType(CS.INFO_TYPE_MCH);
// 存入真实费率
if (payInterfaceConfig.getIfRate() != null) {
payInterfaceConfig.setIfRate(payInterfaceConfig.getIfRate().divide(new BigDecimal("100"), 6, BigDecimal.ROUND_HALF_UP));
}
//添加更新者信息
Long userId = getCurrentUser().getSysUser().getSysUserId();
String realName = getCurrentUser().getSysUser().getRealname();
payInterfaceConfig.setUpdatedUid(userId);
payInterfaceConfig.setUpdatedBy(realName);
//根据 商户号接口类型 获取商户参数配置
PayInterfaceConfig dbRecoed = payInterfaceConfigService.getByInfoIdAndIfCode(CS.INFO_TYPE_MCH, infoId, ifCode);
//若配置存在为saveOrUpdate添加ID第一次配置添加创建者
if (dbRecoed != null) {
payInterfaceConfig.setId(dbRecoed.getId());
}else {
payInterfaceConfig.setCreatedUid(userId);
payInterfaceConfig.setCreatedBy(realName);
}
boolean result = payInterfaceConfigService.saveOrUpdate(payInterfaceConfig);
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYSTEM_ERROR, "配置失败");
}
mqTopic4ModifyMchInfo.push(infoId); // 推送mq到目前节点进行更新数据
return ApiRes.ok();
}
}

View File

@ -0,0 +1,163 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.merchant;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.MchInfo;
import com.jeequan.jeepay.core.entity.MchPayPassage;
import com.jeequan.jeepay.core.entity.PayInterfaceConfig;
import com.jeequan.jeepay.core.entity.PayWay;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MchInfoService;
import com.jeequan.jeepay.service.impl.MchPayPassageService;
import com.jeequan.jeepay.service.impl.PayInterfaceConfigService;
import com.jeequan.jeepay.service.impl.PayWayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.LinkedList;
import java.util.List;
/**
* 商户支付通道管理类
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021-04-27 15:30
*/
@RestController
@RequestMapping("/api/mch/payPassages")
public class MchPayPassageConfigController extends CommonCtrl {
@Autowired private MchPayPassageService mchPayPassageService;
@Autowired private PayInterfaceConfigService payInterfaceConfigService;
@Autowired private PayWayService payWayService;
@Autowired private MchInfoService mchInfoService;
/**
* @Author: ZhuXiao
* @Description: 查询支付方式列表并添加是否配置支付通道状态
* @Date: 15:31 2021/5/10
*/
@PreAuthorize("hasAuthority('ENT_MCH_PAY_PASSAGE_LIST')")
@GetMapping
public ApiRes list() {
String mchNo = getValStringRequired("mchNo");
String wayCode = getValString("wayCode");
String wayName = getValString("wayName");
//支付方式集合
LambdaQueryWrapper<PayWay> wrapper = PayWay.gw();
if (StrUtil.isNotBlank(wayCode)) wrapper.eq(PayWay::getWayCode, wayCode);
if (StrUtil.isNotBlank(wayName)) wrapper.like(PayWay::getWayName, wayName);
IPage<PayWay> payWayPage = payWayService.page(getIPage(), wrapper);
if (!CollectionUtils.isEmpty(payWayPage.getRecords())) {
// 支付方式代码集合
List<String> wayCodeList = new LinkedList<>();
payWayPage.getRecords().stream().forEach(payWay -> wayCodeList.add(payWay.getWayCode()));
// 商户支付通道集合
List<MchPayPassage> mchPayPassageList = mchPayPassageService.list(MchPayPassage.gw()
.select(MchPayPassage::getWayCode, MchPayPassage::getState)
.eq(MchPayPassage::getMchNo, mchNo)
.in(MchPayPassage::getWayCode, wayCodeList));
for (PayWay payWay : payWayPage.getRecords()) {
payWay.addExt("passageState", CS.NO);
for (MchPayPassage mchPayPassage : mchPayPassageList) {
// 某种支付方式多个通道的情况下只要有一个通道状态为开启则该支付方式对应为开启状态
if (payWay.getWayCode().equals(mchPayPassage.getWayCode()) && mchPayPassage.getState() == CS.YES) {
payWay.addExt("passageState", CS.YES);
break;
}
}
}
}
return ApiRes.page(payWayPage);
}
/**
* @Author: ZhuXiao
* @Description: 根据商户号支付方式查询可用的支付接口列表
* @Date: 17:55 2021/5/8
*/
@PreAuthorize("hasAuthority('ENT_MCH_PAY_PASSAGE_CONFIG')")
@GetMapping("/availablePayInterface/{mchNo}/{wayCode}")
public ApiRes availablePayInterface(@PathVariable("mchNo") String mchNo, @PathVariable("wayCode") String wayCode) {
MchInfo mchInfo = mchInfoService.getById(mchNo);
if (mchInfo == null || mchInfo.getState() != CS.YES) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SELETE);
}
// 根据支付方式查询可用支付接口列表
List<JSONObject> list = mchPayPassageService.selectAvailablePayInterfaceList(wayCode, mchNo, CS.INFO_TYPE_MCH, mchInfo.getType());
return ApiRes.ok(list);
}
/**
* @Author: ZhuXiao
* @Description: 根据 商户号接口类型 获取商户参数配置
* @Date: 17:03 2021/4/27
*/
@GetMapping("/{mchNo}/{ifCode}")
public ApiRes getByMchNo(@PathVariable(value = "mchNo") String mchNo, @PathVariable(value = "ifCode") String ifCode) {
PayInterfaceConfig payInterfaceConfig = payInterfaceConfigService.getByInfoIdAndIfCode(CS.INFO_TYPE_MCH, mchNo, ifCode);
if (payInterfaceConfig != null && payInterfaceConfig.getIfRate() != null) {
payInterfaceConfig.setIfRate(payInterfaceConfig.getIfRate().multiply(new BigDecimal("100")));
}
return ApiRes.ok(payInterfaceConfig);
}
/**
* @Author: ZhuXiao
* @Description: 商户支付通道配置
* @Date: 17:36 2021/5/8
*/
@PreAuthorize("hasAuthority('ENT_MCH_PAY_PASSAGE_ADD')")
@PostMapping
@MethodLog(remark = "更新商户支付通道")
public ApiRes saveOrUpdate() {
String reqParams = getValStringRequired("reqParams");
try {
List<MchPayPassage> mchPayPassageList = JSONArray.parseArray(reqParams, MchPayPassage.class);
mchPayPassageService.saveOrUpdateBatchSelf(mchPayPassageList);
return ApiRes.ok();
}catch (Exception e) {
return ApiRes.fail(ApiCodeEnum.SYSTEM_ERROR);
}
}
}

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.order;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.entity.MchNotifyRecord;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MchNotifyRecordService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* 商户通知类
*
* @author pangxiaoyu
* @site https://www.jeepay.vip
* @date 2021-06-07 07:15
*/
@RestController
@RequestMapping("/api/mchNotify")
public class MchNotifyController extends CommonCtrl {
@Autowired private MchNotifyRecordService mchNotifyService;
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:14
* @describe: 商户通知列表
*/
@PreAuthorize("hasAuthority('ENT_MCH_NOTIFY_LIST')")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes list() {
MchNotifyRecord mchNotify = getObject(MchNotifyRecord.class);
JSONObject paramJSON = getReqParamJSON();
LambdaQueryWrapper<MchNotifyRecord> wrapper = MchNotifyRecord.gw();
if (StringUtils.isNotEmpty(mchNotify.getOrderId())) wrapper.eq(MchNotifyRecord::getOrderId, mchNotify.getOrderId());
if (StringUtils.isNotEmpty(mchNotify.getMchNo())) wrapper.eq(MchNotifyRecord::getMchNo, mchNotify.getMchNo());
if (StringUtils.isNotEmpty(mchNotify.getIsvNo())) wrapper.eq(MchNotifyRecord::getIsvNo, mchNotify.getIsvNo());
if (StringUtils.isNotEmpty(mchNotify.getMchOrderNo())) wrapper.eq(MchNotifyRecord::getMchOrderNo, mchNotify.getMchOrderNo());
if (mchNotify.getOrderType() != null) wrapper.eq(MchNotifyRecord::getOrderType, mchNotify.getOrderType());
if (mchNotify.getState() != null) wrapper.eq(MchNotifyRecord::getState, mchNotify.getState());
if (paramJSON != null) {
if (StringUtils.isNotEmpty(paramJSON.getString("createdStart"))) wrapper.ge(MchNotifyRecord::getCreatedAt, paramJSON.getString("createdStart"));
if (StringUtils.isNotEmpty(paramJSON.getString("createdEnd"))) wrapper.le(MchNotifyRecord::getCreatedAt, paramJSON.getString("createdEnd"));
}
wrapper.orderByDesc(MchNotifyRecord::getCreatedAt);
IPage<MchNotifyRecord> pages = mchNotifyService.page(getIPage(), wrapper);
return ApiRes.page(pages);
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:14
* @describe: 商户通知信息
*/
@PreAuthorize("hasAuthority('ENT_MCH_NOTIFY_VIEW')")
@RequestMapping(value="/{notifyId}", method = RequestMethod.GET)
public ApiRes detail(@PathVariable("notifyId") String notifyId) {
MchNotifyRecord mchNotify = mchNotifyService.getById(notifyId);
if (mchNotify == null) return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SELETE);
return ApiRes.ok(mchNotify);
}
}

View File

@ -0,0 +1,110 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.order;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.core.entity.PayWay;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.PayOrderService;
import com.jeequan.jeepay.service.impl.PayWayService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 支付订单类
*
* @author pangxiaoyu
* @site https://www.jeepay.vip
* @date 2021-06-07 07:15
*/
@RestController
@RequestMapping("/api/payOrder")
public class PayOrderController extends CommonCtrl {
@Autowired private PayOrderService payOrderService;
@Autowired private PayWayService payWayService;
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:15
* @describe: 订单信息列表
*/
@PreAuthorize("hasAuthority('ENT_PAY_ORDER_LIST')")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes list() {
PayOrder payOrder = getObject(PayOrder.class);
JSONObject paramJSON = getReqParamJSON();
LambdaQueryWrapper<PayOrder> wrapper = PayOrder.gw();
if (StringUtils.isNotEmpty(payOrder.getPayOrderId())) wrapper.eq(PayOrder::getPayOrderId, payOrder.getPayOrderId());
if (StringUtils.isNotEmpty(payOrder.getMchNo())) wrapper.eq(PayOrder::getMchNo, payOrder.getMchNo());
if (StringUtils.isNotEmpty(payOrder.getIsvNo())) wrapper.eq(PayOrder::getIsvNo, payOrder.getIsvNo());
if (payOrder.getMchType() != null) wrapper.eq(PayOrder::getMchType, payOrder.getMchType());
if (StringUtils.isNotEmpty(payOrder.getWayCode())) wrapper.eq(PayOrder::getWayCode, payOrder.getWayCode());
if (StringUtils.isNotEmpty(payOrder.getMchOrderNo())) wrapper.eq(PayOrder::getMchOrderNo, payOrder.getMchOrderNo());
if (payOrder.getState() != null) wrapper.eq(PayOrder::getState, payOrder.getState());
if (payOrder.getNotifyState() != null) wrapper.eq(PayOrder::getNotifyState, payOrder.getNotifyState());
if (paramJSON != null) {
if (StringUtils.isNotEmpty(paramJSON.getString("createdStart"))) wrapper.ge(PayOrder::getCreatedAt, paramJSON.getString("createdStart"));
if (StringUtils.isNotEmpty(paramJSON.getString("createdEnd"))) wrapper.le(PayOrder::getCreatedAt, paramJSON.getString("createdEnd"));
}
wrapper.orderByDesc(PayOrder::getCreatedAt);
IPage<PayOrder> pages = payOrderService.page(getIPage(), wrapper);
// 得到所有支付方式
Map<String, String> payWayNameMap = new HashMap<>();
List<PayWay> payWayList = payWayService.list();
for (PayWay payWay:payWayList) {
payWayNameMap.put(payWay.getWayCode(), payWay.getWayName());
}
for (PayOrder order:pages.getRecords()) {
// 存入支付方式名称
if (StringUtils.isNotEmpty(payWayNameMap.get(order.getWayCode()))) {
order.addExt("wayName", payWayNameMap.get(order.getWayCode()));
}else {
order.addExt("wayName", order.getWayCode());
}
}
return ApiRes.page(pages);
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:15
* @describe: 支付订单信息
*/
@PreAuthorize("hasAuthority('ENT_PAY_ORDER_VIEW')")
@RequestMapping(value="/{payOrderId}", method = RequestMethod.GET)
public ApiRes detail(@PathVariable("payOrderId") String payOrderId) {
PayOrder payOrder = payOrderService.getById(payOrderId);
if (payOrder == null) return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SELETE);
return ApiRes.ok(payOrder);
}
}

View File

@ -0,0 +1,91 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.order;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.entity.RefundOrder;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.RefundOrderService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* 退款订单类
*
* @author pangxiaoyu
* @site https://www.jeepay.vip
* @date 2021-06-07 07:15
*/
@RestController
@RequestMapping("/api/refundOrder")
public class RefundOrderController extends CommonCtrl {
@Autowired private RefundOrderService refundOrderService;
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:15
* @describe: 退款订单信息列表
*/
@PreAuthorize("hasAuthority('ENT_REFUND_ORDER_LIST')")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes list() {
RefundOrder refundOrder = getObject(RefundOrder.class);
JSONObject paramJSON = getReqParamJSON();
LambdaQueryWrapper<RefundOrder> wrapper = RefundOrder.gw();
if (StringUtils.isNotEmpty(refundOrder.getRefundOrderId())) wrapper.eq(RefundOrder::getRefundOrderId, refundOrder.getRefundOrderId());
if (StringUtils.isNotEmpty(refundOrder.getPayOrderId())) wrapper.eq(RefundOrder::getPayOrderId, refundOrder.getPayOrderId());
if (StringUtils.isNotEmpty(refundOrder.getChannelPayOrderNo())) wrapper.eq(RefundOrder::getChannelPayOrderNo, refundOrder.getChannelPayOrderNo());
if (StringUtils.isNotEmpty(refundOrder.getMchNo())) wrapper.eq(RefundOrder::getMchNo, refundOrder.getMchNo());
if (StringUtils.isNotEmpty(refundOrder.getIsvNo())) wrapper.eq(RefundOrder::getIsvNo, refundOrder.getIsvNo());
if (refundOrder.getMchType() != null) wrapper.eq(RefundOrder::getMchType, refundOrder.getMchType());
if (StringUtils.isNotEmpty(refundOrder.getMchRefundNo())) wrapper.eq(RefundOrder::getMchRefundNo, refundOrder.getMchRefundNo());
if (refundOrder.getState() != null) wrapper.eq(RefundOrder::getState, refundOrder.getState());
if (StringUtils.isNotEmpty(refundOrder.getChannelPayOrderNo())) wrapper.eq(RefundOrder::getChannelPayOrderNo, refundOrder.getChannelPayOrderNo());
if (refundOrder.getResult() != null) wrapper.eq(RefundOrder::getResult, refundOrder.getResult());
if (paramJSON != null) {
if (StringUtils.isNotEmpty(paramJSON.getString("createdStart"))) wrapper.ge(RefundOrder::getCreatedAt, paramJSON.getString("createdStart"));
if (StringUtils.isNotEmpty(paramJSON.getString("createdEnd"))) wrapper.le(RefundOrder::getCreatedAt, paramJSON.getString("createdEnd"));
}
wrapper.orderByDesc(RefundOrder::getCreatedAt);
IPage<RefundOrder> pages = refundOrderService.page(getIPage(), wrapper);
return ApiRes.page(pages);
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:15
* @describe: 退款订单信息
*/
@PreAuthorize("hasAuthority('ENT_REFUND_ORDER_VIEW')")
@RequestMapping(value="/{refundOrderId}", method = RequestMethod.GET)
public ApiRes detail(@PathVariable("refundOrderId") String refundOrderId) {
RefundOrder refundOrder = refundOrderService.getById(refundOrderId);
if (refundOrder == null) return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SELETE);
return ApiRes.ok(refundOrder);
}
}

View File

@ -0,0 +1,157 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.payconfig;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.entity.PayInterfaceConfig;
import com.jeequan.jeepay.core.entity.PayInterfaceDefine;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.PayInterfaceConfigService;
import com.jeequan.jeepay.service.impl.PayInterfaceDefineService;
import com.jeequan.jeepay.service.impl.PayOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 支付接口定义管理类
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021-04-27 15:50
*/
@RestController
@RequestMapping("api/payIfDefines")
public class PayInterfaceDefineController extends CommonCtrl {
@Autowired private PayInterfaceDefineService payInterfaceDefineService;
@Autowired private PayOrderService payOrderService;
@Autowired private PayInterfaceConfigService payInterfaceConfigService;
/**
* @Author: ZhuXiao
* @Description: list
* @Date: 15:51 2021/4/27
*/
@PreAuthorize("hasAuthority('ENT_PC_IF_DEFINE_LIST')")
@GetMapping
public ApiRes list() {
List<PayInterfaceDefine> list = payInterfaceDefineService.list(PayInterfaceDefine.gw()
.orderByAsc(PayInterfaceDefine::getCreatedAt)
);
return ApiRes.ok(list);
}
/**
* @Author: ZhuXiao
* @Description: detail
* @Date: 15:51 2021/4/27
*/
@PreAuthorize("hasAnyAuthority('ENT_PC_IF_DEFINE_VIEW', 'ENT_PC_IF_DEFINE_EDIT')")
@GetMapping("/{ifCode}")
public ApiRes detail(@PathVariable("ifCode") String ifCode) {
return ApiRes.ok(payInterfaceDefineService.getById(ifCode));
}
/**
* @Author: ZhuXiao
* @Description: add
* @Date: 15:51 2021/4/27
*/
@PreAuthorize("hasAuthority('ENT_PC_IF_DEFINE_ADD')")
@PostMapping
@MethodLog(remark = "新增支付接口")
public ApiRes add() {
PayInterfaceDefine payInterfaceDefine = getObject(PayInterfaceDefine.class);
JSONArray jsonArray = new JSONArray();
String[] wayCodes = getValStringRequired("wayCodeStrs").split(",");
for (String wayCode : wayCodes) {
JSONObject object = new JSONObject();
object.put("wayCode", wayCode);
jsonArray.add(object);
}
payInterfaceDefine.setWayCodes(jsonArray);
boolean result = payInterfaceDefineService.save(payInterfaceDefine);
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE);
}
return ApiRes.ok();
}
/**
* @Author: ZhuXiao
* @Description: update
* @Date: 15:51 2021/4/27
*/
@PreAuthorize("hasAuthority('ENT_PC_IF_DEFINE_EDIT')")
@PutMapping("/{ifCode}")
@MethodLog(remark = "更新支付接口")
public ApiRes update(@PathVariable("ifCode") String ifCode) {
PayInterfaceDefine payInterfaceDefine = getObject(PayInterfaceDefine.class);
payInterfaceDefine.setIfCode(ifCode);
JSONArray jsonArray = new JSONArray();
String[] wayCodes = getValStringRequired("wayCodeStrs").split(",");
for (String wayCode : wayCodes) {
JSONObject object = new JSONObject();
object.put("wayCode", wayCode);
jsonArray.add(object);
}
payInterfaceDefine.setWayCodes(jsonArray);
boolean result = payInterfaceDefineService.updateById(payInterfaceDefine);
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
}
return ApiRes.ok();
}
/**
* @Author: ZhuXiao
* @Description: delete
* @Date: 15:52 2021/4/27
*/
@PreAuthorize("hasAuthority('ENT_PC_IF_DEFINE_DEL')")
@DeleteMapping("/{ifCode}")
@MethodLog(remark = "删除支付接口")
public ApiRes delete(@PathVariable("ifCode") String ifCode) {
// 校验该支付方式是否有服务商或商户配置参数或者已有订单
if (payInterfaceConfigService.count(PayInterfaceConfig.gw().eq(PayInterfaceConfig::getIfCode, ifCode)) > 0
|| payOrderService.count(PayOrder.gw().eq(PayOrder::getIfCode, ifCode)) > 0) {
throw new BizException("该支付接口已有服务商或商户配置参数或已发生交易,无法删除!");
}
boolean result = payInterfaceDefineService.removeById(ifCode);
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_DELETE);
}
return ApiRes.ok();
}
}

View File

@ -0,0 +1,154 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.payconfig;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.entity.MchPayPassage;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.core.entity.PayWay;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.utils.StringKit;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.MchPayPassageService;
import com.jeequan.jeepay.service.impl.PayOrderService;
import com.jeequan.jeepay.service.impl.PayWayService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
/**
* 支付方式管理类
*
* @author zhuxiao
* @site https://www.jeepay.vip
* @date 2021-04-27 15:50
*/
@RestController
@RequestMapping("api/payWays")
public class PayWayController extends CommonCtrl {
@Autowired PayWayService payWayService;
@Autowired MchPayPassageService mchPayPassageService;
@Autowired PayOrderService payOrderService;
/**
* @Author: ZhuXiao
* @Description: list
* @Date: 15:52 2021/4/27
*/
@PreAuthorize("hasAuthority('ENT_PC_WAY_LIST')")
@GetMapping
public ApiRes list() {
PayWay queryObject = getObject(PayWay.class);
LambdaQueryWrapper<PayWay> condition = PayWay.gw();
if(StringUtils.isNotEmpty(queryObject.getWayCode())){
condition.like(PayWay::getWayCode, queryObject.getWayCode());
}
if(StringUtils.isNotEmpty(queryObject.getWayName())){
condition.like(PayWay::getWayName, queryObject.getWayName());
}
condition.orderByAsc(PayWay::getWayCode);
IPage<PayWay> pages = payWayService.page(getIPage(true), condition);
return ApiRes.page(pages);
}
/**
* @Author: ZhuXiao
* @Description: detail
* @Date: 15:52 2021/4/27
*/
@PreAuthorize("hasAnyAuthority('ENT_PC_WAY_VIEW', 'ENT_PC_WAY_EDIT')")
@GetMapping("/{wayCode}")
public ApiRes detail(@PathVariable("wayCode") String wayCode) {
return ApiRes.ok(payWayService.getById(wayCode));
}
/**
* @Author: ZhuXiao
* @Description: add
* @Date: 15:52 2021/4/27
*/
@PreAuthorize("hasAuthority('ENT_PC_WAY_ADD')")
@PostMapping
@MethodLog(remark = "新增支付方式")
public ApiRes add() {
PayWay payWay = getObject(PayWay.class);
if (payWayService.count(PayWay.gw().eq(PayWay::getWayCode, payWay.getWayCode())) > 0) {
throw new BizException("支付方式代码已存在");
}
payWay.setWayCode(payWay.getWayCode().toUpperCase());
boolean result = payWayService.save(payWay);
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE);
}
return ApiRes.ok();
}
/**
* @Author: ZhuXiao
* @Description: update
* @Date: 15:52 2021/4/27
*/
@PreAuthorize("hasAuthority('ENT_PC_WAY_EDIT')")
@PutMapping("/{wayCode}")
@MethodLog(remark = "更新支付方式")
public ApiRes update(@PathVariable("wayCode") String wayCode) {
PayWay payWay = getObject(PayWay.class);
payWay.setWayCode(wayCode);
boolean result = payWayService.updateById(payWay);
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
}
return ApiRes.ok();
}
/**
* @Author: ZhuXiao
* @Description: delete
* @Date: 15:52 2021/4/27
*/
@PreAuthorize("hasAuthority('ENT_PC_WAY_DEL')")
@DeleteMapping("/{wayCode}")
@MethodLog(remark = "删除支付方式")
public ApiRes delete(@PathVariable("wayCode") String wayCode) {
// 校验该支付方式是否有商户已配置通道或者已有订单
if (mchPayPassageService.count(MchPayPassage.gw().eq(MchPayPassage::getWayCode, wayCode)) > 0
|| payOrderService.count(PayOrder.gw().eq(PayOrder::getWayCode, wayCode)) > 0) {
throw new BizException("该支付方式已有商户配置通道或已发生交易,无法删除!");
}
boolean result = payWayService.removeById(wayCode);
if (!result) {
return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_DELETE);
}
return ApiRes.ok();
}
}

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.sysuser;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.jeequan.jeepay.core.entity.SysEntitlement;
import com.jeequan.jeepay.service.impl.SysEntitlementService;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.utils.TreeDataBuilder;
import java.util.List;
/*
* 权限 菜单 管理
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:13
*/
@RestController
@RequestMapping("api/sysEnts")
public class SysEntController extends CommonCtrl {
@Autowired SysEntitlementService sysEntitlementService;
/** getOne */
@PreAuthorize("hasAnyAuthority( 'ENT_UR_ROLE_ENT_LIST' )")
@RequestMapping(value="/bySystem", method = RequestMethod.GET)
public ApiRes bySystem() {
return ApiRes.ok(sysEntitlementService.getOne(SysEntitlement.gw()
.eq(SysEntitlement::getEntId, getValStringRequired("entId"))
.eq(SysEntitlement::getSystem, getValStringRequired("system")))
);
}
/** updateById */
@PreAuthorize("hasAuthority( 'ENT_UR_ROLE_ENT_EDIT')")
@MethodLog(remark = "更新资源权限")
@RequestMapping(value="/{entId}", method = RequestMethod.PUT)
public ApiRes updateById(@PathVariable("entId") String entId) {
SysEntitlement queryObject = getObject(SysEntitlement.class);
sysEntitlementService.update(queryObject, SysEntitlement.gw().eq(SysEntitlement::getEntId, entId).eq(SysEntitlement::getSystem, queryObject.getSystem()));
return ApiRes.ok();
}
/** 查询权限集合 */
@PreAuthorize("hasAnyAuthority( 'ENT_UR_ROLE_ENT_LIST', 'ENT_UR_ROLE_DIST' )")
@RequestMapping(value="/showTree", method = RequestMethod.GET)
public ApiRes showTree() {
//查询全部数据
List<SysEntitlement> list = sysEntitlementService.list(SysEntitlement.gw().eq(SysEntitlement::getSystem, getValStringRequired("system")));
//转换为json树状结构
JSONArray jsonArray = (JSONArray) JSONArray.toJSON(list);
List<JSONObject> leftMenuTree = new TreeDataBuilder(jsonArray,
"entId", "pid", "children", "entSort", true)
.buildTreeObject();
return ApiRes.ok(leftMenuTree);
}
}

View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.sysuser;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.entity.SysLog;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.SysLogService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.LinkedList;
import java.util.List;
/**
* 系统日志记录类
*
* @author pangxiaoyu
* @site https://www.jeepay.vip
* @date 2021-06-07 07:15
*/
@RestController
@RequestMapping("api/sysLog")
public class SysLogController extends CommonCtrl {
@Autowired SysLogService sysLogService;
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:15
* @describe: 日志记录列表
*/
@PreAuthorize("hasAuthority('ENT_SYS_LOG_LIST')")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes list() {
SysLog sysLog = getObject(SysLog.class);
JSONObject paramJSON = getReqParamJSON();
// 查询列表
LambdaQueryWrapper<SysLog> condition = SysLog.gw();
condition.orderByDesc(SysLog::getCreatedAt);
if (sysLog.getUserId() != null) condition.eq(SysLog::getUserId, sysLog.getUserId());
if (sysLog.getUserName() != null) condition.eq(SysLog::getUserName, sysLog.getUserName());
if (StringUtils.isNotEmpty(sysLog.getSystem())) condition.eq(SysLog::getSystem, sysLog.getSystem());
if (paramJSON != null) {
if (StringUtils.isNotEmpty(paramJSON.getString("createdStart"))) condition.ge(SysLog::getCreatedAt, paramJSON.getString("createdStart"));
if (StringUtils.isNotEmpty(paramJSON.getString("createdEnd"))) condition.le(SysLog::getCreatedAt, paramJSON.getString("createdEnd"));
}
IPage<SysLog> pages = sysLogService.page(getIPage(), condition);
return ApiRes.page(pages);
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:16
* @describe: 查看日志信息
*/
@PreAuthorize("hasAuthority('ENT_SYS_LOG_VIEW')")
@RequestMapping(value="/{sysLogId}", method = RequestMethod.GET)
public ApiRes detail(@PathVariable("sysLogId") String sysLogId) {
SysLog sysLog = sysLogService.getById(sysLogId);
if (sysLog == null) return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SELETE);
return ApiRes.ok(sysLog);
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:16
* @describe: 删除日志信息
*/
@PreAuthorize("hasAuthority('ENT_SYS_LOG_DEL')")
@MethodLog(remark = "删除日志信息")
@RequestMapping(value="/{selectedIds}", method = RequestMethod.DELETE)
public ApiRes delete(@PathVariable("selectedIds") String selectedIds) {
String[] ids = selectedIds.split(",");
List<Long> idsList = new LinkedList<>();
for (String id : ids) {
idsList.add(Long.valueOf(id));
}
boolean result = sysLogService.removeByIds(idsList);
if (!result) return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_DELETE);
return ApiRes.ok();
}
}

View File

@ -0,0 +1,171 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.sysuser;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.SysRole;
import com.jeequan.jeepay.core.entity.SysUserRoleRela;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.mgr.service.AuthService;
import com.jeequan.jeepay.service.impl.SysRoleEntRelaService;
import com.jeequan.jeepay.service.impl.SysRoleService;
import com.jeequan.jeepay.service.impl.SysUserRoleRelaService;
import com.jeequan.jeepay.core.utils.StringKit;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/*
* 角色管理
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:13
*/
@RestController
@RequestMapping("api/sysRoles")
public class SysRoleController extends CommonCtrl {
@Autowired SysRoleService sysRoleService;
@Autowired SysUserRoleRelaService sysUserRoleRelaService;
@Autowired private AuthService authService;
@Autowired private SysRoleEntRelaService sysRoleEntRelaService;
/** list */
@PreAuthorize("hasAnyAuthority( 'ENT_UR_ROLE_LIST', 'ENT_UR_USER_UPD_ROLE' )")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes list() {
SysRole queryObject = getObject(SysRole.class);
QueryWrapper<SysRole> condition = new QueryWrapper<>();
LambdaQueryWrapper<SysRole> lambdaCondition = condition.lambda();
lambdaCondition.eq(SysRole::getSystem, CS.SYS_TYPE.MGR);
lambdaCondition.eq(SysRole::getBelongInfoId, 0);
if(StringUtils.isNotEmpty(queryObject.getRoleName())){
lambdaCondition.like(SysRole::getRoleName, queryObject.getRoleName());
}
if(StringUtils.isNotEmpty(queryObject.getRoleId())){
lambdaCondition.like(SysRole::getRoleId, queryObject.getRoleId());
}
//是否有排序字段
MutablePair<Boolean, String> orderInfo = getSortInfo();
if(orderInfo != null){
condition.orderBy(true, orderInfo.getLeft(), orderInfo.getRight());
}else{
lambdaCondition.orderByDesc(SysRole::getUpdatedAt);
}
IPage<SysRole> pages = sysRoleService.page(getIPage(true), condition);
return ApiRes.page(pages);
}
/** detail */
@PreAuthorize("hasAuthority( 'ENT_UR_ROLE_EDIT' )")
@RequestMapping(value="/{recordId}", method = RequestMethod.GET)
public ApiRes detail(@PathVariable("recordId") String recordId) {
return ApiRes.ok(sysRoleService.getById(recordId));
}
/** add */
@PreAuthorize("hasAuthority( 'ENT_UR_ROLE_ADD' )")
@MethodLog(remark = "添加角色信息")
@RequestMapping(value="", method = RequestMethod.POST)
public ApiRes add() {
SysRole SysRole = getObject(SysRole.class);
String roleId = "ROLE_" + StringKit.getUUID(6);
SysRole.setRoleId(roleId);
SysRole.setSystem(CS.SYS_TYPE.MGR); //后台系统
sysRoleService.save(SysRole);
//权限信息集合
String entIdListStr = getValString("entIdListStr");
//如果包含 可分配权限的权限 && entIdListStr 不为空
if(getCurrentUser().getAuthorities().contains(new SimpleGrantedAuthority("ENT_UR_ROLE_DIST"))
&& StringUtils.isNotEmpty(entIdListStr)){
List<String> entIdList = JSONArray.parseArray(entIdListStr, String.class);
sysRoleEntRelaService.resetRela(roleId, entIdList);
}
return ApiRes.ok();
}
/** update */
@PreAuthorize("hasAuthority( 'ENT_UR_ROLE_EDIT' )")
@RequestMapping(value="/{recordId}", method = RequestMethod.PUT)
@MethodLog(remark = "更新角色信息")
public ApiRes update(@PathVariable("recordId") String recordId) {
SysRole SysRole = getObject(SysRole.class);
SysRole.setRoleId(recordId);
sysRoleService.updateById(SysRole);
//权限信息集合
String entIdListStr = getValString("entIdListStr");
//如果包含 可分配权限的权限 && entIdListStr 不为空
if(getCurrentUser().getAuthorities().contains(new SimpleGrantedAuthority("ENT_UR_ROLE_DIST"))
&& StringUtils.isNotEmpty(entIdListStr)){
List<String> entIdList = JSONArray.parseArray(entIdListStr, String.class);
sysRoleEntRelaService.resetRela(recordId, entIdList);
List<Long> sysUserIdList = new ArrayList<>();
sysUserRoleRelaService.list(SysUserRoleRela.gw().eq(SysUserRoleRela::getRoleId, recordId)).stream().forEach(item -> sysUserIdList.add(item.getUserId()));
//查询到该角色的人员 将redis更新
authService.refAuthentication(sysUserIdList);
}
return ApiRes.ok();
}
/** delete */
@PreAuthorize("hasAuthority('ENT_UR_ROLE_DEL')")
@MethodLog(remark = "删除角色")
@RequestMapping(value="/{recordId}", method = RequestMethod.DELETE)
public ApiRes del(@PathVariable("recordId") String recordId) {
if(sysUserRoleRelaService.count(SysUserRoleRela.gw().eq(SysUserRoleRela::getRoleId, recordId)) > 0){
throw new BizException("当前角色已分配到用户, 不可删除!");
}
sysRoleService.removeRole(recordId);
return ApiRes.ok();
}
}

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.sysuser;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.entity.SysRoleEntRela;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.mgr.service.AuthService;
import com.jeequan.jeepay.service.impl.SysRoleEntRelaService;
import com.jeequan.jeepay.service.impl.SysUserRoleRelaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/*
* 角色 权限管理
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:13
*/
@RestController
@RequestMapping("api/sysRoleEntRelas")
public class SysRoleEntRelaController extends CommonCtrl {
@Autowired private SysRoleEntRelaService sysRoleEntRelaService;
/** list */
@PreAuthorize("hasAnyAuthority( 'ENT_UR_ROLE_ADD', 'ENT_UR_ROLE_DIST' )")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes list() {
SysRoleEntRela queryObject = getObject(SysRoleEntRela.class);
LambdaQueryWrapper<SysRoleEntRela> condition = SysRoleEntRela.gw();
if(queryObject.getRoleId() != null){
condition.eq(SysRoleEntRela::getRoleId, queryObject.getRoleId());
}
IPage<SysRoleEntRela> pages = sysRoleEntRelaService.page(getIPage(true), condition);
return ApiRes.page(pages);
}
}

View File

@ -0,0 +1,150 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.sysuser;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.utils.StringKit;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.mgr.service.AuthService;
import com.jeequan.jeepay.service.impl.SysUserAuthService;
import com.jeequan.jeepay.service.impl.SysUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;
/*
* 操作员列表
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:13
*/
@RestController
@RequestMapping("api/sysUsers")
public class SysUserController extends CommonCtrl {
@Autowired private SysUserService sysUserService;
@Autowired private SysUserAuthService sysUserAuthService;
@Autowired private AuthService authService;
/** list */
@PreAuthorize("hasAuthority( 'ENT_UR_USER_LIST' )")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes list() {
SysUser queryObject = getObject(SysUser.class);
LambdaQueryWrapper<SysUser> condition = SysUser.gw();
condition.eq(SysUser::getSystem, CS.SYS_TYPE.MGR);
if(StringUtils.isNotEmpty(queryObject.getRealname())){
condition.like(SysUser::getRealname, queryObject.getRealname());
}
if(queryObject.getSysUserId() != null){
condition.eq(SysUser::getSysUserId, queryObject.getSysUserId());
}
condition.orderByDesc(SysUser::getCreatedAt); //时间 降序
IPage<SysUser> pages = sysUserService.page(getIPage(), condition);
return ApiRes.page(pages);
}
/** detail */
@PreAuthorize("hasAuthority( 'ENT_UR_USER_EDIT' )")
@RequestMapping(value="/{recordId}", method = RequestMethod.GET)
public ApiRes detail(@PathVariable("recordId") Integer recordId) {
return ApiRes.ok(sysUserService.getById(recordId));
}
/** add */
@PreAuthorize("hasAuthority( 'ENT_UR_USER_ADD' )")
@MethodLog(remark = "添加管理员")
@RequestMapping(value="", method = RequestMethod.POST)
public ApiRes add() {
SysUser sysUser = getObject(SysUser.class);
sysUser.setBelongInfoId("0");
sysUserService.addSysUser(sysUser, CS.SYS_TYPE.MGR);
return ApiRes.ok();
}
/** 修改操作员 登录认证信息 */
// @RequestMapping(value="/modifyPwd", method = RequestMethod.PUT)
// @MethodLog(remark = "修改操作员密码")
public ApiRes authInfo() {
Long opSysUserId = getValLongRequired("recordId"); //操作员ID
//更改密码 验证当前用户信息
String currentUserPwd = getValStringRequired("originalPwd"); //当前用户登录密码
//验证当前密码是否正确
if(!sysUserAuthService.validateCurrentUserPwd(currentUserPwd)){
throw new BizException("原密码验证失败!");
}
String opUserPwd = getValStringRequired("confirmPwd");
// 验证原密码与新密码是否相同
if (opUserPwd.equals(currentUserPwd)) {
throw new BizException("新密码与原密码相同!");
}
sysUserAuthService.resetAuthInfo(opSysUserId, null, null, opUserPwd, CS.SYS_TYPE.MGR);
return ApiRes.ok();
}
/** update */
@PreAuthorize("hasAuthority( 'ENT_UR_USER_EDIT' )")
@RequestMapping(value="/{recordId}", method = RequestMethod.PUT)
@MethodLog(remark = "修改操作员信息")
public ApiRes update(@PathVariable("recordId") Long recordId) {
SysUser sysUser = getObject(SysUser.class);
sysUser.setSysUserId(recordId);
//判断是否自己禁用自己
if(recordId.equals(getCurrentUser().getSysUser().getSysUserId()) && sysUser.getState() != null && sysUser.getState() == CS.PUB_DISABLE){
throw new BizException("系统不允许禁用当前登陆用户!");
}
sysUserService.updateSysUser(sysUser);
//如果用户被禁用需要更新redis数据
if(sysUser.getState() != null && sysUser.getState() == CS.PUB_DISABLE){
authService.refAuthentication(Arrays.asList(recordId));
}
return ApiRes.ok();
}
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.sysuser;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.entity.SysUserRoleRela;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.mgr.service.AuthService;
import com.jeequan.jeepay.service.impl.SysUserRoleRelaService;
import com.jeequan.jeepay.service.impl.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;
import java.util.List;
/*
* 用户角色关联关系
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:13
*/
@RestController
@RequestMapping("api/sysUserRoleRelas")
public class SysUserRoleRelaController extends CommonCtrl {
@Autowired private SysUserRoleRelaService sysUserRoleRelaService;
@Autowired private SysUserService sysUserService;
@Autowired private AuthService authService;
/** list */
@PreAuthorize("hasAuthority( 'ENT_UR_USER_UPD_ROLE' )")
@RequestMapping(value="", method = RequestMethod.GET)
public ApiRes list() {
SysUserRoleRela queryObject = getObject(SysUserRoleRela.class);
LambdaQueryWrapper<SysUserRoleRela> condition = SysUserRoleRela.gw();
if(queryObject.getUserId() != null){
condition.eq(SysUserRoleRela::getUserId, queryObject.getUserId());
}
IPage<SysUserRoleRela> pages = sysUserRoleRelaService.page(getIPage(true), condition);
return ApiRes.page(pages);
}
/** 重置用户角色关联信息 */
@PreAuthorize("hasAuthority( 'ENT_UR_USER_UPD_ROLE' )")
@RequestMapping(value="relas/{sysUserId}", method = RequestMethod.POST)
@MethodLog(remark = "更改用户角色信息")
public ApiRes relas(@PathVariable("sysUserId") Long sysUserId) {
List<String> roleIdList = JSONArray.parseArray(getValStringRequired("roleIdListStr"), String.class);
sysUserService.saveUserRole(sysUserId, roleIdList);
authService.refAuthentication(Arrays.asList(sysUserId));
return ApiRes.ok();
}
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.mq.queue;
import com.jeequan.jeepay.core.constants.CS;
import lombok.extern.slf4j.Slf4j;
import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;
/**
* 商户用户信息清除
*
* @author pangxiaoyu
* @site https://www.jeepay.vip
* @date 2021-06-07 07:15
*/
@Slf4j
@Component
public class MqQueue4ModifyMchUserRemove extends ActiveMQQueue{
@Autowired private JmsTemplate jmsTemplate;
public MqQueue4ModifyMchUserRemove(){
super(CS.MQ.QUEUE_MODIFY_MCH_USER_REMOVE);
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:16
* @describe: 推送消息到各个节点
*/
public void push(String userIdStr) {
this.jmsTemplate.convertAndSend(this, userIdStr);
}
}

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