登录重构

master
chendt 4 years ago
parent de921aceec
commit b918fad14f

@ -233,28 +233,6 @@ CREATE TABLE `qrtz_triggers` (
/*Data for the table `qrtz_triggers` */
/*Table structure for table `tz_app_connect` */
DROP TABLE IF EXISTS `tz_app_connect`;
CREATE TABLE `tz_app_connect` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`user_id` varchar(36) NOT NULL COMMENT '本系统userId',
`app_id` tinyint(2) DEFAULT NULL COMMENT '第三方系统id 1微信小程序',
`nick_name` varchar(64) DEFAULT NULL COMMENT '第三方系统昵称',
`image_url` varchar(500) DEFAULT NULL COMMENT '第三方系统头像',
`biz_user_id` varchar(255) DEFAULT NULL COMMENT '第三方系统userid',
`biz_unionid` varchar(255) DEFAULT NULL COMMENT '第三方系统unionid',
PRIMARY KEY (`id`),
KEY `user_app_id` (`user_id`,`app_id`) COMMENT '用户id和appid联合索引'
) ENGINE=InnoDB AUTO_INCREMENT=50 DEFAULT CHARSET=utf8;
/*Data for the table `tz_app_connect` */
insert into `tz_app_connect`(`id`,`user_id`,`app_id`,`nick_name`,`image_url`,`biz_user_id`,`biz_unionid`) values
(48,'51540df5255e4d22903b0f83921095ff',1,NULL,NULL,'o-lgc5CUDIn2nkk8512hKumBnjMI','o92Yz1cLnHuo70epfneTG8SaRY0c'),
(49,'5f159317be5b4dc4bf3188f1a3da0369',1,NULL,NULL,'o-lgc5IHLX-RuR1aw5qwP9bpGDuQ','o92Yz1bmhLV8CKMwQkuPk5C8lFfg');
/*Table structure for table `tz_area` */
DROP TABLE IF EXISTS `tz_area`;

@ -79,5 +79,3 @@
}
</script>
<style lang="scss">
</style>

@ -16,7 +16,6 @@
<module>yami-shop-service</module>
<module>yami-shop-security</module>
<module>yami-shop-quartz</module>
<module>yami-shop-mp</module>
</modules>
<properties>
@ -24,25 +23,24 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.plugin.version>3.7.0</maven.compiler.plugin.version>
<spring-boot.version>2.3.6.RELEASE</spring-boot.version>
<security.oauth.auto.version>2.3.4.RELEASE</security.oauth.auto.version>
<spring-boot.version>2.3.12.RELEASE</spring-boot.version>
<java.version>1.8</java.version>
<guava.version>28.2-jre</guava.version>
<hutool.version>4.5.0</hutool.version>
<hutool.version>5.7.15</hutool.version>
<jsoup.version>1.11.3</jsoup.version>
<poi.version>3.17</poi.version>
<qiniu.version>7.2.18</qiniu.version>
<weixin.version>3.5.0</weixin.version>
<orika.version>1.5.4</orika.version>
<swagger2.version>2.9.2</swagger2.version>
<swagger-bootstrap.version>1.9.3</swagger-bootstrap.version>
<swagger-bootstrap.version>1.9.6</swagger-bootstrap.version>
<emoji.version>4.0.0</emoji.version>
<aliyun-core.version>4.3.9</aliyun-core.version>
<aliyun-dysmsapi.version>1.1.0</aliyun-dysmsapi.version>
<mybatis-plus.version>3.1.0</mybatis-plus.version>
<redisson.version>3.10.6</redisson.version>
<fst.version>2.57</fst.version>
<redisson.version>3.12.5</redisson.version>
<kryo.version>4.0.2</kryo.version>
<transmittable-thread-local.version>2.12.1</transmittable-thread-local.version>
<log4j.version>2.17.1</log4j.version>
</properties>
@ -55,11 +53,6 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>${security.oauth.auto.version}</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
@ -138,9 +131,9 @@
</dependency>
<!-- 用于序列化和反序列化-->
<dependency>
<groupId>de.ruedigermoeller</groupId>
<artifactId>fst</artifactId>
<version>${fst.version}</version>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>${kryo.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
@ -157,6 +150,11 @@
<artifactId>log4j-api</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>${transmittable-thread-local.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

@ -7,7 +7,6 @@
<groupId>com.yami.shop</groupId>
<artifactId>yami-shop</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -29,7 +28,7 @@
</dependency>
<dependency>
<groupId>com.yami.shop</groupId>
<artifactId>yami-shop-security</artifactId>
<artifactId>yami-shop-security-admin</artifactId>
<version>${yami.shop.version}</version>
</dependency>
<dependency>
@ -37,11 +36,6 @@
<artifactId>yami-shop-quartz</artifactId>
<version>${yami.shop.version}</version>
</dependency>
<dependency>
<groupId>com.yami.shop</groupId>
<artifactId>yami-shop-mp</artifactId>
<version>${yami.shop.version}</version>
</dependency>
</dependencies>

@ -0,0 +1,129 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.admin.controller;
import cn.hutool.core.util.StrUtil;
import com.anji.captcha.model.common.ResponseModel;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.security.admin.dto.CaptchaAuthenticationDTO;
import com.yami.shop.security.common.bo.UserInfoInTokenBO;
import com.yami.shop.security.common.enums.SysTypeEnum;
import com.yami.shop.security.common.manager.PasswordCheckManager;
import com.yami.shop.security.common.manager.PasswordManager;
import com.yami.shop.security.common.manager.TokenStore;
import com.yami.shop.security.common.vo.TokenInfoVO;
import com.yami.shop.sys.constant.Constant;
import com.yami.shop.sys.model.SysMenu;
import com.yami.shop.sys.model.SysUser;
import com.yami.shop.sys.service.SysMenuService;
import com.yami.shop.sys.service.SysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author FrozenWatermelon
* @date 2020/6/30
*/
@RestController
@Api(tags = "登录")
public class AdminLoginController {
@Autowired
private TokenStore tokenStore;
@Autowired
private SysUserService sysUserService;
@Autowired
private SysMenuService sysMenuService;
@Autowired
private PasswordCheckManager passwordCheckManager;
@Autowired
private CaptchaService captchaService;
@Autowired
private PasswordManager passwordManager;
@PostMapping("/adminLogin")
@ApiOperation(value = "账号密码 + 验证码登录(用于后台登录)", notes = "通过账号/手机号/用户名密码登录")
public ResponseEntity<?> login(
@Valid @RequestBody CaptchaAuthenticationDTO captchaAuthenticationDTO) {
// 登陆后台登录需要再校验一遍验证码
CaptchaVO captchaVO = new CaptchaVO();
captchaVO.setCaptchaVerification(captchaAuthenticationDTO.getCaptchaVerification());
ResponseModel response = captchaService.verification(captchaVO);
if (!response.isSuccess()) {
return ResponseEntity.badRequest().body("验证码有误或已过期");
}
SysUser sysUser = sysUserService.getByUserName(captchaAuthenticationDTO.getUserName());
if (sysUser == null) {
throw new YamiShopBindException("账号或密码不正确");
}
// 半小时内密码输入错误十次已限制登录30分钟
String decryptPassword = passwordManager.decryptPassword(captchaAuthenticationDTO.getPassWord());
passwordCheckManager.checkPassword(SysTypeEnum.ADMIN,captchaAuthenticationDTO.getUserName(), decryptPassword, sysUser.getPassword());
// 不是店铺超级管理员,并且是禁用状态,无法登录
if (Objects.equals(sysUser.getStatus(),0)) {
// 未找到此用户信息
throw new YamiShopBindException("未找到此用户信息");
}
UserInfoInTokenBO userInfoInToken = new UserInfoInTokenBO();
userInfoInToken.setUserId(String.valueOf(sysUser.getUserId()));
userInfoInToken.setSysType(SysTypeEnum.ADMIN.value());
userInfoInToken.setEnabled(sysUser.getStatus() == 1);
userInfoInToken.setPerms(getUserPermissions(sysUser.getUserId()));
userInfoInToken.setNickName(sysUser.getUsername());
userInfoInToken.setShopId(sysUser.getShopId());
// 存储token返回vo
TokenInfoVO tokenInfoVO = tokenStore.storeAndGetVo(userInfoInToken);
return ResponseEntity.ok(tokenInfoVO);
}
private Set<String> getUserPermissions(Long userId) {
List<String> permsList;
//系统管理员,拥有最高权限
if(userId == Constant.SUPER_ADMIN_ID){
List<SysMenu> menuList = sysMenuService.list(Wrappers.emptyWrapper());
permsList = menuList.stream().map(SysMenu::getPerms).collect(Collectors.toList());
}else{
permsList = sysUserService.queryAllPerms(userId);
}
return permsList.stream().flatMap((perms)->{
if (StrUtil.isBlank(perms)) {
return null;
}
return Arrays.stream(perms.trim().split(StrUtil.COMMA));
}
).collect(Collectors.toSet());
}
}

@ -10,31 +10,20 @@
package com.yami.shop.admin.controller;
import java.util.Objects;
import javax.validation.Valid;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.enums.ProdPropRule;
import com.yami.shop.bean.model.ProdProp;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.common.enums.YamiHttpStatus;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.security.admin.util.SecurityUtils;
import com.yami.shop.service.ProdPropService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import com.yami.shop.bean.enums.ProdPropRule;
import com.yami.shop.bean.model.ProdProp;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.service.ProdPropService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import javax.validation.Valid;
import java.util.Objects;
/**
*

@ -10,34 +10,20 @@
package com.yami.shop.admin.controller;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.bean.model.Category;
import com.yami.shop.common.annotation.SysLog;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.security.admin.util.SecurityUtils;
import com.yami.shop.service.CategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import com.yami.shop.bean.model.Category;
import com.yami.shop.common.annotation.SysLog;
import com.yami.shop.service.BrandService;
import com.yami.shop.service.CategoryService;
import com.yami.shop.service.ProdPropService;
import cn.hutool.core.collection.CollectionUtil;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@ -10,34 +10,21 @@
package com.yami.shop.admin.controller;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.security.util.SecurityUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.model.HotSearch;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.admin.util.SecurityUtils;
import com.yami.shop.service.HotSearchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.common.util.PageParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.web.bind.annotation.*;
import com.yami.shop.service.HotSearchService;
import com.yami.shop.bean.model.HotSearch;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;
/**
*

@ -15,7 +15,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.model.IndexImg;
import com.yami.shop.bean.model.Product;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.security.admin.util.SecurityUtils;
import com.yami.shop.service.IndexImgService;
import com.yami.shop.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;

@ -12,10 +12,10 @@ package com.yami.shop.admin.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.bean.model.Notice;
import com.yami.shop.common.annotation.SysLog;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.admin.util.SecurityUtils;
import com.yami.shop.service.NoticeService;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;

@ -10,49 +10,42 @@
package com.yami.shop.admin.controller;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.base.Objects;
import com.yami.shop.bean.enums.OrderStatus;
import com.yami.shop.bean.model.Order;
import com.yami.shop.bean.model.OrderItem;
import com.yami.shop.bean.model.UserAddrOrder;
import com.yami.shop.bean.param.DeliveryOrderParam;
import com.yami.shop.bean.param.OrderParam;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.admin.util.SecurityUtils;
import com.yami.shop.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Sheet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.*;
import com.yami.shop.common.util.PageParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.base.Objects;
import com.yami.shop.bean.enums.OrderStatus;
import com.yami.shop.bean.model.Order;
import com.yami.shop.bean.model.OrderItem;
import com.yami.shop.bean.model.UserAddrOrder;
import com.yami.shop.bean.param.DeliveryOrderParam;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
* @author lgh on 2018/09/15.
*/
@Slf4j
@Controller
@RequestMapping("/order/order")
public class OrderController {
@ -282,16 +275,9 @@ public class OrderController {
writer.flush(servletOutputStream);
servletOutputStream.flush();
} catch (IORuntimeException | IOException e) {
e.printStackTrace();
log.error("写出Excel错误", e);
} finally {
writer.close();
try {
if (servletOutputStream != null) {
servletOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
IoUtil.close(writer);
}
}
}

@ -10,36 +10,23 @@
package com.yami.shop.admin.controller;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import javax.validation.Valid;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.model.PickAddr;
import com.yami.shop.common.enums.YamiHttpStatus;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.admin.util.SecurityUtils;
import com.yami.shop.service.PickAddrService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import com.yami.shop.common.util.PageParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.model.PickAddr;
import com.yami.shop.service.PickAddrService;
import cn.hutool.core.util.StrUtil;
import javax.validation.Valid;
import java.util.Arrays;
import java.util.Objects;

@ -14,11 +14,11 @@ package com.yami.shop.admin.controller;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.bean.model.ProdTag;
import com.yami.shop.common.annotation.SysLog;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.admin.util.SecurityUtils;
import com.yami.shop.service.ProdTagService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;

@ -14,14 +14,13 @@ import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.bean.model.Product;
import com.yami.shop.bean.model.Sku;
import com.yami.shop.bean.param.ProductParam;
import com.yami.shop.common.enums.YamiHttpStatus;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.Json;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.admin.util.SecurityUtils;
import com.yami.shop.service.BasketService;
import com.yami.shop.service.ProdTagReferenceService;
import com.yami.shop.service.ProductService;

@ -10,31 +10,25 @@
package com.yami.shop.admin.controller;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import javax.validation.Valid;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.security.util.SecurityUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.model.ShopDetail;
import com.yami.shop.bean.param.ShopDetailParam;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.admin.util.SecurityUtils;
import com.yami.shop.service.ShopDetailService;
import ma.glasnost.orika.MapperFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import com.yami.shop.common.util.PageParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.model.ShopDetail;
import com.yami.shop.bean.param.ShopDetailParam;
import com.yami.shop.service.ShopDetailService;
import cn.hutool.core.util.StrUtil;
import ma.glasnost.orika.MapperFacade;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@ -10,36 +10,24 @@
package com.yami.shop.admin.controller;
import java.util.List;
import java.util.Objects;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.common.enums.YamiHttpStatus;
import com.yami.shop.security.util.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.common.util.PageParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.enums.ProdPropRule;
import com.yami.shop.bean.model.ProdProp;
import com.yami.shop.bean.model.ProdPropValue;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.admin.util.SecurityUtils;
import com.yami.shop.service.ProdPropService;
import com.yami.shop.service.ProdPropValueService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
import java.util.Objects;
/**
*

@ -10,31 +10,20 @@
package com.yami.shop.admin.controller;
import java.util.Date;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.security.util.SecurityUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.model.Transport;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.admin.util.SecurityUtils;
import com.yami.shop.service.TransportService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import com.yami.shop.common.util.PageParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.model.Transport;
import com.yami.shop.service.TransportService;
import java.util.Date;
import java.util.List;
/**
* @author lgh on 2018/11/16.

@ -1,36 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.admin.security;
import com.yami.shop.security.token.MyAuthenticationToken;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.security.core.userdetails.UserDetails;
/**
*
*/
@Getter
@Setter
@NoArgsConstructor
public class AdminAuthenticationToken extends MyAuthenticationToken {
private String sessionUUID;
private String imageCode;
public AdminAuthenticationToken(UserDetails principal, Object credentials) {
super(principal, credentials, principal.getAuthorities());
}
}

@ -1,31 +0,0 @@
package com.yami.shop.admin.security;
import com.yami.shop.security.service.YamiSysUser;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* token
* @author LGH
*/
@Component
public class AdminTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
final Map<String, Object> additionalInfo = new HashMap<>(8);
YamiSysUser yamiSysUser = (YamiSysUser) authentication.getUserAuthentication().getPrincipal();
additionalInfo.put("shopId", yamiSysUser.getShopId());
additionalInfo.put("userId", yamiSysUser.getUserId());
additionalInfo.put("authorities", yamiSysUser.getAuthorities());
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
}
}

@ -1,154 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.admin.security;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.yami.shop.common.util.Json;
import com.yami.shop.common.util.RedisUtil;
import com.yami.shop.security.constants.SecurityConstants;
import com.yami.shop.security.exception.BadCredentialsExceptionBase;
import com.yami.shop.security.exception.ImageCodeNotMatchExceptionBase;
import com.yami.shop.security.exception.UsernameNotFoundExceptionBase;
import com.yami.shop.security.provider.AuthenticationTokenParser;
import com.yami.shop.security.service.YamiUserDetailsService;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
*
* post: http://127.0.0.1:8085/login
* {principal:username,credentials:password}
*/
@Component
public class LoginAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
private YamiUserDetailsService yamiUserDetailsService;
private PasswordEncoder passwordEncoder;
@Autowired
public LoginAuthenticationFilter(YamiUserDetailsService yamiUserDetailsService, PasswordEncoder passwordEncoder) {
super("/login");
this.yamiUserDetailsService = yamiUserDetailsService;
this.passwordEncoder = passwordEncoder;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (!ServletUtil.METHOD_POST.equals(request.getMethod())) {
throw new AuthenticationServiceException(
"Authentication method not supported: " + request.getMethod());
}
String requestBody = getStringFromStream(request);
if (StrUtil.isBlank(requestBody)) {
throw new AuthenticationServiceException("无法获取输入信息");
}
AdminAuthenticationToken adminAuthenticationToken = Json.parseObject(requestBody, AdminAuthenticationToken.class);
String username = adminAuthenticationToken.getPrincipal() == null?"NONE_PROVIDED":adminAuthenticationToken.getName();
String kaptchaKey = SecurityConstants.SPRING_SECURITY_RESTFUL_IMAGE_CODE + adminAuthenticationToken.getSessionUUID();
String kaptcha = RedisUtil.get(kaptchaKey);
RedisUtil.del(kaptchaKey);
if(StrUtil.isBlank(adminAuthenticationToken.getImageCode()) || !adminAuthenticationToken.getImageCode().equalsIgnoreCase(kaptcha)){
throw new ImageCodeNotMatchExceptionBase("验证码有误");
}
UserDetails user;
try {
user = yamiUserDetailsService.loadUserByUsername(username);
} catch (UsernameNotFoundExceptionBase var6) {
throw new UsernameNotFoundExceptionBase("账号或密码不正确");
}
String encodedPassword = user.getPassword();
String rawPassword = adminAuthenticationToken.getCredentials().toString();
// 密码不正确
if (!passwordEncoder.matches(rawPassword,encodedPassword)){
throw new BadCredentialsExceptionBase("账号或密码不正确");
}
if (!user.isEnabled()) {
throw new UsernameNotFoundExceptionBase("账号已被锁定,请联系管理员");
}
AdminAuthenticationToken result = new AdminAuthenticationToken(user, adminAuthenticationToken.getCredentials());
result.setDetails(adminAuthenticationToken.getDetails());
return result;
}
private String getStringFromStream(HttpServletRequest req) {
ServletInputStream is;
try {
is = req.getInputStream();
int nRead = 1;
int nTotalRead = 0;
byte[] bytes = new byte[10240];
while (nRead > 0) {
nRead = is.read(bytes, nTotalRead, bytes.length - nTotalRead);
if (nRead > 0) {
nTotalRead = nTotalRead + nRead;
}
}
return new String(bytes, 0, nTotalRead, StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
@Override
@Autowired
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
super.setAuthenticationManager(authenticationManager);
}
@Override
@Autowired
public void setAuthenticationSuccessHandler(AuthenticationSuccessHandler successHandler) {
super.setAuthenticationSuccessHandler(successHandler);
}
@Override
@Autowired
public void setAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) {
super.setAuthenticationFailureHandler(failureHandler);
}
}

@ -1,57 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.admin.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsUtils;
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Autowired
private LoginAuthenticationFilter loginAuthenticationFilter;
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.addFilterBefore(loginAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.csrf().disable().cors()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and().authorizeRequests().requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.and().requestMatchers().anyRequest()
.and().anonymous()
.and().authorizeRequests()
.antMatchers(
"/webjars/**",
"/swagger/**",
"/v2/api-docs",
"/doc.html",
"/swagger-ui.html",
"/swagger-resources/**",
"/captcha.jpg").permitAll()
.and()
.authorizeRequests()
.antMatchers("/**").authenticated();//配置所有访问控制,必须认证过后才可以访问
// @formatter:on
}
}

@ -1,136 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.admin.security;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yami.shop.bean.model.User;
import com.yami.shop.common.util.CacheManagerUtil;
import com.yami.shop.sys.constant.Constant;
import com.yami.shop.security.enums.App;
import com.yami.shop.security.exception.UsernameNotFoundExceptionBase;
import com.yami.shop.security.model.AppConnect;
import com.yami.shop.security.service.YamiSysUser;
import com.yami.shop.security.service.YamiUser;
import com.yami.shop.security.service.YamiUserDetailsService;
import com.yami.shop.sys.dao.SysMenuMapper;
import com.yami.shop.sys.dao.SysUserMapper;
import com.yami.shop.sys.model.SysMenu;
import com.yami.shop.sys.model.SysUser;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
*
*
* @author
*/
@Slf4j
@Service
@AllArgsConstructor
public class YamiSysUserDetailsServiceImpl implements YamiUserDetailsService {
private final SysMenuMapper sysMenuMapper;
private final SysUserMapper sysUserMapper;
private final CacheManagerUtil cacheManagerUtil;
/**
*
*
* @param username
* @return
* @throws UsernameNotFoundExceptionBase
*/
@Override
@SneakyThrows
public YamiSysUser loadUserByUsername(String username) {
return getUserDetails(username);
}
/**
* userdetails
*
* @param username
* @return
*/
private YamiSysUser getUserDetails(String username) {
SysUser sysUser = sysUserMapper.selectByUsername(username);
if (sysUser == null) {
throw new UsernameNotFoundExceptionBase("用户不存在");
}
Collection<? extends GrantedAuthority> authorities
= AuthorityUtils.createAuthorityList(getUserPermissions(sysUser.getUserId()).toArray(new String[0]));
// 构造security用户
return new YamiSysUser(sysUser.getUserId(), sysUser.getShopId(), sysUser.getUsername(), sysUser.getPassword(), sysUser.getStatus() == 1,
true, true, true , authorities);
}
private Set<String> getUserPermissions(Long userId) {
List<String> permsList;
//系统管理员,拥有最高权限
if(userId == Constant.SUPER_ADMIN_ID){
List<SysMenu> menuList = sysMenuMapper.selectList(Wrappers.emptyWrapper());
permsList = menuList.stream().map(SysMenu::getPerms).collect(Collectors.toList());
}else{
permsList = sysUserMapper.queryAllPerms(userId);
}
Set<String> permsSet = permsList.stream().flatMap((perms)->{
if (StrUtil.isBlank(perms)) {
return null;
}
return Arrays.stream(perms.trim().split(","));
}
).collect(Collectors.toSet());
return permsSet;
}
@Override
public YamiUser loadUserByAppIdAndBizUserId(App app, String bizUserId) {
return null;
}
@Override
public void insertUserIfNecessary(AppConnect appConnect) {
}
@Override
public YamiUser loadUserByUserMail(String userMail, String loginPassword) {
return null;
}
@Override
public User loadUserByMobileOrUserName(String mobileOrUserName, Integer loginType) {
return null;
}
@Override
public YamiUser getYamiUser(Integer appId, User user, String bizUserId) {
return null;
}
}

@ -19,6 +19,6 @@ spring:
cache-null-values: true
redis:
redisson:
config: classpath:redisson.yml
config: classpath:redisson/redisson.yml
logging:
config: classpath:logback-dev.xml
config: classpath:logback/logback-dev.xml

@ -15,6 +15,6 @@ spring:
connection-test-query: SELECT 1
redis:
redisson:
config: classpath:redisson-docker.yml
config: classpath:redisson/redisson-docker.yml
logging:
config: classpath:logback-prod.xml
config: classpath:logback/logback-prod.xml

@ -15,6 +15,6 @@ spring:
connection-test-query: SELECT 1
redis:
redisson:
config: classpath:redisson.yml
config: classpath:redisson/redisson.yml
logging:
config: classpath:logback-prod.xml
config: classpath:logback/logback-prod.xml

@ -4,28 +4,25 @@ singleServerConfig:
database: ${REDIS_DATABASE}
password: ${REDIS_PASSWORD}
idleConnectionTimeout: 10000
pingTimeout: 1000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
reconnectionTimeout: 3000
failedAttempts: 3
clientName: null
# 发布和订阅连接的最小空闲连接数 默认1
subscriptionConnectionMinimumIdleSize: 1
# 发布和订阅连接池大小 默认50
subscriptionConnectionPoolSize: 10
subscriptionConnectionPoolSize: 1
# 单个连接最大订阅数量 默认5
subscriptionsPerConnection: 5
subscriptionsPerConnection: 1
# 最小空闲连接数 默认32现在暂时不需要那么多的线程
connectionMinimumIdleSize: 4
connectionMinimumIdleSize: 2
# connectionPoolSize 默认64现在暂时不需要那么多的线程
connectionPoolSize: 20
connectionPoolSize: 4
# 这个线程池数量被所有RTopic对象监听器RRemoteService调用者和RExecutorService任务共同共享。
threads: 0
# 这个线程池数量是在一个Redisson实例内被其创建的所有分布式数据类型和服务以及底层客户端所一同共享的线程池里保存的线程数量。
nettyThreads: 0
codec:
class: com.yami.shop.common.serializer.redisson.FstCodec
transportMode: NIO
class: org.redisson.codec.KryoCodec
transportMode: NIO

@ -4,28 +4,25 @@ singleServerConfig:
database: 0
password: null
idleConnectionTimeout: 10000
pingTimeout: 1000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
reconnectionTimeout: 3000
failedAttempts: 3
clientName: null
# 发布和订阅连接的最小空闲连接数 默认1
subscriptionConnectionMinimumIdleSize: 1
# 发布和订阅连接池大小 默认50
subscriptionConnectionPoolSize: 10
subscriptionConnectionPoolSize: 1
# 单个连接最大订阅数量 默认5
subscriptionsPerConnection: 5
subscriptionsPerConnection: 1
# 最小空闲连接数 默认32现在暂时不需要那么多的线程
connectionMinimumIdleSize: 4
connectionMinimumIdleSize: 2
# connectionPoolSize 默认64现在暂时不需要那么多的线程
connectionPoolSize: 20
connectionPoolSize: 4
# 这个线程池数量被所有RTopic对象监听器RRemoteService调用者和RExecutorService任务共同共享。
threads: 0
# 这个线程池数量是在一个Redisson实例内被其创建的所有分布式数据类型和服务以及底层客户端所一同共享的线程池里保存的线程数量。
nettyThreads: 0
codec:
class: com.yami.shop.common.serializer.redisson.FstCodec
transportMode: NIO
class: org.redisson.codec.KryoCodec
transportMode: NIO

@ -20,12 +20,7 @@
</dependency>
<dependency>
<groupId>com.yami.shop</groupId>
<artifactId>yami-shop-security</artifactId>
<version>${yami.shop.version}</version>
</dependency>
<dependency>
<groupId>com.yami.shop</groupId>
<artifactId>yami-shop-mp</artifactId>
<artifactId>yami-shop-security-api</artifactId>
<version>${yami.shop.version}</version>
</dependency>
</dependencies>

@ -10,36 +10,25 @@
package com.yami.shop.api.controller;
import java.util.Date;
import java.util.List;
import javax.validation.Valid;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.security.util.SecurityUtils;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.bean.app.dto.UserAddrDto;
import com.yami.shop.bean.app.param.AddrParam;
import com.yami.shop.bean.model.UserAddr;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.UserAddrService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import ma.glasnost.orika.MapperFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;
@RestController

@ -10,37 +10,30 @@
package com.yami.shop.api.controller;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.enums.OrderStatus;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.bean.app.dto.*;
import com.yami.shop.dao.OrderMapper;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.service.*;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import com.yami.shop.bean.enums.OrderStatus;
import com.yami.shop.bean.model.Order;
import com.yami.shop.bean.model.OrderItem;
import com.yami.shop.bean.model.ShopDetail;
import com.yami.shop.bean.model.UserAddrOrder;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.Arith;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import ma.glasnost.orika.MapperFacade;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@RestController
@RequestMapping("/p/myOrder")

@ -10,15 +10,21 @@
package com.yami.shop.api.controller;
import java.util.*;
import javax.validation.Valid;
import cn.hutool.core.collection.CollectionUtil;
import com.yami.shop.bean.app.dto.*;
import com.yami.shop.bean.app.param.OrderParam;
import com.yami.shop.bean.app.param.OrderShopParam;
import com.yami.shop.bean.app.param.SubmitOrderParam;
import com.yami.shop.bean.event.ConfirmOrderEvent;
import com.yami.shop.bean.model.Order;
import com.yami.shop.bean.model.UserAddr;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.common.util.Arith;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import ma.glasnost.orika.MapperFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.http.ResponseEntity;
@ -27,17 +33,10 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yami.shop.bean.app.param.OrderParam;
import com.yami.shop.bean.app.param.OrderShopParam;
import com.yami.shop.bean.app.param.SubmitOrderParam;
import com.yami.shop.bean.model.Order;
import com.yami.shop.bean.model.UserAddr;
import com.yami.shop.common.util.Arith;
import cn.hutool.core.collection.CollectionUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import ma.glasnost.orika.MapperFacade;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@RestController
@RequestMapping("/p/order")

@ -10,18 +10,11 @@
package com.yami.shop.api.controller;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.service.WxPayService;
import com.yami.shop.api.config.ApiConfig;
import com.yami.shop.bean.app.param.PayParam;
import com.yami.shop.bean.pay.PayInfoDto;
import com.yami.shop.common.util.Arith;
import com.yami.shop.common.util.IPHelper;
import com.yami.shop.security.service.YamiUser;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.security.api.model.YamiUser;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.PayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@ -33,8 +26,6 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/p/order")
@Api(tags = "订单接口")
@ -43,10 +34,6 @@ public class PayController {
private final PayService payService;
private final ApiConfig apiConfig;
private final WxPayService wxMiniPayService;
/**
*
*/
@ -56,21 +43,11 @@ public class PayController {
public ResponseEntity<WxPayMpOrderResult> pay(@RequestBody PayParam payParam) {
YamiUser user = SecurityUtils.getUser();
String userId = user.getUserId();
String openId = user.getBizUserId();
PayInfoDto payInfo = payService.pay(userId, payParam);
WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
orderRequest.setBody(payInfo.getBody());
orderRequest.setOutTradeNo(payInfo.getPayNo());
orderRequest.setTotalFee((int) Arith.mul(payInfo.getPayAmount(), 100));
orderRequest.setSpbillCreateIp(IPHelper.getIpAddr());
orderRequest.setNotifyUrl(apiConfig.getDomainName() + "/notice/pay/order");
orderRequest.setTradeType(WxPayConstants.TradeType.JSAPI);
orderRequest.setOpenid(openId);
return ResponseEntity.ok(wxMiniPayService.createOrder(orderRequest));
payService.paySuccess(payInfo.getPayNo(), "");
return ResponseEntity.ok().build();
}
/**

@ -10,13 +10,7 @@
package com.yami.shop.api.controller;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.yami.shop.service.PayService;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;
@ -26,26 +20,26 @@ import springfox.documentation.annotations.ApiIgnore;
@RequestMapping("/notice/pay")
@AllArgsConstructor
public class PayNoticeController {
/**
*
*/
private final WxPayService wxMiniPayService;
private final PayService payService;
@RequestMapping("/order")
public ResponseEntity<Void> submit(@RequestBody String xmlData) throws WxPayException {
WxPayOrderNotifyResult parseOrderNotifyResult = wxMiniPayService.parseOrderNotifyResult(xmlData);
String payNo = parseOrderNotifyResult.getOutTradeNo();
String bizPayNo = parseOrderNotifyResult.getTransactionId();
// 根据内部订单号更新order settlement
payService.paySuccess(payNo, bizPayNo);
return ResponseEntity.ok().build();
}
//模拟支付不需要回调
// /**
// * 小程序支付
// */
// private final WxPayService wxMiniPayService;
//
// private final PayService payService;
//
//
// @RequestMapping("/order")
// public ResponseEntity<Void> submit(@RequestBody String xmlData) throws WxPayException {
// WxPayOrderNotifyResult parseOrderNotifyResult = wxMiniPayService.parseOrderNotifyResult(xmlData);
//
// String payNo = parseOrderNotifyResult.getOutTradeNo();
// String bizPayNo = parseOrderNotifyResult.getTransactionId();
//
// // 根据内部订单号更新order settlement
// payService.paySuccess(payNo, bizPayNo);
//
//
// return ResponseEntity.ok().build();
// }
}

@ -12,14 +12,12 @@ package com.yami.shop.api.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.bean.app.dto.ProdCommDataDto;
import com.yami.shop.bean.app.dto.ProdCommDto;
import com.yami.shop.bean.app.param.ProdCommParam;
import com.yami.shop.bean.model.ProdComm;
import com.yami.shop.common.util.Json;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.ProdCommService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;

@ -12,24 +12,31 @@ package com.yami.shop.api.controller;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import com.google.common.collect.Lists;
import com.yami.shop.bean.app.dto.*;
import com.yami.shop.bean.app.param.ChangeShopCartParam;
import com.yami.shop.bean.app.param.ShopCartParam;
import com.yami.shop.bean.event.ShopCartEvent;
import com.yami.shop.bean.model.*;
import com.yami.shop.bean.model.Basket;
import com.yami.shop.bean.model.Product;
import com.yami.shop.bean.model.Sku;
import com.yami.shop.common.util.Arith;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.service.*;
import io.swagger.annotations.*;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.BasketService;
import com.yami.shop.service.ProductService;
import com.yami.shop.service.SkuService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
@RestController

@ -10,21 +10,19 @@
package com.yami.shop.api.controller;
import com.yami.shop.security.util.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.google.common.collect.Maps;
import com.yami.shop.bean.app.param.SendSmsParam;
import com.yami.shop.bean.enums.SmsType;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.SmsLogService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/p/sms")

@ -19,7 +19,7 @@ import com.yami.shop.bean.model.Product;
import com.yami.shop.bean.model.UserCollection;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.ProductService;
import com.yami.shop.service.UserCollectionService;
import io.swagger.annotations.Api;

@ -10,32 +10,18 @@
package com.yami.shop.api.controller;
import cn.hutool.core.util.StrUtil;
import com.yami.shop.common.util.CacheManagerUtil;
import com.yami.shop.security.enums.App;
import com.yami.shop.security.service.YamiUser;
import com.yami.shop.security.util.SecurityUtils;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.provider.token.ConsumerTokenServices;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import cn.hutool.extra.emoji.EmojiUtil;
import com.yami.shop.bean.app.dto.UserDto;
import com.yami.shop.bean.app.param.UserInfoParam;
import com.yami.shop.bean.model.User;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.UserService;
import cn.hutool.extra.emoji.EmojiUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import ma.glasnost.orika.MapperFacade;
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/p/user")
@ -46,10 +32,6 @@ public class UserController {
private final UserService userService;
private final MapperFacade mapperFacade;
private final CacheManagerUtil cacheManagerUtil;
private final ConsumerTokenServices consumerTokenServices;
/**
*
*/
@ -71,18 +53,6 @@ public class UserController {
user.setPic(userInfoParam.getAvatarUrl());
user.setNickName(EmojiUtil.toAlias(userInfoParam.getNickName()));
userService.updateById(user);
String cacheKey = App.MINI.value() + StrUtil.COLON + SecurityUtils.getUser().getBizUserId();
cacheManagerUtil.evictCache("yami_user", cacheKey);
return ResponseEntity.ok(null);
}
/**
* 退,redistoken
**/
@GetMapping("/logout")
public Boolean removeToken(HttpServletRequest httpRequest){
String authorization = httpRequest.getHeader("authorization");
String token = authorization.replace("bearer", "");
return consumerTokenServices.revokeToken(token);
return ResponseEntity.ok().build();
}
}

@ -1,40 +1,27 @@
package com.yami.shop.api.controller;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.api.security.AuthenticationToken;
import com.yami.shop.bean.enums.SmsType;
import com.yami.shop.bean.model.User;
import com.yami.shop.bean.param.UserRegisterParam;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.IPHelper;
import com.yami.shop.common.util.PrincipalUtil;
import com.yami.shop.mp.config.WxMaConfiguration;
import com.yami.shop.security.enums.App;
import com.yami.shop.security.handler.LoginAuthSuccessHandler;
import com.yami.shop.security.model.AppConnect;
import com.yami.shop.security.service.AppConnectService;
import com.yami.shop.security.service.YamiUser;
import com.yami.shop.security.service.YamiUserDetailsService;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.service.SmsLogService;
import com.yami.shop.security.common.bo.UserInfoInTokenBO;
import com.yami.shop.security.common.enums.SysTypeEnum;
import com.yami.shop.security.common.manager.PasswordManager;
import com.yami.shop.security.common.manager.TokenStore;
import com.yami.shop.security.common.vo.TokenInfoVO;
import com.yami.shop.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.token.ConsumerTokenServices;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.Date;
import java.util.Objects;
/**
*
@ -49,182 +36,66 @@ public class UserRegisterController {
private final UserService userService;
private final SmsLogService smsLogService;
private final AppConnectService appConnectService;
private final LoginAuthSuccessHandler loginAuthSuccessHandler;
private final WxMaConfiguration wxConfig;
private final YamiUserDetailsService yamiUserDetailsService;
private final PasswordEncoder passwordEncoder;
public static final String CHECK_REGISTER_SMS_FLAG = "checkRegisterSmsFlag";
private final TokenStore tokenStore;
public static final String CHECK_UPDATE_PWD_SMS_FLAG = "updatePwdSmsFlag";
private final PasswordManager passwordManager;
@PostMapping("/register")
@ApiOperation(value = "注册", notes = "用户注册或绑定手机号接口")
public ResponseEntity<Boolean> register(@Valid @RequestBody UserRegisterParam userRegisterParam) {
userRegisterParam.setPassword(passwordEncoder.encode(userRegisterParam.getPassword()));
return ResponseEntity.ok(userService.insertUser(userRegisterParam));
public ResponseEntity<TokenInfoVO> register(@Valid @RequestBody UserRegisterParam userRegisterParam) {
if (StrUtil.isBlank(userRegisterParam.getNickName())) {
userRegisterParam.setNickName(userRegisterParam.getUserName());
}
// 正在进行申请注册
if (userService.count(new LambdaQueryWrapper<User>().eq(User::getNickName, userRegisterParam.getNickName())) > 0) {
// 该用户名已注册,无法重新注册
throw new YamiShopBindException("该用户名已注册,无法重新注册");
}
Date now = new Date();
User user = new User();
user.setModifyTime(now);
user.setUserRegtime(now);
user.setStatus(1);
user.setNickName(userRegisterParam.getNickName());
user.setUserMail(userRegisterParam.getUserMail());
String decryptPassword = passwordManager.decryptPassword(userRegisterParam.getPassWord());
user.setLoginPassword(passwordEncoder.encode(decryptPassword));
String userId = IdUtil.simpleUUID();
user.setUserId(userId);
userService.save(user);
// 2. 登录
UserInfoInTokenBO userInfoInTokenBO = new UserInfoInTokenBO();
userInfoInTokenBO.setUserId(user.getUserId());
userInfoInTokenBO.setSysType(SysTypeEnum.ORDINARY.value());
userInfoInTokenBO.setIsAdmin(0);
userInfoInTokenBO.setEnabled(true);
return ResponseEntity.ok(tokenStore.storeAndGetVo(userInfoInTokenBO));
}
@PutMapping("/updatePwd")
@ApiOperation(value = "修改密码", notes = "修改密码")
public ResponseEntity<Void> updatePwd(@Valid @RequestBody UserRegisterParam userRegisterParam) {
User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getUserMobile, userRegisterParam.getUserMail()));
public ResponseEntity<Void> updatePwd(@Valid @RequestBody UserRegisterParam userPwdUpdateParam) {
User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getNickName, userPwdUpdateParam.getNickName()));
if (user == null) {
// 无法获取用户信息
throw new YamiShopBindException("无法获取用户信息");
}
if (StrUtil.isBlank(userRegisterParam.getPassword())) {
String decryptPassword = passwordManager.decryptPassword(userPwdUpdateParam.getPassWord());
if (StrUtil.isBlank(decryptPassword)) {
// 新密码不能为空
throw new YamiShopBindException("新密码不能为空");
}
if (StrUtil.equals(passwordEncoder.encode(userRegisterParam.getPassword()), user.getLoginPassword())) {
String password = passwordEncoder.encode(decryptPassword);
if (StrUtil.equals(password, user.getLoginPassword())) {
// 新密码不能与原密码相同
throw new YamiShopBindException("新密码不能与原密码相同");
}
user.setModifyTime(new Date());
user.setLoginPassword(passwordEncoder.encode(userRegisterParam.getPassword()));
user.setLoginPassword(password);
userService.updateById(user);
return ResponseEntity.ok().build();
}
@PutMapping("/registerOrBindUser")
@ApiOperation(value="注册或绑定手机号", notes="用户注册或绑定手机号接口")
public ResponseEntity<Void> register(HttpServletRequest request, HttpServletResponse response, @Valid @RequestBody UserRegisterParam userRegisterParam) {
String mobile = userRegisterParam.getMobile();
AppConnect appConnect = null;
User user = null;
String bizUserId = null;
boolean isWxAppId = Objects.equals(userRegisterParam.getAppType(), App.MINI.value()) || Objects.equals(userRegisterParam.getAppType(), App.MP.value());
if(isWxAppId) {
bizUserId = SecurityUtils.getUser().getBizUserId();
}
// 正在进行注册,通过验证码校验
if (Objects.equals(userRegisterParam.getRegisterOrBind(), 1)) {
// 看看有没有校验验证码成功的标识
userService.validate(userRegisterParam, CHECK_REGISTER_SMS_FLAG + userRegisterParam.getCheckRegisterSmsFlag());
// 正在进行申请注册
if (userService.count(new LambdaQueryWrapper<User>().eq(User::getUserMobile,userRegisterParam.getMobile())) > 0) {
// 手机号已存在,无法注册
throw new YamiShopBindException("yami.user.phone.exist");
}
}
// 小程序注册/绑定手机号
else {
YamiUser yamiUser = SecurityUtils.getUser();
appConnect = appConnectService.getByBizUserId(yamiUser.getBizUserId(), App.instance(yamiUser.getAppType()));
// 通过微信手机号校验
if (Objects.equals(2, userRegisterParam.getValidateType())) {
try {
WxMaPhoneNumberInfo wxMaPhoneNumberInfo = wxConfig.wxMaService().getUserService().getPhoneNoInfo(yamiUser.getSessionKey(), userRegisterParam.getEncryptedData(), userRegisterParam.getIvStr());
mobile = wxMaPhoneNumberInfo.getPhoneNumber();
} catch (Exception e) {
// 授权失败,请重新授权
throw new YamiShopBindException(" 授权失败,请重新授权");
}
if (StrUtil.isBlank(mobile)) {
// 无法获取用户手机号信息
throw new YamiShopBindException("无法获取用户手机号信息");
}
user = yamiUserDetailsService.loadUserByMobileOrUserName(mobile, 0);
}
// 通过账号密码校验
else if (Objects.equals(3, userRegisterParam.getValidateType())) {
user = yamiUserDetailsService.loadUserByMobileOrUserName(mobile, 0);
if (user == null) {
// 账号或密码不正确
throw new YamiShopBindException("yami.user.account.error");
}
String encodedPassword = user.getLoginPassword();
String rawPassword = userRegisterParam.getPassword();
// 密码不正确
if (StrUtil.isBlank(encodedPassword) || !passwordEncoder.matches(rawPassword,encodedPassword)){
// 账号或密码不正确
throw new YamiShopBindException("yami.user.account.error");
}
}
// 通过验证码校验
else {
if (!smsLogService.checkValidCode(userRegisterParam.getMobile(), userRegisterParam.getValidCode(), SmsType.VALID)){
// 验证码有误或已过期
throw new YamiShopBindException("yami.user.code.error");
}
}
}
Date now = new Date();
// 尝试用手机号获取用户信息
if (user == null && StrUtil.isNotBlank(mobile)) {
user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getUserMobile,mobile));
}
// 新建用户
if (user == null) {
user = new User();
if (StrUtil.isBlank(userRegisterParam.getUserName())) {
userRegisterParam.setUserName(mobile);
}
// 如果有用户名,就判断用户名格式是否正确
if (!PrincipalUtil.isUserName(userRegisterParam.getUserName())) {
throw new YamiShopBindException("用户名应由4-16位数字字母下划线组成");
}
user.setModifyTime(now);
user.setUserRegtime(now);
user.setUserRegip(IPHelper.getIpAddr());
user.setStatus(1);
user.setPic(userRegisterParam.getImg());
user.setUserMobile(mobile);
if (StrUtil.isNotBlank(userRegisterParam.getPassword())) {
user.setLoginPassword(passwordEncoder.encode(userRegisterParam.getPassword()));
}
// 用户名就是默认的昵称
user.setNickName(StrUtil.isBlank(userRegisterParam.getNickName())? userRegisterParam.getUserName(): userRegisterParam.getNickName());
// } else {
// String userId = user.getUserId();
// // 绑定账号
// if (Objects.equals(userRegisterParam.getRegisterOrBind(),2)) {
// int count = appConnectService.count(new LambdaQueryWrapper<AppConnect>().eq(AppConnect::getUserId, userId).eq(AppConnect::getAppId, userRegisterParam.getAppType()));
// if (count > 0) {
// throw new YamiShopBindException("该账号已被绑定,请换个账号试试");
// }
// }
}
if(Objects.nonNull(bizUserId)){
appConnect = new AppConnect();
appConnect.setBizUserId(bizUserId);
}
appConnectService.registerOrBindUser(user, appConnect, userRegisterParam.getAppType());
//进行授权登录
UserDetails userDetails = yamiUserDetailsService.getYamiUser(userRegisterParam.getAppType(),user, bizUserId);
AuthenticationToken authenticationToken = new AuthenticationToken();
authenticationToken.setPrincipal(user.getUserMobile());
authenticationToken.setCredentials(user.getLoginPassword());
authenticationToken.setPrincipal(userDetails.getUsername());
authenticationToken.setDetails(userDetails);
authenticationToken.setAuthenticated(true);
loginAuthSuccessHandler.onAuthenticationSuccess(request,response,authenticationToken);
return ResponseEntity.ok().build();
}
}

@ -10,34 +10,26 @@
package com.yami.shop.api.listener;
import com.google.common.collect.Lists;
import com.yami.shop.bean.app.dto.*;
import com.yami.shop.bean.app.dto.ShopCartItemDto;
import com.yami.shop.bean.app.dto.ShopCartOrderDto;
import com.yami.shop.bean.app.param.OrderParam;
import com.yami.shop.bean.event.ConfirmOrderEvent;
import com.yami.shop.bean.event.ShopCartEvent;
import com.yami.shop.bean.model.Product;
import com.yami.shop.bean.model.Sku;
import com.yami.shop.bean.model.UserAddr;
import com.yami.shop.bean.order.ConfirmOrderOrder;
import com.yami.shop.bean.order.ShopCartEventOrder;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.Arith;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.ProductService;
import com.yami.shop.service.SkuService;
import com.yami.shop.service.TransportManagerService;
import com.yami.shop.service.UserAddrService;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import ma.glasnost.orika.MapperFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author LGH

@ -23,7 +23,7 @@ import com.yami.shop.bean.order.SubmitOrderOrder;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.Arith;
import com.yami.shop.dao.*;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.ProductService;
import com.yami.shop.service.SkuService;
import com.yami.shop.service.UserAddrOrderService;

@ -1,35 +0,0 @@
package com.yami.shop.api.security;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.emoji.EmojiUtil;
import com.yami.shop.security.service.YamiUser;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* token
* @author LGH
*/
@Component
public class ApiTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
Map<String, Object> additionalInfo = new HashMap<>(8);
YamiUser yamiUser = (YamiUser) authentication.getUserAuthentication().getPrincipal();
additionalInfo.put("userId", yamiUser.getUserId());
additionalInfo.put("nickName", EmojiUtil.toUnicode(StrUtil.isBlank(yamiUser.getName())? "" : yamiUser.getName()));
additionalInfo.put("pic",yamiUser.getPic());
additionalInfo.put("enabled",yamiUser.isEnabled());
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
}
}

@ -1,95 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.api.security;
import lombok.Getter;
import lombok.Setter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.CredentialsContainer;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
/**
* AbstractAuthenticationToken
* @author SJL
*/
@Getter
@Setter
public class AuthenticationToken implements Authentication,
CredentialsContainer {
private Collection<GrantedAuthority> authorities;
private UserDetails details;
/**
*
*/
protected String principal;
/**
*
*/
protected Object credentials;
/**
* uuid
*/
private String sessionUUID;
private boolean authenticated = false;
public void setDetails(UserDetails details) {
this.details = details;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return details.getAuthorities();
}
@Override
public Object getDetails() {
return details;
}
@Override
public boolean isAuthenticated() {
return authenticated;
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
this.authenticated = isAuthenticated;
}
@Override
public String getName() {
return details.getUsername();
}
@Override
public void eraseCredentials() {
eraseSecret(getCredentials());
eraseSecret(getPrincipal());
eraseSecret(details);
}
private void eraseSecret(Object secret) {
if (secret instanceof CredentialsContainer) {
((CredentialsContainer) secret).eraseCredentials();
}
}
}

@ -1,151 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.api.security;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.yami.shop.common.util.Json;
import com.yami.shop.common.util.RedisUtil;
import com.yami.shop.security.constants.SecurityConstants;
import com.yami.shop.security.enums.App;
import com.yami.shop.security.exception.BadCredentialsExceptionBase;
import com.yami.shop.security.exception.ImageCodeNotMatchExceptionBase;
import com.yami.shop.security.exception.UsernameNotFoundExceptionBase;
import com.yami.shop.security.exception.WxErrorExceptionBase;
import com.yami.shop.security.model.AppConnect;
import com.yami.shop.security.service.YamiUser;
import com.yami.shop.security.service.YamiUserDetailsService;
import com.yami.shop.security.token.MyAuthenticationToken;
import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* principalcode
* post:http://127.0.0.1:8086/login
* {principal:code}
*/
@Component
public class LoginAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
private final YamiUserDetailsService yamiUserDetailsService;
private final WxMaService wxMaService;
@Autowired
public LoginAuthenticationFilter(YamiUserDetailsService yamiUserDetailsService, WxMaService wxMaService) {
super("/login");
this.yamiUserDetailsService = yamiUserDetailsService;
this.wxMaService = wxMaService;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (!ServletUtil.METHOD_POST.equals(request.getMethod())) {
throw new AuthenticationServiceException(
"Authentication method not supported: " + request.getMethod());
}
String requestBody = getStringFromStream(request);
if (StrUtil.isBlank(requestBody)) {
throw new AuthenticationServiceException("无法获取输入信息");
}
MiniAppAuthenticationToken authentication = Json.parseObject(requestBody, MiniAppAuthenticationToken.class);
String code = String.valueOf(authentication.getPrincipal());
YamiUser loadedUser = null;
WxMaJscode2SessionResult session = null;
AppConnect appConnect = new AppConnect();
appConnect.setAppId(App.MINI.value());
try {
session = wxMaService.getUserService().getSessionInfo(code);
loadedUser = yamiUserDetailsService.loadUserByAppIdAndBizUserId(App.MINI,session.getOpenid());
} catch (WxErrorException e) {
throw new WxErrorExceptionBase(e.getMessage());
} catch (UsernameNotFoundExceptionBase var6) {
if (session == null) {
throw new WxErrorExceptionBase("无法获取用户登陆信息");
}
appConnect.setBizUserId(session.getOpenid());
appConnect.setBizUnionid(session.getUnionid());
yamiUserDetailsService.insertUserIfNecessary(appConnect);
}
if (loadedUser == null) {
loadedUser = yamiUserDetailsService.loadUserByAppIdAndBizUserId(App.MINI, appConnect.getBizUserId());
}
MiniAppAuthenticationToken result = new MiniAppAuthenticationToken(loadedUser, authentication.getCredentials());
result.setDetails(authentication.getDetails());
return result;
}
private String getStringFromStream(HttpServletRequest req) {
ServletInputStream is;
try {
is = req.getInputStream();
int nRead = 1;
int nTotalRead = 0;
byte[] bytes = new byte[10240];
while (nRead > 0) {
nRead = is.read(bytes, nTotalRead, bytes.length - nTotalRead);
if (nRead > 0) {
nTotalRead = nTotalRead + nRead;
}
}
return new String(bytes, 0, nTotalRead, StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
@Override
@Autowired
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
super.setAuthenticationManager(authenticationManager);
}
@Override
@Autowired
public void setAuthenticationSuccessHandler(AuthenticationSuccessHandler successHandler) {
super.setAuthenticationSuccessHandler(successHandler);
}
@Override
@Autowired
public void setAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) {
super.setAuthenticationFailureHandler(failureHandler);
}
}

@ -1,27 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.api.security;
import com.yami.shop.security.token.MyAuthenticationToken;
import lombok.NoArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
/**
* Token
*/
@NoArgsConstructor
public class MiniAppAuthenticationToken extends MyAuthenticationToken {
public MiniAppAuthenticationToken(UserDetails principal, Object credentials) {
super(principal, credentials, principal.getAuthorities());
}
}

@ -1,44 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.api.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsUtils;
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Autowired
private LoginAuthenticationFilter loginAuthenticationFilter;
@Override
public void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(loginAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.csrf().disable().cors()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().authorizeRequests().requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.and().requestMatchers().anyRequest()
.and().anonymous()
.and().authorizeRequests()
//配置/p访问控制必须认证过后才可以访问
.antMatchers("/p/**").authenticated();
}
}

@ -1,27 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.api.security;
import com.yami.shop.security.token.MyAuthenticationToken;
import lombok.NoArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
/**
* H5Token
*/
@NoArgsConstructor
public class WebAuthenticationToken extends MyAuthenticationToken {
public WebAuthenticationToken(UserDetails principal, Object credentials) {
super(principal, credentials, principal.getAuthorities());
}
}

@ -1,153 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.api.security;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.yami.shop.common.util.Json;
import com.yami.shop.common.util.RedisUtil;
import com.yami.shop.security.constants.SecurityConstants;
import com.yami.shop.security.enums.App;
import com.yami.shop.security.exception.BadCredentialsExceptionBase;
import com.yami.shop.security.exception.ImageCodeNotMatchExceptionBase;
import com.yami.shop.security.exception.UsernameNotFoundExceptionBase;
import com.yami.shop.security.exception.WxErrorExceptionBase;
import com.yami.shop.security.model.AppConnect;
import com.yami.shop.security.service.YamiUser;
import com.yami.shop.security.service.YamiUserDetailsService;
import com.yami.shop.security.token.MyAuthenticationToken;
import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
*
*/
@Component
public class WebLoginAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
private final YamiUserDetailsService yamiUserDetailsService;
private final WxMaService wxMaService;
@Autowired
public WebLoginAuthenticationFilter(YamiUserDetailsService yamiUserDetailsService, WxMaService wxMaService) {
super("/webLogin");
this.yamiUserDetailsService = yamiUserDetailsService;
this.wxMaService = wxMaService;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (!ServletUtil.METHOD_POST.equals(request.getMethod())) {
throw new AuthenticationServiceException(
"Authentication method not supported: " + request.getMethod());
}
String requestBody = getStringFromStream(request);
if (StrUtil.isBlank(requestBody)) {
throw new AuthenticationServiceException("无法获取输入信息");
}
WebAuthenticationToken authentication = Json.parseObject(requestBody, WebAuthenticationToken.class);
String userMail = String.valueOf(authentication.getPrincipal());
String loginPassword = String.valueOf(authentication.getCredentials());
YamiUser loadedUser = null;
// WxMaJscode2SessionResult session = null;
AppConnect appConnect = new AppConnect();
appConnect.setAppId(App.H5.value());
loadedUser = yamiUserDetailsService.loadUserByUserMail(userMail,loginPassword);
// try {
//
//// session = wxMaService.getUserService().getSessionInfo(code);
//
// loadedUser = yamiUserDetailsService.loadUserByAppIdAndBizUserId(App.MINI,session.getOpenid());
// } catch (WxErrorException e) {
// throw new WxErrorExceptionBase(e.getMessage());
// } catch (UsernameNotFoundExceptionBase var6) {
// if (session == null) {
// throw new WxErrorExceptionBase("无法获取用户登陆信息");
// }
// appConnect.setBizUserId(session.getOpenid());
// appConnect.setBizUnionid(session.getUnionid());
// yamiUserDetailsService.insertUserIfNecessary(appConnect);
// }
// if (loadedUser == null) {
// loadedUser = yamiUserDetailsService.loadUserByAppIdAndBizUserId(App.MINI, appConnect.getBizUserId());
// }
// MiniAppAuthenticationToken result = new MiniAppAuthenticationToken(loadedUser, authentication.getCredentials());
WebAuthenticationToken result = new WebAuthenticationToken(loadedUser, authentication.getCredentials());
result.setDetails(authentication.getDetails());
return result;
}
private String getStringFromStream(HttpServletRequest req) {
ServletInputStream is;
try {
is = req.getInputStream();
int nRead = 1;
int nTotalRead = 0;
byte[] bytes = new byte[10240];
while (nRead > 0) {
nRead = is.read(bytes, nTotalRead, bytes.length - nTotalRead);
if (nRead > 0) {
nTotalRead = nTotalRead + nRead;
}
}
return new String(bytes, 0, nTotalRead, StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
@Override
@Autowired
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
super.setAuthenticationManager(authenticationManager);
}
@Override
@Autowired
public void setAuthenticationSuccessHandler(AuthenticationSuccessHandler successHandler) {
super.setAuthenticationSuccessHandler(successHandler);
}
@Override
@Autowired
public void setAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) {
super.setAuthenticationFailureHandler(failureHandler);
}
}

@ -1,154 +0,0 @@
package com.yami.shop.api.security;
import cn.hutool.extra.servlet.ServletUtil;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.Json;
import com.yami.shop.common.xss.XssUtil;
import com.yami.shop.security.exception.BadCredentialsException;
import com.yami.shop.security.exception.UsernameNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
*
* @author SJL
*/
public class YamiAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {
private UserDetailsService userDetailsService;
private PasswordEncoder passwordEncoder;
/**
* 1m
*/
public static final int MAX_STRING_SIZE = 1024 * 1024;
protected YamiAuthenticationProcessingFilter(String defaultFilterProcessesUrl) {
super(defaultFilterProcessesUrl);
}
@Autowired
public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
@Autowired
public void setUserDetailsService(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
@Override
@Autowired
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
super.setAuthenticationManager(authenticationManager);
}
@Override
@Autowired
public void setAuthenticationSuccessHandler(AuthenticationSuccessHandler successHandler) {
super.setAuthenticationSuccessHandler(successHandler);
}
@Override
@Autowired
public void setAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) {
super.setAuthenticationFailureHandler(failureHandler);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, ServletException{
if (!ServletUtil.METHOD_POST.equals(request.getMethod())) {
throw new HttpRequestMethodNotSupportedException(request.getMethod(), new String[] { "POST" });
}
AuthenticationToken authenticationToken = Json.parseObject(getStringFromStream(request), AuthenticationToken.class);
UserDetails userDetails = getUserDetails(authenticationToken);
return handleAuthenticationToken(authenticationToken,userDetails);
}
/**
*
* @param authenticationToken
* @return
*/
protected UserDetails getUserDetails(AuthenticationToken authenticationToken) {
UserDetails user;
try {
user = userDetailsService.loadUserByUsername(authenticationToken.getPrincipal());
} catch (UsernameNotFoundException var6) {
// 账号或密码不正确
throw new UsernameNotFoundException("账号或密码不正确");
}
if (!user.isEnabled()) {
// 账号已被锁定,请联系管理员
throw new UsernameNotFoundException("账号已被锁定,请联系管理员");
}
String encodedPassword = user.getPassword();
String rawPassword = authenticationToken.getCredentials().toString();
// 密码不正确
if (!passwordEncoder.matches(rawPassword,encodedPassword)){
// 账号或密码不正确
throw new BadCredentialsException("账号或密码不正确");
}
return user;
}
/**
*
*/
protected AuthenticationToken handleAuthenticationToken(AuthenticationToken authentication, UserDetails userDetails) {
// 保存用户信息
authentication.setPrincipal(userDetails.getUsername());
authentication.setDetails(userDetails);
authentication.setAuthenticated(true);
return authentication;
}
public String getStringFromStream(HttpServletRequest req) {
if (req.getContentLength() > MAX_STRING_SIZE) {
// 请求数据过长
throw new YamiShopBindException("yami.request.data.too.long");
}
ServletInputStream is;
try {
is = req.getInputStream();
int nRead = 1;
int nTotalRead = 0;
byte[] bytes = new byte[1024];
while (nRead > 0) {
nRead = is.read(bytes, nTotalRead, bytes.length - nTotalRead);
if (nRead > 0) {
nTotalRead = nTotalRead + nRead;
}
}
if (nTotalRead > MAX_STRING_SIZE) {
// 请求数据过长
throw new YamiShopBindException("yami.request.data.too.long");
}
return XssUtil.clean(new String(bytes, 0, nTotalRead, StandardCharsets.UTF_8));
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}

@ -1,176 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.api.security;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.emoji.EmojiUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.bean.model.User;
import com.yami.shop.common.annotation.RedisLock;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.CacheManagerUtil;
import com.yami.shop.common.util.PrincipalUtil;
import com.yami.shop.dao.UserMapper;
import com.yami.shop.security.dao.AppConnectMapper;
import com.yami.shop.security.enums.App;
import com.yami.shop.security.exception.UsernameNotFoundException;
import com.yami.shop.security.exception.UsernameNotFoundExceptionBase;
import com.yami.shop.security.model.AppConnect;
import com.yami.shop.security.service.YamiUser;
import com.yami.shop.security.service.YamiUserDetailsService;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Caching;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
/**
*
*
* @author
*/
@Slf4j
@Service
@AllArgsConstructor
public class YamiUserServiceImpl implements YamiUserDetailsService {
private final UserMapper userMapper;
private final AppConnectMapper appConnectMapper;
private final PasswordEncoder passwordEncoder;
@Override
@SneakyThrows
public YamiUser loadUserByUsername(String username) {
if (StrUtil.isBlank(username) || !username.contains(StrUtil.COLON) ) {
throw new UsernameNotFoundExceptionBase("无法获取用户信息");
}
String[] splitInfo = username.split(StrUtil.COLON);
App app = App.instance(Integer.valueOf(splitInfo[0]));
String bizUserId = splitInfo[1];
return loadUserByAppIdAndBizUserId(app,bizUserId);
}
/**
*
*
* @param app
* @param bizUserId openId
* @return UserDetails
* @throws UsernameNotFoundExceptionBase
*/
@Override
public YamiUser loadUserByAppIdAndBizUserId(App app, String bizUserId) {
String cacheKey = app.value() + StrUtil.COLON + bizUserId;
User user = userMapper.getUserByBizUserId(app.value(), bizUserId);
if (user == null) {
throw new UsernameNotFoundExceptionBase("无法获取用户信息");
}
String name = StrUtil.isBlank(user.getRealName()) ? user.getNickName() : user.getRealName();
YamiUser yamiUser = new YamiUser(user.getUserId(), bizUserId, app.value(), user.getStatus() == 1);
yamiUser.setName(name);
yamiUser.setPic(user.getPic());
return yamiUser;
}
@Override
@Transactional(rollbackFor = Exception.class)
@RedisLock(lockName = "insertUser", key = "#appConnect.appId + ':' + #appConnect.bizUserId")
@Caching(evict = {
@CacheEvict(cacheNames = "yami_user", key = "#appConnect.appId + ':' + #appConnect.bizUserId"),
@CacheEvict(cacheNames = "AppConnect", key = "#appConnect.appId + ':' + #appConnect.bizUserId")
})
public void insertUserIfNecessary(AppConnect appConnect) {
// 进入锁后再重新判断一遍用户是否创建
AppConnect dbAppConnect = appConnectMapper.getByBizUserId(appConnect.getBizUserId(), appConnect.getAppId());
if(dbAppConnect != null) {
return;
}
String bizUnionId = appConnect.getBizUnionid();
String userId = null;
User user;
if (StrUtil.isNotBlank(bizUnionId)) {
userId = appConnectMapper.getUserIdByUnionId(bizUnionId);
}
if (StrUtil.isBlank(userId)) {
userId = IdUtil.simpleUUID();
Date now = new Date();
user = new User();
user.setUserId(userId);
user.setModifyTime(now);
user.setUserRegtime(now);
user.setStatus(1);
user.setNickName(EmojiUtil.toAlias(StrUtil.isBlank(appConnect.getNickName()) ? "" : appConnect.getNickName()));
user.setPic(appConnect.getImageUrl());
userMapper.insert(user);
} else {
user = userMapper.selectById(userId);
}
appConnect.setUserId(user.getUserId());
appConnectMapper.insert(appConnect);
}
@Override
public YamiUser loadUserByUserMail(String userMail, String loginPassword) {
User user = userMapper.getUserByUserMail(userMail);
if (user == null) {
throw new UsernameNotFoundException("用户不存在");
}
if (!passwordEncoder.matches(loginPassword, user.getLoginPassword())) {
// 原密码不正确
throw new UsernameNotFoundException("密码不正确");
}
String name = StrUtil.isBlank(user.getRealName()) ? user.getNickName() : user.getRealName();
YamiUser yamiUser = new YamiUser(user.getUserId(), loginPassword, user.getStatus() == 1);
yamiUser.setName(name);
yamiUser.setPic(user.getPic());
return yamiUser;
}
@Override
public User loadUserByMobileOrUserName(String mobileOrUserName, Integer loginType) {
User user = null;
// 手机验证码登陆,或传过来的账号很像手机号
if (Objects.equals(loginType, 1) || PrincipalUtil.isMobile(mobileOrUserName)) {
user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUserMobile, mobileOrUserName));
}
return user;
}
@Override
public YamiUser getYamiUser(Integer appId, User user, String bizUserId) {
String name = StrUtil.isBlank(user.getRealName()) ? user.getNickName() : user.getRealName();
YamiUser yamiUser = new YamiUser();
yamiUser.setEnabled(user.getStatus() == 1);
yamiUser.setUserId(user.getUserId());
yamiUser.setBizUserId(bizUserId);
yamiUser.setAppType(appId);
yamiUser.setName(name);
yamiUser.setPic(user.getPic());
yamiUser.setPassword(user.getLoginPassword());
return yamiUser;
}
}

@ -14,7 +14,7 @@ spring:
connection-test-query: select 1
redis:
redisson:
config: classpath:redisson.yml
config: classpath:redisson/redisson.yml
logging:
config: classpath:logback-dev.xml
config: classpath:logback/logback-dev.xml

@ -14,6 +14,6 @@ spring:
connection-test-query: select 1
redis:
redisson:
config: classpath:redisson-docker.yml
config: classpath:redisson/redisson-docker.yml
logging:
config: classpath:logback-prod.xml
config: classpath:logback/logback-prod.xml

@ -16,6 +16,6 @@ spring:
connection-test-query: select 1
redis:
redisson:
config: classpath:redisson.yml
config: classpath:redisson/redisson.yml
logging:
config: classpath:logback-prod.xml
config: classpath:logback/logback-prod.xml

@ -4,28 +4,25 @@ singleServerConfig:
database: ${REDIS_DATABASE}
password: ${REDIS_PASSWORD}
idleConnectionTimeout: 10000
pingTimeout: 1000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
reconnectionTimeout: 3000
failedAttempts: 3
clientName: null
# 发布和订阅连接的最小空闲连接数 默认1
subscriptionConnectionMinimumIdleSize: 1
# 发布和订阅连接池大小 默认50
subscriptionConnectionPoolSize: 10
subscriptionConnectionPoolSize: 1
# 单个连接最大订阅数量 默认5
subscriptionsPerConnection: 5
subscriptionsPerConnection: 1
# 最小空闲连接数 默认32现在暂时不需要那么多的线程
connectionMinimumIdleSize: 4
# connectionPoolSize 默认64现在暂时不需要那么多的线程
connectionPoolSize: 20
connectionPoolSize: 4
# 这个线程池数量被所有RTopic对象监听器RRemoteService调用者和RExecutorService任务共同共享。
threads: 0
# 这个线程池数量是在一个Redisson实例内被其创建的所有分布式数据类型和服务以及底层客户端所一同共享的线程池里保存的线程数量。
nettyThreads: 0
codec:
class: com.yami.shop.common.serializer.redisson.FstCodec
transportMode: NIO
class: org.redisson.codec.KryoCodec
transportMode: NIO

@ -4,28 +4,25 @@ singleServerConfig:
database: 0
password: null
idleConnectionTimeout: 10000
pingTimeout: 1000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
reconnectionTimeout: 3000
failedAttempts: 3
clientName: null
# 发布和订阅连接的最小空闲连接数 默认1
subscriptionConnectionMinimumIdleSize: 1
# 发布和订阅连接池大小 默认50
subscriptionConnectionPoolSize: 10
subscriptionConnectionPoolSize: 1
# 单个连接最大订阅数量 默认5
subscriptionsPerConnection: 5
subscriptionsPerConnection: 1
# 最小空闲连接数 默认32现在暂时不需要那么多的线程
connectionMinimumIdleSize: 4
connectionMinimumIdleSize: 2
# connectionPoolSize 默认64现在暂时不需要那么多的线程
connectionPoolSize: 20
connectionPoolSize: 4
# 这个线程池数量被所有RTopic对象监听器RRemoteService调用者和RExecutorService任务共同共享。
threads: 0
# 这个线程池数量是在一个Redisson实例内被其创建的所有分布式数据类型和服务以及底层客户端所一同共享的线程池里保存的线程数量。
nettyThreads: 0
codec:
class: com.yami.shop.common.serializer.redisson.FstCodec
transportMode: NIO
class: org.redisson.codec.KryoCodec
transportMode: NIO

