refactor: 增加微信扫码登录

This commit is contained in:
TS-QD1 2025-04-16 15:17:08 +08:00
parent 5498701eae
commit 8741aadccb
39 changed files with 1397 additions and 82 deletions

View File

@ -1,4 +1,16 @@
# 20250325
# 20250409
## 微信oauth2扫码登录
### user_expand
```sql
ALTER TABLE `sys_user_expand`
ADD COLUMN `wx_open_id` varchar(255) NULL COMMENT '微信-开放平台-openid' AFTER `main_user_id`,
ADD COLUMN `wx_union_id` varchar(255) NULL COMMENT '微信-开放平台-unionid' AFTER `wx_open_id`;
```
# 20250325已上线
## user_expand
@ -15,7 +27,6 @@ ALTER TABLE `sys_user_expand`
## sys_callback
```sql
CREATE TABLE `sys_callback` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`callback_id` char(36) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL COMMENT '名称',

View File

@ -2,9 +2,8 @@ package cn.com.tenlion.operator.controller.api.accountrecharge;
import cn.com.tenlion.operator.pojo.dtos.accountrecharge.AccountRechargePayDTO;
import cn.com.tenlion.operator.pojo.dtos.accountrecharge.AccountRechargePayResultDTO;
import cn.com.tenlion.operator.pojo.vos.accountitem.AccountItemVO;
import cn.com.tenlion.operator.pojo.dtos.accountrecharge.AccountRechargeWxPrepayDTO;
import cn.com.tenlion.operator.pojo.vos.accountrecharge.AccountRechargeWxPrepayVO;
import cn.com.tenlion.operator.util.pay.PayUtil;
import ink.wgink.annotation.CheckRequestBodyAnnotation;
import ink.wgink.common.base.DefaultBaseController;
import ink.wgink.exceptions.ParamsException;
@ -62,9 +61,9 @@ public class AccountRechargeController extends DefaultBaseController {
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@PostMapping("save-wx-pay-prepay-id")
@CheckRequestBodyAnnotation
public SuccessResult saveWxPayPrepayId(@RequestBody AccountRechargeWxPrepayVO accountRechargeWxPrepayVO) {
String prepayId = accountRechargeService.saveWxPayPrepayId(accountRechargeWxPrepayVO);
return new SuccessResultData<>(prepayId);
public AccountRechargeWxPrepayDTO saveWxPayPrepayId(@RequestBody AccountRechargeWxPrepayVO accountRechargeWxPrepayVO) {
AccountRechargeWxPrepayDTO accountRechargeWxPrepayDTO = accountRechargeService.saveWxMiniappPayPrepayId(accountRechargeWxPrepayVO);
return accountRechargeWxPrepayDTO;
}
// @ApiOperation(value = "账户确认到账", notes = "账户确认到账接口")

View File

@ -0,0 +1,48 @@
package cn.com.tenlion.operator.controller.api.user;
import cn.com.tenlion.operator.pojo.pos.user.expand.UserExpandPO;
import cn.com.tenlion.operator.service.user.expand.UserExpandServiceImpl;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.pojo.result.SuccessResult;
import ink.wgink.pojo.result.SuccessResultData;
import ink.wgink.pojo.result.SuccessResultList;
import ink.wgink.service.user.pojo.pos.UserPO;
import ink.wgink.service.user.pojo.vos.UpdateUsernameVO;
import ink.wgink.service.user.service.IUserService;
import io.swagger.annotations.Api;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
@Api(tags = ISystemConstant.API_TAGS_SYSTEM_PREFIX + "企业用户创建员工接口")
@RestController
@RequestMapping(ISystemConstant.API_PREFIX + "/user-wx-update-username")
public class UserWxUpdateUsernameController {
@Autowired
private IUserService userService;
@Autowired
private UserExpandServiceImpl userExpandService;
@GetMapping("check-phone/{phone}")
public SuccessResultData<String> checkPhone(@PathVariable("phone") String phone) {
UserPO existUserPO = userService.getPOByUsername(phone);
String result = "SUCCESS";
if (existUserPO != null) {
UserExpandPO existUserExpandPO = userExpandService.getPO(existUserPO.getUserId());
if (existUserExpandPO != null) {
if (!StringUtils.isBlank(existUserExpandPO.getWxOpenId())) {
result = "FAIL";
}
}
}
return new SuccessResultData<>(result);
}
}

View File

@ -1,5 +1,6 @@
package cn.com.tenlion.operator.controller.route.systemuser;
import cn.com.tenlion.operator.properties.WxOauth2Properties;
import cn.com.tenlion.operator.util.UserUtil;
import cn.com.tenlion.projectconfig.util.ProjectConfigUtil;
import ink.wgink.common.base.DefaultBaseController;
@ -54,6 +55,8 @@ public class SystemUserRouteController extends DefaultBaseController {
@Autowired
private ServerProperties systemProperties;
@Autowired
private WxOauth2Properties wxOauth2Properties;
@GetMapping("index")
public ModelAndView index(HttpServletRequest request) {
@ -87,6 +90,8 @@ public class SystemUserRouteController extends DefaultBaseController {
ModelAndView mv = new ModelAndView();
Map<String, String> pageParams = oAuthService.getPageParams(request);
pageParams.put("loginPhoneAction", "oauth/phone");
pageParams.put("wxAppid", wxOauth2Properties.getAppid());
pageParams.put("wxRedirectUri", wxOauth2Properties.getRedirectUri());
mv.addObject(IUserCenterConst.PAGE_PARAMS, pageParams);
mv.addObject(IUserCenterConst.CUSTOM_LOGIN_FORM, loginFormService.getActive());
mv.addObject("HomeServerUrl", ProjectConfigUtil.getText("HomeServerUrl"));

View File

@ -31,6 +31,10 @@ public interface IUserExpandDao {
void updateWxOfficialAccountOpenId(Map<String, Object> params);
void updateWxOpenIdAndUnionId(Map<String, Object> params);
void updateUserId(Map<String, Object> params);
UserExpandDTO get(Map<String, Object> params);
UserExpandPO getPO(Map<String, Object> params);

View File

@ -37,6 +37,7 @@ public class LoginPhoneConfig extends SecurityConfigurerAdapter<DefaultSecurityF
private ISmsService smsService;
@Autowired
private IUserService iUserService;
@Override
public void configure(HttpSecurity http) throws Exception {
super.configure(http);

View File

@ -19,9 +19,9 @@ import java.io.IOException;
public class LoginPhoneAuthFilter extends AbstractAuthenticationProcessingFilter {
private ISmsService smsService;
private final ISmsService smsService;
private IUserService iUserService;
private final IUserService iUserService;
public LoginPhoneAuthFilter(ISmsService smsService, IUserService iUserService) {
super(new AntPathRequestMatcher("/oauth/phone", "POST"));

View File

@ -17,10 +17,10 @@ import javax.servlet.http.HttpSession;
public class LoginPhoneAuthProvider implements AuthenticationProvider {
private static final Logger LOG = LoggerFactory.getLogger(LoginPhoneAuthProvider.class);
private UserDetailsService userDetailsService;
private UserLoginService userLoginService;
private ILoginHandlerService loginHandler;
private HttpSession httpSession;
private final UserDetailsService userDetailsService;
private final UserLoginService userLoginService;
private final ILoginHandlerService loginHandler;
private final HttpSession httpSession;
public LoginPhoneAuthProvider(UserDetailsService userDetailsService, UserLoginService userLoginService, ILoginHandlerService loginHandler, HttpSession httpSession) {
this.userDetailsService = userDetailsService;

View File

@ -0,0 +1,56 @@
package cn.com.tenlion.operator.login.temporary;
import cn.com.tenlion.operator.login.phone.auth.LoginPhoneAuthFilter;
import cn.com.tenlion.operator.login.phone.auth.LoginPhoneAuthProvider;
import cn.com.tenlion.operator.login.temporary.auth.LoginTemporaryAuthFilter;
import cn.com.tenlion.operator.service.login.temporary.LoginTemporaryService;
import ink.wgink.interfaces.config.ICustomUserSecurityConfig;
import ink.wgink.interfaces.expand.login.ILoginHandlerService;
import ink.wgink.login.base.handler.LoginFailureHandler;
import ink.wgink.login.base.service.user.UserLoginService;
import ink.wgink.module.sms.service.sms.ISmsService;
import ink.wgink.properties.BaseProperties;
import ink.wgink.service.user.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpSession;
@Component
public class LoginTemporaryConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> implements ICustomUserSecurityConfig {
@Autowired
private BaseProperties baseProperties;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private UserLoginService userLoginService;
@Autowired
private LoginTemporaryService loginTemporaryService;
@Autowired
private HttpSession httpSession;
@Autowired(required = false)
private ILoginHandlerService loginHandler;
@Override
public void configure(HttpSecurity http) throws Exception {
super.configure(http);
LoginTemporaryAuthFilter loginTemporaryAuthFilter = new LoginTemporaryAuthFilter(loginTemporaryService);
loginTemporaryAuthFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));
loginTemporaryAuthFilter.setAuthenticationFailureHandler(new LoginFailureHandler(baseProperties.getLoginFailure()));
LoginPhoneAuthProvider loginPhoneAuthProvider = new LoginPhoneAuthProvider(userDetailsService,
userLoginService,
loginHandler,
httpSession
);
http.authenticationProvider(loginPhoneAuthProvider).addFilterBefore(loginTemporaryAuthFilter, UsernamePasswordAuthenticationFilter.class);
}
}

View File

@ -0,0 +1,43 @@
package cn.com.tenlion.operator.login.temporary.auth;
import ch.qos.logback.core.util.StringCollectionUtil;
import cn.com.tenlion.operator.login.phone.auth.LoginPhoneAuthToken;
import cn.com.tenlion.operator.service.login.temporary.LoginTemporaryService;
import ink.wgink.login.base.exceptions.UserAuthenticationException;
import ink.wgink.module.sms.service.sms.ISmsService;
import ink.wgink.service.user.service.IUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginTemporaryAuthFilter extends AbstractAuthenticationProcessingFilter {
private final LoginTemporaryService loginTemporaryService;
public LoginTemporaryAuthFilter(LoginTemporaryService loginTemporaryService) {
super(new AntPathRequestMatcher("/oauth/temporary", "POST"));
this.loginTemporaryService = loginTemporaryService;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
String phone = request.getParameter("username").trim();
String password = loginTemporaryService.getPassword();
if (StringUtils.isBlank(phone)) {
throw new UserAuthenticationException("手机号不能为空");
}
if (StringUtils.isBlank(password)) {
throw new UserAuthenticationException("密码已过期,请重新获取");
}
LoginPhoneAuthToken loginTemporaryAuthToken = new LoginPhoneAuthToken(phone, null);
loginTemporaryAuthToken.setDetails(authenticationDetailsSource.buildDetails(request));
return this.getAuthenticationManager().authenticate(loginTemporaryAuthToken);
}
}

View File

@ -0,0 +1,70 @@
package cn.com.tenlion.operator.login.wx.oauth2;
import cn.com.tenlion.operator.login.wx.oauth2.auth.LoginWxOauth2AuthFilter;
import cn.com.tenlion.operator.login.wx.oauth2.auth.LoginWxOauth2AuthProvider;
import cn.com.tenlion.operator.properties.WxOauth2Properties;
import cn.com.tenlion.operator.remote.wx.IWxOauth2RemoteService;
import cn.com.tenlion.operator.service.user.expand.UserExpandServiceImpl;
import ink.wgink.interfaces.config.ICustomUserSecurityConfig;
import ink.wgink.interfaces.expand.login.ILoginHandlerService;
import ink.wgink.login.base.handler.LoginFailureHandler;
import ink.wgink.login.base.service.user.UserLoginService;
import ink.wgink.properties.BaseProperties;
import ink.wgink.register.base.service.IRegisterService;
import ink.wgink.service.user.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpSession;
@Component
public class LoginWxOauth2Config extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> implements ICustomUserSecurityConfig {
@Autowired
private BaseProperties baseProperties;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private UserLoginService userLoginService;
@Autowired(required = false)
private ILoginHandlerService loginHandler;
@Autowired
private HttpSession httpSession;
@Autowired
private IWxOauth2RemoteService wxOauth2RemoteService;
@Autowired
private WxOauth2Properties wxOauth2Properties;
@Autowired
private IUserService userService;
@Autowired
private UserExpandServiceImpl userExpandService;
@Autowired
private IRegisterService registerService;
@Override
public void configure(HttpSecurity http) throws Exception {
super.configure(http);
LoginWxOauth2AuthFilter loginWxOauth2AuthFilter = new LoginWxOauth2AuthFilter(wxOauth2RemoteService, wxOauth2Properties);
loginWxOauth2AuthFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));
loginWxOauth2AuthFilter.setAuthenticationFailureHandler(new LoginFailureHandler(baseProperties.getLoginFailure()));
LoginWxOauth2AuthProvider loginWxOauth2AuthProvider = new LoginWxOauth2AuthProvider(
userService,
userExpandService,
registerService,
userDetailsService,
userLoginService,
loginHandler,
httpSession
);
http.authenticationProvider(loginWxOauth2AuthProvider).addFilterBefore(loginWxOauth2AuthFilter, UsernamePasswordAuthenticationFilter.class);
}
}

View File

@ -0,0 +1,50 @@
package cn.com.tenlion.operator.login.wx.oauth2.auth;
import cn.com.tenlion.operator.properties.WxOauth2Properties;
import cn.com.tenlion.operator.remote.wx.IWxOauth2RemoteService;
import cn.com.tenlion.operator.remote.wx.entity.WxOauth2AccessToken;
import com.sun.xml.internal.bind.v2.runtime.output.SAXOutput;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginWxOauth2AuthFilter extends AbstractAuthenticationProcessingFilter {
private final IWxOauth2RemoteService wxOauth2RemoteService;
private final WxOauth2Properties wxOauth2Properties;
public LoginWxOauth2AuthFilter(IWxOauth2RemoteService wxOauth2RemoteService, WxOauth2Properties wxOauth2Properties) {
super(new AntPathRequestMatcher("/oauth/wx/qrcode", "GET"));
this.wxOauth2RemoteService = wxOauth2RemoteService;
this.wxOauth2Properties = wxOauth2Properties;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
String code = request.getParameter("code").trim();
if (StringUtils.isBlank(code)) {
throw new BadCredentialsException("code 不存在");
}
WxOauth2AccessToken accessToken = wxOauth2RemoteService.getAccessToken(IWxOauth2RemoteService.WX_API_BASE_URL,
wxOauth2Properties.getAppid(),
wxOauth2Properties.getAppsecret(),
code,
"authorization_code");
if (accessToken.getErrcode() != 0) {
throw new BadCredentialsException(accessToken.getErrmsg());
}
LoginWxOauth2AuthToken loginWxOauth2AuthToken = new LoginWxOauth2AuthToken(accessToken.getOpenid(), accessToken);
loginWxOauth2AuthToken.setDetails(authenticationDetailsSource.buildDetails(request));
return this.getAuthenticationManager().authenticate(loginWxOauth2AuthToken);
}
}

View File

@ -0,0 +1,125 @@
package cn.com.tenlion.operator.login.wx.oauth2.auth;
import cn.com.tenlion.operator.pojo.pos.user.expand.UserExpandPO;
import cn.com.tenlion.operator.remote.wx.entity.WxOauth2AccessToken;
import cn.com.tenlion.operator.service.user.expand.UserExpandServiceImpl;
import ink.wgink.common.manager.env.EnvManager;
import ink.wgink.interfaces.expand.login.ILoginHandlerService;
import ink.wgink.login.base.consts.IUserCenterConst;
import ink.wgink.login.base.enums.LoginTypeEnum;
import ink.wgink.login.base.exceptions.UserAuthenticationException;
import ink.wgink.login.base.service.user.UserLoginService;
import ink.wgink.pojo.bos.LoginUser;
import ink.wgink.register.base.pojo.vos.RegisterDefaultVO;
import ink.wgink.register.base.service.IRegisterService;
import ink.wgink.service.user.enums.UserStateEnum;
import ink.wgink.service.user.pojo.pos.UserPO;
import ink.wgink.service.user.service.IUserService;
import ink.wgink.util.UUIDUtil;
import ink.wgink.util.string.WStringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
public class LoginWxOauth2AuthProvider implements AuthenticationProvider {
private static final Logger LOG = LoggerFactory.getLogger(LoginWxOauth2AuthProvider.class);
private final IUserService userService;
private final UserExpandServiceImpl userExpandService;
private final IRegisterService registerService;
private final UserDetailsService userDetailsService;
private final UserLoginService userLoginService;
private final ILoginHandlerService loginHandler;
private final HttpSession httpSession;
public LoginWxOauth2AuthProvider(IUserService userService,
UserExpandServiceImpl userExpandService,
IRegisterService registerService,
UserDetailsService userDetailsService,
UserLoginService userLoginService,
ILoginHandlerService loginHandler,
HttpSession httpSession) {
this.userService = userService;
this.userExpandService = userExpandService;
this.registerService = registerService;
this.userDetailsService = userDetailsService;
this.userLoginService = userLoginService;
this.loginHandler = loginHandler;
this.httpSession = httpSession;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
LoginWxOauth2AuthToken loginWxOauth2AuthToken = (LoginWxOauth2AuthToken) authentication;
String openid = authentication.getPrincipal().toString();
WxOauth2AccessToken wxOauth2AccessToken = (WxOauth2AccessToken) authentication.getCredentials();
try {
UserExpandPO userExpandPO = userExpandService.getPoByWxOpenid(openid);
String username;
if (userExpandPO == null) {
// 创建用户
RegisterDefaultVO registerDefaultVO = new RegisterDefaultVO();
registerDefaultVO.setUsername(openid);
registerDefaultVO.setPassword(WStringUtil.randomSubStr(UUIDUtil.get32UUID(), 8));
registerService.registerDefault(registerDefaultVO, new HashMap<String, Object>() {{
put("userRole", EnvManager.value("NORMAL_USER_ROLE_ID"));
put("wxOpenId", openid);
put("wxUnionId", wxOauth2AccessToken.getUnionid());
}});
username = openid;
} else {
UserPO userPO = userService.getPO(userExpandPO.getUserId());
username = userPO.getUserName();
if (userPO.getUserState() == 1) {
userService.updateUserState(userPO.getUserId(), UserStateEnum.NORMAL);
}
}
httpSession.setAttribute(IUserCenterConst.LOGIN_USERNAME, username);
LoginUser loginUser = (LoginUser) userDetailsService.loadUserByUsername(username);
userLoginService.setLoginUserInfo(loginUser);
if (loginUser.getAuthorities().isEmpty()) {
throw new UserAuthenticationException(loginUser.getUsername() + "用户无任何角色");
}
// 登录逻辑处理
loginHandler(loginUser);
// 清空session中的错误信息
httpSession.removeAttribute(IUserCenterConst.ERROR_MESSAGE);
httpSession.removeAttribute(IUserCenterConst.LOGIN_USERNAME);
// 更新登录信息
userLoginService.updateUserLoginInfo(loginUser.getUserId(), loginUser.getUserName(), LoginTypeEnum.USERNAME_AND_PASSWORD.getValue());
LoginWxOauth2AuthToken loginPhoneAuthTokenResult = new LoginWxOauth2AuthToken(loginUser, null, loginUser.getAuthorities());
loginPhoneAuthTokenResult.setDetails(loginWxOauth2AuthToken.getDetails());
return loginPhoneAuthTokenResult;
} catch (Exception e) {
LOG.error(e.getMessage(), e);
throw new BadCredentialsException("微信登录失败");
}
}
@Override
public boolean supports(Class<?> authentication) {
return LoginWxOauth2AuthToken.class.isAssignableFrom(authentication);
}
/**
* 登录处理
*
* @param loginUser
*/
private void loginHandler(LoginUser loginUser) {
if (loginHandler != null) {
try {
loginHandler.handle(loginUser);
} catch (Exception e) {
LOG.error(e.getMessage(), e);
throw new UserAuthenticationException("登录异常");
}
}
}
}

View File

@ -0,0 +1,36 @@
package cn.com.tenlion.operator.login.wx.oauth2.auth;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import java.util.Collection;
public class LoginWxOauth2AuthToken extends AbstractAuthenticationToken {
private final Object principal;
private final Object credentials;
public LoginWxOauth2AuthToken(Object principal, Object credentials) {
super(null);
this.principal = principal;
this.credentials = credentials;
setAuthenticated(false);
}
public LoginWxOauth2AuthToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
this.credentials = credentials;
setAuthenticated(true);
}
@Override
public Object getCredentials() {
return credentials;
}
@Override
public Object getPrincipal() {
return principal;
}
}

View File

@ -0,0 +1,63 @@
package cn.com.tenlion.operator.login.wx.update.phone;
import cn.com.tenlion.operator.login.wx.update.phone.auth.LoginWxUpdatePhoneAuthFilter;
import cn.com.tenlion.operator.login.wx.update.phone.auth.LoginWxUpdatePhoneAuthProvider;
import cn.com.tenlion.operator.service.user.expand.UserExpandServiceImpl;
import ink.wgink.interfaces.config.ICustomUserSecurityConfig;
import ink.wgink.interfaces.expand.login.ILoginHandlerService;
import ink.wgink.login.base.handler.LoginFailureHandler;
import ink.wgink.login.base.service.user.UserLoginService;
import ink.wgink.module.sms.service.sms.ISmsService;
import ink.wgink.properties.BaseProperties;
import ink.wgink.service.user.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpSession;
@Component
public class LoginWxUpdatePhoneConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> implements ICustomUserSecurityConfig {
@Autowired
private ISmsService smsService;
@Autowired
private BaseProperties baseProperties;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private UserLoginService userLoginService;
@Autowired(required = false)
private ILoginHandlerService loginHandler;
@Autowired
private IUserService userService;
@Autowired
private UserExpandServiceImpl userExpandService;
@Autowired
private HttpSession httpSession;
@Override
public void configure(HttpSecurity http) throws Exception {
super.configure(http);
LoginWxUpdatePhoneAuthFilter loginWxUpdatePhoneAuthFilter = new LoginWxUpdatePhoneAuthFilter(smsService);
loginWxUpdatePhoneAuthFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));
loginWxUpdatePhoneAuthFilter.setAuthenticationFailureHandler(new LoginFailureHandler(baseProperties.getLoginFailure()));
LoginWxUpdatePhoneAuthProvider loginWxUpdatePhoneAuthProvider = new LoginWxUpdatePhoneAuthProvider(
userService,
userExpandService,
userDetailsService,
userLoginService,
loginHandler,
httpSession
);
http.authenticationProvider(loginWxUpdatePhoneAuthProvider).addFilterBefore(loginWxUpdatePhoneAuthFilter, UsernamePasswordAuthenticationFilter.class);
}
}

View File

@ -0,0 +1,94 @@
package cn.com.tenlion.operator.login.wx.update.phone.auth;
import ink.wgink.exceptions.ParamsException;
import ink.wgink.login.base.exceptions.UserAuthenticationException;
import ink.wgink.module.sms.service.sms.ISmsService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginWxUpdatePhoneAuthFilter extends AbstractAuthenticationProcessingFilter {
private final ISmsService smsService;
public LoginWxUpdatePhoneAuthFilter(ISmsService smsService) {
super(new AntPathRequestMatcher("/oauth/wx/update/phone", "POST"));
this.smsService = smsService;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
PhoneUpdateVO phoneUpdateVO = getPhoneUpdateVO(request);
if (StringUtils.isBlank(phoneUpdateVO.getUserId())) {
throw new BadCredentialsException("userId不能为空");
}
if (StringUtils.isBlank(phoneUpdateVO.getPhone())) {
throw new BadCredentialsException("更新手机号不能为空");
}
if (StringUtils.isBlank(phoneUpdateVO.getSmsCode())) {
throw new BadCredentialsException("手机验证码不能为空");
}
try {
smsService.checkVerifyCode(phoneUpdateVO.getPhone(), phoneUpdateVO.getSmsCode());
} catch (ParamsException e) {
throw new UserAuthenticationException(e.getMessage());
}
LoginWxUpdatePhoneAuthToken loginWxUpdatePhoneAuthToken = new LoginWxUpdatePhoneAuthToken(phoneUpdateVO.getUserId(), phoneUpdateVO);
loginWxUpdatePhoneAuthToken.setDetails(authenticationDetailsSource.buildDetails(request));
return this.getAuthenticationManager().authenticate(loginWxUpdatePhoneAuthToken);
}
private PhoneUpdateVO getPhoneUpdateVO(HttpServletRequest request) {
String userId = request.getParameter("userId");
String phone = request.getParameter("phone");
String smsCode = request.getParameter("smsCode");
return new PhoneUpdateVO(userId, phone, smsCode);
}
public static class PhoneUpdateVO {
private String userId;
private String phone;
private String smsCode;
public PhoneUpdateVO(String userId, String phone, String smsCode) {
this.userId = userId;
this.phone = phone;
this.smsCode = smsCode;
}
public String getUserId() {
return userId == null ? "" : userId.trim();
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getPhone() {
return phone == null ? "" : phone.trim();
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getSmsCode() {
return smsCode == null ? "" : smsCode.trim();
}
public void setSmsCode(String smsCode) {
this.smsCode = smsCode;
}
}
}

View File

@ -0,0 +1,126 @@
package cn.com.tenlion.operator.login.wx.update.phone.auth;
import cn.com.tenlion.operator.pojo.pos.user.expand.UserExpandPO;
import cn.com.tenlion.operator.service.user.expand.UserExpandServiceImpl;
import ink.wgink.interfaces.expand.login.ILoginHandlerService;
import ink.wgink.login.base.consts.IUserCenterConst;
import ink.wgink.login.base.enums.LoginTypeEnum;
import ink.wgink.login.base.exceptions.UserAuthenticationException;
import ink.wgink.login.base.service.user.UserLoginService;
import ink.wgink.pojo.bos.LoginUser;
import ink.wgink.service.user.pojo.pos.UserPO;
import ink.wgink.service.user.pojo.vos.UpdateUsernameVO;
import ink.wgink.service.user.service.IUserService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import javax.servlet.http.HttpSession;
import java.util.Collections;
public class LoginWxUpdatePhoneAuthProvider implements AuthenticationProvider {
private static final Logger LOG = LoggerFactory.getLogger(LoginWxUpdatePhoneAuthProvider.class);
private final IUserService userService;
private final UserExpandServiceImpl userExpandService;
private final UserDetailsService userDetailsService;
private final UserLoginService userLoginService;
private final ILoginHandlerService loginHandler;
private final HttpSession httpSession;
public LoginWxUpdatePhoneAuthProvider(IUserService userService,
UserExpandServiceImpl userExpandService,
UserDetailsService userDetailsService,
UserLoginService userLoginService,
ILoginHandlerService loginHandler,
HttpSession httpSession) {
this.userService = userService;
this.userExpandService = userExpandService;
this.userDetailsService = userDetailsService;
this.userLoginService = userLoginService;
this.loginHandler = loginHandler;
this.httpSession = httpSession;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
LoginWxUpdatePhoneAuthToken loginWxUpdatePhoneAuthToken = (LoginWxUpdatePhoneAuthToken) authentication;
String userId = (String) authentication.getPrincipal();
LoginWxUpdatePhoneAuthFilter.PhoneUpdateVO phoneUpdateVO = (LoginWxUpdatePhoneAuthFilter.PhoneUpdateVO) authentication.getCredentials();
UserPO userPO = userService.getPO(userId);
if (userPO == null) {
throw new BadCredentialsException("用户不存在");
}
String username = userPO.getUserUsername();
UserPO existUserPO = userService.getPOByUsername(phoneUpdateVO.getPhone());
if (existUserPO == null) {
LOG.debug("更新的手机号用户不存在");
UpdateUsernameVO updateUsernameVO = new UpdateUsernameVO();
updateUsernameVO.setUsername(phoneUpdateVO.getPhone());
updateUsernameVO.setUpdateReason("用户自行修改用户名为手机号");
userService.updateUsername(userPO.getUserId(), updateUsernameVO, false);
} else {
LOG.debug("更新的手机号用户已存在,绑定拓展信息");
UserExpandPO existUserExpandPO = userExpandService.getPO(existUserPO.getUserId());
if (existUserExpandPO == null) {
LOG.debug("更新的手机号用户拓展信息不存在,修改现在的手机号用户拓展信息");
userExpandService.updateUserId(userId, existUserPO.getUserId());
} else {
if (!StringUtils.isBlank(existUserExpandPO.getWxOpenId())) {
throw new BadCredentialsException("手机号已经被绑定");
}
UserExpandPO userExpandPO = userExpandService.getPO(userId);
LOG.debug("更新的手机号用户拓展信息已存在绑定wxOpenid和wxUnionid");
userExpandService.updateWxOpenIdAndUnionId(existUserExpandPO.getUserId(), userExpandPO.getWxOpenId(), userExpandPO.getWxUnionId());
LOG.debug("删除原有账号拓展信息");
userExpandService.deleteByUserIds(Collections.singletonList(userExpandPO.getUserId()));
}
LOG.debug("删除原有账号");
userService.delete(Collections.singletonList(userId));
username = existUserPO.getUserUsername();
}
LOG.debug("登录");
httpSession.setAttribute(IUserCenterConst.LOGIN_USERNAME, username);
LoginUser loginUser = (LoginUser) userDetailsService.loadUserByUsername(username);
userLoginService.setLoginUserInfo(loginUser);
if (loginUser.getAuthorities().isEmpty()) {
throw new UserAuthenticationException(loginUser.getUsername() + "用户无任何角色");
}
// 登录逻辑处理
loginHandler(loginUser);
// 清空session中的错误信息
httpSession.removeAttribute(IUserCenterConst.ERROR_MESSAGE);
httpSession.removeAttribute(IUserCenterConst.LOGIN_USERNAME);
// 更新登录信息
userLoginService.updateUserLoginInfo(loginUser.getUserId(), loginUser.getUserName(), LoginTypeEnum.USERNAME_AND_PASSWORD.getValue());
LoginWxUpdatePhoneAuthToken loginPhoneAuthTokenResult = new LoginWxUpdatePhoneAuthToken(loginUser, null, loginUser.getAuthorities());
loginPhoneAuthTokenResult.setDetails(loginWxUpdatePhoneAuthToken.getDetails());
return loginPhoneAuthTokenResult;
}
@Override
public boolean supports(Class<?> authentication) {
return LoginWxUpdatePhoneAuthToken.class.isAssignableFrom(authentication);
}
/**
* 登录处理
*
* @param loginUser
*/
private void loginHandler(LoginUser loginUser) {
if (loginHandler != null) {
try {
loginHandler.handle(loginUser);
} catch (Exception e) {
LOG.error(e.getMessage(), e);
throw new UserAuthenticationException("登录异常");
}
}
}
}

View File

@ -0,0 +1,36 @@
package cn.com.tenlion.operator.login.wx.update.phone.auth;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import java.util.Collection;
public class LoginWxUpdatePhoneAuthToken extends AbstractAuthenticationToken {
private final Object principal;
private final Object credentials;
public LoginWxUpdatePhoneAuthToken(Object principal, Object credentials) {
super(null);
this.principal = principal;
this.credentials = credentials;
setAuthenticated(false);
}
public LoginWxUpdatePhoneAuthToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
this.credentials = credentials;
setAuthenticated(true);
}
@Override
public Object getCredentials() {
return credentials;
}
@Override
public Object getPrincipal() {
return principal;
}
}

View File

@ -0,0 +1,41 @@
package cn.com.tenlion.operator.pojo.dtos.accountrecharge;
public class AccountRechargeWxPrepayDTO {
private String prepayId;
private String paySign;
private long timeStamp;
private String nonceStr;
public String getPrepayId() {
return prepayId == null ? "" : prepayId.trim();
}
public void setPrepayId(String prepayId) {
this.prepayId = prepayId;
}
public String getPaySign() {
return paySign == null ? "" : paySign.trim();
}
public void setPaySign(String paySign) {
this.paySign = paySign;
}
public long getTimeStamp() {
return timeStamp;
}
public void setTimeStamp(long timeStamp) {
this.timeStamp = timeStamp;
}
public String getNonceStr() {
return nonceStr == null ? "" : nonceStr.trim();
}
public void setNonceStr(String nonceStr) {
this.nonceStr = nonceStr;
}
}

View File

@ -1,7 +1,5 @@
package cn.com.tenlion.operator.pojo.dtos.user.expand;
import ink.wgink.annotation.CheckEmptyAnnotation;
import ink.wgink.annotation.CheckNumberAnnotation;
import ink.wgink.pojo.dtos.user.UserDTO;
/**
@ -46,6 +44,8 @@ public class UserExpandDTO extends UserDTO {
private String mainUserId;
private String wxMiniappOpenId;
private String wxOfficialAccountOpenId;
private String wxOpenId;
private String wxUnionId;
public String getSubUserIds() {
return subUserIds == null ? "" : subUserIds.trim();
@ -262,4 +262,20 @@ public class UserExpandDTO extends UserDTO {
public void setWxOfficialAccountOpenId(String wxOfficialAccountOpenId) {
this.wxOfficialAccountOpenId = wxOfficialAccountOpenId;
}
public String getWxOpenId() {
return wxOpenId == null ? "" : wxOpenId.trim();
}
public void setWxOpenId(String wxOpenId) {
this.wxOpenId = wxOpenId;
}
public String getWxUnionId() {
return wxUnionId == null ? "" : wxUnionId.trim();
}
public void setWxUnionId(String wxUnionId) {
this.wxUnionId = wxUnionId;
}
}

View File

@ -39,6 +39,12 @@ public class UserExpandPO {
private String mainUserId;
private String wxMiniappOpenId;
private String wxOfficialAccountOpenId;
private String wxOpenId;
private String wxUnionId;
/**
* 是否更新用户名为手机号该字段在微信扫码登录后用户名不是手机号时有效-1表示无效
*/
private Integer isUpdateWxUsernamePhone;
public String getUserId() {
return userId == null ? "" : userId.trim();
@ -263,4 +269,28 @@ public class UserExpandPO {
public void setWxOfficialAccountOpenId(String wxOfficialAccountOpenId) {
this.wxOfficialAccountOpenId = wxOfficialAccountOpenId;
}
public String getWxOpenId() {
return wxOpenId == null ? "" : wxOpenId.trim();
}
public void setWxOpenId(String wxOpenId) {
this.wxOpenId = wxOpenId;
}
public String getWxUnionId() {
return wxUnionId == null ? "" : wxUnionId.trim();
}
public void setWxUnionId(String wxUnionId) {
this.wxUnionId = wxUnionId;
}
public Integer getIsUpdateWxUsernamePhone() {
return isUpdateWxUsernamePhone == null ? -1 : isUpdateWxUsernamePhone;
}
public void setIsUpdateWxUsernamePhone(Integer isUpdateWxUsernamePhone) {
this.isUpdateWxUsernamePhone = isUpdateWxUsernamePhone;
}
}

View File

@ -50,6 +50,8 @@ public class UserExpandVO {
* 子账号关联的主账号ID
*/
private String mainUserId;
private String wxOpenId;
private String wxUnionId;
public String getSubUserIds() {
return subUserIds == null ? "" : subUserIds.trim();
@ -210,4 +212,20 @@ public class UserExpandVO {
public void setWxOfficialAccountOpenId(String wxOfficialAccountOpenId) {
this.wxOfficialAccountOpenId = wxOfficialAccountOpenId;
}
public String getWxOpenId() {
return wxOpenId == null ? "" : wxOpenId.trim();
}
public void setWxOpenId(String wxOpenId) {
this.wxOpenId = wxOpenId;
}
public String getWxUnionId() {
return wxUnionId == null ? "" : wxUnionId.trim();
}
public void setWxUnionId(String wxUnionId) {
this.wxUnionId = wxUnionId;
}
}

View File

@ -0,0 +1,38 @@
package cn.com.tenlion.operator.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "wx-oauth2")
public class WxOauth2Properties {
private String appid;
private String appsecret;
private String redirectUri;
public String getAppid() {
return appid == null ? "" : appid.trim();
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getAppsecret() {
return appsecret == null ? "" : appsecret.trim();
}
public void setAppsecret(String appsecret) {
this.appsecret = appsecret;
}
public String getRedirectUri() {
return redirectUri == null ? "" : redirectUri.trim();
}
public void setRedirectUri(String redirectUri) {
this.redirectUri = redirectUri;
}
}

View File

@ -0,0 +1,28 @@
package cn.com.tenlion.operator.remote.wx;
import cn.com.tenlion.operator.remote.wx.entity.WxOauth2AccessToken;
import cn.com.tenlion.operator.remote.wx.entity.WxUserinfo;
import ink.wgink.annotation.rpc.rest.RemoteService;
import ink.wgink.annotation.rpc.rest.method.RemoteGetMethod;
import ink.wgink.annotation.rpc.rest.params.RemoteQueryParams;
import ink.wgink.annotation.rpc.rest.params.RemoteServerParams;
@RemoteService
public interface IWxOauth2RemoteService {
String WX_API_BASE_URL = "https://api.weixin.qq.com";
@RemoteGetMethod("/sns/oauth2/access_token")
WxOauth2AccessToken getAccessToken(@RemoteServerParams String server,
@RemoteQueryParams("appid") String appid,
@RemoteQueryParams("secret") String appSecret,
@RemoteQueryParams("code") String code,
@RemoteQueryParams("grant_type") String grant_type);
@RemoteGetMethod("/sns/userinfo")
WxUserinfo getUserinfo(@RemoteServerParams String server,
@RemoteQueryParams("access_token") String accessToken,
@RemoteQueryParams("openid") String openid,
@RemoteQueryParams("lang") String lang);
}

View File

@ -0,0 +1,59 @@
package cn.com.tenlion.operator.remote.wx.entity;
public class WxOauth2AccessToken extends WxAccessToken {
private String refresh_token;
private String openid;
private String scope;
private String unionid;
private Integer errcode;
private String errmsg;
public String getRefresh_token() {
return refresh_token == null ? "" : refresh_token.trim();
}
public void setRefresh_token(String refresh_token) {
this.refresh_token = refresh_token;
}
public String getOpenid() {
return openid == null ? "" : openid.trim();
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getScope() {
return scope == null ? "" : scope.trim();
}
public void setScope(String scope) {
this.scope = scope;
}
public String getUnionid() {
return unionid == null ? "" : unionid.trim();
}
public void setUnionid(String unionid) {
this.unionid = unionid;
}
public Integer getErrcode() {
return errcode == null ? 0 : errcode;
}
public void setErrcode(Integer errcode) {
this.errcode = errcode;
}
public String getErrmsg() {
return errmsg == null ? "" : errmsg.trim();
}
public void setErrmsg(String errmsg) {
this.errmsg = errmsg;
}
}

View File

@ -0,0 +1,77 @@
package cn.com.tenlion.operator.remote.wx.entity;
public class WxUserinfo extends WxResult {
private String openid;
private String nickname;
private Integer sex;
private String province;
private String city;
private String country;
private String headimgurl;
private String unionid;
public String getOpenid() {
return openid == null ? "" : openid.trim();
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getNickname() {
return nickname == null ? "" : nickname.trim();
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public Integer getSex() {
return sex == null ? 0 : sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public String getProvince() {
return province == null ? "" : province.trim();
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city == null ? "" : city.trim();
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country == null ? "" : country.trim();
}
public void setCountry(String country) {
this.country = country;
}
public String getHeadimgurl() {
return headimgurl == null ? "" : headimgurl.trim();
}
public void setHeadimgurl(String headimgurl) {
this.headimgurl = headimgurl;
}
public String getUnionid() {
return unionid == null ? "" : unionid.trim();
}
public void setUnionid(String unionid) {
this.unionid = unionid;
}
}

View File

@ -57,6 +57,8 @@ public class UserRegisterService implements IRegisterHandlerService, IRegisterWi
// 4.初始化用户拓展信息
UserExpandVO userExpandVO = new UserExpandVO();
userExpandVO.setWxMiniappOpenId(requestParams.get("wxMiniappOpenId") == null ? "" : requestParams.get("wxMiniappOpenId").toString());
userExpandVO.setWxOpenId(requestParams.get("wxOpenId") == null ? "" : requestParams.get("wxOpenId").toString());
userExpandVO.setWxUnionId(requestParams.get("wxUnionId") == null ? "" : requestParams.get("wxUnionId").toString());
userExpandService.saveOrUpdate(userId, userExpandVO);
}

View File

@ -3,6 +3,7 @@ package cn.com.tenlion.operator.service.accountrecharge;
import cn.com.tenlion.operator.enums.RechargeCheckEnum;
import cn.com.tenlion.operator.pojo.dtos.accountrecharge.AccountRechargePayDTO;
import cn.com.tenlion.operator.pojo.dtos.accountrecharge.AccountRechargePayResultDTO;
import cn.com.tenlion.operator.pojo.dtos.accountrecharge.AccountRechargeWxPrepayDTO;
import cn.com.tenlion.operator.pojo.vos.accountrecharge.AccountRechargeWxPrepayVO;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.result.SuccessResultList;
@ -192,7 +193,7 @@ public interface IAccountRechargeService {
AccountRechargePayDTO saveAccount(String thirdParty, AccountRechargeVO accountRechargeVO);
String saveWxPayPrepayId(AccountRechargeWxPrepayVO accountRechargeWxPrepayVO);
AccountRechargeWxPrepayDTO saveWxMiniappPayPrepayId(AccountRechargeWxPrepayVO accountRechargeWxPrepayVO);
void updateClose(String accountRechargeId);

View File

@ -8,6 +8,8 @@ import cn.com.tenlion.operator.pojo.dtos.account.AccountDTO;
import cn.com.tenlion.operator.pojo.dtos.accountbank.AccountBankDTO;
import cn.com.tenlion.operator.pojo.dtos.accountrecharge.AccountRechargePayDTO;
import cn.com.tenlion.operator.pojo.dtos.accountrecharge.AccountRechargePayResultDTO;
import cn.com.tenlion.operator.pojo.dtos.accountrecharge.AccountRechargeWxPrepayDTO;
import cn.com.tenlion.operator.pojo.pos.user.expand.UserExpandPO;
import cn.com.tenlion.operator.pojo.vos.accountitem.AccountItemVO;
import cn.com.tenlion.operator.pojo.vos.accountrecharge.AccountRechargeWxPrepayVO;
import cn.com.tenlion.operator.properties.SystemApiPathProperties;
@ -18,6 +20,7 @@ import cn.com.tenlion.operator.service.account.IAccountService;
import cn.com.tenlion.operator.service.accountbank.IAccountBankService;
import cn.com.tenlion.operator.service.accountitem.IAccountItemService;
import cn.com.tenlion.operator.service.sys.callback.SysCallbackService;
import cn.com.tenlion.operator.service.user.expand.UserExpandServiceImpl;
import cn.com.tenlion.operator.util.TenlionSMS;
import cn.com.tenlion.operator.util.UserUtil;
import cn.com.tenlion.operator.util.pay.ALiPay;
@ -88,6 +91,8 @@ public class AccountRechargeServiceImpl extends DefaultBaseService implements IA
private SystemApiPathProperties systemApiPathProperties;
@Autowired
private IOperatorPluginRemoteService operatorPluginRemoteService;
@Autowired
private UserExpandServiceImpl userExpandServiceImpl;
@Override
public void save(AccountRechargeVO accountRechargeVO) {
@ -190,7 +195,9 @@ public class AccountRechargeServiceImpl extends DefaultBaseService implements IA
// 2. 修改状态为2
updateCheck(po.getAccountRechargeId(), RechargeCheckEnum.RECHARGE_SUCCESS, rechargeRemark, accountItemId, "", DateUtil.getTime());
// 3.通知到账
sysCallbackService.save("项目充值到账", systemApiPathProperties.getCopyright() + "api/pay/recharge-success/user-id/" + po.getAccountId(), null);
JSONObject jsonObject = new JSONObject();
jsonObject.put("money", accountRechargeVO.getRechargeMoney());
sysCallbackService.save("项目充值到账", systemApiPathProperties.getCopyright() + "api/pay/recharge-success/user-id/" + po.getAccountId(), jsonObject);
}
}
@ -464,9 +471,15 @@ public class AccountRechargeServiceImpl extends DefaultBaseService implements IA
* @return
*/
@Override
public String saveWxPayPrepayId(AccountRechargeWxPrepayVO accountRechargeWxPrepayVO) {
public AccountRechargeWxPrepayDTO saveWxMiniappPayPrepayId(AccountRechargeWxPrepayVO accountRechargeWxPrepayVO) {
String userId = securityComponent.getCurrentUser().getUserId();
UserExpandPO po = userExpandServiceImpl.getPO(userId);
if (po == null) {
throw new SearchException("用户小程序信息不存在");
}
if (StringUtils.isBlank(po.getWxMiniappOpenId())) {
throw new SearchException("用户未绑定微信小程序");
}
AccountRechargeVO accountRechargeVO = new AccountRechargeVO();
accountRechargeVO.setUserId(userId);
accountRechargeVO.setThirdParty("微信");
@ -491,7 +504,7 @@ public class AccountRechargeServiceImpl extends DefaultBaseService implements IA
params.put("isDelete", 0);
accountRechargeDao.save(params);
savePackageInfo(accountRechargeId, accountRechargeVO);
return WXPay.createPrepayId(accountRechargeId, totalMoney, ProjectConfigUtil.getText("RechargePayTitle"));
return WXPay.createPrepayId(po.getWxMiniappOpenId(), accountRechargeId, totalMoney, ProjectConfigUtil.getText("RechargePayTitle"));
}
/**
@ -717,8 +730,11 @@ public class AccountRechargeServiceImpl extends DefaultBaseService implements IA
String accountItemId = iAccountItemService.saveReturnId(vo);
// 2. 修改状态为2
updateCheck(dto.getAccountRechargeId(), RechargeCheckEnum.RECHARGE_SUCCESS, "线上充值", accountItemId, orderId, successTime);
// 3. 调用第三方接口, 告知充值到账
sysCallbackService.save("项目充值到账", systemApiPathProperties.getCopyright() + "api/pay/recharge-success/user-id/" + dto.getAccountId(), null);
JSONObject jsonObject = new JSONObject();
jsonObject.put("money", dto.getRechargeMoney());
sysCallbackService.save("项目充值到账", systemApiPathProperties.getCopyright() + "api/pay/recharge-success/user-id/" + dto.getAccountId(), jsonObject);
}
}

View File

@ -24,7 +24,7 @@ public class LoginHandlerServiceImpl extends BaseAppSignService implements ILogi
@Override
public void handle(LoginUser loginUser) throws Exception {
userExpandService.updateRedis(loginUser.getUserId());
userExpandService.updateRedis(loginUser.getUserId(), loginUser);
UserPO userPO = new UserPO();
BeanUtils.copyProperties(loginUser, userPO);
accessTokenService.set2Redis(loginUser.getUserId(), getToken(userPO));

View File

@ -0,0 +1,31 @@
package cn.com.tenlion.operator.service.login.temporary;
import ink.wgink.util.string.WStringUtil;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
@Service
public class LoginTemporaryService {
private String password = "";
private long lastUpdateTime = 0;
public String generatePassword() {
String code = "" + System.currentTimeMillis();
this.lastUpdateTime = System.currentTimeMillis();
return WStringUtil.randomSubStr(code, 6);
}
public String getPassword() {
return password;
}
@Scheduled(fixedRate = 10 * 1000)
public void autoClearPassword() {
long now = System.currentTimeMillis();
if(now - lastUpdateTime > 180 * 1000) {
password = "";
}
}
}

View File

@ -19,6 +19,7 @@ import ink.wgink.interfaces.user.IUserExpandBaseService;
import ink.wgink.module.oauth2.manager.OAuth2ClientTokenManager;
import ink.wgink.module.sms.manager.VerifyCodeManager;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.bos.LoginUser;
import ink.wgink.pojo.dtos.role.RoleDTO;
import ink.wgink.pojo.dtos.user.UserDTO;
import ink.wgink.pojo.result.SuccessResultList;
@ -155,6 +156,18 @@ public class UserExpandServiceImpl extends DefaultBaseService implements IUserEx
updateRedis(po);
}
public void updateRedis(String userId, LoginUser loginUser) {
UserExpandPO po = getPO(userId);
if (po == null) {
po = new UserExpandPO();
po.setUserId(userId);
}
if (!StringUtils.isBlank(po.getWxOpenId())) {
po.setIsUpdateWxUsernamePhone(RegexUtil.isPhone(loginUser.getUsername()) ? 0 : 1);
}
updateRedis(po);
}
public void updateRedis(UserExpandPO userExpandPO) {
redisTemplate.opsForValue().set("user:expand:" + userExpandPO.getUserId(), JSON.toJSONString(userExpandPO));
}
@ -200,14 +213,14 @@ public class UserExpandServiceImpl extends DefaultBaseService implements IUserEx
UserExpandVO userExpandVO = new UserExpandVO();
userExpandVO.setPriceAdditionalPkg(userExpandDTO.getPriceAdditionalPkg() * 1.0);
userExpandVO.setPriceAdditionalVideoDemo(userExpandDTO.getPriceAdditionalVideoDemo() * 1.0);
userExpandVO.setPriceAdditionalUrgent(userExpandDTO.getPriceAdditionalUrgent() * 1.0);
userExpandVO.setPriceAll(userExpandDTO.getPriceAll() * 1.0);
userExpandVO.setPriceMaterial(userExpandDTO.getPriceMaterial() * 1.0);
userExpandVO.setPriceMaterialAgent(userExpandDTO.getPriceMaterialAgent() * 1.0);
userExpandVO.setPriceMaterialAgentUrgent(userExpandDTO.getPriceMaterialAgentUrgent() * 1.0);
userExpandVO.setIcPriceAll(userExpandDTO.getIcPriceAll() * 1.0);
userExpandVO.setIcPriceMaterial(userExpandDTO.getIcPriceMaterial() * 1.0);
userExpandVO.setPriceAdditionalVideoDemo(userExpandDTO.getPriceAdditionalVideoDemo() * 1.0);
userExpandVO.setPriceAdditionalUrgent(userExpandDTO.getPriceAdditionalUrgent() * 1.0);
userExpandVO.setPriceAll(userExpandDTO.getPriceAll() * 1.0);
userExpandVO.setPriceMaterial(userExpandDTO.getPriceMaterial() * 1.0);
userExpandVO.setPriceMaterialAgent(userExpandDTO.getPriceMaterialAgent() * 1.0);
userExpandVO.setPriceMaterialAgentUrgent(userExpandDTO.getPriceMaterialAgentUrgent() * 1.0);
userExpandVO.setIcPriceAll(userExpandDTO.getIcPriceAll() * 1.0);
userExpandVO.setIcPriceMaterial(userExpandDTO.getIcPriceMaterial() * 1.0);
userExpandVO.setIcRebateRatio(userExpandDTO.getIcRebateRatio());
Map<String, Object> params = HashMapUtil.beanToMap(userExpandVO);
params.put("userId", userId);
@ -432,4 +445,30 @@ public class UserExpandServiceImpl extends DefaultBaseService implements IUserEx
userExpandDao.updateWxMiniappOpenId(params);
updateRedis(userId);
}
public UserExpandPO getPoByWxOpenid(String openid) {
Map<String, Object> params = getHashMap(4);
params.put("wxOpenId", openid);
return userExpandDao.getPO(params);
}
public void updateWxOpenIdAndUnionId(String userId, String openid, String unionid) {
Map<String, Object> params = getHashMap(4);
params.put("wxOpenId", openid);
params.put("wxUnionId", unionid);
params.put("userId", userId);
userExpandDao.updateWxOpenIdAndUnionId(params);
updateRedis(userId);
}
public void updateUserId(String userId, String updateUserId) {
Map<String, Object> params = getHashMap(4);
params.put("userId", userId);
params.put("updateUserId", updateUserId);
userExpandDao.updateUserId(params);
}
public void deleteByUserIds(List<String> strings) {
}
}

View File

@ -4,6 +4,7 @@ import cn.com.tenlion.operator.pojo.dtos.user.wx.UserWxLoginDTO;
import cn.com.tenlion.operator.pojo.pos.user.expand.UserExpandPO;
import cn.com.tenlion.operator.properties.WxMiniappProperties;
import cn.com.tenlion.operator.remote.wx.IWxMiniappRemoteService;
import cn.com.tenlion.operator.remote.wx.IWxOauth2RemoteService;
import cn.com.tenlion.operator.remote.wx.entity.*;
import cn.com.tenlion.operator.service.accesstoken.AccessTokenService;
import cn.com.tenlion.operator.service.user.expand.UserExpandServiceImpl;
@ -33,7 +34,6 @@ public class UserWxMiniappService {
private static final Logger LOG = LoggerFactory.getLogger(UserWxMiniappService.class);
public static final String WX_API_BASE_URL = "https://api.weixin.qq.com";
private WxMiniappAccessToken miniappAccessToken = null;
@Autowired
private WxMiniappProperties wxMiniappProperties;
@ -64,7 +64,7 @@ public class UserWxMiniappService {
return;
}
LOG.debug("小程序 access_token 刷新");
WxAccessToken wxAccessToken = wxMiniappRemoteService.getAccessToken(WX_API_BASE_URL, new HashMap<String, Object>() {{
WxAccessToken wxAccessToken = wxMiniappRemoteService.getAccessToken(IWxOauth2RemoteService.WX_API_BASE_URL, new HashMap<String, Object>() {{
put("grant_type", "client_credential");
put("appid", wxMiniappProperties.getAppid());
put("secret", wxMiniappProperties.getAppsecret());
@ -82,7 +82,7 @@ public class UserWxMiniappService {
if (miniappAccessToken == null) {
throw new SystemException("系统错误");
}
WxLoginResult wxLoginResult = wxMiniappRemoteService.login(WX_API_BASE_URL, wxMiniappProperties.getAppid(), wxMiniappProperties.getAppsecret(), jsCode, "authorization_code");
WxLoginResult wxLoginResult = wxMiniappRemoteService.login(IWxOauth2RemoteService.WX_API_BASE_URL, wxMiniappProperties.getAppid(), wxMiniappProperties.getAppsecret(), jsCode, "authorization_code");
checkResult(wxLoginResult);
// 查看是否有账号
UserExpandPO userExpandPO = userExpandService.getPOByWxMiniappOpenId(wxLoginResult.getOpenid());
@ -161,7 +161,7 @@ public class UserWxMiniappService {
* @return
*/
private String getPhone(String code) {
WxPhoneResult wxPhoneResult = wxMiniappRemoteService.getPhone(WX_API_BASE_URL, miniappAccessToken.getWxAccessToken().getAccess_token(), new HashMap<String, Object>() {{
WxPhoneResult wxPhoneResult = wxMiniappRemoteService.getPhone(IWxOauth2RemoteService.WX_API_BASE_URL, miniappAccessToken.getWxAccessToken().getAccess_token(), new HashMap<String, Object>() {{
put("code", code);
}});
checkResult(wxPhoneResult);

View File

@ -1,11 +1,17 @@
package cn.com.tenlion.operator.util.pay;
import cn.com.tenlion.operator.pojo.dtos.accountrecharge.AccountRechargeWxPrepayDTO;
import cn.com.tenlion.operator.properties.WxMiniappProperties;
import cn.com.tenlion.operator.util.Sha256Util;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.payments.model.TransactionAmount;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.*;
import ink.wgink.exceptions.SaveException;
import ink.wgink.util.UUIDUtil;
import ink.wgink.util.string.WStringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -13,6 +19,8 @@ import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.awt.image.BufferedImage;
import java.io.*;
import java.security.*;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
@ -28,14 +36,19 @@ import java.time.format.DateTimeFormatter;
public class WXPay {
private static final Logger LOG = LoggerFactory.getLogger(WXPay.class);
private static final String HMAC_SHA256_ALGORITHM = "HmacSHA256";
@Autowired
private WxPayProperties wxPayProperties;
private static WxPayProperties wxPayStaticProperties;
@Autowired
private WxMiniappProperties wxMiniappProperties;
private static WxMiniappProperties wxMiniappStaticProperties;
@PostConstruct
public void init() {
wxPayStaticProperties = this.wxPayProperties;
wxMiniappStaticProperties = this.wxMiniappProperties;
}
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@ -128,7 +141,7 @@ public class WXPay {
* @param orderDescription
* @return
*/
public static String createPrepayId(String orderNo, Integer money, String orderDescription) {
public static AccountRechargeWxPrepayDTO createPrepayId(String openid, String orderNo, Integer money, String orderDescription) {
if (PayUtil.buiderMoney(money) > wxPayStaticProperties.getMaxMoney() || PayUtil.buiderMoney(money) < wxPayStaticProperties.getMinMoney()) {
throw new SaveException("支付金额超出范围");
}
@ -137,24 +150,58 @@ public class WXPay {
com.wechat.pay.java.service.payments.jsapi.model.Amount amount = new com.wechat.pay.java.service.payments.jsapi.model.Amount();
amount.setTotal(money); // 金额
request.setAmount(amount);
request.setAppid(wxPayStaticProperties.getAppId());
request.setAppid(wxMiniappStaticProperties.getAppid());
request.setMchid(wxPayStaticProperties.getMchId());
request.setTimeExpire(getTimeExpire());// 超时时间
request.setDescription(orderDescription);// 商品描述
String notifyUrl = wxPayStaticProperties.getNotifyUrl().replaceAll("\\{orderNo}", orderNo);
request.setNotifyUrl(notifyUrl);// 支付成功的回调地址
request.setOutTradeNo(orderNo);
Payer payer = new Payer();
payer.setOpenid(openid);
request.setPayer(payer);
// 调用下单方法得到应答
try {
// 发送请求
com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse response = service.prepay(request);
return response.getPrepayId();
String prepayId = response.getPrepayId();
long timeStamp = System.currentTimeMillis() / 1000;
String randomStr = WStringUtil.randomSubStr(UUIDUtil.get32UUID(), 10);
String paySign = createPaySign(prepayId, timeStamp, randomStr);
AccountRechargeWxPrepayDTO dto = new AccountRechargeWxPrepayDTO();
dto.setPrepayId(prepayId);
dto.setPaySign(paySign);
dto.setTimeStamp(timeStamp);
dto.setNonceStr(randomStr);
return dto;
} catch (Exception e) {
e.printStackTrace();
throw new SaveException("生成支付二维码失败");
throw new SaveException("生成预支付ID失败");
}
}
public static String createPaySign(String prepayId, long timeStamp, String randomStr) throws Exception {
StringBuilder sb = new StringBuilder();
sb.append(wxPayStaticProperties.getAppId()).append("\n");
sb.append(timeStamp).append("\n");
sb.append(randomStr).append("\n");
sb.append("prepay_id=").append(prepayId).append("\n");
PrivateKey privateKey = Sha256Util.loadPrivateKeyByPath(wxPayStaticProperties.getPrivateKeyPath());
return Sha256Util.sign(sb.toString(), privateKey);
}
public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeyException {
// BufferedReader bufferedReader = new BufferedReader(new FileReader(new File("D:\\WxCertUtils\\WXCertUtil\\cert\\1609461201_20240203_cert\\apiclient_key.pem")));
// StringBuffer sb = new StringBuffer();
// String line = null;
// while ((line = bufferedReader.readLine()) != null) {
// sb.append(line);
// }
// System.out.println(sb);
}
/**
* 获取二维码超时时间
*

View File

@ -1,6 +1,7 @@
server:
port: 8091
url: http://127.0.0.1:8091/operator/
# url: http://127.0.0.1:8091/operator/
url: http://121.36.71.250:58038/operator/
ip: 127.0.0.1
system-title: 运营平台
system-sub-title: 运营平台
@ -134,7 +135,7 @@ api-path:
user-center: http://127.0.0.1:8091/operator/
copyright: http://127.0.0.1:7025/copyright/
copyright-external: http://192.168.0.15:7025/copyright/
operator-plugin: http://192.168.0.115:8099/operator-plugin/
operator-plugin: http://192.168.0.15:8099/operator-plugin/
#
@ -204,4 +205,9 @@ app-token:
wx-miniapp:
appid: wxe17874894f7ff27b
appsecret: 0c2b1371e4fb32514030233da4ef094d
appsecret: 0c2b1371e4fb32514030233da4ef094d
wx-oauth2:
appid: wxb6296ee6223aafa0
appsecret: 09c423893098cd5566aead093ea5c25c
# redirect-uri: https://www.aimzhu.com/operator/oauth/wx/oauth2
redirect-uri: http://121.36.71.250:58038/operator/oauth/wx/qrcode

View File

@ -31,6 +31,8 @@
<result column="main_user_id" property="mainUserId"/>
<result column="wx_miniapp_open_id" property="wxMiniappOpenId"/>
<result column="wx_official_account_open_id" property="wxOfficialAccountOpenId"/>
<result column="wx_open_id" property="wxOpenId"/>
<result column="wx_union_id" property="wxUnionId"/>
</resultMap>
<resultMap id="userExpandPO" type="cn.com.tenlion.operator.pojo.pos.user.expand.UserExpandPO">
@ -62,6 +64,8 @@
<result column="main_user_id" property="mainUserId"/>
<result column="wx_miniapp_open_id" property="wxMiniappOpenId"/>
<result column="wx_official_account_open_id" property="wxOfficialAccountOpenId"/>
<result column="wx_open_id" property="wxOpenId"/>
<result column="wx_union_id" property="wxUnionId"/>
</resultMap>
<insert id="save" parameterType="map">
@ -89,7 +93,9 @@
sub_user_ids,
main_user_id,
wx_miniapp_open_id,
wx_official_account_open_id
wx_official_account_open_id,
wx_open_id,
wx_union_id
) VALUES (
#{userId},
#{priceAdditionalPkg},
@ -114,7 +120,9 @@
#{subUserIds},
#{mainUserId},
#{wxMiniappOpenId},
#{wxOfficialAccountOpenId}
#{wxOfficialAccountOpenId},
#{wxOpenId},
#{wxUnionId}
)
</insert>
@ -152,6 +160,12 @@
<if test="wxOfficialAccountOpenId != null">
wx_official_account_open_id = #{wxOfficialAccountOpenId},
</if>
<if test="wxOpenId != null">
wx_open_id = #{wxOpenId},
</if>
<if test="wxUnionId != null">
wx_union_id = #{wxUnionId},
</if>
price_additional_pkg = #{priceAdditionalPkg},
price_additional_video_demo = #{priceAdditionalVideoDemo},
price_additional_urgent = #{priceAdditionalUrgent},
@ -215,7 +229,6 @@
user_id = #{userId}
</update>
<update id="updateWxOfficialAccountOpenId">
UPDATE
sys_user_expand
@ -225,6 +238,25 @@
user_id = #{userId}
</update>
<update id="updateWxOpenIdAndUnionId">
UPDATE
sys_user_expand
SET
wx_open_id = #{wxOpenId},
wx_union_id = #{wxUnionId}
WHERE
user_id = #{userId}
</update>
<update id="updateUserId">
UPDATE
sys_user_expand
SET
user_id = #{updateUserId}
WHERE
user_id = #{userId}
</update>
<select id="get" parameterType="map" resultMap="userExpandDTO">
SELECT
price_additional_pkg,
@ -253,13 +285,21 @@
sub_user_ids,
main_user_id,
wx_miniapp_open_id,
wx_official_account_open_id
wx_official_account_open_id,
wx_open_id,
wx_union_id
FROM
sys_user_expand
WHERE
<if test="userId != null and userId != ''">
user_id = #{userId}
</if>
<if test="wxOpenId != null and wxOpenId != ''">
wx_open_id = #{wxOpenId}
</if>
<if test="wxUnionId != null and wxUnionId != ''">
wx_union_id = #{wxUnionId}
</if>
<if test="wxMiniappOpenId != null and wxMiniappOpenId != ''">
wx_miniapp_open_id = #{wxMiniappOpenId}
</if>
@ -297,7 +337,9 @@
sub_user_ids,
main_user_id,
wx_miniapp_open_id,
wx_official_account_open_id
wx_official_account_open_id,
wx_open_id,
wx_union_id
FROM
sys_user_expand
WHERE
@ -307,6 +349,12 @@
<if test="ic != null and ic != ''">
ic = #{ic}
</if>
<if test="wxOpenId != null and wxOpenId != ''">
wx_open_id = #{wxOpenId}
</if>
<if test="wxUnionId != null and wxUnionId != ''">
wx_union_id = #{wxUnionId}
</if>
<if test="wxMiniappOpenId != null and wxMiniappOpenId != ''">
wx_miniapp_open_id = #{wxMiniappOpenId}
</if>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1 @@
!function(e,t){e.WxLogin=function(n){var r="default";!0===n.self_redirect?r="true":!1===n.self_redirect&&(r="false");var o=t.createElement("iframe"),s="https://open.weixin.qq.com/connect/qrconnect?appid="+n.appid+"&scope="+n.scope+"&redirect_uri="+n.redirect_uri+"&state="+n.state+"&login_type=jssdk&self_redirect="+r+"&styletype="+(n.styletype||"")+"&sizetype="+(n.sizetype||"")+"&bgcolor="+(n.bgcolor||"")+"&rst="+(n.rst||"");s+=n.style?"&style="+n.style:"",s+=n.href?"&href="+n.href:"",s+="en"===n.lang?"&lang=en":"",s+=1===n.stylelite?"&stylelite=1":"",s+=0===n.fast_login?"&fast_login=0":"",o.src=s,o.frameBorder="0",o.allowTransparency="true",o.scrolling="no",o.width="300px",o.height="400px";var i=t.getElementById(n.id);if(i.innerHTML="",i.appendChild(o),e.addEventListener&&e.JSON&&n.onReady&&"function"==typeof n.onReady){var a=function(t){if("https://open.weixin.qq.com"===t.origin)try{var r=JSON.parse(t.data);if(r&&"status"===r.type){var o="wxReady"===r.status;o&&n.onReady(o)}}catch(t){e.console&&"function"==typeof e.console.log&&e.console.log("wxLogin postMessage error",t)}};e.addEventListener("message",a,!1);var l=!1;n.onCleanup=function(){!l&&e.removeEventListener&&(e.removeEventListener("message",a,!1),l=!0)}}}}(window,document);

View File

@ -85,7 +85,18 @@
font-size: 12px;
}
#app .container .footer .login-type {
text-align: right;
display: flex;
justify-content: space-between;
align-items: center;
}
#app .container .footer .login-type .third-login .logo {
width: 28px;
height: 28px;
display: block;
}
#app .container .footer .login-type .third-login .logo img {
width: 100%;
height: 100%;
}
#app .container .footer a {
color: #1e9fff;
@ -120,50 +131,68 @@
<div class="body">
<form id="loginForm" :action="activeAction" method="post" @submit.prevent="submitForm">
<input type="hidden" name="referToken" v-model="formData.referToken"/>
<div class="layui-form-item">
<label class="layadmin-user-login-icon layui-icon layui-icon-username" for="username"></label>
<input type="text" v-model="formData.username" id="username" name="username" lay-verify="username" placeholder="用户名 / 手机号" class="layui-input">
</div>
<div class="layui-form-item" v-if="loginType === 'username'">
<label class="layadmin-user-login-icon layui-icon layui-icon-password" for="password"></label>
<input type="password" v-model="formData.password" id="password" name="password" lay-verify="password" placeholder="密码" class="layui-input">
</div>
<div class="layui-form-item" v-if="loginType === 'username' && pageParams.verificationCode == 'true'" >
<!-- 验证码 -->
<div class="layui-row">
<div class="layui-col-xs7">
<label class="layadmin-user-login-icon layui-icon layui-icon-vercode" for="verificationCode"></label>
<input type="text" v-model="formData.verificationCode" id="verificationCode" name="verificationCode" lay-verify="verificationCode" placeholder="图形验证码" class="layui-input">
</div>
<div class="layui-col-xs5">
<div style="margin-left: 10px;">
<img src="oauth/verification-code/png" class="layadmin-user-login-codeimg" @click="refreshVerificationCode($event)">
<div v-if="loginType !== 'wx'">
<!-- 用户名密码登录 start -->
<div class="layui-form-item">
<label class="layadmin-user-login-icon layui-icon layui-icon-username" for="username"></label>
<input type="text" v-model="formData.username" id="username" name="username" lay-verify="username" placeholder="用户名 / 手机号" class="layui-input">
</div>
<div class="layui-form-item" v-if="loginType === 'username'">
<label class="layadmin-user-login-icon layui-icon layui-icon-password" for="password"></label>
<input type="password" v-model="formData.password" id="password" name="password" lay-verify="password" placeholder="密码" class="layui-input">
</div>
<div class="layui-form-item" v-if="loginType === 'username' && pageParams.verificationCode == 'true'" >
<!-- 验证码 -->
<div class="layui-row">
<div class="layui-col-xs7">
<label class="layadmin-user-login-icon layui-icon layui-icon-vercode" for="verificationCode"></label>
<input type="text" v-model="formData.verificationCode" id="verificationCode" name="verificationCode" lay-verify="verificationCode" placeholder="图形验证码" class="layui-input">
</div>
<div class="layui-col-xs5">
<div style="margin-left: 10px;">
<img src="oauth/verification-code/png" class="layadmin-user-login-codeimg" @click="refreshVerificationCode($event)">
</div>
</div>
</div>
</div>
</div>
<div class="layui-form-item" v-if="loginType === 'sms'">
<div class="layui-col-xs7">
<label class="layadmin-user-login-icon layui-icon layui-icon-vercode" for="verificationCode"></label>
<input type="text" v-model="sms.smsCode" id="smsCode" name="smsCode" placeholder="验证码" class="layui-input">
<!-- 用户名密码登录 end -->
<!-- 短信登录 start -->
<div class="layui-form-item" v-if="loginType === 'sms'">
<div class="layui-col-xs7">
<label class="layadmin-user-login-icon layui-icon layui-icon-vercode" for="verificationCode"></label>
<input type="text" v-model="sms.smsCode" id="smsCode" name="smsCode" placeholder="验证码" class="layui-input">
</div>
<div class="layui-col-xs5 verify-code">
<a href="javascript:void(0);" v-if="!sms.isCountingDown" @click="onLoginSmsCodeClick" style="font-size: 13px;">获取验证码</a>
<a href="javascript:void(0);" style="color: #d2d2d2; font-size: 13px;" v-if="sms.isCountingDown">{{sms.countDownSeconds}}秒后重试</a>
</div>
</div>
<div class="layui-col-xs5 verify-code">
<a href="javascript:void(0);" v-if="!sms.isCountingDown" @click="onLoginSmsCodeClick" style="font-size: 13px;">获取验证码</a>
<a href="javascript:void(0);" style="color: #d2d2d2; font-size: 13px;" v-if="sms.isCountingDown">{{sms.countDownSeconds}}秒后重试</a>
<!-- 短信登录 end -->
<div class="layui-form remember-username" v-if="loginType !== 'wx'">
<input type="checkbox" v-model="formData.remember" name="remember" lay-skin="primary" title="记住账号" lay-filter="rememberFilter">
</div>
<div class="layui-form-item">
<button type="submit" class="layui-btn layui-btn-fluid login-btn" lay-submit style="background-color: #fda633;">登录</button>
</div>
</div>
<div class="layui-form remember-username">
<input type="checkbox" v-model="formData.remember" name="remember" lay-skin="primary" title="记住账号" lay-filter="rememberFilter">
</div>
<div class="layui-form-item">
<button type="submit" class="layui-btn layui-btn-fluid login-btn" lay-submit style="background-color: #fda633;">登录</button>
<!-- 微信登录 start -->
<div class="layui-form-item" v-if="loginType === 'wx'">
<div id="wxQrcode"></div>
</div>
<!-- 微信登录 end -->
</form>
</div>
<div class="footer">
<div class="login-type">
<a href="javascript:void(0);" v-if="loginType === 'sms'" @click="onLoginTypeClick('username')">账号密码登录 <i class="fa fa-angle-right"></i></a>
<a href="javascript:void(0);" v-if="loginType === 'username'" @click="onLoginTypeClick('sms')">短信登录 <i class="fa fa-angle-right"></i></a>
<div class="third-login">
<a href="javascript:void(0);" class="wx-login logo" @click="onLoginTypeClick('wx')" v-if="loginType !== 'wx'">
<img src="assets/images/wx-login.png" alt="加载失败"/>
</a>
</div>
<div class="self-login">
<a href="javascript:void(0);" v-if="loginType === 'sms' || loginType === 'wx'" @click="onLoginTypeClick('username')">账号密码登录 <i class="fa fa-angle-right"></i></a>
<a href="javascript:void(0);" v-if="loginType === 'username'" @click="onLoginTypeClick('sms')">短信登录 <i class="fa fa-angle-right"></i></a>
</div>
</div>
<div class="other">
<div>
@ -210,6 +239,7 @@
</div>
</div>
</div>
<div class="layui-trans layadmin-user-login-footer footer-text">
<p v-if="pageParams.copyRightYear"><span>{{'© '+ pageParams.copyRightYear +' '}}</span><a href="javascript:void(0);" v-if="pageParams.copyleft">{{pageParams.copyleft}}</a></p>
<p v-if="pageParams.officialUrl">
@ -218,6 +248,7 @@
</div>
</div>
</div>
<script type="text/javascript" src="assets/js/wxLogin.js"></script>
<script type="text/javascript" src="assets/js/vue.min.js"></script>
<script type="text/javascript" src="assets/layuiadmin/layui/layui.js"></script>
<script type="text/javascript" th:inline="javascript">
@ -396,12 +427,32 @@
self.isCountClick = false;
})
},
initWxQrcode: function() {
// var layIndex = layer.msg('正在加载二维码,请稍后...', {icon: 16, shade: 0.1, time: 0});
var obj = new WxLogin({
self_redirect: false,
id: 'wxQrcode',
appid: this.pageParams.wxAppid,
redirect_uri: this.pageParams.wxRedirectUri,
scope: 'snsapi_login',
state: '',
style: 'black',
onReady: function(isReady) {
// layer.close(layIndex);
}
});
},
onLoginTypeClick: function(type) {
this.loginType = type;
var self = this;
if(type === 'username') {
this.activeAction = pageParams.loginFormAction;
} else if(type === 'sms') {
this.activeAction = pageParams.loginPhoneAction;
} else if(type === 'wx') {
this.$nextTick(function() {
self.initWxQrcode();
})
}
},
showErrorMessage: function() {
@ -462,10 +513,9 @@
form.render();
});
},
loginTypeChange: function(type) {
this.loginType = type;
}
},
},
mounted: function() {
var self = this;