Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
peizhen-java
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PeiZhen-Java
peizhen-java
Commits
40b78f19
Commit
40b78f19
authored
Sep 08, 2023
by
Wangmin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
新增 小程序登录/退出 文件上传/下载接口
parent
e9af6a2f
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
709 additions
and
8 deletions
+709
-8
pz-admin/src/main/resources/application.yml
+17
-0
pz-common/pom.xml
+8
-0
pz-common/src/main/java/com/pz/common/config/FileSystemProperties.java
+36
-0
pz-common/src/main/java/com/pz/common/config/WechatConfiguration.java
+144
-0
pz-common/src/main/java/com/pz/common/config/WechatProperties.java
+43
-0
pz-common/src/main/java/com/pz/common/core/domain/entity/SysUser.java
+6
-1
pz-common/src/main/java/com/pz/common/utils/file/FileTool.java
+140
-0
pz-common/src/main/java/com/pz/common/utils/file/MimeTypeUtils.java
+21
-0
pz-merchant/pom.xml
+0
-2
pz-merchant/src/main/java/com/pz/merchant/controller/applet/WechatLoginController.java
+82
-0
pz-merchant/src/main/java/com/pz/merchant/controller/file/FileSystemController.java
+77
-0
pz-system/src/main/java/com/pz/merchant/domain/WechatUserInfo.java
+34
-0
pz-system/src/main/java/com/pz/merchant/domain/bo/WechatLoginBo.java
+46
-0
pz-system/src/main/java/com/pz/system/mapper/SysUserMapper.java
+2
-0
pz-system/src/main/java/com/pz/system/service/SysLoginService.java
+53
-5
No files found.
pz-admin/src/main/resources/application.yml
View file @
40b78f19
...
@@ -237,6 +237,8 @@ springdoc:
...
@@ -237,6 +237,8 @@ springdoc:
packages-to-scan
:
com.pz.accompany
packages-to-scan
:
com.pz.accompany
-
group
:
5.小程序用户模块
-
group
:
5.小程序用户模块
packages-to-scan
:
com.pz.applet
packages-to-scan
:
com.pz.applet
-
group
:
6.小程序商户模块
packages-to-scan
:
com.pz.merchant.controller
# 防止XSS攻击
# 防止XSS攻击
xss
:
xss
:
...
@@ -274,3 +276,18 @@ management:
...
@@ -274,3 +276,18 @@ management:
show-details
:
ALWAYS
show-details
:
ALWAYS
logfile
:
logfile
:
external-file
:
./logs/sys-console.log
external-file
:
./logs/sys-console.log
---
# 小程序设置
wechat
:
applet
:
appid
:
wxe9c227afec04271d
secret
:
1edb961b25799225b894e2e6f6989651
token
:
#微信小程序消息服务器配置的token
aesKey
:
#微信小程序消息服务器配置的EncodingAESKey
msgDataFormat
:
JSON
---
# 文件上传设置
file
:
#upload-path: /www/wwwroot/pz/upload
upload-path
:
D:/www/wwwroot/pz/upload
#注意:响应路径必须加上file后缀
response-path
:
https://www.pz.com/file
pz-common/pom.xml
View file @
40b78f19
...
@@ -165,6 +165,14 @@
...
@@ -165,6 +165,14 @@
<artifactId>
ip2region
</artifactId>
<artifactId>
ip2region
</artifactId>
</dependency>
</dependency>
<!--微信登录-->
<dependency>
<groupId>
com.github.binarywang
</groupId>
<artifactId>
weixin-java-miniapp
</artifactId>
<version>
4.5.5.B
</version>
</dependency>
</dependencies>
</dependencies>
</project>
</project>
pz-common/src/main/java/com/pz/common/config/FileSystemProperties.java
0 → 100644
View file @
40b78f19
package
com
.
pz
.
common
.
config
;
import
com.pz.common.utils.file.FileTool
;
import
lombok.Data
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.context.annotation.Configuration
;
import
javax.annotation.PostConstruct
;
/**
* <p>created in 2023/9/8 14:24
*
* @author WangMin
* @version 1.0
*/
@Data
@Configuration
@ConfigurationProperties
(
prefix
=
"file"
)
public
class
FileSystemProperties
{
/**
* 文件上传路径
*/
private
String
uploadPath
;
/**
* 文件上传返回路径
*/
private
String
responsePath
;
@PostConstruct
public
void
loadPropertiesToTools
()
{
FileTool
.
setProperties
(
this
);
}
}
pz-common/src/main/java/com/pz/common/config/WechatConfiguration.java
0 → 100644
View file @
40b78f19
package
com
.
pz
.
common
.
config
;
import
cn.binarywang.wx.miniapp.api.WxMaService
;
import
cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl
;
import
cn.binarywang.wx.miniapp.bean.WxMaKefuMessage
;
import
cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage
;
import
cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl
;
import
cn.binarywang.wx.miniapp.message.WxMaMessageHandler
;
import
cn.binarywang.wx.miniapp.message.WxMaMessageRouter
;
import
com.google.common.collect.Lists
;
import
lombok.extern.slf4j.Slf4j
;
import
me.chanjar.weixin.common.bean.result.WxMediaUploadResult
;
import
me.chanjar.weixin.common.error.WxErrorException
;
import
me.chanjar.weixin.common.error.WxRuntimeException
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.context.properties.EnableConfigurationProperties
;
import
org.springframework.context.annotation.Configuration
;
import
javax.annotation.PostConstruct
;
import
java.io.File
;
/**
* 微信小程序配置类
*
* @author WangMin
*/
@Slf4j
@Configuration
@EnableConfigurationProperties
(
WechatProperties
.
class
)
public
class
WechatConfiguration
{
private
final
WechatProperties
properties
;
private
static
WxMaMessageRouter
router
;
private
static
WxMaService
maServices
;
@Autowired
public
WechatConfiguration
(
WechatProperties
properties
)
{
this
.
properties
=
properties
;
}
public
static
WxMaService
getMaService
()
{
if
(
maServices
==
null
)
{
throw
new
IllegalArgumentException
(
"未检测到合法微信配置属性,请核实!"
);
}
return
maServices
;
}
public
static
WxMaMessageRouter
getRouter
()
{
if
(
router
==
null
)
{
throw
new
IllegalArgumentException
(
"未检测到合法微信配置属性,请核实!"
);
}
return
router
;
}
@PostConstruct
public
void
init
()
{
WechatProperties
properties
=
this
.
properties
;
if
(
properties
==
null
)
{
throw
new
WxRuntimeException
(
"未检测到合法微信配置属性"
);
}
WxMaDefaultConfigImpl
config
=
new
WxMaDefaultConfigImpl
();
config
.
setAppid
(
properties
.
getAppid
());
config
.
setSecret
(
properties
.
getSecret
());
config
.
setToken
(
properties
.
getToken
());
config
.
setAesKey
(
properties
.
getAesKey
());
config
.
setMsgDataFormat
(
properties
.
getMsgDataFormat
());
WxMaService
service
=
new
WxMaServiceImpl
();
service
.
setWxMaConfig
(
config
);
router
=
this
.
newRouter
(
service
);
maServices
=
service
;
}
private
WxMaMessageRouter
newRouter
(
WxMaService
service
)
{
final
WxMaMessageRouter
router
=
new
WxMaMessageRouter
(
service
);
router
.
rule
().
handler
(
logHandler
).
next
()
.
rule
().
async
(
false
).
content
(
"订阅消息"
).
handler
(
subscribeMsgHandler
).
end
()
.
rule
().
async
(
false
).
content
(
"文本"
).
handler
(
textHandler
).
end
()
.
rule
().
async
(
false
).
content
(
"图片"
).
handler
(
picHandler
).
end
()
.
rule
().
async
(
false
).
content
(
"二维码"
).
handler
(
qrcodeHandler
).
end
();
return
router
;
}
private
final
WxMaMessageHandler
subscribeMsgHandler
=
(
wxMessage
,
context
,
service
,
sessionManager
)
->
{
service
.
getMsgService
().
sendSubscribeMsg
(
WxMaSubscribeMessage
.
builder
()
.
templateId
(
"此处更换为自己的模板id"
)
.
data
(
Lists
.
newArrayList
(
new
WxMaSubscribeMessage
.
MsgData
(
"keyword1"
,
"339208499"
)))
.
toUser
(
wxMessage
.
getFromUser
())
.
build
());
return
null
;
};
private
final
WxMaMessageHandler
logHandler
=
(
wxMessage
,
context
,
service
,
sessionManager
)
->
{
service
.
getMsgService
().
sendKefuMsg
(
WxMaKefuMessage
.
newTextBuilder
().
content
(
"收到信息为:"
+
wxMessage
.
toJson
())
.
toUser
(
wxMessage
.
getFromUser
()).
build
());
return
null
;
};
private
final
WxMaMessageHandler
textHandler
=
(
wxMessage
,
context
,
service
,
sessionManager
)
->
{
service
.
getMsgService
().
sendKefuMsg
(
WxMaKefuMessage
.
newTextBuilder
().
content
(
"回复文本消息"
)
.
toUser
(
wxMessage
.
getFromUser
()).
build
());
return
null
;
};
private
final
WxMaMessageHandler
picHandler
=
(
wxMessage
,
context
,
service
,
sessionManager
)
->
{
try
{
WxMediaUploadResult
uploadResult
=
service
.
getMediaService
()
.
uploadMedia
(
"image"
,
"png"
,
ClassLoader
.
getSystemResourceAsStream
(
"tmp.png"
));
service
.
getMsgService
().
sendKefuMsg
(
WxMaKefuMessage
.
newImageBuilder
()
.
mediaId
(
uploadResult
.
getMediaId
())
.
toUser
(
wxMessage
.
getFromUser
())
.
build
());
}
catch
(
WxErrorException
e
)
{
log
.
error
(
e
.
getLocalizedMessage
());
}
return
null
;
};
private
final
WxMaMessageHandler
qrcodeHandler
=
(
wxMessage
,
context
,
service
,
sessionManager
)
->
{
try
{
final
File
file
=
service
.
getQrcodeService
().
createQrcode
(
"123"
,
430
);
WxMediaUploadResult
uploadResult
=
service
.
getMediaService
().
uploadMedia
(
"image"
,
file
);
service
.
getMsgService
().
sendKefuMsg
(
WxMaKefuMessage
.
newImageBuilder
()
.
mediaId
(
uploadResult
.
getMediaId
())
.
toUser
(
wxMessage
.
getFromUser
())
.
build
());
}
catch
(
WxErrorException
e
)
{
log
.
error
(
e
.
getLocalizedMessage
());
}
return
null
;
};
}
pz-common/src/main/java/com/pz/common/config/WechatProperties.java
0 → 100644
View file @
40b78f19
package
com
.
pz
.
common
.
config
;
import
lombok.Data
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
java.util.List
;
/**
* 微信小程序配置属性
*
* @author Wangmin
*/
@Data
@ConfigurationProperties
(
prefix
=
"wechat.applet"
)
public
class
WechatProperties
{
/**
* 设置微信小程序的appid
*/
private
String
appid
;
/**
* 设置微信小程序的Secret
*/
private
String
secret
;
/**
* 设置微信小程序消息服务器配置的token
*/
private
String
token
;
/**
* 设置微信小程序消息服务器配置的EncodingAESKey
*/
private
String
aesKey
;
/**
* 消息格式,XML或者JSON
*/
private
String
msgDataFormat
;
}
pz-common/src/main/java/com/pz/common/core/domain/entity/SysUser.java
View file @
40b78f19
...
@@ -33,10 +33,15 @@ public class SysUser extends BaseEntity {
...
@@ -33,10 +33,15 @@ public class SysUser extends BaseEntity {
/**
/**
* 用户ID
* 用户ID
*/
*/
@TableId
(
value
=
"user_id"
)
@TableId
(
value
=
"user_id"
,
type
=
IdType
.
AUTO
)
private
Long
userId
;
private
Long
userId
;
/**
/**
* 微信OpenID
*/
private
String
openId
;
/**
* 部门ID
* 部门ID
*/
*/
private
Long
deptId
;
private
Long
deptId
;
...
...
pz-common/src/main/java/com/pz/common/utils/file/FileTool.java
0 → 100644
View file @
40b78f19
package
com
.
pz
.
common
.
utils
.
file
;
import
cn.hutool.core.util.IdUtil
;
import
cn.hutool.core.util.RandomUtil
;
import
com.pz.common.config.FileSystemProperties
;
import
com.pz.common.exception.ServiceException
;
import
com.pz.common.utils.DateUtils
;
import
com.pz.common.utils.StringUtils
;
import
lombok.Setter
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.web.multipart.MultipartFile
;
import
java.io.*
;
import
java.rmi.ServerException
;
import
java.util.function.Supplier
;
/**
* 文件上传/下载工具
* <p>created in 2023/9/8 15:03
*
* @author WangMin
* @version 1.0
*/
@Slf4j
public
class
FileTool
{
/**
* 文件系统属性
*/
@Setter
private
static
FileSystemProperties
properties
;
/**
* @param fileName 设置文件名
* @param file 文件数据
* @return 文件路径
*/
public
static
String
upload
(
MultipartFile
file
,
String
fileName
)
throws
IOException
{
if
(
file
==
null
)
{
throw
new
ServerException
(
"文件为空"
);
}
String
finalName
=
generateRandomFileName
(
file
,
fileName
);
File
desc
=
getAbsoluteFile
(
finalName
);
file
.
transferTo
(
desc
);
return
properties
.
getResponsePath
()
+
"/"
+
finalName
;
}
/**
* 输出指定文件的byte数组
*
* @param filePath 文件路径
* @param os 输出流
*/
public
static
void
writeBytes
(
String
filePath
,
OutputStream
os
)
throws
IOException
{
try
{
FileInputStream
fis
=
null
;
try
{
File
file
=
new
File
(
filePath
);
if
(!
file
.
exists
())
{
throw
new
FileNotFoundException
(
filePath
);
}
fis
=
new
FileInputStream
(
file
);
byte
[]
b
=
new
byte
[
1024
];
int
length
;
while
((
length
=
fis
.
read
(
b
))
>
0
)
{
os
.
write
(
b
,
0
,
length
);
}
}
finally
{
if
(
os
!=
null
)
{
os
.
close
();
}
if
(
fis
!=
null
)
{
fis
.
close
();
}
}
}
catch
(
Exception
e
)
{
log
.
error
(
"文件下载失败,cause:{}"
,
e
.
getMessage
());
throw
e
;
}
}
/**
* 生成文件名(包含文件路径)
*
* @param file 文件
* @param fileName 指定文件名
* @return 文件路径(相对路径) + 文件名
*/
private
static
String
generateRandomFileName
(
MultipartFile
file
,
String
fileName
)
{
String
finalName
;
if
(
StringUtils
.
isNotEmpty
(
fileName
))
{
finalName
=
fileName
;
}
else
{
finalName
=
IdUtil
.
fastSimpleUUID
();
}
return
DateUtils
.
datePath
()
+
"/"
+
finalName
+
"."
+
getExtensionName
(
file
);
}
/**
* 获取文件拓展名
*
* @param file 文件
* @return 文件拓展名
*/
private
static
String
getExtensionName
(
MultipartFile
file
)
{
String
extensionName
=
null
;
if
(
StringUtils
.
isNotEmpty
(
file
.
getOriginalFilename
()))
{
StringBuilder
originName
=
new
StringBuilder
(
file
.
getOriginalFilename
());
int
index
=
originName
.
lastIndexOf
(
"."
);
extensionName
=
index
!=
-
1
?
originName
.
substring
(
index
+
1
)
:
null
;
}
if
(
StringUtils
.
isEmpty
(
extensionName
))
{
extensionName
=
MimeTypeUtils
.
getExtension
(()
->
StringUtils
.
isNotEmpty
(
file
.
getContentType
())
?
file
.
getContentType
()
:
""
);
}
return
extensionName
;
}
/**
* 获取上传文件File
*
* @param fileName 文件名称
* @return file
*/
private
static
File
getAbsoluteFile
(
String
fileName
)
{
File
desc
=
new
File
(
properties
.
getUploadPath
()
+
File
.
separator
+
fileName
);
if
(!
desc
.
exists
())
{
if
(!
desc
.
getParentFile
().
exists
())
{
if
(!
desc
.
getParentFile
().
mkdirs
())
{
throw
new
ServiceException
(
"文件创建失败"
);
}
}
}
return
desc
;
}
}
pz-common/src/main/java/com/pz/common/utils/file/MimeTypeUtils.java
View file @
40b78f19
package
com
.
pz
.
common
.
utils
.
file
;
package
com
.
pz
.
common
.
utils
.
file
;
import
java.util.function.Supplier
;
/**
/**
* 媒体类型工具类
* 媒体类型工具类
*
*
...
@@ -37,4 +39,23 @@ public class MimeTypeUtils {
...
@@ -37,4 +39,23 @@ public class MimeTypeUtils {
// pdf
// pdf
"pdf"
};
"pdf"
};
public
static
String
getExtension
(
Supplier
<
String
>
supplier
)
{
switch
(
supplier
.
get
())
{
case
IMAGE_PNG:
return
"png"
;
case
IMAGE_JPG:
return
"jpg"
;
case
IMAGE_JPEG:
return
"jpeg"
;
case
IMAGE_BMP:
return
"bmp"
;
case
IMAGE_GIF:
return
"gif"
;
default
:
return
""
;
}
}
}
}
pz-merchant/pom.xml
View file @
40b78f19
...
@@ -10,7 +10,6 @@
...
@@ -10,7 +10,6 @@
</parent>
</parent>
<artifactId>
pz-merchant
</artifactId>
<artifactId>
pz-merchant
</artifactId>
<packaging>
jar
</packaging>
<description>
<description>
商户端
商户端
</description>
</description>
...
@@ -21,7 +20,6 @@
...
@@ -21,7 +20,6 @@
<groupId>
com.pz
</groupId>
<groupId>
com.pz
</groupId>
<artifactId>
pz-system
</artifactId>
<artifactId>
pz-system
</artifactId>
</dependency>
</dependency>
</dependencies>
</dependencies>
</project>
</project>
pz-merchant/src/main/java/com/pz/merchant/controller/applet/WechatLoginController.java
0 → 100644
View file @
40b78f19
package
com
.
pz
.
merchant
.
controller
.
applet
;
import
cn.binarywang.wx.miniapp.api.WxMaService
;
import
cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult
;
import
cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo
;
import
cn.dev33.satoken.annotation.SaIgnore
;
import
cn.dev33.satoken.stp.StpUtil
;
import
cn.dev33.satoken.util.SaResult
;
import
com.pz.common.constant.Constants
;
import
com.pz.common.core.controller.BaseController
;
import
com.pz.common.core.domain.R
;
import
com.pz.common.exception.ServiceException
;
import
com.pz.common.utils.StringUtils
;
import
com.pz.common.config.WechatConfiguration
;
import
com.pz.merchant.domain.WechatUserInfo
;
import
com.pz.merchant.domain.bo.WechatLoginBo
;
import
com.pz.system.service.SysLoginService
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.*
;
import
java.util.HashMap
;
/**
* 微信登录
* <p>created in 2023/9/8 9:59
*
* @author WangMin
* @version 1.0
*/
@RestController
@RequiredArgsConstructor
@RequestMapping
(
"/app"
)
@Validated
@SaIgnore
public
class
WechatLoginController
extends
BaseController
{
private
final
SysLoginService
loginService
;
/**
* 登录
*
* @param loginData 用户信息
* @return token
*/
@PostMapping
(
"/login"
)
public
R
<
HashMap
<
String
,
String
>>
login
(
@RequestBody
@Validated
WechatLoginBo
loginData
)
{
final
WxMaService
wxService
=
WechatConfiguration
.
getMaService
();
WechatUserInfo
userInfo
=
new
WechatUserInfo
();
try
{
WxMaJscode2SessionResult
session
=
wxService
.
getUserService
().
getSessionInfo
(
loginData
.
getJsCode
());
// 解密手机号
WxMaPhoneNumberInfo
phoneNoInfo
=
wxService
.
getUserService
().
getPhoneNoInfo
(
session
.
getSessionKey
(),
loginData
.
getEncryptedData
(),
loginData
.
getIv
());
String
phoneNumber
=
phoneNoInfo
.
getPhoneNumber
();
if
(
StringUtils
.
isEmpty
(
phoneNumber
))
{
throw
new
ServiceException
(
"获取手机号码失败"
);
}
userInfo
.
setOpenId
(
session
.
getOpenid
());
// unionId只有绑定到微信开放平台账号下才会返回
userInfo
.
setUnionId
(
session
.
getUnionid
());
userInfo
.
setNikeName
(
loginData
.
getNickName
());
userInfo
.
setMobilePhone
(
phoneNumber
);
}
catch
(
Exception
e
)
{
throw
new
SecurityException
(
"登录失败,请检查信息"
);
}
HashMap
<
String
,
String
>
result
=
new
HashMap
<>(
2
);
String
token
=
loginService
.
xccLogin
(
userInfo
);
result
.
put
(
Constants
.
TOKEN
,
token
);
return
R
.
ok
(
result
);
}
/**
* 注销
*/
@GetMapping
(
"logout"
)
public
SaResult
logout
()
{
StpUtil
.
logout
();
return
SaResult
.
ok
();
}
}
pz-merchant/src/main/java/com/pz/merchant/controller/file/FileSystemController.java
0 → 100644
View file @
40b78f19
package
com
.
pz
.
merchant
.
controller
.
file
;
import
cn.dev33.satoken.annotation.SaIgnore
;
import
com.pz.common.config.FileSystemProperties
;
import
com.pz.common.core.controller.BaseController
;
import
com.pz.common.core.domain.R
;
import
com.pz.common.utils.file.FileTool
;
import
com.pz.common.utils.file.FileUtils
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.http.MediaType
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.multipart.MultipartFile
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
/**
* 文件上传下载
* <p>created in 2023/9/8 16:01
*
* @author WangMin
* @version 1.0
*/
@RestController
@RequiredArgsConstructor
@RequestMapping
(
"/file"
)
@SaIgnore
@Slf4j
public
class
FileSystemController
extends
BaseController
{
private
final
FileSystemProperties
properties
;
private
static
final
String
DOWNLOAD_SUFFIX
=
"file"
;
/**
* 上传文件
*
* @param file 待上传文件
* @param fileName 指定文件名,若无需指定文件名可忽略
* @return 文件访问路径
*/
@PostMapping
(
"/upload"
)
public
R
<
String
>
uploadFile
(
MultipartFile
file
,
String
fileName
)
{
try
{
return
R
.
ok
(
FileTool
.
upload
(
file
,
fileName
));
}
catch
(
Exception
e
)
{
return
R
.
fail
(
e
.
getMessage
());
}
}
/**
* 下载文件
*
* @param path 文件路径
* @return 文件
*/
@GetMapping
(
"/download"
)
public
void
downloadFile
(
String
path
,
HttpServletResponse
response
)
{
// 根据路径拼装文件实际存储路径
int
index
=
path
.
indexOf
(
DOWNLOAD_SUFFIX
);
if
(
index
==
-
1
)
{
log
.
error
(
"文件路径非法"
);
}
String
downloadPath
=
properties
.
getUploadPath
()
+
path
.
substring
(
index
+
DOWNLOAD_SUFFIX
.
length
());
try
{
response
.
setContentType
(
MediaType
.
APPLICATION_OCTET_STREAM_VALUE
);
FileUtils
.
setAttachmentResponseHeader
(
response
,
downloadPath
.
substring
(
downloadPath
.
lastIndexOf
(
"/"
)
+
1
));
FileTool
.
writeBytes
(
downloadPath
,
response
.
getOutputStream
());
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
());
}
}
}
pz-system/src/main/java/com/pz/merchant/domain/WechatUserInfo.java
0 → 100644
View file @
40b78f19
package
com
.
pz
.
merchant
.
domain
;
import
lombok.Data
;
/**
* 微信用户信息
* <p>created in 2023/9/8 10:48
*
* @author WangMin
* @version 1.0
*/
@Data
public
class
WechatUserInfo
{
/**
* 微信openID
*/
private
String
openId
;
/**
* 微信unionId
*/
private
String
unionId
;
/**
* 电话号码
*/
private
String
mobilePhone
;
/**
* 用户昵称
*/
private
String
nikeName
;
}
pz-system/src/main/java/com/pz/merchant/domain/bo/WechatLoginBo.java
0 → 100644
View file @
40b78f19
package
com
.
pz
.
merchant
.
domain
.
bo
;
import
com.pz.common.core.validate.AddGroup
;
import
com.pz.common.core.validate.EditGroup
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
/**
* 微信登录参数实体
* <p>created in 2023/9/8 10:01
*
* @author WangMin
* @version 1.0
*/
@Data
public
class
WechatLoginBo
{
/**
* 用户登录凭证
* <p>参见:wx.login # js_code属性
*/
@NotBlank
(
message
=
"jsCode不能为空"
)
private
String
jsCode
;
/**
* 用户昵称
* <p>参见:wx.getUserProfile success回调函数#UserInfo属性
*/
private
String
nickName
;
/**
* 用户信息加密数据
* <p>参见:wx.getUserProfile success回调函#encryptedData属性
*/
@NotBlank
(
message
=
"encryptedData不能为空"
)
private
String
encryptedData
;
/**
* 加密算法初始向量
* <p>参见:wx.getUserProfile success回调函#iv属性
*/
@NotBlank
(
message
=
"encryptedData不能为空"
)
private
String
iv
;
}
pz-system/src/main/java/com/pz/system/mapper/SysUserMapper.java
View file @
40b78f19
...
@@ -7,6 +7,7 @@ import com.pz.common.annotation.DataColumn;
...
@@ -7,6 +7,7 @@ import com.pz.common.annotation.DataColumn;
import
com.pz.common.annotation.DataPermission
;
import
com.pz.common.annotation.DataPermission
;
import
com.pz.common.core.domain.entity.SysUser
;
import
com.pz.common.core.domain.entity.SysUser
;
import
com.pz.common.core.mapper.BaseMapperPlus
;
import
com.pz.common.core.mapper.BaseMapperPlus
;
import
org.apache.ibatis.annotations.Mapper
;
import
org.apache.ibatis.annotations.Param
;
import
org.apache.ibatis.annotations.Param
;
import
java.util.List
;
import
java.util.List
;
...
@@ -16,6 +17,7 @@ import java.util.List;
...
@@ -16,6 +17,7 @@ import java.util.List;
*
*
* @author Lion Li
* @author Lion Li
*/
*/
@Mapper
public
interface
SysUserMapper
extends
BaseMapperPlus
<
SysUserMapper
,
SysUser
,
SysUser
>
{
public
interface
SysUserMapper
extends
BaseMapperPlus
<
SysUserMapper
,
SysUser
,
SysUser
>
{
@DataPermission
({
@DataPermission
({
...
...
pz-system/src/main/java/com/pz/system/service/SysLoginService.java
View file @
40b78f19
...
@@ -5,7 +5,9 @@ import cn.dev33.satoken.secure.BCrypt;
...
@@ -5,7 +5,9 @@ import cn.dev33.satoken.secure.BCrypt;
import
cn.dev33.satoken.stp.StpUtil
;
import
cn.dev33.satoken.stp.StpUtil
;
import
cn.hutool.core.bean.BeanUtil
;
import
cn.hutool.core.bean.BeanUtil
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.core.util.RandomUtil
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.core.toolkit.Wrappers
;
import
com.pz.common.constant.CacheConstants
;
import
com.pz.common.constant.CacheConstants
;
import
com.pz.common.constant.Constants
;
import
com.pz.common.constant.Constants
;
import
com.pz.common.core.domain.dto.RoleDTO
;
import
com.pz.common.core.domain.dto.RoleDTO
;
...
@@ -16,6 +18,7 @@ import com.pz.common.core.domain.model.XcxLoginUser;
...
@@ -16,6 +18,7 @@ import com.pz.common.core.domain.model.XcxLoginUser;
import
com.pz.common.enums.DeviceType
;
import
com.pz.common.enums.DeviceType
;
import
com.pz.common.enums.LoginType
;
import
com.pz.common.enums.LoginType
;
import
com.pz.common.enums.UserStatus
;
import
com.pz.common.enums.UserStatus
;
import
com.pz.common.enums.UserType
;
import
com.pz.common.exception.user.CaptchaException
;
import
com.pz.common.exception.user.CaptchaException
;
import
com.pz.common.exception.user.CaptchaExpireException
;
import
com.pz.common.exception.user.CaptchaExpireException
;
import
com.pz.common.exception.user.UserException
;
import
com.pz.common.exception.user.UserException
;
...
@@ -26,6 +29,8 @@ import com.pz.common.utils.ServletUtils;
...
@@ -26,6 +29,8 @@ import com.pz.common.utils.ServletUtils;
import
com.pz.common.utils.StringUtils
;
import
com.pz.common.utils.StringUtils
;
import
com.pz.common.utils.redis.RedisUtils
;
import
com.pz.common.utils.redis.RedisUtils
;
import
com.pz.common.utils.spring.SpringUtils
;
import
com.pz.common.utils.spring.SpringUtils
;
import
com.pz.merchant.domain.WechatUserInfo
;
import
com.pz.merchant.domain.bo.WechatLoginBo
;
import
com.pz.system.mapper.SysUserMapper
;
import
com.pz.system.mapper.SysUserMapper
;
import
lombok.RequiredArgsConstructor
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
...
@@ -138,6 +143,53 @@ public class SysLoginService {
...
@@ -138,6 +143,53 @@ public class SysLoginService {
}
}
/**
/**
* 小程序登录
*
* @param loginBo 微信用户信息
* @return token
*/
public
String
xccLogin
(
WechatUserInfo
loginBo
)
{
SysUser
user
=
loadUserByOpenid
(
loginBo
.
getOpenId
());
if
(
user
==
null
)
{
SysUser
userByPhone
=
userMapper
.
selectOne
(
Wrappers
.<
SysUser
>
lambdaQuery
().
eq
(
SysUser:
:
getPhonenumber
,
loginBo
.
getMobilePhone
()));
// 若该手机号已经被注册,则直接绑定OpenID
if
(
userByPhone
!=
null
)
{
userByPhone
.
setOpenId
(
loginBo
.
getOpenId
());
if
(
userMapper
.
updateById
(
userByPhone
)
<
1
)
{
throw
new
UserException
(
"用户绑定微信失败,请检查用户信息"
);
}
user
=
userByPhone
;
}
else
{
// 注册用户
SysUser
sysUser
=
new
SysUser
();
sysUser
.
setOpenId
(
loginBo
.
getOpenId
());
sysUser
.
setPhonenumber
(
loginBo
.
getMobilePhone
());
sysUser
.
setUserName
(
loginBo
.
getMobilePhone
());
String
nikeName
=
StringUtils
.
isNoneBlank
(
loginBo
.
getNikeName
())
?
loginBo
.
getNikeName
()
:
"用户"
+
RandomUtil
.
randomString
(
8
);
sysUser
.
setNickName
(
nikeName
);
sysUser
.
setUserType
(
UserType
.
APP_USER
.
getUserType
());
sysUser
.
setSex
(
"2"
);
// 初始密码为123456
sysUser
.
setPassword
(
BCrypt
.
hashpw
(
"123456"
));
if
(
userMapper
.
insert
(
sysUser
)
<
1
)
{
throw
new
UserException
(
"用户注册失败,请检查用户信息"
);
}
user
=
sysUser
;
}
}
XcxLoginUser
loginUser
=
new
XcxLoginUser
();
loginUser
.
setUserId
(
user
.
getUserId
());
loginUser
.
setUsername
(
user
.
getUserName
());
loginUser
.
setUserType
(
user
.
getUserType
());
loginUser
.
setOpenid
(
loginBo
.
getOpenId
());
// 生成token
LoginHelper
.
loginByDevice
(
loginUser
,
DeviceType
.
XCX
);
recordLogininfor
(
user
.
getUserName
(),
Constants
.
LOGIN_SUCCESS
,
MessageUtils
.
message
(
"user.login.success"
));
recordLoginInfo
(
user
.
getUserId
(),
user
.
getUserName
());
return
StpUtil
.
getTokenValue
();
}
/**
* 退出登录
* 退出登录
*/
*/
public
void
logout
()
{
public
void
logout
()
{
...
@@ -253,15 +305,11 @@ public class SysLoginService {
...
@@ -253,15 +305,11 @@ public class SysLoginService {
}
}
private
SysUser
loadUserByOpenid
(
String
openid
)
{
private
SysUser
loadUserByOpenid
(
String
openid
)
{
// 使用 openid 查询绑定用户 如未绑定用户 则根据业务自行处理 例如 创建默认用户
SysUser
user
=
userMapper
.
selectOne
(
Wrappers
.<
SysUser
>
lambdaQuery
().
eq
(
SysUser:
:
getOpenId
,
openid
));
// todo 自行实现 userService.selectUserByOpenid(openid);
SysUser
user
=
new
SysUser
();
if
(
ObjectUtil
.
isNull
(
user
))
{
if
(
ObjectUtil
.
isNull
(
user
))
{
log
.
info
(
"登录用户:{} 不存在."
,
openid
);
log
.
info
(
"登录用户:{} 不存在."
,
openid
);
// todo 用户不存在 业务逻辑自行实现
}
else
if
(
UserStatus
.
DISABLE
.
getCode
().
equals
(
user
.
getStatus
()))
{
}
else
if
(
UserStatus
.
DISABLE
.
getCode
().
equals
(
user
.
getStatus
()))
{
log
.
info
(
"登录用户:{} 已被停用."
,
openid
);
log
.
info
(
"登录用户:{} 已被停用."
,
openid
);
// todo 用户已被停用 业务逻辑自行实现
}
}
return
user
;
return
user
;
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment