Browse Source

feature1.0.0:img服务添加完成小程序登录;图片压缩上传;

master
chengkun 4 years ago
parent
commit
37d6de2b33
  1. 9
      bnyer-common/bnyer-common-core/pom.xml
  2. 18
      bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/annotation/TokenCheck.java
  3. 57
      bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/utils/Sm4Util.java
  4. 6
      bnyer-services/bnyer-file/pom.xml
  5. 38
      bnyer-services/bnyer-file/src/main/java/com/bnyer/file/controller/SysFileController.java
  6. 29
      bnyer-services/bnyer-file/src/main/java/com/bnyer/file/service/MinioService.java
  7. 29
      bnyer-services/bnyer-file/src/main/java/com/bnyer/file/service/MinioSysFileServiceImpl.java
  8. 131
      bnyer-services/bnyer-file/src/main/java/com/bnyer/file/utils/ImgUtil.java
  9. 21
      bnyer-services/bnyer-img/src/main/java/com/bnyer/img/config/TiktokConfig.java
  10. 5
      bnyer-services/bnyer-img/src/main/java/com/bnyer/img/constants/RedisKeyConstant.java
  11. 36
      bnyer-services/bnyer-img/src/main/java/com/bnyer/img/controller/TiktokMiniController.java
  12. 31
      bnyer-services/bnyer-img/src/main/java/com/bnyer/img/controller/TiktokUserController.java
  13. 31
      bnyer-services/bnyer-img/src/main/java/com/bnyer/img/dto/TiktokBindPhoneDto.java
  14. 37
      bnyer-services/bnyer-img/src/main/java/com/bnyer/img/dto/TiktokCreaterDto.java
  15. 27
      bnyer-services/bnyer-img/src/main/java/com/bnyer/img/dto/TiktokLoginDto.java
  16. 54
      bnyer-services/bnyer-img/src/main/java/com/bnyer/img/handler/TokenCheckHandler.java
  17. 26
      bnyer-services/bnyer-img/src/main/java/com/bnyer/img/service/TiktokUserService.java
  18. 214
      bnyer-services/bnyer-img/src/main/java/com/bnyer/img/service/impl/TiktokUserServiceImpl.java
  19. 36
      bnyer-services/bnyer-img/src/main/java/com/bnyer/img/vo/TiktokUserInfoVo.java
  20. 24
      bnyer-services/bnyer-img/src/main/java/com/bnyer/img/vo/TiktokUserPhoneInfoVo.java
  21. 7
      pom.xml

9
bnyer-common/bnyer-common-core/pom.xml

@ -10,7 +10,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>bnyer-common-core</artifactId>
<description>
bnyer-common-core核心模块
</description>
@ -22,7 +22,7 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- SpringCloud Loadbalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
@ -124,6 +124,11 @@
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
</dependencies>
</project>

18
bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/annotation/TokenCheck.java

@ -0,0 +1,18 @@
package com.bnyer.common.core.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 小程序用户token检测注解
*
* @author chengkun
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TokenCheck
{
}

57
bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/utils/Sm4Util.java

@ -0,0 +1,57 @@
package com.bnyer.common.core.utils;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.KeyGenerator;
import java.security.SecureRandom;
import java.util.Base64;
/**
* @author kevin
* @date 2020/10/22 17:19
*/
public class Sm4Util {
private static byte[] sm4Key;
public static void utilInit(String key) {
sm4Key = Base64.getDecoder().decode(key);
}
/**
* SM4加密
*
* @param src
* @return
*/
public static String sm4Encryption(String src) {
//账户加密
SymmetricCrypto sm4 = new SymmetricCrypto("SM4/ECB/PKCS5Padding", sm4Key);
byte[] bytes = sm4.encrypt(src);
return Base64.getEncoder().encodeToString(bytes);
}
/**
* SM4加密
*
* @param src
* @return
*/
public static String sm4Decrypt(String src) {
//账户加密
SymmetricCrypto sm4 = new SymmetricCrypto("SM4/ECB/PKCS5Padding", sm4Key);
byte[] bytes = sm4.decrypt(src);
return new String(bytes);
}
/**
* @explain
* @param keySize
* @return
* @throws Exception
*/
public static byte[] generateKey(int keySize) throws Exception {
KeyGenerator kg = KeyGenerator.getInstance("SM4", BouncyCastleProvider.PROVIDER_NAME);
kg.init(keySize, new SecureRandom());
return kg.generateKey().getEncoded();
}
}

6
bnyer-services/bnyer-file/pom.xml

@ -65,6 +65,12 @@
<groupId>com.dimensionalnode</groupId>
<artifactId>bnyer-common-swagger</artifactId>
</dependency>
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
</dependencies>

38
bnyer-services/bnyer-file/src/main/java/com/bnyer/file/controller/SysFileController.java

@ -1,15 +1,19 @@
package com.bnyer.file.controller;
import com.bnyer.common.core.domain.R;
import com.bnyer.common.core.utils.file.FileUtils;
import com.bnyer.file.service.ISysFileService;
import com.bnyer.file.service.MinioService;
import com.bnyer.system.api.domain.SysFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.bnyer.common.core.domain.R;
import com.bnyer.common.core.utils.file.FileUtils;
import com.bnyer.file.service.ISysFileService;
import com.bnyer.system.api.domain.SysFile;
import java.util.ArrayList;
import java.util.List;
/**
* 文件请求处理
@ -24,6 +28,9 @@ public class SysFileController
@Autowired
private ISysFileService sysFileService;
@Autowired
private MinioService minioService;
/**
* 文件上传请求
*/
@ -45,4 +52,27 @@ public class SysFileController
return R.fail(e.getMessage());
}
}
/**
* 批量压缩上传图片
*/
@PostMapping("uploadBatch")
public R<List<String>> uploadBatch(MultipartFile[] files)
{
try
{
List<String> list = new ArrayList<>();
for (MultipartFile file : files) {
String url = minioService.uploadFileByThumb(file);
list.add(url);
}
// 上传并返回访问地址
return R.ok(list);
}
catch (Exception e)
{
log.error("上传文件失败", e);
return R.fail(e.getMessage());
}
}
}

29
bnyer-services/bnyer-file/src/main/java/com/bnyer/file/service/MinioService.java

@ -0,0 +1,29 @@
package com.bnyer.file.service;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
/**
* @author chengkun
* @date 2022/4/22 19:33
*/
public interface MinioService {
/**
* 文件上传接口
*
* @param file 上传的文件
* @return 访问地址
* @throws Exception
*/
public String uploadFile(MultipartFile file) throws Exception;
/**
* 压缩图片上传
* @param file 文件
* @return -
* @throws Exception
*/
String uploadFileByThumb(MultipartFile file) throws Exception;
}

29
bnyer-services/bnyer-file/src/main/java/com/bnyer/file/service/MinioSysFileServiceImpl.java

@ -1,6 +1,9 @@
package com.bnyer.file.service;
import com.bnyer.common.core.exception.ServiceException;
import com.bnyer.file.config.MinioConfig;
import com.bnyer.file.utils.ImgUtil;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
@ -8,13 +11,16 @@ import com.bnyer.file.utils.FileUploadUtils;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import java.awt.image.BufferedImage;
import java.io.InputStream;
/**
* Minio 文件存储
*
* @author ruoyi
*/
@Service
public class MinioSysFileServiceImpl implements ISysFileService
public class MinioSysFileServiceImpl implements MinioService
{
@Autowired
private MinioConfig minioConfig;
@ -42,4 +48,25 @@ public class MinioSysFileServiceImpl implements ISysFileService
client.putObject(args);
return minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + fileName;
}
@Override
public String uploadFileByThumb(MultipartFile file) throws Exception {
boolean b = ImgUtil.isPicture(file.getName());
if(!b){
throw new ServiceException("文件类型不是图片类型,上传失败!");
}
BufferedImage image = ImgUtil.toBufferedImage(file);
BufferedImage bufferedImage = Thumbnails.of(image).size(700, 467).asBufferedImage();
InputStream inputStream = ImgUtil.bufferedImageToInputStream(bufferedImage);
String fileName = FileUploadUtils.extractFilename(file);
MultipartFile multipartFile = ImgUtil.getMultipartFile(inputStream, fileName);
PutObjectArgs args = PutObjectArgs.builder()
.bucket(minioConfig.getBucketName())
.object(multipartFile.getName())
.stream(multipartFile.getInputStream(), multipartFile.getSize(), -1)
.contentType(multipartFile.getContentType())
.build();
client.putObject(args);
return minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + multipartFile.getName();
}
}

131
bnyer-services/bnyer-file/src/main/java/com/bnyer/file/utils/ImgUtil.java

@ -0,0 +1,131 @@
package com.bnyer.file.utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
/**
* 图片处理工具类
* @author chengkun
* @date 2022/4/22 18:05
*/
@Slf4j
public class ImgUtil {
/**
* 将MultipartFile类转为BufferedImage对象
* @param file 文件
* @return -
*/
public static BufferedImage toBufferedImage(MultipartFile file) {
BufferedImage srcImage = null;
try {
FileInputStream in = (FileInputStream) file.getInputStream();
srcImage = javax.imageio.ImageIO.read(in);
} catch (IOException e) {
}
return srcImage;
}
/**
* 将BufferedImage转为InputStream
* @param image 图片
* @return -
*/
public static InputStream bufferedImageToInputStream(BufferedImage image){
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
ImageIO.write(image, "jpg", os);
InputStream input = new ByteArrayInputStream(os.toByteArray());
return input;
} catch (IOException e) {
log.error("提示:",e);
}
return null;
}
/**
* 获取封装得MultipartFile
*
* @param inputStream inputStream
* @param fileName fileName
* @return MultipartFile
*/
public static MultipartFile getMultipartFile(InputStream inputStream, String fileName) {
FileItem fileItem = createFileItem(inputStream, fileName);
return new CommonsMultipartFile(fileItem);
}
/**
* FileItem类对象创建
*
* @param inputStream inputStream
* @param fileName fileName
* @return FileItem
*/
public static FileItem createFileItem(InputStream inputStream, String fileName) {
FileItemFactory factory = new DiskFileItemFactory(16, null);
String textFieldName = "file";
FileItem item = factory.createItem(textFieldName, MediaType.MULTIPART_FORM_DATA_VALUE, true, fileName);
int bytesRead = 0;
byte[] buffer = new byte[8192];
OutputStream os = null;
//使用输出流输出输入流的字节
try {
os = item.getOutputStream();
while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
inputStream.close();
} catch (IOException e) {
log.error("Stream copy exception", e);
throw new IllegalArgumentException("文件上传失败");
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
log.error("Stream close exception", e);
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
log.error("Stream close exception", e);
}
}
}
return item;
}
/**
* 判断文件是否为图片
*/
public static boolean isPicture(String imgName) {
boolean flag = false;
if (StringUtils.isBlank(imgName)) {
return false;
}
String[] arr = {"bmp", "dib", "gif", "jfif", "jpe", "jpeg", "jpg", "png", "tif", "tiff", "ico"};
for (String item : arr) {
if (item.equals(imgName)) {
flag = true;
break;
}
}
return flag;
}
}

21
bnyer-services/bnyer-img/src/main/java/com/bnyer/img/config/TiktokConfig.java

@ -1,9 +1,14 @@
package com.bnyer.img.config;
import com.bnyer.img.handler.TokenCheckHandler;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
/**
* @author chengkun
@ -12,7 +17,7 @@ import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "bnyer.img.tiktok")
@Getter
public class TiktokConfig {
public class TiktokConfig implements WebMvcConfigurer {
@Value("${bnyer.img.tiktok.appId}")
private String appId;
@ -26,9 +31,19 @@ public class TiktokConfig {
@Value("${bnyer.img.tiktok.tokenUrl}")
public String tokenUrl;
@Resource
private TokenCheckHandler tokenCheckHandler;
/** 不需要拦截地址 */
public static final String[] excludeUrls = { "/mini/tiktok/login", "/mini/tiktok/insertFeedback"};
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册Token拦截器
registry.addInterceptor(tokenCheckHandler)
.addPathPatterns("/**")
.excludePathPatterns(excludeUrls)
.order(-10);
}
}

5
bnyer-services/bnyer-img/src/main/java/com/bnyer/img/constants/RedisKeyConstant.java

@ -26,4 +26,9 @@ public class RedisKeyConstant {
* 抖音小程序图片点赞数量键
*/
public static final String TIKTOK_IMG_LIKE_NUM_KEY = "bnyer.tiktok.likeNum";
/**
* 抖音小程序用户登录键
*/
public static final String TIKTOK_USER_LOGIN_KEY = "bnyer.titok.user:";
}

36
bnyer-services/bnyer-img/src/main/java/com/bnyer/img/controller/TiktokMiniController.java

