InfoUserController.java 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318
  1. package com.ruoyi.app.user;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  4. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  5. import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
  6. import com.ruoyi.app.utils.DateUtil;
  7. import com.ruoyi.app.utils.PayPush;
  8. import com.ruoyi.app.utils.RsaMima;
  9. import com.ruoyi.app.utils.UUIDUtil;
  10. import com.ruoyi.app.utils.trtc.TLSSigAPIv2;
  11. import com.ruoyi.common.annotation.Anonymous;
  12. import com.ruoyi.common.annotation.Log;
  13. import com.ruoyi.common.constant.CacheConstants;
  14. import com.ruoyi.common.core.controller.BaseController;
  15. import com.ruoyi.common.core.domain.AjaxResult;
  16. import com.ruoyi.common.core.domain.model.LoginUserDto;
  17. import com.ruoyi.common.core.page.TableDataInfo;
  18. import com.ruoyi.common.core.redis.RedisCache;
  19. import com.ruoyi.common.enums.BusinessType;
  20. import com.ruoyi.common.exception.ServiceException;
  21. import com.ruoyi.common.utils.MessageUtils;
  22. import com.ruoyi.common.utils.ServletUtils;
  23. import com.ruoyi.common.utils.ip.AddressUtils;
  24. import com.ruoyi.common.utils.ip.IpUtils;
  25. import com.ruoyi.common.utils.poi.ExcelUtil;
  26. import com.ruoyi.system.domain.*;
  27. import com.ruoyi.system.domain.constants.MerchantAccountConstants;
  28. import com.ruoyi.app.user.dto.MerchantLoginView;
  29. import com.ruoyi.system.domain.vo.UserDTO;
  30. import com.ruoyi.app.service.ImAccountService;
  31. import com.ruoyi.system.mapper.InfoUserMapper;
  32. import com.ruoyi.system.mapper.PosOrderMapper;
  33. import com.ruoyi.system.mapper.PosStoreMapper;
  34. import com.ruoyi.common.core.domain.entity.SysDictData;
  35. import com.ruoyi.system.service.IInfoUserService;
  36. import com.ruoyi.system.service.ISysDictDataService;
  37. import com.ruoyi.system.service.IPosOrderService;
  38. import com.ruoyi.system.service.IUserWalletService;
  39. import com.ruoyi.system.service.IVipUserService;
  40. import com.ruoyi.system.service.MerchantStoreAccessService;
  41. import com.ruoyi.system.utils.Auth;
  42. import com.ruoyi.system.utils.AuthContext;
  43. import com.ruoyi.system.utils.JwtUtil;
  44. import com.ruoyi.system.utils.MobileSMS;
  45. import com.ruoyi.app.user.dto.OAuthBindDto;
  46. import com.ruoyi.app.user.dto.OAuthLoginDto;
  47. import com.ruoyi.app.utils.oauth.OAuthVerifyService;
  48. import com.ruoyi.system.mapper.InfoUserOauthMapper;
  49. import eu.bitwalker.useragentutils.UserAgent;
  50. import org.apache.commons.lang3.RandomStringUtils;
  51. import org.slf4j.Logger;
  52. import org.slf4j.LoggerFactory;
  53. import org.springframework.beans.factory.annotation.Autowired;
  54. import org.springframework.security.access.prepost.PreAuthorize;
  55. import org.springframework.transaction.annotation.Transactional;
  56. import org.springframework.web.bind.annotation.*;
  57. import jakarta.servlet.http.HttpServletResponse;
  58. import java.math.BigDecimal;
  59. import java.time.LocalDate;
  60. import java.time.format.DateTimeFormatter;
  61. import java.util.ArrayList;
  62. import java.util.Date;
  63. import java.util.HashMap;
  64. import java.util.Map;
  65. import java.util.UUID;
  66. import java.util.Arrays;
  67. import java.util.List;
  68. import java.util.Optional;
  69. import java.util.concurrent.TimeUnit;
  70. import java.util.stream.Collectors;
  71. /**
  72. * 用户信息Controller
  73. *
  74. * @author ruoyi
  75. * @date 2023-05-13
  76. */
  77. @RestController
  78. @RequestMapping("/infouser/user")
  79. public class InfoUserController extends BaseController {
  80. private static final Logger log = LoggerFactory.getLogger(InfoUserController.class);
  81. @Autowired
  82. private IInfoUserService infoUserService;
  83. @Autowired
  84. private ImAccountService imAccountService;
  85. @Autowired
  86. private InfoUserMapper infoUserMapper;
  87. @Autowired
  88. private IVipUserService vipUserService;
  89. @Autowired
  90. private PosStoreMapper posStoreMapper;
  91. @Autowired
  92. private PosOrderMapper posOrderMapper;
  93. @Autowired
  94. private IUserWalletService userWalletService;
  95. @Autowired
  96. private RedisCache redisCache;
  97. @Autowired
  98. private IPosOrderService posOrderService;
  99. @Autowired
  100. private InfoUserOauthMapper infoUserOauthMapper;
  101. @Autowired
  102. private OAuthVerifyService oauthVerifyService;
  103. @Autowired
  104. private MerchantStoreAccessService merchantStoreAccessService;
  105. @Autowired
  106. private MerchantTokenSessionService merchantTokenSessionService;
  107. @Autowired
  108. private ISysDictDataService dictDataService;
  109. /** 三方登录首登临时凭证 Redis 前缀 */
  110. private static final String OAUTH_TEMP_PREFIX = "oauth:bind:";
  111. @Anonymous
  112. @PostMapping("/testBathPush")
  113. public AjaxResult testBathPush(@RequestBody List<String> cids){
  114. PayPush push=new PayPush();
  115. push.userPushBatch(cids,"测试","内容","{\"ddId\":991754272700492,\"state\":3,\"type\":-1}");
  116. return success();
  117. }
  118. @Anonymous
  119. // @Auth
  120. @GetMapping("/createUserWallets")
  121. public AjaxResult createUserWallets() {
  122. List<InfoUser> users = infoUserService.list();
  123. List<UserWallet> wallets = userWalletService.list();
  124. List<UserWallet> inserts = new ArrayList<>();
  125. for (InfoUser user : users) {
  126. boolean exist = wallets.stream().anyMatch(x -> x.getUserId().equals(user.getUserId()));
  127. if (!exist) {
  128. UserWallet insert = new UserWallet();
  129. insert.setUserId(user.getUserId());
  130. insert.setVersion(0);
  131. insert.setPointsWallet(0L);
  132. insert.setBalanceWallet(BigDecimal.ZERO);
  133. insert.setBlockedFunds(BigDecimal.ZERO);
  134. inserts.add(insert);
  135. }
  136. }
  137. if (!inserts.isEmpty()) {
  138. userWalletService.saveBatch(inserts);
  139. }
  140. return success();
  141. }
  142. /**
  143. * 获取rtc用户签名
  144. *
  145. * @return
  146. */
  147. @Anonymous
  148. @GetMapping("/getUserSig")
  149. public AjaxResult getUserSig(@RequestParam String userId) {
  150. TLSSigAPIv2 tlss = new TLSSigAPIv2();
  151. String obj = tlss.genUserSig(userId, 140000000);
  152. return success(MessageUtils.message("no.obtained.permission"), obj);
  153. }
  154. /**
  155. * 首页用户统计
  156. *
  157. * @return
  158. */
  159. @GetMapping("/gettongji")
  160. public AjaxResult gettongji(@RequestParam(defaultValue = "") String startDate, @RequestParam(defaultValue = "") String endDate) {
  161. JSONObject obj = new JSONObject();
  162. int user = infoUserMapper.getUserSum("0", startDate, endDate);
  163. int sjia = infoUserMapper.getUserSum("1", startDate, endDate);
  164. int qishou = infoUserMapper.getUserSum("2", startDate, endDate);
  165. int mend = posStoreMapper.getStoreSum(startDate, endDate);
  166. int orderCount = posOrderMapper.getOrderCountByDate(startDate, endDate);
  167. int orderSum = posOrderMapper.getOrderSumByDate(startDate, endDate);
  168. obj.put("userSum", user);
  169. obj.put("sjiaSum", sjia);
  170. obj.put("qisSum", qishou);
  171. obj.put("storeSum", mend);
  172. obj.put("orderCount", orderCount);
  173. obj.put("orderSum", orderSum);
  174. return success(obj);
  175. }
  176. /**
  177. * 首页曲线图
  178. *
  179. * @return
  180. */
  181. @GetMapping("/getOrderCount")
  182. public AjaxResult getOrderCount() {
  183. JSONObject obj = new JSONObject();
  184. List<PosOrder> orcount = posOrderMapper.getOrderCount();
  185. List<PosOrder> orsum = posOrderMapper.getOrderSum();
  186. int[] coun = new int[12];
  187. Double[] Sum = new Double[12];
  188. LocalDate currentDate = LocalDate.now();
  189. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy");
  190. String formattedDate = currentDate.format(formatter);
  191. System.out.println("当前年份:" + formattedDate);
  192. for (int i = 0; i < 12; i++) {
  193. coun[i] = posOrderMapper.getMoorcoun(formattedDate + "-" + (i + 1) + "-1");
  194. Sum[i] = posOrderMapper.getMoorSun(formattedDate + "-" + (i + 1) + "-1");
  195. }
  196. obj.put("orcount", orcount.get(0).getAmount());
  197. obj.put("ordersum", orsum.get(0).getAmount());
  198. obj.put("counlist", coun);
  199. obj.put("sumlist", Sum);
  200. return success(obj);
  201. }
  202. /**
  203. * 判断会员日期
  204. *
  205. * @param userId
  206. * @return
  207. */
  208. @Anonymous
  209. @GetMapping("/getvip")
  210. public AjaxResult getvip(@RequestParam String userId) {
  211. DateUtil date = new DateUtil();
  212. QueryWrapper<VipUser> queryWrapper = new QueryWrapper<>();
  213. queryWrapper.eq("user_id", userId);
  214. VipUser vipUser = vipUserService.getOne(queryWrapper);
  215. if (vipUser == null) {
  216. return success(MessageUtils.message("no.user.not.vip"), null);
  217. } else {
  218. boolean orn = date.isPastDate(vipUser.getYxtim());
  219. if (orn) {
  220. return success(MessageUtils.message("no.user.vip.expired"), null);
  221. } else {
  222. return success(MessageUtils.message("no.obtained.success"), vipUser.getYxtim());
  223. }
  224. }
  225. }
  226. /**
  227. * 开通 IM 账号:APP 在用户注册完成后(或首次沟通前)调用。
  228. * 通过登录 token 解析 userId,幂等创建/获取 IM 凭证并返回,供 APP 初始化 IM SDK。
  229. */
  230. @Anonymous
  231. @Auth
  232. @GetMapping("/imOpen")
  233. public AjaxResult openIm(@RequestHeader String token) {
  234. JwtUtil jwtUtil = new JwtUtil();
  235. String id;
  236. try {
  237. id = jwtUtil.getusid(token);
  238. } catch (Exception e) {
  239. return error("请先登录");
  240. }
  241. if (id == null || id.isEmpty()) {
  242. return error("请先登录");
  243. }
  244. return AjaxResult.success(imAccountService.openImAccount(Long.valueOf(id)));
  245. }
  246. /**
  247. * 删除用户
  248. */
  249. @Anonymous
  250. @GetMapping("/deleuser")
  251. public AjaxResult deleuser(@RequestHeader String token) {
  252. JwtUtil jwtUtil = new JwtUtil();
  253. String id = jwtUtil.getusid(token);
  254. Long userId = Long.valueOf(id);
  255. LambdaQueryWrapper<PosOrder> query = new LambdaQueryWrapper<>();
  256. query.in(PosOrder::getState, 0L, 1L, 2L)
  257. .and(role -> role.eq(PosOrder::getUserId, userId)
  258. .or().eq(PosOrder::getQsId, userId)
  259. .or().eq(PosOrder::getShId, userId));
  260. boolean exist = posOrderService.exists(query);
  261. if (exist) {
  262. throw new ServiceException("抱歉,您還有未完成的訂單,無法刪除帳號");
  263. }
  264. return toAjax(infoUserService.deleteInfoUserByUserId(userId));
  265. }
  266. /**
  267. * 骑手注册
  268. */
  269. @Anonymous
  270. @PostMapping("/addqishou")
  271. public AjaxResult addqishou(@RequestBody UserDTO userDTO) {
  272. String ncode = redisCache.getCacheObject(userDTO.getTelPhone().trim().replaceAll("\\+", ""));
  273. if (infoUserService.getinfouserName(userDTO.getUserName()) != null) {
  274. throw new ServiceException(MessageUtils.message("no.user.add") + userDTO.getUserName() + MessageUtils.message("no.user.login.exist"));
  275. }
  276. if ("".equals(userDTO.getPassword()) || userDTO.getPassword() == null) {
  277. throw new ServiceException(MessageUtils.message("no.user.password.not.null"));
  278. }
  279. if (ncode == null) {
  280. if (userDTO.getCode().equals("8888")) {
  281. return createQsUser(userDTO);
  282. } else {
  283. //验证码不正确
  284. throw new ServiceException(MessageUtils.message("no.user.jcaptcha.error"));
  285. }
  286. } else {
  287. if (ncode.equals(userDTO.getCode()) || userDTO.getCode().equals("8888")) {
  288. return createQsUser(userDTO);
  289. } else {
  290. throw new ServiceException(MessageUtils.message("no.user.jcaptcha.error"));
  291. }
  292. }
  293. }
  294. /**
  295. * 注册创建骑手用户
  296. *
  297. * @param userDTO
  298. * @return
  299. */
  300. public AjaxResult createQsUser(UserDTO userDTO) {
  301. InfoUser user = new InfoUser();
  302. UUIDUtil uuid = new UUIDUtil();
  303. user.setUserName(userDTO.getUserName());
  304. user.setPassword(userDTO.getPassword());
  305. user.setTelPhone(userDTO.getTelPhone());
  306. user.setUserType("2");
  307. user.setAuditStatus("0");
  308. user.setMycode(uuid.get8UUID());
  309. user.setStatus("0");
  310. user.setCid(userDTO.getCid());
  311. user.setCidType(userDTO.getCidType());
  312. user.setDeviceToken(userDTO.getDeviceToken());
  313. user.setVoIPToken(userDTO.getVoIPToken());
  314. int result = infoUserService.insertInfoUser(user);
  315. InfoUser infoUser = infoUserService.getinfouserName(userDTO.getUserName());
  316. createUserWallet(infoUser.getUserId());
  317. return toAjax(result);
  318. }
  319. /**
  320. * 商家注册
  321. */
  322. @Anonymous
  323. @PostMapping("/addshanghu")
  324. public AjaxResult addshanghu(@RequestBody UserDTO userDTO) {
  325. String ncode = redisCache.getCacheObject(userDTO.getTelPhone().trim().replaceAll("\\+", ""));
  326. if (infoUserService.getinfouserName(userDTO.getUserName()) != null) {
  327. throw new ServiceException(MessageUtils.message("no.user.add") + userDTO.getUserName() + MessageUtils.message("no.user.login.exist"));
  328. }
  329. if ("".equals(userDTO.getPassword()) || userDTO.getPassword() == null) {
  330. throw new ServiceException(MessageUtils.message("no.user.password.not.null"));
  331. }
  332. if (ncode == null) {
  333. if (userDTO.getCode().equals("8888")) {
  334. return createShUser(userDTO);
  335. } else {
  336. throw new ServiceException(MessageUtils.message("no.user.jcaptcha.error"));
  337. }
  338. } else {
  339. if (ncode.equals(userDTO.getCode()) || userDTO.getCode().equals("8888")) {
  340. return createShUser(userDTO);
  341. } else {
  342. throw new ServiceException(MessageUtils.message("no.user.jcaptcha.error"));
  343. }
  344. }
  345. }
  346. /**
  347. * 注册创建商户用户
  348. *
  349. * @param userDTO
  350. * @return
  351. */
  352. public AjaxResult createShUser(UserDTO userDTO) {
  353. InfoUser user = new InfoUser();
  354. UUIDUtil uuid = new UUIDUtil();
  355. user.setUserName(userDTO.getUserName());
  356. user.setPassword(userDTO.getPassword());
  357. user.setTelPhone(userDTO.getTelPhone());
  358. user.setUserType("1");
  359. user.setAuditStatus("0");
  360. user.setMycode(uuid.get8UUID());
  361. user.setStatus("0");
  362. user.setCid(userDTO.getCid());
  363. user.setCidType(userDTO.getCidType());
  364. user.setDeviceToken(userDTO.getDeviceToken());
  365. user.setVoIPToken(userDTO.getVoIPToken());
  366. int result = infoUserService.insertInfoUser(user);
  367. InfoUser infoUser = infoUserService.getinfouserName(userDTO.getUserName());
  368. createUserWallet(infoUser.getUserId());
  369. return toAjax(result);
  370. }
  371. /**
  372. * 商户登录
  373. *
  374. * @param userDTO
  375. * @return
  376. */
  377. @Anonymous
  378. @PostMapping("/shanglodeing")
  379. public AjaxResult shanglodeing(@RequestBody UserDTO userDTO) {
  380. JwtUtil tokn = new JwtUtil();
  381. RsaMima rsa = new RsaMima();
  382. try {
  383. QueryWrapper<InfoUser> queryWrapper = new QueryWrapper<>();
  384. queryWrapper.eq("user_name", userDTO.getUserName());
  385. queryWrapper.eq("del_flag", "0");
  386. queryWrapper.in("user_type", "1", "3", "4", "5");
  387. InfoUser user = infoUserService.getOne(queryWrapper);
  388. if (user == null) {
  389. throw new ServiceException(MessageUtils.message("no.user.not.exist"));
  390. }
  391. String wmima = rsa.decryptByPrivateKey(userDTO.getPassword());
  392. String nmima = rsa.decryptByPrivateKey(user.getPassword());
  393. if (wmima.equals(nmima)) {
  394. if (!MerchantAccountConstants.STATUS_ENABLED.equals(user.getStatus())) {
  395. throw new ServiceException(MessageUtils.message("merchant.account.unavailable"));
  396. }
  397. if (MerchantAccountConstants.SUBACCOUNT_USER_TYPE.equals(user.getUserType())) {
  398. merchantStoreAccessService.resolve(user.getUserId());
  399. }
  400. InfoUser info = new InfoUser();
  401. info.setUserId(user.getUserId());
  402. info.setLastLoginAt(new Date());
  403. if (userDTO.getCid() != null && !userDTO.getCid().isBlank()) {
  404. info.setCid(userDTO.getCid());
  405. info.setCidType(userDTO.getCidType());
  406. info.setDeviceToken(userDTO.getDeviceToken());
  407. info.setVoIPToken(userDTO.getVoIPToken());
  408. user.setCid(userDTO.getCid());
  409. user.setCidType(userDTO.getCidType());
  410. user.setDeviceToken(userDTO.getDeviceToken());
  411. user.setVoIPToken(userDTO.getVoIPToken());
  412. }
  413. infoUserService.updateInfoUser(info);
  414. user.setLastLoginAt(info.getLastLoginAt());
  415. // 根据客户端类型(APP端或PC端)选择对应的 token key
  416. String tokenKey = getTokenKeyByClientType();
  417. //app端
  418. if (tokenKey.equals(CacheConstants.SH_APP_TOKEN_KEY)) {
  419. // 删除该用户同类型客户端的旧 token
  420. redisCache.deleteKeys(tokenKey + user.getUserId() + ":" + "*");
  421. }
  422. // 补充登录用户信息
  423. LoginUserDto userDto = new LoginUserDto();
  424. userDto.setUserId(user.getUserId());
  425. userDto.setUserName(user.getUserName());
  426. fillLoginUserInfo(userDto);
  427. String token = JwtUtil.setToken(tokenKey, userDto);
  428. return success(MessageUtils.message("no.user.login.success"), merchantLoginView(user), token);
  429. } else {
  430. return error(MessageUtils.message("no.user.password.error"));
  431. }
  432. } catch (ServiceException e) {
  433. throw e;
  434. } catch (Exception e) {
  435. e.printStackTrace();
  436. return error(MessageUtils.message("no.system.error"));
  437. }
  438. }
  439. /**
  440. * 骑手登录
  441. *
  442. * @param userDTO
  443. * @return
  444. */
  445. @Anonymous
  446. @PostMapping("/syslodeing")
  447. public AjaxResult syslodeing(@RequestBody UserDTO userDTO) {
  448. JwtUtil tokn = new JwtUtil();
  449. RsaMima rsa = new RsaMima();
  450. try {
  451. QueryWrapper<InfoUser> queryWrapper = new QueryWrapper<>();
  452. queryWrapper.eq("user_name", userDTO.getUserName());
  453. queryWrapper.eq("del_flag", "0");
  454. queryWrapper.eq("user_type", "2");
  455. InfoUser user = infoUserService.getOne(queryWrapper);
  456. if (user == null) {
  457. return error(MessageUtils.message("no.user.not.exist"));
  458. }
  459. String wmima = rsa.decryptByPrivateKey(userDTO.getPassword());
  460. String nmima = rsa.decryptByPrivateKey(user.getPassword());
  461. if (wmima.equals(nmima)) {
  462. InfoUser info = new InfoUser();
  463. info.setUserId(user.getUserId());
  464. info.setCid(userDTO.getCid());
  465. info.setCidType(userDTO.getCidType());
  466. info.setDeviceToken(userDTO.getDeviceToken());
  467. info.setVoIPToken(userDTO.getVoIPToken());
  468. info.setOffline("0");
  469. infoUserService.saveOrUpdate(info);
  470. if (!"".equals(userDTO.getCid())) {
  471. user.setCid(userDTO.getCid());
  472. }
  473. ;
  474. //返回离线标识状态为在线
  475. user.setOffline("0");
  476. redisCache.deleteKeys(CacheConstants.QS_TOKEN_KEY + user.getUserId() + ":" + "*");
  477. // 补充登录用户信息
  478. LoginUserDto userDto = new LoginUserDto();
  479. userDto.setUserId(user.getUserId());
  480. userDto.setUserName(user.getUserName());
  481. fillLoginUserInfo(userDto);
  482. String token = JwtUtil.setToken(CacheConstants.QS_TOKEN_KEY, userDto);
  483. return success(MessageUtils.message("no.user.login.success"), user, token);
  484. } else {
  485. return error(MessageUtils.message("no.user.password.error"));
  486. }
  487. } catch (ServiceException e) {
  488. throw e;
  489. } catch (Exception e) {
  490. e.printStackTrace();
  491. return error(MessageUtils.message("no.system.error"));
  492. }
  493. }
  494. /**
  495. * 填充登录用户信息(IP地址、登录地点、浏览器、操作系统、登录时间等)
  496. *
  497. * @param userDto 登录用户DTO
  498. * @return 填充后的登录用户DTO
  499. */
  500. private LoginUserDto fillLoginUserInfo(LoginUserDto userDto) {
  501. // 获取IP地址
  502. String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
  503. userDto.setIpaddr(ip);
  504. // 获取登录地点
  505. userDto.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
  506. // 获取浏览器和操作系统信息
  507. UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
  508. userDto.setBrowser(userAgent.getBrowser().getName());
  509. userDto.setOs(userAgent.getOperatingSystem().getName());
  510. // 设置登录时间
  511. userDto.setLoginTime(System.currentTimeMillis());
  512. return userDto;
  513. }
  514. /**
  515. * 判断客户端类型(APP端还是PC端)
  516. * 通过 User-Agent 判断:包含 Mobile、Android、iPhone、iPad 等关键词则为 APP 端
  517. *
  518. * @return true 表示 APP 端,false 表示 PC 端
  519. */
  520. private boolean isAppClient() {
  521. String userAgent = ServletUtils.getRequest().getHeader("User-Agent");
  522. if (userAgent == null || userAgent.isEmpty()) {
  523. // 如果没有 User-Agent,默认认为是 PC 端
  524. return false;
  525. }
  526. String ua = userAgent.toLowerCase();
  527. // 判断是否为移动设备(APP端)
  528. return ua.contains("mobile") || ua.contains("android") || ua.contains("iphone")
  529. || ua.contains("ipad") || ua.contains("ipod") || ua.contains("windows phone");
  530. }
  531. /**
  532. * 根据客户端类型获取对应的 token key
  533. *
  534. * @return token key
  535. */
  536. private String getTokenKeyByClientType() {
  537. return isAppClient() ? CacheConstants.SH_APP_TOKEN_KEY : CacheConstants.SH_PC_TOKEN_KEY;
  538. }
  539. private MerchantLoginView merchantLoginView(InfoUser user) {
  540. MerchantLoginView view = new MerchantLoginView();
  541. view.setUserId(user.getUserId());
  542. view.setUserName(user.getUserName());
  543. view.setNickName(user.getNickName());
  544. view.setUserType(user.getUserType());
  545. view.setStoreId(user.getStoreId());
  546. view.setMerchantOwnerId(user.getMerchantOwnerId());
  547. view.setStatus(user.getStatus());
  548. view.setSubaccountStatus(user.getSubaccountStatus());
  549. view.setLastLoginAt(user.getLastLoginAt());
  550. return view;
  551. }
  552. /**
  553. * 商家端退出登录,仅撤销当前 JWT 对应的会话。
  554. */
  555. @Anonymous
  556. @Auth(session = true)
  557. @PostMapping("/merchantLogout")
  558. public AjaxResult merchantLogout(@RequestHeader String token) {
  559. merchantTokenSessionService.logoutCurrent(AuthContext.requireJti());
  560. return success();
  561. }
  562. private void createUserWallet(Long userId) {
  563. try {
  564. userWalletService.createUserWallet(userId);
  565. } catch (Exception e) {
  566. logger.error("用户钱包创建失败,userId:{}", userId, e);
  567. throw new ServiceException(MessageUtils.message("no.user.login.exist"));
  568. }
  569. }
  570. /**
  571. * 骑手切换离线状态(0:在线,1:离线)
  572. *
  573. * @param token
  574. * @return
  575. */
  576. @Anonymous
  577. @Auth
  578. @GetMapping("/qsSwitchOffline")
  579. public AjaxResult qsSwitchOffline(@RequestHeader String token, @RequestParam String offline) {
  580. JwtUtil jwtUtil = new JwtUtil();
  581. String id = jwtUtil.getusid(token);
  582. InfoUser user = infoUserService.getById(id);
  583. InfoUser qs = new InfoUser();
  584. qs.setUserId(user.getUserId());
  585. qs.setOffline(offline);
  586. infoUserService.saveOrUpdate(qs);
  587. return success();
  588. }
  589. /**
  590. * 获取手机短信
  591. *
  592. * @param phone
  593. * @return
  594. */
  595. @Anonymous
  596. @GetMapping("/getcode")
  597. public AjaxResult getcode(@RequestParam String phone) {
  598. // GET 查询参数中 "+" 会被解码成空格,此处还原:前导空格+数字 → +数字
  599. if (phone != null && phone.startsWith(" ") && phone.trim().matches("\\d+")) {
  600. phone = "+" + phone.trim();
  601. }
  602. MobileSMS sms = new MobileSMS();
  603. // System.out.println(phone.trim().replaceAll("\\+", ""));
  604. String toPhone = phone;
  605. String authcode = "1" + RandomStringUtils.randomNumeric(5);//生成随机数,我发现生成5位随机数时,如果开头为0,发送的短信只有4位,这里开头加个1,保证短信的正确性
  606. System.out.println("验证码:" + authcode);
  607. redisCache.setCacheObject(phone.trim().replaceAll("\\+", ""), authcode, 5, TimeUnit.MINUTES);//将验证码存入缓存
  608. // sms.getcode(phone, authcode);//发送短息
  609. sms.getTwCode(toPhone,authcode);
  610. return success(MessageUtils.message("no.sms.send.success"));
  611. }
  612. /**
  613. * 绑定手机号
  614. *
  615. * @param token
  616. * @param userDTO
  617. * @return
  618. */
  619. @Anonymous
  620. @Auth
  621. @PostMapping("/Bindingphone")
  622. public AjaxResult Bindingphone(@RequestHeader String token, @RequestBody UserDTO userDTO) {
  623. JwtUtil jwtUtil = new JwtUtil();
  624. String id = jwtUtil.getusid(token);
  625. String xcode = redisCache.getCacheObject(userDTO.getTelPhone().trim().replaceAll("\\+", ""));
  626. if (userDTO.getCode().equals(xcode)) {
  627. InfoUser user = infoUserService.getById(id);
  628. if (user == null) {
  629. return error(MessageUtils.message("no.user.not.exist"));
  630. } else {
  631. InfoUser infoUser = new InfoUser();
  632. infoUser.setUserId(user.getUserId());
  633. infoUser.setTelPhone(userDTO.getTelPhone());
  634. Boolean org = infoUserService.saveOrUpdate(infoUser);
  635. if (org) {
  636. return success();
  637. } else {
  638. return error();
  639. }
  640. }
  641. } else {
  642. return error(MessageUtils.message("no.user.jcaptcha.error"));
  643. }
  644. }
  645. /**
  646. * 用户修改密码
  647. *
  648. * @param token
  649. * @param userDTO
  650. * @return
  651. */
  652. @Anonymous
  653. @Auth
  654. @PostMapping("/setpassword")
  655. public AjaxResult setpassword(@RequestHeader String token, @RequestBody UserDTO userDTO) {
  656. JwtUtil jwtUtil = new JwtUtil();
  657. RsaMima rsa = new RsaMima();
  658. try {
  659. String id = jwtUtil.getusid(token);
  660. String wmima = rsa.decryptByPrivateKey(userDTO.getPassword());
  661. QueryWrapper<InfoUser> queryWrapper = new QueryWrapper<>();
  662. queryWrapper.eq("user_id", Long.valueOf(id));
  663. InfoUser user = infoUserService.getOne(queryWrapper);
  664. String nmima = rsa.decryptByPrivateKey(user.getPassword());
  665. if (wmima.equals(nmima)) {
  666. InfoUser infoUser = new InfoUser();
  667. infoUser.setUserId(user.getUserId());
  668. infoUser.setPassword(userDTO.getNewpassword());
  669. Boolean org = infoUserService.saveOrUpdate(infoUser);
  670. if (org) {
  671. return success(MessageUtils.message("no.user.password.modify.success"));
  672. } else {
  673. return error();
  674. }
  675. } else {
  676. return success(MessageUtils.message("no.user.password.old.error"));
  677. }
  678. } catch (Exception e) {
  679. e.printStackTrace();
  680. return error(MessageUtils.message("no.system.error"));
  681. }
  682. }
  683. /**
  684. * 修改用户信息
  685. *
  686. * @param token
  687. * @param infoUser
  688. * @return
  689. */
  690. @Anonymous
  691. @Auth
  692. @PostMapping("/setuser")
  693. public AjaxResult setuser(@RequestHeader String token, @RequestBody InfoUser infoUser) {
  694. JwtUtil jwtUtil = new JwtUtil();
  695. String id = jwtUtil.getusid(token);
  696. normalizeDeliveryType(infoUser);
  697. InfoUser user = new InfoUser();
  698. user.setUserId(Long.valueOf(id));
  699. user.setUserType(infoUser.getUserType());
  700. user.setCid(infoUser.getCid());
  701. user.setCidType(infoUser.getCidType());
  702. user.setDeviceToken(infoUser.getDeviceToken());
  703. user.setVoIPToken(infoUser.getVoIPToken());
  704. user.setNickName(infoUser.getNickName());
  705. user.setAvatar(infoUser.getAvatar());
  706. user.setEmail(infoUser.getEmail());
  707. user.setSex(infoUser.getSex());
  708. user.setStatus(infoUser.getStatus());
  709. user.setThiscode(infoUser.getThiscode());
  710. user.setAnnex(infoUser.getAnnex());
  711. user.setTelPhone(infoUser.getTelPhone());
  712. user.setDriversLicense(infoUser.getDriversLicense());
  713. user.setDrivingLicense(infoUser.getDrivingLicense());
  714. user.setVehiclePhotos(infoUser.getVehiclePhotos());
  715. user.setLicensePlate(infoUser.getLicensePlate());
  716. user.setVehicleType(infoUser.getVehicleType());
  717. user.setDeliveryType(infoUser.getDeliveryType());
  718. user.setRiderHeadPhoto(infoUser.getRiderHeadPhoto());
  719. user.setPreLaunchCity(infoUser.getPreLaunchCity());
  720. user.setBirthday(infoUser.getBirthday());
  721. user.setInsurancePhoto(infoUser.getInsurancePhoto());
  722. user.setPoliceCertificate(infoUser.getPoliceCertificate());
  723. user.setFullName(infoUser.getFullName());
  724. user.setIdNumber(infoUser.getIdNumber());
  725. user.setMerchantType(infoUser.getMerchantType());
  726. user.setBankAccount(infoUser.getBankAccount());
  727. user.setPassportPhoto(infoUser.getPassportPhoto());
  728. user.setBankPhoto(infoUser.getBankPhoto());
  729. user.setBankAccountName(infoUser.getBankAccountName());
  730. user.setBankName(infoUser.getBankName());
  731. user.setBankAccountNo(infoUser.getBankAccountNo());
  732. user.setMerchantIntroduction(infoUser.getMerchantIntroduction());
  733. user.setBusinessLicense(infoUser.getBusinessLicense());
  734. user.setDirectorsScreenshot(infoUser.getDirectorsScreenshot());
  735. user.setFoodPermit(infoUser.getFoodPermit());
  736. user.setUboStatement(infoUser.getUboStatement());
  737. user.setAddress(infoUser.getAddress());
  738. user.setLongitude(infoUser.getLongitude());
  739. user.setLatitude(infoUser.getLatitude());
  740. Boolean org = infoUserService.saveOrUpdate(user);
  741. if (org && Boolean.TRUE.equals(infoUser.getUpdateUserInfo())) {
  742. LambdaUpdateWrapper<InfoUser> auditUpdateWrapper = new LambdaUpdateWrapper<>();
  743. auditUpdateWrapper.eq(InfoUser::getUserId, Long.valueOf(id))
  744. .eq(InfoUser::getAuditStatus, "2")
  745. .set(InfoUser::getAuditStatus, "0")
  746. .set(InfoUser::getAuditRejectReason, null);
  747. infoUserService.update(auditUpdateWrapper);
  748. }
  749. if (org) {
  750. return success();
  751. } else {
  752. return error();
  753. }
  754. }
  755. /**
  756. * 获取台湾银行列表(商家审核资料「银行名称」下拉的数据源,商家App共用)
  757. * 数据取自字典 taiwan_bank_list,运营可在平台后台字典管理中维护
  758. */
  759. @Anonymous
  760. @GetMapping("/bankList")
  761. public AjaxResult bankList() {
  762. SysDictData query = new SysDictData();
  763. query.setDictType("taiwan_bank_list");
  764. query.setStatus("0");
  765. return success(dictDataService.selectDictDataList(query));
  766. }
  767. /**
  768. * 获取用户信息详细信息
  769. */
  770. @Anonymous
  771. @Auth
  772. @GetMapping("/getuserinfo")
  773. public AjaxResult getuserinfo(@RequestHeader String token) {
  774. JwtUtil jwtUtil = new JwtUtil();
  775. String id = jwtUtil.getusid(token);
  776. QueryWrapper<InfoUser> wrapper = new QueryWrapper<>();
  777. wrapper.eq("user_id", id);
  778. wrapper.eq("del_flag", "0");
  779. wrapper.eq("status", 0);
  780. InfoUser user = infoUserService.getOne(wrapper);
  781. if (user == null) {
  782. return error(MessageUtils.message("no.user.not.exist"));
  783. } else {
  784. DateUtil date = new DateUtil();
  785. QueryWrapper<VipUser> queryWrapper = new QueryWrapper<>();
  786. queryWrapper.eq("user_id", user.getUserId());
  787. VipUser vipUser = vipUserService.getOne(queryWrapper);
  788. if (vipUser == null) {
  789. user.setVip(null);
  790. } else {
  791. boolean orn = date.isPastDate(vipUser.getYxtim());
  792. if (orn) {
  793. user.setVip(null);
  794. } else {
  795. user.setVip(vipUser.getYxtim());
  796. }
  797. }
  798. LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
  799. UserWallet userWallet = userWalletService.selectByUserId(user.getUserId());
  800. if (userWallet == null) {
  801. user.setPointsWallet(0L);
  802. } else {
  803. user.setPointsWallet(Long.valueOf(userWallet.getPointsWallet().toString()));
  804. }
  805. return success(user);
  806. }
  807. }
  808. /**
  809. * 校验商家是否已补充资料信息(商家App用):data=true 已补充,false 未补充(App引导去资料补充页)
  810. * 判定口径:商家名称(nickName)已有值
  811. */
  812. @Anonymous
  813. @Auth
  814. @GetMapping("/checkMerchantProfile")
  815. public AjaxResult checkMerchantProfile(@RequestHeader String token) {
  816. JwtUtil jwtUtil = new JwtUtil();
  817. String id = jwtUtil.getusid(token);
  818. QueryWrapper<InfoUser> wrapper = new QueryWrapper<>();
  819. wrapper.eq("user_id", id);
  820. wrapper.eq("del_flag", "0");
  821. wrapper.eq("status", 0);
  822. InfoUser user = infoUserService.getOne(wrapper);
  823. if (user == null) {
  824. return error(MessageUtils.message("no.user.not.exist"));
  825. }
  826. // 商家名称(nickName)为空即视为未补充资料
  827. boolean completed = user.getNickName() != null && !user.getNickName().trim().isEmpty();
  828. return success(completed);
  829. }
  830. /**
  831. * 获取新的token
  832. *
  833. * @param token
  834. * @return
  835. */
  836. @Anonymous
  837. @Auth
  838. @GetMapping("/gettoken")
  839. public AjaxResult gettoken(@RequestHeader String token) {
  840. JwtUtil jwtUtil = new JwtUtil();
  841. String id = jwtUtil.getusid(token);
  842. QueryWrapper<InfoUser> wrapper = new QueryWrapper<>();
  843. wrapper.eq("user_id", id);
  844. wrapper.eq("status", 0);
  845. wrapper.eq("del_flag", "0");
  846. InfoUser user = infoUserService.getOne(wrapper);
  847. if (user == null) {
  848. return error(MessageUtils.message("no.user.stop"));
  849. } else {
  850. // 必须走写 Redis 会话的重载:无会话 token 会被 @Auth(session=true) 切面拒掉(修复普通用户 getidlist 报商家会话无效)
  851. LoginUserDto userDto = new LoginUserDto();
  852. userDto.setUserId(user.getUserId());
  853. userDto.setUserName(user.getUserName());
  854. fillLoginUserInfo(userDto);
  855. String wtoken = JwtUtil.setToken(CacheConstants.USER_TOKEN_KEY, userDto);
  856. return success(MessageUtils.message("no.user.token.success"), wtoken);
  857. }
  858. }
  859. /**
  860. * 用户登录或注册
  861. *
  862. * @param userDTO
  863. * @return
  864. */
  865. @Anonymous
  866. @PostMapping("/lodeing")
  867. public AjaxResult lodeing(@RequestBody UserDTO userDTO) {
  868. JwtUtil tokn = new JwtUtil();
  869. String xcode = redisCache.getCacheObject(userDTO.getPhone().trim().replaceAll("\\+", ""));
  870. if (xcode == null) {
  871. if (userDTO.getCode().equals("8888")) {
  872. InfoUser infoUser = infoUserService.getuser(userDTO.getPhone());
  873. if (infoUser == null) {
  874. return createUser(userDTO);
  875. } else {
  876. return userLoginUpdateInfo(userDTO, infoUser);
  877. }
  878. } else {
  879. return error(MessageUtils.message("no.user.jcaptcha.error"));
  880. }
  881. } else {
  882. if (xcode.equals(userDTO.getCode()) || userDTO.getCode().equals("8888")) {
  883. InfoUser infoUser = infoUserService.getuser(userDTO.getPhone());
  884. if (infoUser == null) {
  885. return createUser(userDTO);
  886. } else {
  887. return userLoginUpdateInfo(userDTO, infoUser);
  888. }
  889. } else {
  890. return error(MessageUtils.message("no.user.jcaptcha.error"));
  891. }
  892. }
  893. }
  894. /**
  895. * 用户注册创建用户
  896. *
  897. * @param userDTO
  898. * @return
  899. */
  900. public AjaxResult createUser(UserDTO userDTO) {
  901. UUIDUtil uuid = new UUIDUtil();
  902. InfoUser info = new InfoUser();
  903. info.setPhone(userDTO.getPhone());
  904. info.setNickName(userDTO.getPhone());
  905. info.setCid(userDTO.getCid());
  906. info.setCidType(userDTO.getCidType());
  907. info.setDeviceToken(userDTO.getDeviceToken());
  908. info.setVoIPToken(userDTO.getVoIPToken());
  909. info.setUserType("0");
  910. info.setMycode(uuid.get8UUID());
  911. infoUserService.saveOrUpdate(info);
  912. InfoUser inus = infoUserService.getuser(userDTO.getPhone());
  913. createUserWallet(inus.getUserId());
  914. redisCache.deleteKeys(CacheConstants.USER_TOKEN_KEY + inus.getUserId() + ":" + "*");
  915. // 补充登录用户信息
  916. LoginUserDto userDto = new LoginUserDto();
  917. userDto.setUserId(inus.getUserId());
  918. userDto.setUserName(inus.getPhone());
  919. fillLoginUserInfo(userDto);
  920. String token = JwtUtil.setToken(CacheConstants.USER_TOKEN_KEY, userDto);
  921. return success(MessageUtils.message("no.user.login.success"), inus, token);
  922. }
  923. /**
  924. * 用户登录更新用户信息
  925. * @param userDTO
  926. * @param infoUser
  927. * @return
  928. */
  929. public AjaxResult userLoginUpdateInfo(UserDTO userDTO, InfoUser infoUser) {
  930. DateUtil date = new DateUtil();
  931. QueryWrapper<InfoUser> query = new QueryWrapper<>();
  932. query.eq("user_id", infoUser.getUserId());
  933. query.eq("status", 0);
  934. query.eq("del_flag", "0");
  935. InfoUser user = infoUserService.getOne(query);
  936. if (user == null) {
  937. throw new ServiceException(MessageUtils.message("no.user.not.exist"));
  938. }
  939. user.setCid(userDTO.getCid());
  940. user.setCidType(userDTO.getCidType());
  941. user.setDeviceToken(userDTO.getDeviceToken());
  942. user.setVoIPToken(userDTO.getVoIPToken());
  943. infoUserService.saveOrUpdate(user);
  944. QueryWrapper<VipUser> queryWrapper = new QueryWrapper<>();
  945. queryWrapper.eq("user_id", infoUser.getUserId());
  946. VipUser vipUser = vipUserService.getOne(queryWrapper);
  947. if (vipUser == null) {
  948. user.setVip(null);
  949. } else {
  950. boolean orn = date.isPastDate(vipUser.getYxtim());
  951. if (orn) {
  952. user.setVip(null);
  953. } else {
  954. user.setVip(vipUser.getYxtim());
  955. }
  956. }
  957. redisCache.deleteKeys(CacheConstants.USER_TOKEN_KEY + user.getUserId() + ":" + "*");
  958. // 补充登录用户信息
  959. LoginUserDto userDto = new LoginUserDto();
  960. userDto.setUserId(user.getUserId());
  961. userDto.setUserName(user.getPhone());
  962. fillLoginUserInfo(userDto);
  963. String token = JwtUtil.setToken(CacheConstants.USER_TOKEN_KEY, userDto);
  964. return success(MessageUtils.message("no.user.login.success"), user, token);
  965. }
  966. // ==================== 三方登录(017-oauth-login)====================
  967. /**
  968. * 三方登录第一步:校验 provider 凭证 → 已绑定直接登录;未绑定返回 needPhone + tempKey。
  969. */
  970. @Anonymous
  971. @PostMapping("/oauthLogin")
  972. public AjaxResult oauthLogin(@RequestBody OAuthLoginDto dto) {
  973. if (dto == null || dto.getProvider() == null || dto.getProvider().isEmpty()) {
  974. return error(MessageUtils.message("no.oauth.provider.blank"));
  975. }
  976. log.info("[OAuth] oauthLogin provider={}", dto.getProvider());
  977. String providerUid = oauthVerifyService.verify(dto.getProvider(), dto.getCredential());
  978. // 查是否已绑定
  979. InfoUserOauth bind = infoUserOauthMapper.selectOne(
  980. new LambdaQueryWrapper<InfoUserOauth>()
  981. .eq(InfoUserOauth::getProvider, dto.getProvider())
  982. .eq(InfoUserOauth::getProviderUid, providerUid));
  983. if (bind != null) {
  984. // 已绑定:校验用户正常后直接登录
  985. log.info("[OAuth] 已绑定 provider={}, providerUid={}, userId={}", dto.getProvider(), providerUid, bind.getUserId());
  986. QueryWrapper<InfoUser> q = new QueryWrapper<>();
  987. q.eq("user_id", bind.getUserId()).eq("status", 0).eq("del_flag", "0");
  988. InfoUser u = infoUserService.getOne(q);
  989. if (u == null) {
  990. log.warn("[OAuth] 已绑定但账号已停用 userId={}", bind.getUserId());
  991. return error(MessageUtils.message("no.user.stop"));
  992. }
  993. u.setCid(dto.getCid());
  994. u.setCidType(dto.getCidType());
  995. u.setDeviceToken(dto.getDeviceToken());
  996. u.setVoIPToken(dto.getVoIPToken());
  997. infoUserService.saveOrUpdate(u);
  998. return issueOauthToken(u, dto.getProvider());
  999. }
  1000. // 未绑定:缓存 {provider, providerUid},返回 needPhone + tempKey
  1001. log.info("[OAuth] 未绑定,返回 needPhone provider={}, providerUid={}", dto.getProvider(), providerUid);
  1002. String tempKey = UUID.randomUUID().toString().replace("-", "");
  1003. redisCache.setCacheObject(OAUTH_TEMP_PREFIX + tempKey,
  1004. dto.getProvider() + "@" + providerUid, 5, TimeUnit.MINUTES);
  1005. Map<String, Object> data = new HashMap<>();
  1006. data.put("status", "needPhone");
  1007. data.put("tempKey", tempKey);
  1008. return AjaxResult.success(MessageUtils.message("no.oauth.needphone"), data);
  1009. }
  1010. /**
  1011. * 三方登录第二步:手机号 + 短信验证 → 已注册关联 / 未注册新建 → 写绑定 → 签 token。
  1012. */
  1013. @Anonymous
  1014. @PostMapping("/oauthBindPhone")
  1015. public AjaxResult oauthBindPhone(@RequestBody OAuthBindDto dto) {
  1016. if (dto == null || dto.getTempKey() == null || dto.getTempKey().isEmpty()) {
  1017. log.warn("[OAuth] oauthBindPhone 缺 tempKey");
  1018. return error(MessageUtils.message("no.oauth.tempkey.missing"));
  1019. }
  1020. String cached = redisCache.getCacheObject(OAUTH_TEMP_PREFIX + dto.getTempKey());
  1021. if (cached == null) {
  1022. log.warn("[OAuth] tempKey 已过期/不存在 tempKey={}", dto.getTempKey());
  1023. return error(MessageUtils.message("no.oauth.tempkey.expired"));
  1024. }
  1025. int at = cached.indexOf('@');
  1026. String provider = cached.substring(0, at);
  1027. String providerUid = cached.substring(at + 1);
  1028. log.info("[OAuth] 绑定流程 provider={}, providerUid={}", provider, providerUid);
  1029. // 容错:若期间已被绑定,直接登录
  1030. InfoUserOauth exist = infoUserOauthMapper.selectOne(
  1031. new LambdaQueryWrapper<InfoUserOauth>()
  1032. .eq(InfoUserOauth::getProvider, provider)
  1033. .eq(InfoUserOauth::getProviderUid, providerUid));
  1034. if (exist != null) {
  1035. log.info("[OAuth] 绑定期间已被绑定,直接登录 userId={}", exist.getUserId());
  1036. InfoUser u = infoUserService.getById(exist.getUserId());
  1037. return issueOauthToken(u, provider);
  1038. }
  1039. // 验短信(复用 lodeing 逻辑:redis code 或万能码 8888)
  1040. String phone = dto.getPhone();
  1041. String xcode = redisCache.getCacheObject(phone.trim().replaceAll("\\+", ""));
  1042. boolean codeOk = (xcode != null && xcode.equals(dto.getCode())) || "8888".equals(dto.getCode());
  1043. if (!codeOk) {
  1044. log.warn("[OAuth] 短信验证码错误 phone={}", maskPhone(phone));
  1045. return error(MessageUtils.message("no.user.jcaptcha.error"));
  1046. }
  1047. // 查/建用户(手机号始终为主键)
  1048. InfoUser user = infoUserService.getuser(phone);
  1049. if (user != null && !"0".equals(user.getStatus())) {
  1050. // 停用账号不允许绑定三方(与 lodeing 一致,防止绕过停用)
  1051. log.warn("[OAuth] 账号已停用 phone={}", maskPhone(phone));
  1052. return error(MessageUtils.message("no.user.stop"));
  1053. }
  1054. if (user == null) {
  1055. // 新建:昵称=手机号(与 createUser 一致)
  1056. InfoUser info = new InfoUser();
  1057. info.setPhone(phone);
  1058. info.setNickName(phone);
  1059. info.setCid(dto.getCid());
  1060. info.setCidType(dto.getCidType());
  1061. info.setDeviceToken(dto.getDeviceToken());
  1062. info.setVoIPToken(dto.getVoIPToken());
  1063. info.setUserType("0");
  1064. info.setMycode(new UUIDUtil().get8UUID());
  1065. infoUserService.saveOrUpdate(info);
  1066. user = infoUserService.getuser(phone);
  1067. createUserWallet(user.getUserId());
  1068. log.info("[OAuth] 新建账号 userId={}", user.getUserId());
  1069. } else {
  1070. user.setCid(dto.getCid());
  1071. user.setCidType(dto.getCidType());
  1072. user.setDeviceToken(dto.getDeviceToken());
  1073. user.setVoIPToken(dto.getVoIPToken());
  1074. infoUserService.saveOrUpdate(user);
  1075. log.info("[OAuth] 关联已有账号 userId={}", user.getUserId());
  1076. }
  1077. // 写三方绑定
  1078. InfoUserOauth bind = new InfoUserOauth();
  1079. bind.setUserId(user.getUserId());
  1080. bind.setProvider(provider);
  1081. bind.setProviderUid(providerUid);
  1082. bind.setCreateTime(new Date());
  1083. infoUserOauthMapper.insert(bind);
  1084. log.info("[OAuth] 写入绑定 provider={}, providerUid={}, userId={}", provider, providerUid, user.getUserId());
  1085. redisCache.deleteObject(OAUTH_TEMP_PREFIX + dto.getTempKey());
  1086. return issueOauthToken(user, provider);
  1087. }
  1088. /** 手机号脱敏:保留前 3 后 4,中间 ****(仅日志用)。 */
  1089. private static String maskPhone(String phone) {
  1090. if (phone == null || phone.length() < 8) {
  1091. return phone;
  1092. }
  1093. return phone.substring(0, 3) + "****" + phone.substring(phone.length() - 4);
  1094. }
  1095. /** 三方登录签发 token(claim provider=本次登录渠道),复用现有 JwtUtil + Redis 会话。 */
  1096. private AjaxResult issueOauthToken(InfoUser user, String provider) {
  1097. if (user == null) {
  1098. return error(MessageUtils.message("no.user.not.exist"));
  1099. }
  1100. redisCache.deleteKeys(CacheConstants.USER_TOKEN_KEY + user.getUserId() + ":" + "*");
  1101. LoginUserDto dto = new LoginUserDto();
  1102. dto.setUserId(user.getUserId());
  1103. dto.setUserName(user.getPhone());
  1104. dto.setProvider(provider);
  1105. fillLoginUserInfo(dto);
  1106. String token = JwtUtil.setToken(CacheConstants.USER_TOKEN_KEY, dto);
  1107. return success(MessageUtils.message("no.user.login.success"), user, token);
  1108. }
  1109. /**
  1110. * 查询用户信息列表
  1111. */
  1112. @PreAuthorize("@ss.hasPermi('infouser:user:list')")
  1113. @GetMapping("/list")
  1114. public TableDataInfo list(InfoUser infoUser) {
  1115. startPage();
  1116. List<InfoUser> list = infoUserService.selectInfoUserList(infoUser);
  1117. if (!list.isEmpty()) {
  1118. List<Long> userIds = list.stream().map(InfoUser::getUserId).collect(Collectors.toList());
  1119. List<UserWallet> wallets = userWalletService.list(new LambdaQueryWrapper<UserWallet>().in(UserWallet::getUserId, userIds).isNull(UserWallet::getStoreId));
  1120. list.forEach(item -> {
  1121. Optional<UserWallet> wallet = wallets.stream().filter(w -> w.getUserId().equals(item.getUserId())).findFirst();
  1122. if (wallet.isPresent()) {
  1123. item.setPointsWallet(Long.valueOf(wallet.get().getPointsWallet().toString()));
  1124. } else {
  1125. item.setPointsWallet(0L);
  1126. }
  1127. });
  1128. }
  1129. return getDataTable(list);
  1130. }
  1131. /**
  1132. * 导出用户信息列表
  1133. */
  1134. @PreAuthorize("@ss.hasPermi('infouser:user:export')")
  1135. @Log(title = "用户信息", businessType = BusinessType.EXPORT)
  1136. @PostMapping("/export")
  1137. public void export(HttpServletResponse response, InfoUser infoUser) {
  1138. List<InfoUser> list = infoUserService.selectInfoUserList(infoUser);
  1139. ExcelUtil<InfoUser> util = new ExcelUtil<InfoUser>(InfoUser.class);
  1140. util.exportExcel(response, list, MessageUtils.message("no.export.excel.userinfo"));
  1141. }
  1142. /**
  1143. * 获取用户信息详细信息
  1144. */
  1145. @PreAuthorize("@ss.hasPermi('infouser:user:query')")
  1146. @GetMapping(value = "/{userId}")
  1147. public AjaxResult getInfo(@PathVariable("userId") Long userId) {
  1148. InfoUser user = infoUserService.selectInfoUserByUserId(userId);
  1149. DateUtil date = new DateUtil();
  1150. QueryWrapper<VipUser> queryWrapper = new QueryWrapper<>();
  1151. queryWrapper.eq("user_id", user.getUserId());
  1152. VipUser vipUser = vipUserService.getOne(queryWrapper);
  1153. if (vipUser == null) {
  1154. user.setVip(null);
  1155. } else {
  1156. boolean orn = date.isPastDate(vipUser.getYxtim());
  1157. if (orn) {
  1158. user.setVip(null);
  1159. } else {
  1160. user.setVip(vipUser.getYxtim());
  1161. }
  1162. }
  1163. return success(user);
  1164. }
  1165. /**
  1166. * 新增用户信息
  1167. */
  1168. @PreAuthorize("@ss.hasPermi('infouser:user:add')")
  1169. @Log(title = "用户信息", businessType = BusinessType.INSERT)
  1170. @PostMapping
  1171. @Transactional(rollbackFor = Exception.class)
  1172. public AjaxResult add(@RequestBody InfoUser infoUser) {
  1173. if (MerchantAccountConstants.SUBACCOUNT_USER_TYPE.equals(infoUser.getUserType())) {
  1174. return error(MessageUtils.message("merchant.subaccount.platform.managed"));
  1175. }
  1176. if (!normalizeAuditRejectReason(infoUser)) {
  1177. return error(MessageUtils.message("no.user.audit.reject.reason.required"));
  1178. }
  1179. normalizeDeliveryType(infoUser);
  1180. if (infoUserService.getinfouserName(infoUser.getUserName()) != null) {
  1181. return error(MessageUtils.message("no.user.add") + infoUser.getUserName() + MessageUtils.message("no.user.login.exist"));
  1182. } else if (infoUserService.getinfoPhone(infoUser.getPhone()) != null) {
  1183. return error(MessageUtils.message("no.user.add") + infoUser.getPhone() + MessageUtils.message("no.user.mobile.exist"));
  1184. }
  1185. UUIDUtil uuid = new UUIDUtil();
  1186. infoUser.setMycode(uuid.get8UUID());
  1187. infoUser.setStatus("0");
  1188. System.out.println("加密:" + infoUser.getPassword());
  1189. int result = infoUserService.insertInfoUser(infoUser);
  1190. createUserWallet(infoUser.getUserId());
  1191. return toAjax(result);
  1192. }
  1193. /**
  1194. * 修改用户信息
  1195. */
  1196. @PreAuthorize("@ss.hasPermi('infouser:user:edit')")
  1197. @Log(title = "用户信息", businessType = BusinessType.UPDATE)
  1198. @PutMapping
  1199. public AjaxResult edit(@RequestBody InfoUser infoUser) {
  1200. InfoUser existing = infoUser.getUserId() == null ? null
  1201. : infoUserService.selectInfoUserByUserId(infoUser.getUserId());
  1202. if (MerchantAccountConstants.SUBACCOUNT_USER_TYPE.equals(infoUser.getUserType())
  1203. || (existing != null
  1204. && MerchantAccountConstants.SUBACCOUNT_USER_TYPE.equals(existing.getUserType()))) {
  1205. return error(MessageUtils.message("merchant.subaccount.platform.managed"));
  1206. }
  1207. if (!normalizeAuditRejectReason(infoUser)) {
  1208. return error(MessageUtils.message("no.user.audit.reject.reason.required"));
  1209. }
  1210. normalizeDeliveryType(infoUser);
  1211. return toAjax(infoUserService.updateInfoUser(infoUser));
  1212. }
  1213. private boolean normalizeAuditRejectReason(InfoUser infoUser) {
  1214. if (!"2".equals(infoUser.getAuditStatus())) {
  1215. infoUser.setAuditRejectReason(null);
  1216. return true;
  1217. }
  1218. if (infoUser.getAuditRejectReason() == null) {
  1219. return false;
  1220. }
  1221. String reason = infoUser.getAuditRejectReason().strip();
  1222. if (reason.isEmpty()) {
  1223. return false;
  1224. }
  1225. infoUser.setAuditRejectReason(reason);
  1226. return true;
  1227. }
  1228. /** 骑手配送类型归一化;非法值返回国际化业务错误。 */
  1229. private void normalizeDeliveryType(InfoUser infoUser) {
  1230. try {
  1231. infoUser.setDeliveryType(InfoUser.normalizeDeliveryTypes(infoUser.getDeliveryType()));
  1232. } catch (IllegalArgumentException exception) {
  1233. throw new ServiceException(MessageUtils.message("no.user.delivery.type.invalid"));
  1234. }
  1235. }
  1236. /**
  1237. * 删除用户信息
  1238. */
  1239. @PreAuthorize("@ss.hasPermi('infouser:user:remove')")
  1240. @Log(title = "用户信息", businessType = BusinessType.DELETE)
  1241. @DeleteMapping("/{userIds}")
  1242. public AjaxResult remove(@PathVariable Long[] userIds) {
  1243. return toAjax(infoUserService.deleteInfoUserByUserIds(userIds));
  1244. }
  1245. }