@ -0,0 +1,66 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.bean.enums;
/**
* @author lh
*/
public enum SendType {
/**
*
*/
REGISTER(12, 1,"用户注册验证码"),
/**
*
*/
LOGIN(13, 1,"发送登录验证码"),
/**
*
*/
UPDATE_PASSWORD(14, 1,"修改密码验证码"),
/**
*
*/
VALID(15, 1,"身份验证验证码")
;
private Integer value;
/**
* 12
*/
private Integer type;
private String desc;
SendType(Integer value, Integer type, String desc) {
this.value = value;
this.type = type;
this.desc = desc;
}
public Integer getValue() {
return value;
}
public String getDesc() {
return desc;
}
public static SendType instance(Integer value) {
SendType[] enums = values();
for (SendType statusEnum : enums) {
if (statusEnum.getValue().equals(value)) {
return statusEnum;
}
}
return null;
}
public Integer getType() {
return type;
}
}

@ -14,12 +14,15 @@ import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author lh
*/
@Data
@ApiModel(value= "设置用户信息")
public class UserRegisterParam {
@ApiModelProperty(value = "密码")
private String password;
private String passWord;
@ApiModelProperty(value = "邮箱")
private String userMail;
@ -30,30 +33,18 @@ public class UserRegisterParam {
@ApiModelProperty(value = "用户名")
private String userName;
@ApiModelProperty(value = "应用类型 1小程序 2微信公众号 3 PC 4 h5")
private Integer appType;
@ApiModelProperty(value = "手机号")
private String mobile;
@ApiModelProperty(value = "验证码")
private String validCode;
@ApiModelProperty(value = "微信小程序的encryptedData")
private String encryptedData;
@ApiModelProperty(value = "微信小程序的ivStr")
private String ivStr;
@ApiModelProperty(value = "头像")
private String img;
@ApiModelProperty(value = "校验登陆注册验证码成功的标识")
private String checkRegisterSmsFlag;
@ApiModelProperty(value = "验证类型 1验证码验证 2 小程序encryptedData验证 3 密码验证 ")
private Integer validateType;
@ApiModelProperty(value = "当账户未绑定时临时的uid")
private String tempUid;
@ApiModelProperty(value = "验证类型 1注册 2绑定 ")
private Integer registerOrBind;
@ApiModelProperty(value = "用户id")
private Long userId;
}

@ -82,8 +82,8 @@
<artifactId>emoji-java</artifactId>
</dependency>
<dependency>
<groupId>de.ruedigermoeller</groupId>
<artifactId>fst</artifactId>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
@ -97,5 +97,9 @@
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
</dependency>
</dependencies>
</project>

@ -11,6 +11,7 @@
package com.yami.shop.common.config;
import com.yami.shop.common.exception.YamiShopBindException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
@ -23,6 +24,7 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
*
* @author LGH
*/
@Slf4j
@Controller
@RestControllerAdvice
public class DefaultExceptionHandlerConfig {
@ -30,20 +32,20 @@ public class DefaultExceptionHandlerConfig {
@ExceptionHandler(BindException.class)
public ResponseEntity<String> bindExceptionHandler(BindException e){
e.printStackTrace();
log.error("BindException:", e);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getBindingResult().getFieldErrors().get(0).getDefaultMessage());
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<String> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e){
e.printStackTrace();
log.error("MethodArgumentNotValidException:", e);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getBindingResult().getFieldErrors().get(0).getDefaultMessage());
}
@ExceptionHandler(YamiShopBindException.class)
public ResponseEntity<String> unauthorizedExceptionHandler(YamiShopBindException e){
e.printStackTrace();
log.error("YamiShopBindException Message :{}",e.getMessage());
return ResponseEntity.status(e.getHttpStatusCode()).body(e.getMessage());
}
}

@ -10,11 +10,7 @@
package com.yami.shop.common.config;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import com.yami.shop.common.serializer.redis.FstRedisSerializer;
import com.yami.shop.common.serializer.redis.KryoRedisSerializer;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
@ -24,7 +20,13 @@ import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.*;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
/**
* redis spring.cache.type = redis
@ -57,14 +59,11 @@ public class RedisCacheConfig {
}
private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
FstRedisSerializer kryoRedisSerializer = new FstRedisSerializer();
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(
RedisSerializationContext
.SerializationPair
.fromSerializer(kryoRedisSerializer)
.fromSerializer(new KryoRedisSerializer<>())
).entryTtl(Duration.ofSeconds(seconds));
return redisCacheConfiguration;
@ -72,14 +71,24 @@ public class RedisCacheConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
KryoRedisSerializer kryoRedisSerializer = new KryoRedisSerializer();
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new FstRedisSerializer());
redisTemplate.setHashValueSerializer(new FstRedisSerializer());
redisTemplate.setValueSerializer(kryoRedisSerializer);
redisTemplate.setHashValueSerializer(kryoRedisSerializer);
redisTemplate.setEnableTransactionSupport(false);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory){
StringRedisTemplate redisTemplate = new StringRedisTemplate(redisConnectionFactory);
redisTemplate.setEnableTransactionSupport(false);
return redisTemplate;
}
}

@ -0,0 +1,33 @@
package com.yami.shop.common.constants;
/**
* @author
* @date 2022/3/28 14:32
*/
public interface OauthCacheNames {
/**
* oauth key
*/
String OAUTH_PREFIX = "mall4j_oauth:";
/**
* token key
*/
String OAUTH_TOKEN_PREFIX = OAUTH_PREFIX + "token:";
/**
* token 使key
*/
String ACCESS = OAUTH_TOKEN_PREFIX + "access:";
/**
* token 使key
*/
String REFRESH_TO_ACCESS = OAUTH_TOKEN_PREFIX + "refresh_to_access:";
/**
* uidtoken key使key
*/
String UID_TO_ACCESS = OAUTH_TOKEN_PREFIX + "uid_to_access:";
}