@ -1,6 +1,7 @@
package com.bnyer.img.controller;
import com.alibaba.fastjson.JSON;
import com.bnyer.common.core.annotation.TokenCheck;
import com.bnyer.common.core.web.controller.BaseController;
import com.bnyer.common.core.web.domain.AjaxResult;
import com.bnyer.img.domain.Feedback;
@ -20,7 +21,7 @@ import java.util.List;
@Api("img-抖音平台-【小程序】接口")
@RestController
@RequestMapping("/tiktok")
@RequestMapping("/mini/tiktok")
@Slf4j
public class TiktokMiniController extends BaseController {
@ -45,6 +46,7 @@ public class TiktokMiniController extends BaseController {
@Autowired
private TiktokLikeService tiktokLikeService;
@TokenCheck
@ApiOperation(value="查询banner列表")
@GetMapping(value = "/listBanner")
public AjaxResult listBanner(){
@ -60,12 +62,14 @@ public class TiktokMiniController extends BaseController {
return AjaxResult.success(feedBackService.insert(feedback));
}
@TokenCheck
@ApiOperation(value="查询type列表")
@GetMapping(value = "/listType")
public AjaxResult listType(){
return AjaxResult.success(typeService.queryList());
}
@TokenCheck
@ApiOperation(value="新增TiktokImg")
@PostMapping(value = "/insertTiktokImg")
public AjaxResult insertTiktokImg(@Validated @RequestBody @ApiParam("TiktokImg对象") TiktokImgMiniDto dto){
@ -75,6 +79,7 @@ public class TiktokMiniController extends BaseController {
return AjaxResult.success(tiktokImgService.insert(tiktokImg));
}
@TokenCheck
@ApiOperation(value="修改TiktokImg")
@PostMapping(value = "/updateTiktokImg")
public AjaxResult updateTiktokImg(@Validated @RequestBody @ApiParam("TiktokImg对象") TiktokImgMiniDto dto){
@ -84,6 +89,7 @@ public class TiktokMiniController extends BaseController {
return AjaxResult.success(tiktokImgService.update(dto.extractParam()));
}
@TokenCheck
@ApiOperation(value="删除TiktokImg")
@DeleteMapping(value = "/deleteTiktokImg/{ids}")
public AjaxResult deleteTiktokImg(@PathVariable @ApiParam("主键ids") List<Long> ids){
@ -91,30 +97,35 @@ public class TiktokMiniController extends BaseController {
return AjaxResult.success(tiktokImgService.delete(ids));
}
@TokenCheck
@ApiOperation(value="查询指定用户对内的图片集合")
@PostMapping(value = "/listTiktokImgIn")
public AjaxResult listTiktokImgIn(@Validated @RequestBody @ApiParam("TiktokImg对象") TiktokImgListMiniDto dto){
return AjaxResult.success(tiktokImgService.queryInList(dto.getUserId(),dto.getTypeId()));
}
@TokenCheck
@ApiOperation(value="查询指定用户对外的图片集合")
@PostMapping(value = "/listTiktokImgOut")
public AjaxResult listTiktokImgOut(@Validated @RequestBody @ApiParam("TiktokImg对象") TiktokImgListMiniDto dto){
return AjaxResult.success(tiktokImgService.queryOutList(dto.getUserId(),dto.getTypeId()));
}
@TokenCheck
@ApiOperation(value="查询小程序审核通过图片详情")
@GetMapping(value = "/detailsTiktokImg/{id}")
public AjaxResult detailsTiktokImg(@ApiParam("图片id") @PathVariable Long id){
return AjaxResult.success(tiktokImgService.queryImgDetails(String.valueOf(id)));
}
@TokenCheck
@ApiOperation(value="查询小程序用户图片列表")
@GetMapping(value = "/tiktokUserImgs")
public AjaxResult tiktokUserImgs(){
return AjaxResult.success(tiktokUserService.queryUserImgList());
}
@TokenCheck
@ApiOperation(value="收藏")
@PostMapping(value = "/tiktokCollect")
public AjaxResult tiktokCollect(@Validated @RequestBody @ApiParam("收藏对象") CollectionDto dto){
@ -123,6 +134,7 @@ public class TiktokMiniController extends BaseController {
return AjaxResult.success();
}
@TokenCheck
@ApiOperation(value="取消收藏")
@PostMapping(value = "/tiktokUnCollect")
public AjaxResult tiktokUnCollect(@Validated @RequestBody @ApiParam("收藏对象") CollectionDto dto){
@ -131,6 +143,7 @@ public class TiktokMiniController extends BaseController {
return AjaxResult.success();
}
@TokenCheck
@ApiOperation(value="查询是否收藏过")
@PostMapping(value = "/judgeTiktokCollect")
public AjaxResult judgeTiktokCollect(@Validated @RequestBody @ApiParam("收藏对象") CollectionDto dto){
@ -138,6 +151,7 @@ public class TiktokMiniController extends BaseController {
return AjaxResult.success(tiktokCollectionService.judgeCollect(dto.getUserId(),dto.getImgId()));
}
@TokenCheck
@ApiOperation(value="查看用户收藏列表")
@PostMapping(value = "/listTiktokCollection")
public AjaxResult listTiktokCollection(@Validated @RequestBody @ApiParam("用户收藏对象") CollectionUserDto dto){
@ -145,6 +159,7 @@ public class TiktokMiniController extends BaseController {
return AjaxResult.success(tiktokCollectionService.getCollectionByUserId(dto.getUserId()));
}
@TokenCheck
@ApiOperation(value="点赞")
@PostMapping(value = "/tiktokLike")
public AjaxResult tiktokLike(@Validated @RequestBody @ApiParam("点赞对象") CollectionDto dto){
@ -153,6 +168,7 @@ public class TiktokMiniController extends BaseController {
return AjaxResult.success();
}
@TokenCheck
@ApiOperation(value="取消点赞")
@PostMapping(value = "/tiktokUnLike")
public AjaxResult tiktokUnLike(@Validated @RequestBody @ApiParam("点赞对象") CollectionDto dto){
@ -161,10 +177,28 @@ public class TiktokMiniController extends BaseController {
return AjaxResult.success();
}
@TokenCheck
@ApiOperation(value="查询是否点赞过")
@PostMapping(value = "/judgeTiktokLike")
public AjaxResult judgeTiktokLike(@Validated @RequestBody @ApiParam("点赞对象") CollectionDto dto){
log.debug("查询是否点赞过参数为:{}", JSON.toJSONString(dto));
return AjaxResult.success(tiktokLikeService.judgeLike(dto.getUserId(),dto.getImgId()));
}
@ApiOperation(value="用户登录")
@PostMapping(value = "/login")
public AjaxResult login(@Validated @RequestBody @ApiParam("登录对象") TiktokLoginDto dto){
log.debug("用户登录参数为:{}", JSON.toJSONString(dto));
return AjaxResult.success(tiktokUserService.login(dto));
}
@TokenCheck
@ApiOperation(value="绑定手机号")
@PostMapping(value = "/bindPhone")
public AjaxResult bindPhone(@Validated @RequestBody @ApiParam("绑定对象") TiktokBindPhoneDto dto){
log.debug("绑定手机号参数为:{}", JSON.toJSONString(dto));
tiktokUserService.bindPhone(dto);
return AjaxResult.success();
}
}

31
bnyer-services/bnyer-img/src/main/java/com/bnyer/img/controller/TiktokUserController.java

@ -1,10 +1,12 @@
package com.bnyer.img.controller;
import com.alibaba.fastjson.JSON;
import com.bnyer.common.core.utils.Sm4Util;
import com.bnyer.common.core.web.controller.BaseController;
import com.bnyer.common.core.web.domain.AjaxResult;
import com.bnyer.common.core.web.page.TableDataInfo;
import com.bnyer.img.domain.TiktokUser;
import com.bnyer.img.dto.TiktokCreaterDto;
import com.bnyer.img.dto.TiktokUserDto;
import com.bnyer.img.dto.TiktokUserPageDto;
import com.bnyer.img.service.TiktokUserService;
@ -33,24 +35,28 @@ public class TiktokUserController extends BaseController {
public TableDataInfo list(TiktokUserPageDto dto){
startPage();
List<TiktokUser> tiktokUsers = tiktokUserService.queryPage(dto);
for (TiktokUser tiktokUser : tiktokUsers) {
tiktokUser.setPhone(Sm4Util.sm4Decrypt(tiktokUser.getPhone()));
tiktokUser.setTiktokCode(Sm4Util.sm4Decrypt(tiktokUser.getTiktokCode()));
}
return getDataTable(tiktokUsers);
}
//@RequiresPermissions("system:config:list")
@ApiOperation(value="新增user")
@ApiOperation(value="成为艺术家")
@PostMapping(value = "/insert")
public AjaxResult insert(@Validated @RequestBody @ApiParam("user对象") TiktokUserDto dto){
log.debug("新增user参数为:{}", JSON.toJSONString(dto));
return AjaxResult.success(tiktokUserService.insert(dto.extractParam()));
public AjaxResult insert(@Validated @RequestBody @ApiParam("user对象") TiktokCreaterDto dto){
log.debug("成为艺术家参数为:{}", JSON.toJSONString(dto));
return AjaxResult.success(tiktokUserService.insertCreator(dto));
}
//@RequiresPermissions("system:config:list")
@ApiOperation(value="修改user")
@PostMapping(value = "/update")
public AjaxResult update(@Validated @RequestBody @ApiParam("user对象") TiktokUserDto dto){
log.debug("修改user参数为:{}", JSON.toJSONString(dto));
return AjaxResult.success(tiktokUserService.update(dto.extractParam()));
}
// @ApiOperation(value="修改user")
// @PostMapping(value = "/update")
// public AjaxResult update(@Validated @RequestBody @ApiParam("user对象") TiktokUserDto dto){
// log.debug("修改user参数为:{}", JSON.toJSONString(dto));
// return AjaxResult.success(tiktokUserService.update(dto.extractParam()));
// }
//@RequiresPermissions("system:config:list")
@ApiOperation(value="删除user")
@ -64,6 +70,9 @@ public class TiktokUserController extends BaseController {
@ApiOperation(value="查询user详情")
@GetMapping(value = "/details/{id}")
public AjaxResult details(@PathVariable @ApiParam("主键id") Long id){
return AjaxResult.success(tiktokUserService.queryDetails(id));
TiktokUser tiktokUser = tiktokUserService.queryDetails(id);
tiktokUser.setPhone(Sm4Util.sm4Decrypt(tiktokUser.getPhone()));
tiktokUser.setTiktokCode(Sm4Util.sm4Decrypt(tiktokUser.getTiktokCode()));
return AjaxResult.success(tiktokUser);
}
}

31
bnyer-services/bnyer-img/src/main/java/com/bnyer/img/dto/TiktokBindPhoneDto.java

@ -0,0 +1,31 @@
package com.bnyer.img.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
@Getter
@Setter
@ApiModel("抖音登录入参")
public class TiktokBindPhoneDto implements Serializable {
@NotNull(message = "用户Id不能为空!")
@ApiModelProperty(value = "用户Id")
private Long userId;
@NotNull(message = "加密数据不能为空!")
@ApiModelProperty(value = "加密数据")
private String encryptedData;
@NotNull(message = "sessionKey不能为空!")
@ApiModelProperty(value = "sessionKey")
private String sessionKey;
@NotNull(message = "加密算法向量不能为空!")
@ApiModelProperty(value = "加密算法向量")
private String iv;
}

37
bnyer-services/bnyer-img/src/main/java/com/bnyer/img/dto/TiktokCreaterDto.java

@ -0,0 +1,37 @@
package com.bnyer.img.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* @author chengkun
* @date 2022/4/22 16:06
*/
@Getter
@Setter
@ApiModel("抖音艺术家接收类")
public class TiktokCreaterDto implements Serializable {
@NotNull(message = "抖音号不能为空")
@ApiModelProperty(value="抖音号")
private String tiktokNum;
@NotNull(message = "搜索码不能为空")
@ApiModelProperty(value="搜索码")
private String scanCode;
@ApiModelProperty(value="邀请码")
private String inviteCode;
@NotNull(message = "手机号不能为空!")
@ApiModelProperty(value="手机号")
private String phone;
@ApiModelProperty(value="简介")
private String intro;
}

27
bnyer-services/bnyer-img/src/main/java/com/bnyer/img/dto/TiktokLoginDto.java

@ -0,0 +1,27 @@
package com.bnyer.img.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
@Getter
@Setter
@ApiModel("抖音登录入参")
public class TiktokLoginDto implements Serializable {
@NotNull(message = "code不能为空!")
@ApiModelProperty(value = "微信code")
private String code;
@NotNull(message = "加密数据不能为空!")
@ApiModelProperty(value = "加密数据")
private String encryptedData;
@NotNull(message = "加密算法向量不能为空!")
@ApiModelProperty(value = "加密算法向量")
private String iv;
}

54
bnyer-services/bnyer-img/src/main/java/com/bnyer/img/handler/TokenCheckHandler.java

@ -0,0 +1,54 @@
package com.bnyer.img.handler;
import com.bnyer.common.core.annotation.TokenCheck;
import com.bnyer.common.core.exception.ServiceException;
import com.bnyer.common.redis.service.RedisService;
import com.bnyer.img.constants.RedisKeyConstant;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author chengkun
* @date 2022/4/22 15:04
*/
@Component
public class TokenCheckHandler implements HandlerInterceptor {
String tokenKey = RedisKeyConstant.TIKTOK_USER_LOGIN_KEY;
@Autowired
private RedisService redisService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 判断访问的方法上是否有注解
HandlerMethod handlerMethod = (HandlerMethod) handler;
boolean tokenCheck = handlerMethod.hasMethodAnnotation(TokenCheck.class);
// 尝试从请求头从获取token值
String token = request.getHeader("token");
if(StringUtils.isEmpty(token)){
if(tokenCheck){
throw new ServiceException("token为空,无权访问!");
}
}
String[] split = token.split("#");
//从token中获取openId
String openId = split[1];
//组装redisKey
String redisKey = tokenKey+openId;
//判断redis中是否存在该key,存在则放行,不存在则过期
if(redisService.hasKey(redisKey)){
return true;
}else{
throw new ServiceException("token失效,请重新授权!");
}
}
}

26
bnyer-services/bnyer-img/src/main/java/com/bnyer/img/service/TiktokUserService.java

@ -1,27 +1,32 @@
package com.bnyer.img.service;
import com.bnyer.img.domain.TiktokUser;
import com.bnyer.img.dto.TiktokBindPhoneDto;
import com.bnyer.img.dto.TiktokCreaterDto;
import com.bnyer.img.dto.TiktokLoginDto;
import com.bnyer.img.dto.TiktokUserPageDto;
import com.bnyer.img.vo.TiktokSessionInfoVo;
import com.bnyer.img.vo.TiktokUserPhoneInfoVo;
import com.bnyer.img.vo.TiktokUserVo;
import java.util.List;
import java.util.Map;
public interface TiktokUserService {
/**
* 新增抖音用户
* @param tiktokUser 抖音用户
* 新增艺术家
* @param dto 艺术家参数
* @return -
*/
int insert(TiktokUser tiktokUser);
int insertCreator(TiktokCreaterDto dto);
/**
* 修改抖音用户
* @param tiktokUser 抖音用户
* @return -
*/
int update(TiktokUser tiktokUser);
//int update(TiktokUser tiktokUser);
/**
* 批量删除抖音用户
@ -51,9 +56,16 @@ public interface TiktokUserService {
List<TiktokUserVo> queryUserImgList();
/**
* 查询tiktok小程序sessionInfo
* @param code 登录凭证code
* 抖音登录参数
* @param dto 登录参数
* @return -
*/
TiktokSessionInfoVo getSessionInfo(String code);
Map<String,Object> login(TiktokLoginDto dto);
/**
* 绑定手机号
* @param dto 绑定对象参数
*/
void bindPhone(TiktokBindPhoneDto dto);
}

214
bnyer-services/bnyer-img/src/main/java/com/bnyer/img/service/impl/TiktokUserServiceImpl.java

@ -2,29 +2,38 @@ package com.bnyer.img.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.bnyer.common.core.exception.ServiceException;
import com.bnyer.common.core.utils.Sm4Util;
import com.bnyer.common.core.utils.StringUtils;
import com.bnyer.common.core.utils.uuid.IdUtils;
import com.bnyer.common.redis.service.RedisService;
import com.bnyer.img.config.TiktokConfig;
import com.bnyer.img.constants.RedisKeyConstant;
import com.bnyer.img.constants.TiktokConstant;
import com.bnyer.img.domain.TiktokImg;
import com.bnyer.img.domain.TiktokUser;
import com.bnyer.img.dto.TiktokBindPhoneDto;
import com.bnyer.img.dto.TiktokCreaterDto;
import com.bnyer.img.dto.TiktokLoginDto;
import com.bnyer.img.dto.TiktokUserPageDto;
import com.bnyer.img.feign.TiktokFeign;
import com.bnyer.img.mapper.TiktokImgMapper;
import com.bnyer.img.mapper.TiktokUserMapper;
import com.bnyer.img.service.TiktokUserService;
import com.bnyer.img.vo.TiktokSessionInfoVo;
import com.bnyer.img.vo.TiktokUserInfoVo;
import com.bnyer.img.vo.TiktokUserPhoneInfoVo;
import com.bnyer.img.vo.TiktokUserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.*;
import java.util.concurrent.TimeUnit;
@Service
@ -46,16 +55,67 @@ public class TiktokUserServiceImpl implements TiktokUserService {
@Autowired
private TiktokFeign tiktokFeign;
@Override
public int insert(TiktokUser tiktokUser) {
return 0;
/**
* 检查搜索码是否重复
* @param scanCode 搜索码
* @return -
*/
private boolean checkScanCode(String scanCode){
LambdaQueryWrapper<TiktokUser> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(TiktokUser::getScanCode, scanCode);
List<TiktokUser> tiktokUsers = tiktokUserMapper.selectList(wrapper);
if(tiktokUsers.size() > 0){
return true;
}else{
return false;
}
}
/**
* 检查用户是否绑定过手机号
* @param phone 手机号
* @return -
*/
private boolean checkPhone(String phone){
LambdaQueryWrapper<TiktokUser> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(TiktokUser::getPhone, phone);
List<TiktokUser> tiktokUsers = tiktokUserMapper.selectList(wrapper);
if(tiktokUsers.size() > 0){
return true;
}else{
return false;
}
}
@Override
public int update(TiktokUser tiktokUser) {
return 0;
public int insertCreator(TiktokCreaterDto dto) {
//检查手机号是否存在
boolean b1 = checkPhone(Sm4Util.sm4Encryption(dto.getPhone()));
if(!b1){
throw new ServiceException("用户尚未绑定手机号,请手动绑定!");
}
//检查搜索码是否重复
boolean b = this.checkScanCode(dto.getScanCode());
if(b){
throw new ServiceException("搜索码重复,请重新编辑!");
}
TiktokUser user = new TiktokUser();
user.setIntro(dto.getIntro());
user.setScanCode(dto.getScanCode());
user.setInviteCode(dto.getInviteCode());
user.setTiktokNumber(dto.getTiktokNum());
LambdaUpdateWrapper<TiktokUser> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(TiktokUser::getPhone, Sm4Util.sm4Encryption(dto.getPhone()));
int update = tiktokUserMapper.update(user, updateWrapper);
log.info("用户【{}】成为艺术家成功!",dto.getPhone());
return update;
}
// @Override
// public int update(TiktokUser tiktokUser) {
// return 0;
// }
@Override
public int delete(List<Long> ids) {
int delete = tiktokUserMapper.deleteBatchIds(ids);
@ -72,7 +132,7 @@ public class TiktokUserServiceImpl implements TiktokUserService {
public List<TiktokUser> queryPage(TiktokUserPageDto dto) {
LambdaQueryWrapper<TiktokUser> wrapper = new LambdaQueryWrapper<>();
wrapper.like(StringUtils.isNotNull(dto.getUsername()), TiktokUser::getUsername, dto.getUsername());
wrapper.eq(StringUtils.isNotNull(dto.getPhone()),TiktokUser::getPhone, dto.getPhone());
wrapper.eq(StringUtils.isNotNull(dto.getPhone()),TiktokUser::getPhone, Sm4Util.sm4Encryption(dto.getPhone()));
wrapper.eq(StringUtils.isNotNull(dto.getTiktokNumber()), TiktokUser::getTiktokNumber, dto.getTiktokNumber());
wrapper.eq(StringUtils.isNotNull(dto.getScanCode()), TiktokUser::getScanCode, dto.getScanCode());
wrapper.eq(StringUtils.isNotNull(dto.getInviteCode()), TiktokUser::getInviteCode, dto.getInviteCode());
@ -98,8 +158,12 @@ public class TiktokUserServiceImpl implements TiktokUserService {
return tiktokUserVo;
}
@Override
public TiktokSessionInfoVo getSessionInfo(String code) {
/**
* 获取用户openId及sessionKey
* @param code 登录凭证code
* @return -
*/
private TiktokSessionInfoVo getSessionInfo(String code) {
Map<String, String> params = new HashMap(8);
params.put("appid", tiktokConfig.getAppId());
params.put("secret", tiktokConfig.getSecret());
@ -118,4 +182,132 @@ public class TiktokUserServiceImpl implements TiktokUserService {
result.setUnionId(data.getString("unionid"));
return result;
}
/**
* 获取用户敏感信息
* @param sessionKey -
* @param encryptedData 敏感数据
* @param iv 加密向量
* @return -
*/
private TiktokUserInfoVo getUserInfo(String sessionKey,String encryptedData,String iv){
Base64.Decoder decoder = Base64.getDecoder();
byte[] sessionKeyBytes = decoder.decode(sessionKey);
byte[] ivBytes = decoder.decode(iv);
byte[] encryptedBytes = decoder.decode(encryptedData);
Cipher cipher = null;
try {
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec skeySpec = new SecretKeySpec(sessionKeyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivSpec);
byte[] ret = cipher.doFinal(encryptedBytes);
if (null != ret && ret.length > 0) {
String result = new String(ret, "UTF-8");
return JSONObject.parseObject(result,TiktokUserInfoVo.class);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 保存用户
* @param openId 抖音id
* @param sessionKey -
* @param encryptedData 敏感信息数据
* @param iv 加密向量
* @return -
*/
private TiktokUser saveUserInfo(String openId,String sessionKey,String encryptedData,String iv){
//获取敏感信息
TiktokUserInfoVo userInfo = this.getUserInfo(sessionKey, encryptedData, iv);
TiktokUser user = new TiktokUser();
user.setUsername(userInfo.getNickName());
user.setImg(userInfo.getAvatarUrl());
user.setTiktokCode(Sm4Util.sm4Encryption(openId));
user.setIsHot("0");
user.setIsShow("1");
user.setCreateTime(new Date());
user.setUpdateTime(new Date());
tiktokUserMapper.insert(user);
log.info("抖音用户【{}】创建成功!",user.getId());
return user;
}
@Override
public Map<String, Object> login(TiktokLoginDto dto) {
TiktokSessionInfoVo sessionInfo = this.getSessionInfo(dto.getCode());
//检查数据库中是否存在该openId,存在则直接设置会话状态登录;不存在则新增
LambdaQueryWrapper<TiktokUser> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(sessionInfo.getOpenId() != null,TiktokUser::getTiktokCode,dto.getCode());
TiktokUser tiktokUser = tiktokUserMapper.selectOne(wrapper);
if(tiktokUser == null){
//新用户,新增
tiktokUser = this.saveUserInfo(sessionInfo.getOpenId(), sessionInfo.getSessionKey(), dto.getEncryptedData(), dto.getIv());
}
//设置会话状态
String redisKey = RedisKeyConstant.TIKTOK_USER_LOGIN_KEY+sessionInfo.getOpenId();
//存在该登录态则删除刷新
if(redisService.hasKey(redisKey)){
redisService.deleteObject(redisKey);
}
StringBuffer sb = new StringBuffer();
String randomId = IdUtils.fastSimpleUUID();
sb.append(randomId).append("#").append(sessionInfo.getOpenId());
//设置登录会话
redisService.setCacheObject(redisKey,sb.toString(),30L, TimeUnit.DAYS);
Map<String, Object> map = new HashMap<>(2);
map.put("token", sb.toString());
map.put("userInfo",tiktokUser);
return map;
}
@Override
public void bindPhone(TiktokBindPhoneDto dto) {
TiktokUserPhoneInfoVo phoneInfo = this.getPhone(dto.getSessionKey(), dto.getEncryptedData(), dto.getIv());
if(phoneInfo != null){
TiktokUser user = new TiktokUser();
user.setId(dto.getUserId());
user.setPhone(Sm4Util.sm4Encryption(phoneInfo.getPhoneNumber()));
tiktokUserMapper.updateById(user);
log.info("获取用户【{}】手机号成功!",dto.getUserId());
}else{
log.error("获取用户【{}】手机号失败!",dto.getUserId());
throw new ServiceException("用户手机号绑定失败!");
}
}
/**
* 获取用户手机号
* @param sessionKey -
* @param encryptedData 敏感信息
* @param iv 加密向量
* @return -
*/
private TiktokUserPhoneInfoVo getPhone(String sessionKey, String encryptedData, String iv) {
Base64.Decoder decoder = Base64.getDecoder();
byte[] sessionKeyBytes = decoder.decode(sessionKey);
byte[] ivBytes = decoder.decode(iv);
byte[] encryptedBytes = decoder.decode(encryptedData);
Cipher cipher = null;
try {
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec skeySpec = new SecretKeySpec(sessionKeyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivSpec);
byte[] ret = cipher.doFinal(encryptedBytes);
if (null != ret && ret.length > 0) {
String result = new String(ret, "UTF-8");
return JSONObject.parseObject(result,TiktokUserPhoneInfoVo.class);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

36
bnyer-services/bnyer-img/src/main/java/com/bnyer/img/vo/TiktokUserInfoVo.java

@ -0,0 +1,36 @@
package com.bnyer.img.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
@Getter
@Setter
@ApiModel("抖音平台用户响应类")
public class TiktokUserInfoVo implements Serializable {
@ApiModelProperty(value="用户昵称")
private String nickName;
@ApiModelProperty(value="用户头像网络地址")
private String avatarUrl;
@ApiModelProperty(value="用户性别,0: 未知;1:男性;2:女性")
private String gender;
@ApiModelProperty(value="用户所在城市")
private String city;
@ApiModelProperty(value="用户所在省份")
private String province;
@ApiModelProperty(value="用户所在国家")
private String country;
@ApiModelProperty(value="用户openId")
private String openId;
}

24
bnyer-services/bnyer-img/src/main/java/com/bnyer/img/vo/TiktokUserPhoneInfoVo.java

@ -0,0 +1,24 @@
package com.bnyer.img.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
@Getter
@Setter
@ApiModel("抖音平台用户响应类")
public class TiktokUserPhoneInfoVo implements Serializable {
@ApiModelProperty(value="用户绑定的手机号")
private String phoneNumber;
@ApiModelProperty(value="没有区号的手机号")
private String purePhoneNumber;
@ApiModelProperty(value="区号")
private String countryCode;
}

7
pom.xml

@ -41,6 +41,7 @@
<commons-collections.version>3.2.2</commons-collections.version>
<transmittable-thread-local.version>2.12.2</transmittable-thread-local.version>
<lombok>1.18.12</lombok>
<hutool.version>5.8.0.M3</hutool.version>
</properties>
<!-- 依赖声明 -->
@ -245,6 +246,12 @@
<version>${bnyer.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

Loading…
Cancel
Save