From 8741aadccbfcfd7a04c66e058feb99d67655bb15 Mon Sep 17 00:00:00 2001 From: TS-QD1 Date: Wed, 16 Apr 2025 15:17:08 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=A2=9E=E5=8A=A0=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E6=89=AB=E7=A0=81=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/readme.md | 15 ++- .../AccountRechargeController.java | 9 +- .../user/UserWxUpdateUsernameController.java | 48 +++++++ .../systemuser/SystemUserRouteController.java | 5 + .../dao/user/expand/IUserExpandDao.java | 4 + .../login/phone/LoginPhoneConfig.java | 1 + .../phone/auth/LoginPhoneAuthFilter.java | 4 +- .../phone/auth/LoginPhoneAuthProvider.java | 8 +- .../login/temporary/LoginTemporaryConfig.java | 56 ++++++++ .../auth/LoginTemporaryAuthFilter.java | 43 ++++++ .../login/wx/oauth2/LoginWxOauth2Config.java | 70 ++++++++++ .../oauth2/auth/LoginWxOauth2AuthFilter.java | 50 +++++++ .../auth/LoginWxOauth2AuthProvider.java | 125 +++++++++++++++++ .../oauth2/auth/LoginWxOauth2AuthToken.java | 36 +++++ .../phone/LoginWxUpdatePhoneConfig.java | 63 +++++++++ .../auth/LoginWxUpdatePhoneAuthFilter.java | 94 +++++++++++++ .../auth/LoginWxUpdatePhoneAuthProvider.java | 126 ++++++++++++++++++ .../auth/LoginWxUpdatePhoneAuthToken.java | 36 +++++ .../AccountRechargeWxPrepayDTO.java | 41 ++++++ .../pojo/dtos/user/expand/UserExpandDTO.java | 20 ++- .../pojo/pos/user/expand/UserExpandPO.java | 30 +++++ .../pojo/vos/user/expand/UserExpandVO.java | 18 +++ .../properties/WxOauth2Properties.java | 38 ++++++ .../remote/wx/IWxOauth2RemoteService.java | 28 ++++ .../remote/wx/entity/WxOauth2AccessToken.java | 59 ++++++++ .../operator/remote/wx/entity/WxUserinfo.java | 77 +++++++++++ .../operator/service/UserRegisterService.java | 2 + .../IAccountRechargeService.java | 3 +- .../impl/AccountRechargeServiceImpl.java | 26 +++- .../handler/LoginHandlerServiceImpl.java | 2 +- .../temporary/LoginTemporaryService.java | 31 +++++ .../user/expand/UserExpandServiceImpl.java | 55 ++++++-- .../service/user/wx/UserWxMiniappService.java | 8 +- .../com/tenlion/operator/util/pay/WXPay.java | 55 +++++++- src/main/resources/application-dev.yml | 12 +- .../mapper/user/expand/user-expand.xml | 58 +++++++- .../static/assets/images/wx-login.png | Bin 0 -> 1926 bytes .../resources/static/assets/js/wxLogin.js | 1 + .../resources/templates/systemuser/login.html | 122 ++++++++++++----- 39 files changed, 1397 insertions(+), 82 deletions(-) create mode 100644 src/main/java/cn/com/tenlion/operator/controller/api/user/UserWxUpdateUsernameController.java create mode 100644 src/main/java/cn/com/tenlion/operator/login/temporary/LoginTemporaryConfig.java create mode 100644 src/main/java/cn/com/tenlion/operator/login/temporary/auth/LoginTemporaryAuthFilter.java create mode 100644 src/main/java/cn/com/tenlion/operator/login/wx/oauth2/LoginWxOauth2Config.java create mode 100644 src/main/java/cn/com/tenlion/operator/login/wx/oauth2/auth/LoginWxOauth2AuthFilter.java create mode 100644 src/main/java/cn/com/tenlion/operator/login/wx/oauth2/auth/LoginWxOauth2AuthProvider.java create mode 100644 src/main/java/cn/com/tenlion/operator/login/wx/oauth2/auth/LoginWxOauth2AuthToken.java create mode 100644 src/main/java/cn/com/tenlion/operator/login/wx/update/phone/LoginWxUpdatePhoneConfig.java create mode 100644 src/main/java/cn/com/tenlion/operator/login/wx/update/phone/auth/LoginWxUpdatePhoneAuthFilter.java create mode 100644 src/main/java/cn/com/tenlion/operator/login/wx/update/phone/auth/LoginWxUpdatePhoneAuthProvider.java create mode 100644 src/main/java/cn/com/tenlion/operator/login/wx/update/phone/auth/LoginWxUpdatePhoneAuthToken.java create mode 100644 src/main/java/cn/com/tenlion/operator/pojo/dtos/accountrecharge/AccountRechargeWxPrepayDTO.java create mode 100644 src/main/java/cn/com/tenlion/operator/properties/WxOauth2Properties.java create mode 100644 src/main/java/cn/com/tenlion/operator/remote/wx/IWxOauth2RemoteService.java create mode 100644 src/main/java/cn/com/tenlion/operator/remote/wx/entity/WxOauth2AccessToken.java create mode 100644 src/main/java/cn/com/tenlion/operator/remote/wx/entity/WxUserinfo.java create mode 100644 src/main/java/cn/com/tenlion/operator/service/login/temporary/LoginTemporaryService.java create mode 100644 src/main/resources/static/assets/images/wx-login.png create mode 100644 src/main/resources/static/assets/js/wxLogin.js diff --git a/doc/readme.md b/doc/readme.md index b780ef8..658e430 100644 --- a/doc/readme.md +++ b/doc/readme.md @@ -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 '名称', diff --git a/src/main/java/cn/com/tenlion/operator/controller/api/accountrecharge/AccountRechargeController.java b/src/main/java/cn/com/tenlion/operator/controller/api/accountrecharge/AccountRechargeController.java index 0a15aa3..2e49ce9 100644 --- a/src/main/java/cn/com/tenlion/operator/controller/api/accountrecharge/AccountRechargeController.java +++ b/src/main/java/cn/com/tenlion/operator/controller/api/accountrecharge/AccountRechargeController.java @@ -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 = "账户确认到账接口") diff --git a/src/main/java/cn/com/tenlion/operator/controller/api/user/UserWxUpdateUsernameController.java b/src/main/java/cn/com/tenlion/operator/controller/api/user/UserWxUpdateUsernameController.java new file mode 100644 index 0000000..b5482d4 --- /dev/null +++ b/src/main/java/cn/com/tenlion/operator/controller/api/user/UserWxUpdateUsernameController.java @@ -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 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); + } + +} diff --git a/src/main/java/cn/com/tenlion/operator/controller/route/systemuser/SystemUserRouteController.java b/src/main/java/cn/com/tenlion/operator/controller/route/systemuser/SystemUserRouteController.java index b19bba3..1a307aa 100644 --- a/src/main/java/cn/com/tenlion/operator/controller/route/systemuser/SystemUserRouteController.java +++ b/src/main/java/cn/com/tenlion/operator/controller/route/systemuser/SystemUserRouteController.java @@ -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 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")); diff --git a/src/main/java/cn/com/tenlion/operator/dao/user/expand/IUserExpandDao.java b/src/main/java/cn/com/tenlion/operator/dao/user/expand/IUserExpandDao.java index f77ffeb..f6e8e6e 100644 --- a/src/main/java/cn/com/tenlion/operator/dao/user/expand/IUserExpandDao.java +++ b/src/main/java/cn/com/tenlion/operator/dao/user/expand/IUserExpandDao.java @@ -31,6 +31,10 @@ public interface IUserExpandDao { void updateWxOfficialAccountOpenId(Map params); + void updateWxOpenIdAndUnionId(Map params); + + void updateUserId(Map params); + UserExpandDTO get(Map params); UserExpandPO getPO(Map params); diff --git a/src/main/java/cn/com/tenlion/operator/login/phone/LoginPhoneConfig.java b/src/main/java/cn/com/tenlion/operator/login/phone/LoginPhoneConfig.java index 4470743..ee171b0 100644 --- a/src/main/java/cn/com/tenlion/operator/login/phone/LoginPhoneConfig.java +++ b/src/main/java/cn/com/tenlion/operator/login/phone/LoginPhoneConfig.java @@ -37,6 +37,7 @@ public class LoginPhoneConfig extends SecurityConfigurerAdapter 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); + } + +} diff --git a/src/main/java/cn/com/tenlion/operator/login/temporary/auth/LoginTemporaryAuthFilter.java b/src/main/java/cn/com/tenlion/operator/login/temporary/auth/LoginTemporaryAuthFilter.java new file mode 100644 index 0000000..ac13f05 --- /dev/null +++ b/src/main/java/cn/com/tenlion/operator/login/temporary/auth/LoginTemporaryAuthFilter.java @@ -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); + } +} diff --git a/src/main/java/cn/com/tenlion/operator/login/wx/oauth2/LoginWxOauth2Config.java b/src/main/java/cn/com/tenlion/operator/login/wx/oauth2/LoginWxOauth2Config.java new file mode 100644 index 0000000..02f05d1 --- /dev/null +++ b/src/main/java/cn/com/tenlion/operator/login/wx/oauth2/LoginWxOauth2Config.java @@ -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 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); + } + +} diff --git a/src/main/java/cn/com/tenlion/operator/login/wx/oauth2/auth/LoginWxOauth2AuthFilter.java b/src/main/java/cn/com/tenlion/operator/login/wx/oauth2/auth/LoginWxOauth2AuthFilter.java new file mode 100644 index 0000000..05306aa --- /dev/null +++ b/src/main/java/cn/com/tenlion/operator/login/wx/oauth2/auth/LoginWxOauth2AuthFilter.java @@ -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); + } + +} diff --git a/src/main/java/cn/com/tenlion/operator/login/wx/oauth2/auth/LoginWxOauth2AuthProvider.java b/src/main/java/cn/com/tenlion/operator/login/wx/oauth2/auth/LoginWxOauth2AuthProvider.java new file mode 100644 index 0000000..e1b22e3 --- /dev/null +++ b/src/main/java/cn/com/tenlion/operator/login/wx/oauth2/auth/LoginWxOauth2AuthProvider.java @@ -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() {{ + 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("登录异常"); + } + } + } +} diff --git a/src/main/java/cn/com/tenlion/operator/login/wx/oauth2/auth/LoginWxOauth2AuthToken.java b/src/main/java/cn/com/tenlion/operator/login/wx/oauth2/auth/LoginWxOauth2AuthToken.java new file mode 100644 index 0000000..f28ed79 --- /dev/null +++ b/src/main/java/cn/com/tenlion/operator/login/wx/oauth2/auth/LoginWxOauth2AuthToken.java @@ -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 authorities) { + super(authorities); + this.principal = principal; + this.credentials = credentials; + setAuthenticated(true); + } + + @Override + public Object getCredentials() { + return credentials; + } + + @Override + public Object getPrincipal() { + return principal; + } +} diff --git a/src/main/java/cn/com/tenlion/operator/login/wx/update/phone/LoginWxUpdatePhoneConfig.java b/src/main/java/cn/com/tenlion/operator/login/wx/update/phone/LoginWxUpdatePhoneConfig.java new file mode 100644 index 0000000..2d1c217 --- /dev/null +++ b/src/main/java/cn/com/tenlion/operator/login/wx/update/phone/LoginWxUpdatePhoneConfig.java @@ -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 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); + } + +} diff --git a/src/main/java/cn/com/tenlion/operator/login/wx/update/phone/auth/LoginWxUpdatePhoneAuthFilter.java b/src/main/java/cn/com/tenlion/operator/login/wx/update/phone/auth/LoginWxUpdatePhoneAuthFilter.java new file mode 100644 index 0000000..7e4dcd0 --- /dev/null +++ b/src/main/java/cn/com/tenlion/operator/login/wx/update/phone/auth/LoginWxUpdatePhoneAuthFilter.java @@ -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; + } + } + + +} diff --git a/src/main/java/cn/com/tenlion/operator/login/wx/update/phone/auth/LoginWxUpdatePhoneAuthProvider.java b/src/main/java/cn/com/tenlion/operator/login/wx/update/phone/auth/LoginWxUpdatePhoneAuthProvider.java new file mode 100644 index 0000000..861d196 --- /dev/null +++ b/src/main/java/cn/com/tenlion/operator/login/wx/update/phone/auth/LoginWxUpdatePhoneAuthProvider.java @@ -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("登录异常"); + } + } + } +} diff --git a/src/main/java/cn/com/tenlion/operator/login/wx/update/phone/auth/LoginWxUpdatePhoneAuthToken.java b/src/main/java/cn/com/tenlion/operator/login/wx/update/phone/auth/LoginWxUpdatePhoneAuthToken.java new file mode 100644 index 0000000..2ab18b6 --- /dev/null +++ b/src/main/java/cn/com/tenlion/operator/login/wx/update/phone/auth/LoginWxUpdatePhoneAuthToken.java @@ -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 authorities) { + super(authorities); + this.principal = principal; + this.credentials = credentials; + setAuthenticated(true); + } + + @Override + public Object getCredentials() { + return credentials; + } + + @Override + public Object getPrincipal() { + return principal; + } +} diff --git a/src/main/java/cn/com/tenlion/operator/pojo/dtos/accountrecharge/AccountRechargeWxPrepayDTO.java b/src/main/java/cn/com/tenlion/operator/pojo/dtos/accountrecharge/AccountRechargeWxPrepayDTO.java new file mode 100644 index 0000000..0497f4f --- /dev/null +++ b/src/main/java/cn/com/tenlion/operator/pojo/dtos/accountrecharge/AccountRechargeWxPrepayDTO.java @@ -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; + } +} diff --git a/src/main/java/cn/com/tenlion/operator/pojo/dtos/user/expand/UserExpandDTO.java b/src/main/java/cn/com/tenlion/operator/pojo/dtos/user/expand/UserExpandDTO.java index bdc0a01..62438f0 100644 --- a/src/main/java/cn/com/tenlion/operator/pojo/dtos/user/expand/UserExpandDTO.java +++ b/src/main/java/cn/com/tenlion/operator/pojo/dtos/user/expand/UserExpandDTO.java @@ -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; + } } diff --git a/src/main/java/cn/com/tenlion/operator/pojo/pos/user/expand/UserExpandPO.java b/src/main/java/cn/com/tenlion/operator/pojo/pos/user/expand/UserExpandPO.java index b99f622..f0f0dbd 100644 --- a/src/main/java/cn/com/tenlion/operator/pojo/pos/user/expand/UserExpandPO.java +++ b/src/main/java/cn/com/tenlion/operator/pojo/pos/user/expand/UserExpandPO.java @@ -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; + } } diff --git a/src/main/java/cn/com/tenlion/operator/pojo/vos/user/expand/UserExpandVO.java b/src/main/java/cn/com/tenlion/operator/pojo/vos/user/expand/UserExpandVO.java index 4ba75da..82db9b4 100644 --- a/src/main/java/cn/com/tenlion/operator/pojo/vos/user/expand/UserExpandVO.java +++ b/src/main/java/cn/com/tenlion/operator/pojo/vos/user/expand/UserExpandVO.java @@ -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; + } } diff --git a/src/main/java/cn/com/tenlion/operator/properties/WxOauth2Properties.java b/src/main/java/cn/com/tenlion/operator/properties/WxOauth2Properties.java new file mode 100644 index 0000000..5d5cd2e --- /dev/null +++ b/src/main/java/cn/com/tenlion/operator/properties/WxOauth2Properties.java @@ -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; + } +} diff --git a/src/main/java/cn/com/tenlion/operator/remote/wx/IWxOauth2RemoteService.java b/src/main/java/cn/com/tenlion/operator/remote/wx/IWxOauth2RemoteService.java new file mode 100644 index 0000000..192c2d0 --- /dev/null +++ b/src/main/java/cn/com/tenlion/operator/remote/wx/IWxOauth2RemoteService.java @@ -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); + +} diff --git a/src/main/java/cn/com/tenlion/operator/remote/wx/entity/WxOauth2AccessToken.java b/src/main/java/cn/com/tenlion/operator/remote/wx/entity/WxOauth2AccessToken.java new file mode 100644 index 0000000..ae1d27f --- /dev/null +++ b/src/main/java/cn/com/tenlion/operator/remote/wx/entity/WxOauth2AccessToken.java @@ -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; + } +} diff --git a/src/main/java/cn/com/tenlion/operator/remote/wx/entity/WxUserinfo.java b/src/main/java/cn/com/tenlion/operator/remote/wx/entity/WxUserinfo.java new file mode 100644 index 0000000..9d21b8d --- /dev/null +++ b/src/main/java/cn/com/tenlion/operator/remote/wx/entity/WxUserinfo.java @@ -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; + } +} diff --git a/src/main/java/cn/com/tenlion/operator/service/UserRegisterService.java b/src/main/java/cn/com/tenlion/operator/service/UserRegisterService.java index 94c61c2..28c1ff5 100644 --- a/src/main/java/cn/com/tenlion/operator/service/UserRegisterService.java +++ b/src/main/java/cn/com/tenlion/operator/service/UserRegisterService.java @@ -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); } diff --git a/src/main/java/cn/com/tenlion/operator/service/accountrecharge/IAccountRechargeService.java b/src/main/java/cn/com/tenlion/operator/service/accountrecharge/IAccountRechargeService.java index 225812a..d3d07f1 100644 --- a/src/main/java/cn/com/tenlion/operator/service/accountrecharge/IAccountRechargeService.java +++ b/src/main/java/cn/com/tenlion/operator/service/accountrecharge/IAccountRechargeService.java @@ -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); diff --git a/src/main/java/cn/com/tenlion/operator/service/accountrecharge/impl/AccountRechargeServiceImpl.java b/src/main/java/cn/com/tenlion/operator/service/accountrecharge/impl/AccountRechargeServiceImpl.java index 264645f..0cec732 100644 --- a/src/main/java/cn/com/tenlion/operator/service/accountrecharge/impl/AccountRechargeServiceImpl.java +++ b/src/main/java/cn/com/tenlion/operator/service/accountrecharge/impl/AccountRechargeServiceImpl.java @@ -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); } } diff --git a/src/main/java/cn/com/tenlion/operator/service/login/handler/LoginHandlerServiceImpl.java b/src/main/java/cn/com/tenlion/operator/service/login/handler/LoginHandlerServiceImpl.java index 491b956..e1200c8 100644 --- a/src/main/java/cn/com/tenlion/operator/service/login/handler/LoginHandlerServiceImpl.java +++ b/src/main/java/cn/com/tenlion/operator/service/login/handler/LoginHandlerServiceImpl.java @@ -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)); diff --git a/src/main/java/cn/com/tenlion/operator/service/login/temporary/LoginTemporaryService.java b/src/main/java/cn/com/tenlion/operator/service/login/temporary/LoginTemporaryService.java new file mode 100644 index 0000000..9c957ed --- /dev/null +++ b/src/main/java/cn/com/tenlion/operator/service/login/temporary/LoginTemporaryService.java @@ -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 = ""; + } + } + +} diff --git a/src/main/java/cn/com/tenlion/operator/service/user/expand/UserExpandServiceImpl.java b/src/main/java/cn/com/tenlion/operator/service/user/expand/UserExpandServiceImpl.java index 7f82ef3..bb13b08 100644 --- a/src/main/java/cn/com/tenlion/operator/service/user/expand/UserExpandServiceImpl.java +++ b/src/main/java/cn/com/tenlion/operator/service/user/expand/UserExpandServiceImpl.java @@ -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 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 params = getHashMap(4); + params.put("wxOpenId", openid); + return userExpandDao.getPO(params); + } + + public void updateWxOpenIdAndUnionId(String userId, String openid, String unionid) { + Map 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 params = getHashMap(4); + params.put("userId", userId); + params.put("updateUserId", updateUserId); + userExpandDao.updateUserId(params); + } + + public void deleteByUserIds(List strings) { + + } } diff --git a/src/main/java/cn/com/tenlion/operator/service/user/wx/UserWxMiniappService.java b/src/main/java/cn/com/tenlion/operator/service/user/wx/UserWxMiniappService.java index 7e92b24..6f01be6 100644 --- a/src/main/java/cn/com/tenlion/operator/service/user/wx/UserWxMiniappService.java +++ b/src/main/java/cn/com/tenlion/operator/service/user/wx/UserWxMiniappService.java @@ -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() {{ + WxAccessToken wxAccessToken = wxMiniappRemoteService.getAccessToken(IWxOauth2RemoteService.WX_API_BASE_URL, new HashMap() {{ 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() {{ + WxPhoneResult wxPhoneResult = wxMiniappRemoteService.getPhone(IWxOauth2RemoteService.WX_API_BASE_URL, miniappAccessToken.getWxAccessToken().getAccess_token(), new HashMap() {{ put("code", code); }}); checkResult(wxPhoneResult); diff --git a/src/main/java/cn/com/tenlion/operator/util/pay/WXPay.java b/src/main/java/cn/com/tenlion/operator/util/pay/WXPay.java index a05bb1b..7a74942 100644 --- a/src/main/java/cn/com/tenlion/operator/util/pay/WXPay.java +++ b/src/main/java/cn/com/tenlion/operator/util/pay/WXPay.java @@ -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); + + } + + /** * 获取二维码超时时间 * diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 7683142..83c06c8 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -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 \ No newline at end of file + 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 diff --git a/src/main/resources/mybatis/mapper/user/expand/user-expand.xml b/src/main/resources/mybatis/mapper/user/expand/user-expand.xml index 73db61d..2216760 100644 --- a/src/main/resources/mybatis/mapper/user/expand/user-expand.xml +++ b/src/main/resources/mybatis/mapper/user/expand/user-expand.xml @@ -31,6 +31,8 @@ + + @@ -62,6 +64,8 @@ + + @@ -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} ) @@ -152,6 +160,12 @@ wx_official_account_open_id = #{wxOfficialAccountOpenId}, + + wx_open_id = #{wxOpenId}, + + + wx_union_id = #{wxUnionId}, + price_additional_pkg = #{priceAdditionalPkg}, price_additional_video_demo = #{priceAdditionalVideoDemo}, price_additional_urgent = #{priceAdditionalUrgent}, @@ -215,7 +229,6 @@ user_id = #{userId} - UPDATE sys_user_expand @@ -225,6 +238,25 @@ user_id = #{userId} + + UPDATE + sys_user_expand + SET + wx_open_id = #{wxOpenId}, + wx_union_id = #{wxUnionId} + WHERE + user_id = #{userId} + + + + UPDATE + sys_user_expand + SET + user_id = #{updateUserId} + WHERE + user_id = #{userId} + + -
- - -
-
- - -
-
- -
-
- - -
-
-
- +
+ +
+ + +
+
+ + +
+
+ +
+
+ + +
+
+
+ +
-
-
-
- - + + + - -
- -
-
- + +
+
+
+
+