LoginController.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are met:
  6. *
  7. * Redistributions of source code must retain the above copyright notice,
  8. * this list of conditions and the following disclaimer.
  9. * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * Neither the name of the dreamlu.net developer nor the names of its
  13. * contributors may be used to endorse or promote products derived from
  14. * this software without specific prior written permission.
  15. * Author: Chill 庄骞 (smallchill@163.com)
  16. */
  17. package org.springblade.modules.api.controller;
  18. import cn.hutool.core.util.DesensitizedUtil;
  19. import cn.hutool.core.util.IdcardUtil;
  20. import cn.hutool.core.util.ObjectUtil;
  21. import cn.hutool.core.util.PhoneUtil;
  22. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  23. import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
  24. import io.swagger.annotations.Api;
  25. import io.swagger.annotations.ApiOperation;
  26. import io.swagger.annotations.ApiParam;
  27. import lombok.AllArgsConstructor;
  28. import org.springblade.common.cache.ParamCache;
  29. import org.springblade.common.constant.CommonConstant;
  30. import org.springblade.common.enums.ResultCode;
  31. import org.springblade.common.utils.CommonUtil;
  32. import org.springblade.core.boot.ctrl.BladeController;
  33. import org.springblade.core.cache.utils.CacheUtil;
  34. import org.springblade.core.jwt.JwtUtil;
  35. import org.springblade.core.jwt.props.JwtProperties;
  36. import org.springblade.core.launch.constant.TokenConstant;
  37. import org.springblade.core.log.annotation.ApiLog;
  38. import org.springblade.core.redis.cache.BladeRedis;
  39. import org.springblade.core.secure.BladeUser;
  40. import org.springblade.core.secure.utils.AuthUtil;
  41. import org.springblade.core.sms.model.SmsCode;
  42. import org.springblade.core.tool.api.R;
  43. import org.springblade.core.tool.support.Kv;
  44. import org.springblade.core.tool.utils.*;
  45. import org.springblade.modules.api.request.MerchantRegisterRequest;
  46. import org.springblade.modules.auth.enums.UserEnum;
  47. import org.springblade.modules.auth.granter.PasswordTokenGranter;
  48. import org.springblade.modules.auth.provider.ITokenGranter;
  49. import org.springblade.modules.auth.provider.TokenGranterBuilder;
  50. import org.springblade.modules.auth.provider.TokenParameter;
  51. import org.springblade.modules.auth.utils.TokenUtil;
  52. import org.springblade.modules.platform.entity.UserRecom;
  53. import org.springblade.modules.platform.entity.UserScores;
  54. import org.springblade.modules.platform.service.IUserRecomService;
  55. import org.springblade.modules.platform.service.IUserScoresService;
  56. import org.springblade.modules.platform.service.UserAppService;
  57. import org.springblade.modules.resource.builder.sms.SmsBuilder;
  58. import org.springblade.modules.system.entity.User;
  59. import org.springblade.modules.system.entity.UserApp;
  60. import org.springblade.modules.system.entity.UserInfo;
  61. import org.springblade.modules.system.entity.UserMerchant;
  62. import org.springblade.modules.system.service.IUserMerchantService;
  63. import org.springblade.modules.system.service.IUserService;
  64. import org.springblade.modules.system.service.IUserWeChatService;
  65. import org.springframework.transaction.annotation.Transactional;
  66. import org.springframework.web.bind.annotation.*;
  67. import javax.annotation.Resource;
  68. import javax.servlet.http.HttpServletResponse;
  69. import javax.validation.Valid;
  70. import static org.springblade.core.cache.constant.CacheConstant.USER_CACHE;
  71. import static org.springblade.modules.resource.utils.SmsUtil.VALIDATE_FAIL;
  72. import static org.springblade.modules.resource.utils.SmsUtil.VALIDATE_SUCCESS;
  73. /**
  74. * 控制器
  75. *
  76. * @author xuwei
  77. * @since 2022-02-12
  78. */
  79. @RestController
  80. @AllArgsConstructor
  81. @RequestMapping(CommonConstant.API_URL)
  82. @Api(value = "登录注册", tags = "03.登录注册")
  83. public class LoginController extends BladeController {
  84. private final IUserService userService;
  85. private final IUserRecomService userRecomService;
  86. private final IUserScoresService userScoresService;
  87. private final BladeRedis bladeRedis;
  88. private final JwtProperties jwtProperties;
  89. private final UserAppService userAppService;
  90. private final IUserWeChatService userWeChatService;
  91. private final IUserMerchantService iUserMerchantService;
  92. @ApiLog("用户注册")
  93. @PostMapping("/user-register")
  94. @ApiOperationSupport(order = 1)
  95. @ApiOperation(value = "用户注册", notes = "手机号注册")
  96. @Transactional(rollbackFor = Exception.class)
  97. public R userRegister(@ApiParam(value = "邀请码", required = true) @RequestParam(value = "inviteCode", required = false) String inviteCode,
  98. @ApiParam(value = "手机号", required = true) @RequestParam(value = "phone") String phone,
  99. @ApiParam(value = "密码", required = true) @RequestParam(value = "password") String password,
  100. @ApiParam(value = "验证码", required = true) @RequestParam(value = "captchaCode", required = false) String captchaCode,
  101. @ApiParam(value = "验证ID, 发送验证码返回的ID", required = true) @RequestParam(value = "captchaId") String captchaId){
  102. if(StringUtil.isEmpty(inviteCode)){
  103. inviteCode = "TPSL5I";
  104. }
  105. User query = userService.getOne(Wrappers.<User>query().lambda().eq(User::getCode, inviteCode));
  106. if (query == null){
  107. return R.fail("邀请码输入错误!");
  108. }
  109. if (!PhoneUtil.isPhone(phone)){
  110. return R.fail("请输入正确的手机号!");
  111. }
  112. if (StringUtil.isBlank(captchaCode) || StringUtil.isBlank(captchaId)){
  113. return R.fail("请输入手机验证码!");
  114. }
  115. User query1 = userService.getOne(Wrappers.<User>query().lambda().eq(User::getAccount, phone));
  116. if (query1 != null){
  117. return R.fail("手机号已注册!");
  118. }
  119. boolean flg = captchaCode(phone, captchaId, captchaCode);
  120. if (!flg){
  121. return R.fail(VALIDATE_FAIL);
  122. }
  123. String tenantId = WebUtil.getRequest().getHeader(TokenUtil.TENANT_HEADER_KEY);
  124. User user = new User();
  125. user.setAccount(phone);
  126. user.setPhone(phone);
  127. user.setTenantId(tenantId);
  128. user.setPassword(password);
  129. user.setName(DesensitizedUtil.mobilePhone(phone));
  130. CacheUtil.clear(USER_CACHE);
  131. flg = userService.registerApp(user, query.getId());
  132. if (flg){
  133. //添加用户推荐记录表数据
  134. query1 = userService.getOne(Wrappers.<User>query().lambda().eq(User::getAccount, phone));
  135. UserRecom userRecom = new UserRecom();
  136. userRecom.setUserId(query1.getId()); //团队用户
  137. userRecom.setRecomId(query.getId()); //推荐人
  138. userRecom.setCreateTime(DateUtil.now());
  139. userRecomService.save(userRecom);
  140. UserApp userApp = new UserApp();
  141. UserApp userAppQuery = userApp.selectOne(Wrappers.<UserApp>query().lambda().eq(UserApp::getUserId, query.getId()));
  142. //邀请好友注册完善资料(+5信誉分)
  143. UserScores userScores = new UserScores();
  144. userScores.setUserId(query.getId());//推荐人
  145. int score = Integer.parseInt(ParamCache.getValue(CommonConstant.SCORE_USER_REGISTER));
  146. userScores.setScore(score);
  147. String dataRemarks = "推荐用户注册";
  148. if (userAppQuery.getCreditScore() >= 500){
  149. score = Integer.parseInt(ParamCache.getValue(CommonConstant.SCORE_CONSIGN_REGISTER));
  150. userScores.setScore(score);
  151. dataRemarks = "推荐用户注册(500信誉分以上或含有500信誉分)";
  152. }
  153. userScores.setDataSrc("1");
  154. userScores.setDataId(query1.getId());
  155. userScores.setDataType(1);
  156. userScores.setDataRemarks(dataRemarks);
  157. userScoresService.save(userScores);
  158. //修改用户信誉积分
  159. UserApp userAppUpdate = new UserApp();
  160. userAppUpdate.setId(userAppQuery.getId());
  161. userAppUpdate.setCreditScore(userAppQuery.getCreditScore() + score);
  162. userAppUpdate.updateById();
  163. return R.success("注册成功");
  164. }else{
  165. return R.success("注册失败");
  166. }
  167. }
  168. @ApiLog("修改支付密码")
  169. @PostMapping("/modifyPayPassword")
  170. @ApiOperationSupport(order = 2)
  171. @ApiOperation(value = "修改支付密码", notes = "通过验证码修改支付密码")
  172. public R modifyPayPassword(@ApiParam(value = "验证码", required = true) @RequestParam(value = "captchaCode") String captchaCode,
  173. @ApiParam(value = "验证ID, 发送验证码返回的ID", required = true) @RequestParam(value = "captchaId") String captchaId,
  174. @ApiParam(value = "支付密码", required = true) @RequestParam(value = "payPassword") String payPassword){
  175. BladeUser user = getUser();
  176. boolean flg = captchaCode(user.getAccount(), captchaId, captchaCode);
  177. if (!flg){
  178. return R.fail(VALIDATE_FAIL);
  179. }
  180. String offsetCode = CommonUtil.genTimeID();
  181. UserApp userApp = userAppService.getOne(Wrappers.<UserApp>query().lambda().eq(UserApp::getUserId, user.getUserId()));
  182. userApp.setPayPassword(DigestUtil.encrypt(offsetCode + payPassword));
  183. userApp.setOffsetCode(offsetCode);
  184. userAppService.updateById(userApp);
  185. return R.success("修改支付密码成功");
  186. }
  187. @ApiLog("登录用户验证-账号密码")
  188. @PostMapping("/login_account")
  189. @ApiOperationSupport(order = 2)
  190. @ApiOperation(value = "账号密码登录", notes = "账号:account,密码:password")
  191. public R accountLogin(@ApiParam(value = "账号", required = true) @RequestParam String username,
  192. @ApiParam(value = "密码", required = true) @RequestParam String password,
  193. @ApiParam(value = "微信小程序code") @RequestParam(required = false) String code) {
  194. String tenantId = WebUtil.getRequest().getHeader(TokenUtil.TENANT_HEADER_KEY);
  195. String refreshToken = WebUtil.getRequest().getParameter("refresh_token");
  196. String userType = Func.toStr(WebUtil.getRequest().getHeader(TokenUtil.USER_TYPE_HEADER_KEY), UserEnum.APP.getName());
  197. TokenParameter tokenParameter = new TokenParameter();
  198. tokenParameter.getArgs().set("tenantId", tenantId)
  199. .set("username", username)
  200. .set("password", password)
  201. .set("grantType", PasswordTokenGranter.GRANT_TYPE)
  202. .set("refreshToken", refreshToken)
  203. .set("userType", userType);
  204. ITokenGranter granter = TokenGranterBuilder.getGranter(PasswordTokenGranter.GRANT_TYPE);
  205. UserInfo userInfo = granter.grant(tokenParameter);
  206. if (userInfo == null || userInfo.getUser() == null) {
  207. return R.fail("用户名或密码不正确");
  208. }
  209. if (StringUtil.isNoneBlank(code)) {
  210. userWeChatService.saveUserInfo(userInfo, code);
  211. }
  212. User user = userService.getById(userInfo.getUser().getId());
  213. if(ObjectUtil.isNotNull(user.getLogOut()) && user.getLogOut() == 1){
  214. return R.fail("用户已注销无法正常使用,如需使用请联系管理员");
  215. }
  216. return R.data(TokenUtil.createAuthInfo(userInfo));
  217. }
  218. @ApiLog("微信授权登录")
  219. @PostMapping("/login/wx-auth")
  220. @ApiOperationSupport(order = 2)
  221. @ApiOperation(value = "微信授权登录", tags = "通过 getPhoneNumberCode 获取手机号")
  222. public R wxAuthLogin(@ApiParam(value = "微信code", required = true) @RequestParam String code,
  223. @ApiParam(value = "获取手机号的code,五分钟有效", required = true) @RequestParam String getPhoneNumberCode) {
  224. String tenantId = WebUtil.getRequest().getHeader(TokenUtil.TENANT_HEADER_KEY);
  225. TokenParameter tokenParameter = new TokenParameter();
  226. tokenParameter.getArgs()
  227. .set("tenantId", tenantId)
  228. .set("getPhoneNumberCode", getPhoneNumberCode)
  229. .set("code", code);
  230. ITokenGranter granter = TokenGranterBuilder.getGranter("wxAuth");
  231. UserInfo userInfo;
  232. userInfo = granter.grant(tokenParameter);
  233. if (userInfo == null || userInfo.getUser() == null) {
  234. return R.fail(ResultCode.USER_NOT_EXIST);
  235. }
  236. User user = userService.getById(userInfo.getUser().getId());
  237. if(ObjectUtil.isNotNull(user.getLogOut()) && user.getLogOut() == 1){
  238. return R.fail("用户已注销无法正常使用,如需使用请联系管理员");
  239. }
  240. return R.data(TokenUtil.createAuthInfo(userInfo));
  241. }
  242. @ApiLog("登录用户验证-手机验证码登录")
  243. @PostMapping("/login_phone")
  244. @ApiOperationSupport(order = 3)
  245. @ApiOperation(value = "手机验证码登录", notes = "账号:account,密码:password")
  246. public R phoneLogin(@ApiParam(value = "账号", required = true) @RequestParam String username,
  247. @ApiParam(value = "验证码", required = true) @RequestParam(value = "captchaCode") String captchaCode,
  248. @ApiParam(value = "验证ID, 发送验证码返回的ID", required = true) @RequestParam(value = "captchaId") String captchaId) {
  249. if (!PhoneUtil.isPhone(username)){
  250. return R.fail("请输入正确的手机号!");
  251. }
  252. if (StringUtil.isEmpty(captchaCode) ||StringUtil.isEmpty(captchaId)){
  253. return R.fail("请输入手机验证码!");
  254. }
  255. String tenantId = WebUtil.getRequest().getHeader(TokenUtil.TENANT_HEADER_KEY);
  256. String grantType = "phone";
  257. String userType = Func.toStr(WebUtil.getRequest().getHeader(TokenUtil.USER_TYPE_HEADER_KEY), UserEnum.APP.getName());
  258. TokenParameter tokenParameter = new TokenParameter();
  259. tokenParameter.getArgs().set("tenantId", tenantId)
  260. .set("username", username)
  261. .set("captchaId", captchaId)
  262. .set("captchaCode", captchaCode)
  263. .set("grantType", grantType)
  264. .set("userType", userType);
  265. ITokenGranter granter = TokenGranterBuilder.getGranter(grantType);
  266. UserInfo userInfo = granter.grant(tokenParameter);
  267. return R.data(TokenUtil.createAuthInfo(userInfo));
  268. }
  269. @ApiLog("修改密码")
  270. @PostMapping("/reset_password")
  271. @ApiOperationSupport(order = 4)
  272. @ApiOperation(value = "修改密码", notes = "账号:account,密码:password")
  273. public R resetPassword(@ApiParam(value = "手机号", required = true) @RequestParam String username,
  274. @ApiParam(value = "密码", required = true) @RequestParam String password,
  275. @ApiParam(value = "验证码", required = true) @RequestParam(value = "captchaCode") String captchaCode,
  276. @ApiParam(value = "验证ID, 发送验证码返回的ID", required = true) @RequestParam(value = "captchaId") String captchaId) {
  277. String tenantId = WebUtil.getRequest().getHeader(TokenUtil.TENANT_HEADER_KEY);
  278. if (!PhoneUtil.isPhone(username)){
  279. return R.fail("请输入正确的手机号!");
  280. }
  281. if (StringUtil.isEmpty(captchaCode) ||StringUtil.isEmpty(captchaId)){
  282. return R.fail("请输入手机验证码!");
  283. }
  284. User user = userService.userByAccount(tenantId, username);
  285. if (user == null){
  286. return R.fail("该手机号为注册!");
  287. }
  288. boolean flg = captchaCode(username, captchaId,captchaCode);
  289. if (!flg){
  290. return R.fail(VALIDATE_FAIL);
  291. }
  292. User updateUser = new User();
  293. updateUser.setId(user.getId());
  294. updateUser.setPassword(DigestUtil.encrypt(password));
  295. flg = userService.updateById(updateUser);
  296. if (!flg){
  297. return R.fail("操作失败");
  298. }
  299. CacheUtil.clear(USER_CACHE);
  300. return R.success("操作成功");
  301. }
  302. @GetMapping("/logout")
  303. @ApiOperation(value = "退出登录")
  304. @ApiOperationSupport(order = 5)
  305. public R logout() {
  306. BladeUser user = AuthUtil.getUser();
  307. if (user != null && jwtProperties.getState()) {
  308. String token = JwtUtil.getToken(WebUtil.getRequest().getHeader(TokenConstant.HEADER));
  309. JwtUtil.removeAccessToken(user.getTenantId(), String.valueOf(user.getUserId()), token);
  310. }
  311. return R.success("退出成功");
  312. }
  313. @ApiLog("商家注册")
  314. @PostMapping("/merchant-register")
  315. @ApiOperationSupport(order = 6)
  316. @ApiOperation(value = "商家注册", notes = "商家注册")
  317. @Transactional
  318. public R<Void> merchantRegister(@Valid @RequestBody MerchantRegisterRequest request) {
  319. if (!PhoneUtil.isPhone(request.getPhone())){
  320. return R.fail("请输入正确的手机号!");
  321. }
  322. if (!IdcardUtil.isValidCard(request.getIdCard())) {
  323. return R.fail("请输入正确的身份证号!");
  324. }
  325. if (!request.getPassword().equals(request.getRePassword())) {
  326. return R.fail("密码不一致");
  327. }
  328. User query1 = userService.getOne(Wrappers.<User>query().lambda().eq(User::getAccount, request.getPhone()));
  329. if (query1 != null){
  330. return R.fail("手机号已注册!");
  331. }
  332. boolean flg = captchaCode(request.getPhone(), request.getCaptchaId(), request.getCaptchaCode());
  333. if (!flg){
  334. return R.fail(VALIDATE_FAIL);
  335. }
  336. String tenantId = WebUtil.getRequest().getHeader(TokenUtil.TENANT_HEADER_KEY);
  337. User user = new User();
  338. user.setAccount(request.getPhone());
  339. user.setPhone(request.getPhone());
  340. user.setTenantId(tenantId);
  341. user.setUserType(UserEnum.MERCHANT.getCategory());
  342. user.setPassword(DigestUtil.encrypt(request.getPassword()));
  343. user.setName(request.getMerchantName());
  344. user.setRealName(request.getName());
  345. userService.save(user);
  346. UserMerchant userMerchant = new UserMerchant();
  347. userMerchant.setUserId(user.getId());
  348. userMerchant.setAddress(request.getAddress());
  349. userMerchant.setIdCard(request.getIdCard());
  350. userMerchant.setBusinessLicence(request.getBusinessLicence());
  351. userMerchant.setParentId(0L);
  352. iUserMerchantService.save(userMerchant);
  353. return R.success("注册成功");
  354. }
  355. private boolean captchaCode(String phone, String captchaId, String captchaCode){
  356. String key = "blade:sms::captcha:" + phone + ":" + captchaId;
  357. String cache = bladeRedis.get(key);
  358. if (captchaCode.equals(cache)){
  359. return true;
  360. }
  361. return false;
  362. }
  363. }