增加H5端注册、登录、退出,支付功能

This commit is contained in:
sjl
2021-02-26 13:37:27 +08:00
parent c8565d7e9b
commit 4dea290b68
17 changed files with 11 additions and 661 deletions

View File

@@ -10,7 +10,6 @@
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;
@@ -33,8 +32,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 = "订单接口")
@@ -72,22 +69,4 @@ public class PayController {
return ResponseEntity.ok(wxMiniPayService.createOrder(orderRequest));
}
/**
* 普通支付接口
*/
@PostMapping("/normalPay")
@ApiOperation(value = "根据订单号进行支付", notes = "根据订单号进行支付")
@SneakyThrows
public ResponseEntity<Boolean> normalPay(@RequestBody PayParam payParam) {
YamiUser user = SecurityUtils.getUser();
String userId = user.getUserId();
PayInfoDto pay = payService.pay(userId, payParam);
// 根据内部订单号更新order settlement
payService.paySuccess(pay.getPayNo(), "");
return ResponseEntity.ok(true);
}
}

View File

@@ -18,7 +18,6 @@ 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;
@@ -35,8 +34,6 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import ma.glasnost.orika.MapperFacade;
import javax.servlet.http.HttpServletRequest;
@RestController
@RequestMapping("/p/user")
@Api(tags="用户接口")
@@ -44,12 +41,10 @@ import javax.servlet.http.HttpServletRequest;
public class UserController {
private final UserService userService;
private final MapperFacade mapperFacade;
private final CacheManagerUtil cacheManagerUtil;
private final ConsumerTokenServices consumerTokenServices;
/**
* 查看用户接口
*/
@@ -61,7 +56,7 @@ public class UserController {
UserDto userDto = mapperFacade.map(user, UserDto.class);
return ResponseEntity.ok(userDto);
}
@PutMapping("/setUserInfo")
@ApiOperation(value="设置用户信息", notes="设置用户信息")
public ResponseEntity<Void> setUserInfo(@RequestBody UserInfoParam userInfoParam) {
@@ -75,14 +70,4 @@ public class UserController {
cacheManagerUtil.evictCache("yami_user", cacheKey);
return ResponseEntity.ok(null);
}
/**
* 退出登录,并清除redis中的token
**/
@GetMapping("/logout")
public Boolean removeToken(HttpServletRequest httpRequest){
String authorization = httpRequest.getHeader("authorization");
String token = authorization.replace("bearer", "");
return consumerTokenServices.revokeToken(token);
}
}

View File

@@ -1,72 +0,0 @@
package com.yami.shop.api.controller;
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.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.security.handler.LoginAuthSuccessHandler;
import com.yami.shop.security.model.AppConnect;
import com.yami.shop.security.service.YamiUserDetailsService;
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.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;
/**
* 用户信息
*
* @author SJL
*/
@RestController
@RequestMapping("/user")
@Api(tags = "用户注册相关接口")
@AllArgsConstructor
public class UserRegisterController {
private final UserService userService;
private final PasswordEncoder passwordEncoder;
@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));
}
@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()));
if (user == null) {
// 无法获取用户信息
throw new YamiShopBindException("yami.user.no.exist");
}
if (StrUtil.isBlank(userRegisterParam.getPassword())) {
// 新密码不能为空
throw new YamiShopBindException("yami.user.password.no.exist");
}
if (StrUtil.equals(passwordEncoder.encode(userRegisterParam.getPassword()), user.getLoginPassword())) {
// 新密码不能与原密码相同
throw new YamiShopBindException("yami.user.password.check");
}
user.setModifyTime(new Date());
user.setLoginPassword(passwordEncoder.encode(userRegisterParam.getPassword()));
userService.updateById(user);
return ResponseEntity.ok().build();
}
}

View File

@@ -1,95 +0,0 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.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();
}
}
}

View File

@@ -1,27 +0,0 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package com.yami.shop.api.security;
import com.yami.shop.security.token.MyAuthenticationToken;
import lombok.NoArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
/**
* H5端Token
*/
@NoArgsConstructor
public class WebAuthenticationToken extends MyAuthenticationToken {
public WebAuthenticationToken(UserDetails principal, Object credentials) {
super(principal, credentials, principal.getAuthorities());
}
}

View File

@@ -1,153 +0,0 @@
/*
* Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
*
* https://www.gz-yami.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);
}
}

View File

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

View File

@@ -15,7 +15,6 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.emoji.EmojiUtil;
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.dao.UserMapper;
import com.yami.shop.security.dao.AppConnectMapper;
@@ -29,8 +28,6 @@ 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;
@@ -52,7 +49,7 @@ public class YamiUserServiceImpl implements YamiUserDetailsService {
private final CacheManagerUtil cacheManagerUtil;
private final PasswordEncoder passwordEncoder;
@Override
@SneakyThrows
public YamiUser loadUserByUsername(String username) {
@@ -130,22 +127,4 @@ public class YamiUserServiceImpl implements YamiUserDetailsService {
appConnectMapper.insert(appConnect);
}
@Override
public YamiUser loadUserByUserMail(String userMail, String loginPassword) {
User user = userMapper.getUserByUserMail(userMail);
if (user == null) {
throw new YamiShopBindException("用户不存在");
}
String paramPassword = passwordEncoder.encode(loginPassword);
if (!passwordEncoder.matches(loginPassword, user.getLoginPassword())) {
// 原密码不正确
throw new YamiShopBindException("密码不正确");
}
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;
}
}