@ -21,6 +21,9 @@ public enum YamiHttpStatus {
UNAUTHORIZED(401, "未授权"),
COUPONCANNOTUSETOGETHER(601, "优惠券不能共用"),
SOCIAL_ACCOUNT_NOT_BIND(475, "social account not bind"),
ACCOUNT_NOT_REGISTER(476, "account not register"),
;

@ -25,6 +25,8 @@ public class YamiShopBindException extends RuntimeException{
*/
private Integer httpStatusCode;
private Object object;
/**
* @param httpStatus http
@ -48,6 +50,11 @@ public class YamiShopBindException extends RuntimeException{
this.httpStatusCode = HttpStatus.BAD_REQUEST.value();
}
public YamiShopBindException(String msg, Object object) {
super(msg);
this.httpStatusCode = HttpStatus.BAD_REQUEST.value();
this.object = object;
}
public Integer getHttpStatusCode() {
return httpStatusCode;

@ -1,38 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.common.filter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.DispatcherType;
/**
* @author lgh
*/
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<XssFilter> filterRegistration() {
FilterRegistrationBean<XssFilter> registration = new FilterRegistrationBean<>();
//添加过滤器
registration.setFilter(new XssFilter());
//设置过滤路径,/*所有路径
registration.addUrlPatterns("/*");
registration.setName("xssFilter");
//设置优先级
registration.setOrder(Integer.MAX_VALUE);
registration.setDispatcherTypes(DispatcherType.REQUEST);
return registration;
}
}

@ -10,27 +10,22 @@
package com.yami.shop.common.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.yami.shop.common.xss.XssWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.yami.shop.common.xss.XssWrapper;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
*
* xss
* @author lgh
*/
@Component
public class XssFilter implements Filter {
Logger logger = LoggerFactory.getLogger(getClass().getName());

@ -0,0 +1,51 @@
package com.yami.shop.common.handler;
import cn.hutool.core.util.CharsetUtil;
import com.yami.shop.common.exception.YamiShopBindException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @author
* @date 2022/3/28 14:15
*/
@Component
public class HttpHandler {
private static final Logger logger = LoggerFactory.getLogger(HttpHandler.class);
public <T> void printServerResponseToWeb(String str, int status) {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
if (requestAttributes == null) {
logger.error("requestAttributes is null, can not print to web");
return;
}
HttpServletResponse response = requestAttributes.getResponse();
if (response == null) {
logger.error("httpServletResponse is null, can not print to web");
return;
}
logger.error("response error: " + str);
response.setCharacterEncoding(CharsetUtil.UTF_8);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setStatus(status);
PrintWriter printWriter = null;
try {
printWriter = response.getWriter();
printWriter.write(str);
}
catch (IOException e) {
throw new YamiShopBindException("io 异常", e);
}
}
}

@ -1,107 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.common.serializer;
import org.nustaq.serialization.FSTConfiguration;
import org.nustaq.serialization.FSTDecoder;
import org.nustaq.serialization.FSTEncoder;
import org.nustaq.serialization.coders.FSTStreamDecoder;
import org.nustaq.serialization.coders.FSTStreamEncoder;
import java.io.IOException;
import java.lang.reflect.Field;
/**
* 使fts
* @author LGH
*/
public class FSTSerializer {
static class FSTDefaultStreamCoderFactory implements FSTConfiguration.StreamCoderFactory {
Field chBufField;
Field ascStringCacheField;
{
try {
chBufField = FSTStreamDecoder.class.getDeclaredField("chBufS");
ascStringCacheField = FSTStreamDecoder.class.getDeclaredField("ascStringCache");
} catch (Exception e) {
throw new IllegalStateException(e);
}
ascStringCacheField.setAccessible(true);
chBufField.setAccessible(true);
}
private FSTConfiguration fstConfiguration;
FSTDefaultStreamCoderFactory(FSTConfiguration fstConfiguration) {
this.fstConfiguration = fstConfiguration;
}
@Override
public FSTEncoder createStreamEncoder() {
return new FSTStreamEncoder(fstConfiguration);
}
@Override
public FSTDecoder createStreamDecoder() {
return new FSTStreamDecoder(fstConfiguration) {
@Override
public String readStringUTF() throws IOException {
try {
String res = super.readStringUTF();
chBufField.set(this, null);
return res;
} catch (Exception e) {
throw new IOException(e);
}
}
@Override
public String readStringAsc() throws IOException {
try {
String res = super.readStringAsc();
ascStringCacheField.set(this, null);
return res;
} catch (Exception e) {
throw new IOException(e);
}
}
};
}
static ThreadLocal input = new ThreadLocal();
static ThreadLocal output = new ThreadLocal();
@Override
public ThreadLocal getInput() {
return input;
}
@Override
public ThreadLocal getOutput() {
return output;
}
}
private static class InstanceHolder {
private static final FSTConfiguration INSTANCE = FSTConfiguration.createDefaultConfiguration();
static {
INSTANCE.setStreamCoderFactory(new FSTDefaultStreamCoderFactory(INSTANCE));
}
}
public FSTConfiguration getConfig() {
return InstanceHolder.INSTANCE;
}
}

@ -1,47 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.common.serializer.redis;
import com.yami.shop.common.serializer.FSTSerializer;
import lombok.SneakyThrows;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.lang.Nullable;
/**
* 使fst reids
* @author LGH
*/
public class FstRedisSerializer implements RedisSerializer<Object> {
private static final byte[] EMPTY_ARRAY = new byte[0];
@Override
@SneakyThrows
public byte[] serialize(Object o) {
if (o == null) {
return EMPTY_ARRAY;
}
return new FSTSerializer().getConfig().asByteArray(o);
}
@Override
@SneakyThrows
public Object deserialize(byte[] bytes) {
if (isEmpty(bytes)) {
return null;
}
return new FSTSerializer().getConfig().asObject(bytes);
}
private static boolean isEmpty(@Nullable byte[] data) {
return (data == null || data.length == 0);
}
}

@ -0,0 +1,74 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.common.serializer.redis;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import lombok.extern.slf4j.Slf4j;
import org.redisson.codec.KryoCodec;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import java.io.ByteArrayOutputStream;
import java.util.Collections;
/**
* 使Kryo reids
* @author LGH
*/
@Slf4j
public class KryoRedisSerializer<T> implements RedisSerializer<T> {
private final KryoCodec kryoPool;
public KryoRedisSerializer() {
kryoPool = new KryoCodec(Collections.emptyList(), null);
}
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
@Override
public byte[] serialize(T t) throws SerializationException {
if (t == null) {
return EMPTY_BYTE_ARRAY;
}
Kryo kryo = kryoPool.get();
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
Output output = new Output(baos)) {
kryo.writeClassAndObject(output, t);
output.flush();
return baos.toByteArray();
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return EMPTY_BYTE_ARRAY;
}
@Override
@SuppressWarnings("unchecked")
public T deserialize(byte[] bytes) throws SerializationException {
if (bytes == null || bytes.length <= 0) {
return null;
}
Kryo kryo = kryoPool.get();
try (Input input = new Input(bytes)) {
return (T) kryo.readClassAndObject(input);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return null;
}
}

@ -1,104 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.common.serializer.redisson;
import java.io.IOException;
import com.yami.shop.common.serializer.FSTSerializer;
import org.nustaq.serialization.FSTConfiguration;
import org.nustaq.serialization.FSTObjectInput;
import org.nustaq.serialization.FSTObjectOutput;
import org.redisson.client.codec.BaseCodec;
import org.redisson.client.handler.State;
import org.redisson.client.protocol.Decoder;
import org.redisson.client.protocol.Encoder;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.ByteBufOutputStream;
/**
* redisson使
* Efficient and speedy serialization codec fully
* compatible with JDK Serialization codec.
*
* https://github.com/RuedigerMoeller/fast-serialization
*
* @author Nikita Koksharov
*
*/
public class FstCodec extends BaseCodec {
private final FSTConfiguration config;
public FstCodec() {
config = new FSTSerializer().getConfig();
}
private final Decoder<Object> decoder = new Decoder<Object>() {
@Override
public Object decode(ByteBuf buf, State state) throws IOException {
ByteBufInputStream in = new ByteBufInputStream(buf);
FSTObjectInput inputStream = config.getObjectInput(in);
try {
return inputStream.readObject();
} catch (IOException e) {
throw e;
} catch (Exception e) {
throw new IOException(e);
}
}
};
private final Encoder encoder = new Encoder() {
@Override
public ByteBuf encode(Object in) throws IOException {
ByteBuf out = ByteBufAllocator.DEFAULT.buffer();
ByteBufOutputStream os = new ByteBufOutputStream(out);
FSTObjectOutput oos = config.getObjectOutput(os);
try {
oos.writeObject(in);
oos.flush();
return os.buffer();
} catch (IOException e) {
out.release();
throw e;
} catch (Exception e) {
out.release();
throw new IOException(e);
}
}
};
@Override
public Decoder<Object> getValueDecoder() {
return decoder;
}
@Override
public Encoder getValueEncoder() {
return encoder;
}
@Override
public ClassLoader getClassLoader() {
if (config.getClassLoader() != null) {
return config.getClassLoader();
}
return super.getClassLoader();
}
}

@ -11,23 +11,20 @@
package com.yami.shop.common.util;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonGenerator.Feature;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@Slf4j
public class Json {
private static ObjectMapper objectMapper = new ObjectMapper();
@ -80,7 +77,7 @@ public class Json {
try {
return objectMapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
log.error("对象转json错误", e);
}
return null;
}
@ -96,7 +93,7 @@ public class Json {
try {
result = objectMapper.readValue(json, clazz);
} catch (Exception e) {
e.printStackTrace();
log.error("对象转json错误", e);
}
return result;
}
@ -117,7 +114,7 @@ public class Json {
try {
result = objectMapper.readValue(json, clazz);
} catch (Exception e) {
e.printStackTrace();
log.error("Json转换错误", e);
}
if (result == null) {
return Collections.emptyList();
@ -136,18 +133,8 @@ public class Json {
try {
jsonNode = objectMapper.readTree(jsonStr);
} catch (Exception e) {
e.printStackTrace();
log.error("Json转换错误", e);
}
return jsonNode;
}
// public static void main(String[] args){
// String arr = "[1.01,1.03,1.23]";
//
// List<Double> doubles = parseArray(arr, Double[].class);
// for (Double aDouble : doubles) {
// System.out.println(aDouble);
// }
//
// }
}

@ -14,6 +14,9 @@ import cn.hutool.core.util.PageUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Data;
/**
* @author lh
*/
@Data
public class PageAdapter{
@ -22,7 +25,7 @@ public class PageAdapter{
private int size;
public PageAdapter(Page page) {
int[] startEnd = PageUtil.transToStartEnd((int) page.getCurrent(), (int) page.getSize());
int[] startEnd = PageUtil.transToStartEnd((int) page.getCurrent() - 1, (int) page.getSize());
this.begin = startEnd[0];
this.size = (int)page.getSize();
}

@ -20,6 +20,11 @@ public class PrincipalUtil {
*/
public static final String USER_NAME_REGEXP = "([a-zA-Z0-9_]{4,16})";
/**
* 线
*/
public static final String SIMPLE_CHAR_REGEXP = "([a-z0-9]+)";
public static boolean isMobile(String value) {
if(StrUtil.isBlank(value)) {
return false;
@ -33,4 +38,20 @@ public class PrincipalUtil {
}
return Pattern.matches(USER_NAME_REGEXP, value);
}
public static boolean isMatching(String regexp, String value) {
if (StrUtil.isBlank(value)) {
return false;
}
return Pattern.matches(regexp, value);
}
/**
*
* @param value
* @return
*/
public static boolean isSimpleChar(String value) {
return isMatching(SIMPLE_CHAR_REGEXP, value);
}
}

@ -10,97 +10,107 @@
package com.yami.shop.common.util;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import java.util.concurrent.TimeUnit;
/**
* @author lh
*/
@Slf4j
public class RedisUtil {
private static RedisTemplate<String,Object> redisTemplate = SpringContextUtils.getBean("redisTemplate",RedisTemplate.class);
private static RedisTemplate<String, Object> redisTemplate = SpringContextUtils.getBean("redisTemplate", RedisTemplate.class);
//=============================common============================
/**
*
* @param key
*
* @param key
* @param time ()
* @return
*/
public static boolean expire(String key,long time){
public static boolean expire(String key, long time) {
try {
if(time>0){
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
log.error("设置redis指定key失效时间错误:", e);
return false;
}
}
/**
* key
*
* @param key null
* @return () 0 -1
*/
public static long getExpire(String key){
return redisTemplate.getExpire(key,TimeUnit.SECONDS);
public static long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* key
*
* @param key
* @return true false
*/
public static boolean hasKey(String key){
public static boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
log.error("redis判断key是否存在错误", e);
return false;
}
}
/**
*
*
* @param key
*/
@SuppressWarnings("unchecked")
public static void del(String ... key){
if(key!=null&&key.length>0){
if(key.length==1){
public static void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
}else{
} else {
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
//============================String=============================
/**
*
*
* @param key
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T get(String key){
return key==null?null:(T)redisTemplate.opsForValue().get(key);
public static <T> T get(String key) {
return key == null ? null : (T) redisTemplate.opsForValue().get(key);
}
/**
*
* @param key
*
* @param key
* @param value
* @return true false
*/
public static boolean set(String key,Object value) {
public static boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
log.error("设置redis缓存错误", e);
return false;
}
@ -108,16 +118,17 @@ public class RedisUtil {
/**
*
* @param key
*
* @param key
* @param value
* @param time () time0 time0
* @param time () time0 time0
* @return true false
*/
public static boolean set(String key,Object value,long time){
public static boolean set(String key, Object value, long time) {
try {
if(time>0){
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
}else{
} else {
set(key, value);
}
return true;
@ -129,12 +140,13 @@ public class RedisUtil {
/**
* valueint
* @param key
*
* @param key
* @param delta (0)
* @return
*/
public static long incr(String key, long delta){
if(delta<0){
public static long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, delta);
@ -142,12 +154,13 @@ public class RedisUtil {
/**
*
* @param key
*
* @param key
* @param delta (0)
* @return
*/
public static long decr(String key, long delta){
if(delta<0){
public static long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, -delta);

@ -1,82 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.common.util;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.util.ImageUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.concurrent.ThreadLocalRandom;
public class SimpleCaptcha extends LineCaptcha{
private static final long serialVersionUID = -9042552338521307038L;
private static final String CAPTCHA_CODE = "abcdefhjkmnpqrstuvwxyz2345678";
public SimpleCaptcha(int width, int height, int codeCount, int interfereCount) {
super(width, height, codeCount, interfereCount);
}
@Override
protected void generateCode() {
this.code = RandomUtil.randomString(CAPTCHA_CODE,this.generator.getLength());
}
@Override
public Image createImage(String code) {
// 图像buffer
final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
final ThreadLocalRandom random = RandomUtil.getRandom();
final Graphics2D g = ImageUtil.createGraphics(image, new Color(249,249,249));
// 干扰线
drawInterfere(g, random);
// 创建字体
g.setFont(this.font);
final FontMetrics metrics = g.getFontMetrics();
int minY = metrics.getAscent() - metrics.getLeading() - metrics.getDescent();
// 文字
final int len = this.generator.getLength();
int charWidth = width / len;
for (int i = 0; i < len; i++) {
// 产生随机的颜色值,让输出的每个字符的颜色值都将不同。
g.setColor(ImageUtil.randomColor(random));
g.drawString(String.valueOf(code.charAt(i)), i * charWidth, RandomUtil.randomInt(minY, this.height));
}
return image;
}
/**
* 线
*
* @param g {@link Graphics2D}
* @param random
*/
private void drawInterfere(Graphics2D g, ThreadLocalRandom random) {
// 干扰线
for (int i = 0; i < this.interfereCount; i++) {
int xs = random.nextInt(width);
int ys = random.nextInt(height);
int xe = xs + random.nextInt(width / 8);
int ye = ys + random.nextInt(height / 8);
g.setColor(ImageUtil.randomColor(random));
g.drawLine(xs, ys, xe, ye);
}
}
}

@ -1,21 +0,0 @@
<?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">
<parent>
<artifactId>yami-shop</artifactId>
<groupId>com.yami.shop</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yami-shop-mp</artifactId>
<dependencies>
<dependency>
<groupId>com.yami.shop</groupId>
<artifactId>yami-shop-security</artifactId>
<version>${yami.shop.version}</version>
</dependency>
</dependencies>
</project>

@ -1,27 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.mp.builder;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Binary Wang(https://github.com/binarywang)
*/
public abstract class AbstractBuilder {
protected final Logger logger = LoggerFactory.getLogger(getClass());
public abstract WxMpXmlOutMessage build(String content,
WxMpXmlMessage wxMessage, WxMpService service);
}

@ -1,34 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.mp.builder;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutImageMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
/**
* @author Binary Wang(https://github.com/binarywang)
*/
public class ImageBuilder extends AbstractBuilder {
@Override
public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage,
WxMpService service) {
WxMpXmlOutImageMessage m = WxMpXmlOutMessage.IMAGE().mediaId(content)
.fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
.build();
return m;
}
}

@ -1,33 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.mp.builder;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTextMessage;
/**
* @author Binary Wang(https://github.com/binarywang)
*/
public class TextBuilder extends AbstractBuilder {
@Override
public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage,
WxMpService service) {
WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT().content(content)
.fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
.build();
return m;
}
}

@ -1,156 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.mp.component;
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
import com.yami.shop.common.annotation.RedisLock;
import com.yami.shop.common.util.RedisUtil;
import com.yami.shop.mp.config.bean.WxMiniApp;
import me.chanjar.weixin.common.bean.WxAccessToken;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.locks.Lock;
/**
* Redisprovider.
*
*
*
* @author LGH
*/
@Component
public class WxMaInRedisConfig extends WxMaDefaultConfigImpl {
private static final String ACCESS_TOKEN_KEY = "wxMa:access_token:";
private static final String JSAPI_TICKET_KEY = "wxMa:jsapi_ticket:";
private static final String CARD_API_TICKET_KEY = "wxMa:card_api_ticket:";
private static final String WX_MA_ACCESS_TOKEN_LOCK = "wxMa:access_token_lock:";
private static final String WX_MA_JSAPI_TICKET_LOCK = "wxMa:jsapi_ticket_lock:";
private static final String WX_MA_CARD_API_TICKET_LOCK = "wxMa:card_api_ticket_lock:";
private String accessTokenKey;
private String jsapiTicketKey;
private String cardApiTicketKey;
@Autowired
private RedissonClient redissonClient;
public WxMaInRedisConfig (WxMiniApp wxMiniApp) {
this.setAppid(wxMiniApp.getAppid());
this.setSecret(wxMiniApp.getSecret());
}
/**
* key.
*/
@Override
public void setAppid(String appId) {
super.setAppid(appId);
this.accessTokenKey = ACCESS_TOKEN_KEY.concat(appId);
this.jsapiTicketKey = JSAPI_TICKET_KEY.concat(appId);
this.cardApiTicketKey = CARD_API_TICKET_KEY.concat(appId);
}
@Override
public String getAccessToken() {
return RedisUtil.get(accessTokenKey);
}
@Override
public Lock getAccessTokenLock(){
return redissonClient.getLock(WX_MA_ACCESS_TOKEN_LOCK);
}
@Override
public boolean isAccessTokenExpired() {
return !RedisUtil.hasKey(accessTokenKey);
}
@Override
public void expireAccessToken() {
RedisUtil.del(accessTokenKey);
}
@Override
@RedisLock(lockName = "updateMaAccessToken")
public void updateAccessToken(WxAccessToken accessToken) {
updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
}
@Override
@RedisLock(lockName = "updateMaAccessToken")
public void updateAccessToken(String accessToken, int expiresInSeconds) {
RedisUtil.set(accessTokenKey, accessToken, expiresInSeconds - 200);
}
@Override
public String getJsapiTicket() {
return RedisUtil.get(jsapiTicketKey);
}
@Override
public Lock getJsapiTicketLock() {
return redissonClient.getLock(WX_MA_JSAPI_TICKET_LOCK);
}
@Override
public boolean isJsapiTicketExpired() {
return !RedisUtil.hasKey(jsapiTicketKey);
}
@Override
public void expireJsapiTicket() {
RedisUtil.del(jsapiTicketKey);
}
@Override
@RedisLock(lockName = "updateMaJsapiTicket")
public void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) {
RedisUtil.set(jsapiTicketKey, jsapiTicket, expiresInSeconds - 200);
}
@Override
public String getCardApiTicket() {
return RedisUtil.get(cardApiTicketKey);
}
@Override
public Lock getCardApiTicketLock() {
return redissonClient.getLock(WX_MA_CARD_API_TICKET_LOCK);
}
@Override
public boolean isCardApiTicketExpired() {
return !RedisUtil.hasKey(cardApiTicketKey);
}
@Override
public void expireCardApiTicket() {
RedisUtil.del(cardApiTicketKey);
}
@Override
@RedisLock(lockName = "updateMaCardJsapiTicket")
public void updateCardApiTicket(String cardApiTicket, int expiresInSeconds) {
RedisUtil.set(cardApiTicketKey, cardApiTicket, expiresInSeconds - 200);
}
}

@ -1,72 +0,0 @@
package com.yami.shop.mp.component;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.hutool.http.HttpUtil;
import com.yami.shop.common.exception.YamiShopBindException;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import java.util.concurrent.TimeUnit;
/**
* WxMaServiceImpl accessToken
* @author LGH
*/
@Slf4j
public class WxMaServiceClusterImpl extends WxMaServiceImpl {
private static final String REDISSON_LOCK_PREFIX = "redisson_lock:";
private RedissonClient redissonClient;
public void setRedissonClient(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
@Override
public String getAccessToken(boolean forceRefresh) throws WxErrorException {
if (!this.getWxMaConfig().isAccessTokenExpired() && !forceRefresh) {
return this.getWxMaConfig().getAccessToken();
}
RLock rLock = redissonClient.getLock(REDISSON_LOCK_PREFIX + ":WxMaServiceCluster:getAccessToken");
try {
boolean lockSuccess;
try {
lockSuccess = rLock.tryLock(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
return this.getWxMaConfig().getAccessToken();
}
if (!lockSuccess) {
throw new YamiShopBindException("服务器繁忙,请稍后再试");
}
if (!this.getWxMaConfig().isAccessTokenExpired()) {
return this.getWxMaConfig().getAccessToken();
}
String url = String.format(WxMaService.GET_ACCESS_TOKEN_URL, this.getWxMaConfig().getAppid(),
this.getWxMaConfig().getSecret());
String resultContent = HttpUtil.get(url);
WxError error = WxError.fromJson(resultContent);
if (error.getErrorCode() != 0) {
throw new WxErrorException(error);
}
WxAccessToken accessToken = WxAccessToken.fromJson(resultContent);
this.getWxMaConfig().updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
return this.getWxMaConfig().getAccessToken();
} finally {
rLock.unlock();
}
}
}

@ -1,104 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.mp.component;
import com.yami.shop.common.annotation.RedisLock;
import com.yami.shop.common.util.RedisUtil;
import com.yami.shop.mp.config.bean.WxMp;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
import me.chanjar.weixin.mp.enums.TicketType;
import org.springframework.stereotype.Component;
/**
* Redisprovider.
*
*
*
* @author LGH
*/
@Component
public class WxMpInRedisConfigStorage extends WxMpDefaultConfigImpl {
private static final String ACCESS_TOKEN_KEY = "wxMp:access_token:";
private String accessTokenKey;
public WxMpInRedisConfigStorage (WxMp wxMp) {
this.setAppId(wxMp.getAppid());
this.setSecret(wxMp.getSecret());
this.setToken(wxMp.getToken());
this.setAesKey(wxMp.getAesKey());
}
/**
* key.
*/
@Override
public void setAppId(String appId) {
super.setAppId(appId);
this.accessTokenKey = ACCESS_TOKEN_KEY.concat(appId);
}
private String getTicketRedisKey(TicketType type) {
return String.format("wx:ticket:key:%s:%s", this.appId, type.getCode());
}
@Override
public String getAccessToken() {
return RedisUtil.get(accessTokenKey);
}
@Override
public boolean isAccessTokenExpired() {
return !RedisUtil.hasKey(accessTokenKey);
}
@Override
@RedisLock(lockName = "updateMpAccessToken")
public void updateAccessToken(WxAccessToken accessToken) {
updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
}
@Override
@RedisLock(lockName = "updateMpAccessToken")
public void updateAccessToken(String accessToken, int expiresInSeconds) {
RedisUtil.set(accessTokenKey, accessToken, expiresInSeconds - 200);
}
@Override
public void expireAccessToken() {
RedisUtil.del(accessTokenKey);
}
@Override
public String getTicket(TicketType type) {
return RedisUtil.get(this.getTicketRedisKey(type));
}
@Override
public boolean isTicketExpired(TicketType type) {
return !RedisUtil.hasKey(this.getTicketRedisKey(type));
}
@Override
@RedisLock(lockName = "updateMpJsapiTicket")
public void updateTicket(TicketType type, String jsapiTicket, int expiresInSeconds) {
RedisUtil.set(this.getTicketRedisKey(type), jsapiTicket, expiresInSeconds - 200);
}
@Override
public void expireTicket(TicketType type) {
RedisUtil.del(this.getTicketRedisKey(type));
}
}

@ -1,70 +0,0 @@
package com.yami.shop.mp.component;
import cn.hutool.http.HttpUtil;
import com.yami.shop.common.exception.YamiShopBindException;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.impl.WxMpServiceHttpClientImpl;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import java.util.concurrent.TimeUnit;
import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Other.GET_ACCESS_TOKEN_URL;
/**
* WxMpServiceImpl accessToken
* @author LGH
*/
public class WxMpServiceClusterImpl extends WxMpServiceHttpClientImpl {
private static final String REDISSON_LOCK_PREFIX = "redisson_lock:";
private RedissonClient redissonClient;
public void setRedissonClient(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
@Override
public String getAccessToken(boolean forceRefresh) throws WxErrorException {
if (!this.getWxMpConfigStorage().isAccessTokenExpired() && !forceRefresh) {
return this.getWxMpConfigStorage().getAccessToken();
}
RLock rLock = redissonClient.getLock(REDISSON_LOCK_PREFIX + ":WxMpServiceCluster:getAccessToken");
try {
boolean doingUpdateAccessToken;
try {
doingUpdateAccessToken = rLock.tryLock(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
return this.getWxMpConfigStorage().getAccessToken();
}
if (!doingUpdateAccessToken) {
throw new YamiShopBindException("服务器繁忙,请稍后再试");
}
if (!this.getWxMpConfigStorage().isAccessTokenExpired()) {
return this.getWxMpConfigStorage().getAccessToken();
}
String url = String.format(GET_ACCESS_TOKEN_URL.getUrl(this.getWxMpConfigStorage()), this.getWxMpConfigStorage().getAppId(), this.getWxMpConfigStorage().getSecret());
String resultContent = HttpUtil.get(url);
WxError error = WxError.fromJson(resultContent, WxType.MP);
if (error.getErrorCode() != 0) {
throw new WxErrorException(error);
}
WxAccessToken accessToken = WxAccessToken.fromJson(resultContent);
this.getWxMpConfigStorage().updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
return this.getWxMpConfigStorage().getAccessToken();
} finally {
rLock.unlock();
}
}
}

@ -1,46 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.mp.config;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import com.yami.shop.mp.component.WxMaInRedisConfig;
import com.yami.shop.mp.component.WxMaServiceClusterImpl;
import lombok.AllArgsConstructor;
import org.redisson.api.RedissonClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
*
* @author LGH
*/
@Configuration
@AllArgsConstructor
@ConditionalOnClass(WxMaService.class)
public class WxMaConfiguration {
private final WxMaInRedisConfig wxMaInRedisConfig;
private final RedissonClient redissonClient;
@Bean
public WxMaService wxMaService() {
WxMaServiceClusterImpl service = new WxMaServiceClusterImpl();
service.setWxMaConfig(wxMaInRedisConfig);
service.setRedissonClient(redissonClient);
return service;
}
}

@ -1,61 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.mp.config;
import com.yami.shop.mp.component.WxMpInRedisConfigStorage;
import com.yami.shop.mp.component.WxMpServiceClusterImpl;
import com.yami.shop.mp.handler.MenuHandler;
import lombok.AllArgsConstructor;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import org.redisson.api.RedissonClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType;
import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType;
/**
*
* @author LGH
*/
@Configuration
@AllArgsConstructor
@ConditionalOnClass(WxMpService.class)
public class WxMpConfiguration {
private final MenuHandler menuHandler;
private final WxMpInRedisConfigStorage wxMpInRedisConfigStorage;
private final RedissonClient redissonClient;
@Bean
public WxMpService wxMpService() {
WxMpServiceClusterImpl service = new WxMpServiceClusterImpl();
service.setWxMpConfigStorage(wxMpInRedisConfigStorage);
service.setRedissonClient(redissonClient);
return service;
}
@Bean
public WxMpMessageRouter messageRouter() {
final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService());
// 自定义菜单事件
newRouter.rule().async(false).msgType(XmlMsgType.EVENT)
.event(MenuButtonType.CLICK).handler(this.menuHandler).end();
return newRouter;
}
}

@ -1,87 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.mp.config;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import com.yami.shop.mp.config.bean.WxMiniApp;
import com.yami.shop.mp.config.bean.WxMp;
import com.yami.shop.mp.config.bean.WxPay;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Objects;
/**
*
*
* @author LGH
*/
@Configuration
@RequiredArgsConstructor
@ConditionalOnClass(WxPayService.class)
public class WxPayConfiguration {
private final WxMp wxMp;
private final WxMiniApp wxMiniApp;
private final WxPay wxPay;
@Value("${spring.profiles.active}")
private String profile;
@Bean
public WxPayService wxMiniPayService() {
return getWxMpPayServiceByAppId(wxMiniApp.getAppid());
}
@Bean
public WxPayService wxMpPayService() {
return getWxMpPayServiceByAppId(wxMp.getAppid());
}
private WxPayService getWxMpPayServiceByAppId(String appid) {
WxPayConfig payConfig = new WxPayConfig();
payConfig.setAppId(appid);
payConfig.setMchId(wxPay.getMchId());
payConfig.setMchKey(wxPay.getMchKey());
payConfig.setKeyPath(wxPay.getKeyPath());
payConfig.setSignType(WxPayConstants.SignType.MD5);
WxPayService wxPayService = new WxPayServiceImpl();
// 打开下面的代码,开启沙箱模式
// if (Objects.equals(profile, "dev")) {
// String sandboxSignKey = null;
// try {
// wxPayService.setConfig(payConfig);
// sandboxSignKey = wxPayService.getSandboxSignKey();
// } catch (WxPayException e) {
// e.printStackTrace();
// }
// payConfig.setUseSandboxEnv(true);
// payConfig.setMchKey(sandboxSignKey);
// }
wxPayService.setConfig(payConfig);
return wxPayService;
}
}

@ -1,34 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.mp.config.bean;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Data
@Component
@PropertySource("classpath:ma.properties")
@ConfigurationProperties(prefix = "ma")
public class WxMiniApp {
/**
* appid
*/
private String appid;
/**
* Secret
*/
private String secret;
}

@ -1,43 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.mp.config.bean;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Data
@Component
@PropertySource("classpath:mp.properties")
@ConfigurationProperties(prefix = "mp")
public class WxMp {
/**
* appid
*/
private String appid;
/**
* Secret
*/
private String secret;
/**
* token
*/
private String token;
/**
* aesKey
*/
private String aesKey;
}

@ -1,45 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.mp.config.bean;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Data
@Component
@PropertySource("classpath:pay.properties")
@ConfigurationProperties(prefix = "pay")
public class WxPay {
/**
* mchId
*/
private String mchId;
/**
* mchKey
*/
private String mchKey;
/**
*
*/
private String signType;
/**
*
*/
private String keyPath;
}

@ -1,116 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.mp.controller.api;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.*;
/**
*/
@RestController
@RequestMapping("/wx/portal")
public class WxPortalController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private WxMpService wxMpService;
@Autowired
private WxMpMessageRouter wxMpMessageRouter;
/**
*
* ->->->
*
* @return
*/
@GetMapping(produces = "text/plain;charset=utf-8")
public String authGet(@RequestParam(name = "signature", required = false) String signature,
@RequestParam(name = "timestamp", required = false) String timestamp,
@RequestParam(name = "nonce", required = false) String nonce,
@RequestParam(name = "echostr", required = false) String echostr) {
this.logger.info("\n接收到来自微信服务器的认证消息[{}, {}, {}, {}]", signature,
timestamp, nonce, echostr);
if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
throw new IllegalArgumentException("请求参数非法,请核实!");
}
if (wxMpService.checkSignature(timestamp, nonce, signature)) {
return echostr;
}
return "非法请求";
}
/**
*
*
* @return
*/
@PostMapping(produces = "application/xml; charset=UTF-8")
public String post(@RequestBody String requestBody,
@RequestParam("signature") String signature,
@RequestParam("timestamp") String timestamp,
@RequestParam("nonce") String nonce,
@RequestParam("openid") String openid,
@RequestParam(name = "encrypt_type", required = false) String encType,
@RequestParam(name = "msg_signature", required = false) String msgSignature) {
this.logger.info("\n接收微信请求[openid=[{}], [signature=[{}], encType=[{}], msgSignature=[{}],"
+ " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
openid, signature, encType, msgSignature, timestamp, nonce, requestBody);
String out = null;
if (encType == null) {
// 明文传输的消息
WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
WxMpXmlOutMessage outMessage = this.route(inMessage);
if (outMessage == null) {
return "";
}
out = outMessage.toXml();
} else if ("aes".equalsIgnoreCase(encType)) {
// aes加密的消息
WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxMpService.getWxMpConfigStorage(),
timestamp, nonce, msgSignature);
this.logger.debug("\n消息解密后内容为\n{} ", inMessage.toString());
WxMpXmlOutMessage outMessage = this.route(inMessage);
if (outMessage == null) {
return "";
}
out = outMessage.toEncryptedXml(wxMpService.getWxMpConfigStorage());
}
this.logger.debug("\n组装回复信息{}", out);
return out;
}
private WxMpXmlOutMessage route(WxMpXmlMessage message) {
try {
return wxMpMessageRouter.route(message);
} catch (Exception e) {
this.logger.error("路由消息时出现异常!", e);
}
return null;
}
}

@ -1,22 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.mp.handler;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Binary Wang(https://github.com/binarywang)
*/
public abstract class AbstractHandler implements WxMpMessageHandler {
protected Logger logger = LoggerFactory.getLogger(getClass());
}

@ -1,46 +0,0 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.mp.handler;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.springframework.stereotype.Component;
import java.util.Map;
import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType;
/**
* @author Binary Wang(https://github.com/binarywang)
*/
@Component
public class MenuHandler extends AbstractHandler {
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
Map<String, Object> context, WxMpService weixinService,
WxSessionManager sessionManager) {
String msg = String.format("type:%s, event:%s, key:%s",
wxMessage.getMsgType(), wxMessage.getEvent(),
wxMessage.getEventKey());
if (MenuButtonType.VIEW.equals(wxMessage.getEvent())) {
return null;
}
return WxMpXmlOutMessage.TEXT().content(msg)
.fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
.build();
}
}

@ -1,4 +0,0 @@
mp.appid=
mp.secret=
mp.token=
mp.aesKey=

@ -1,3 +0,0 @@
pay.mchId=
pay.mchKey=
pay.keyPath=classpath:xxx.p12

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

Loading…
Cancel
Save