UserServiceImpl.java 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068
  1. package com.uas.sso.service.impl;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.uas.sso.common.encrypt.MD5;
  5. import com.uas.sso.common.util.HttpUtil;
  6. import com.uas.sso.core.Const;
  7. import com.uas.sso.core.Status;
  8. import com.uas.sso.core.Type;
  9. import com.uas.sso.dao.UserDao;
  10. import com.uas.sso.dao.UserRecordDao;
  11. import com.uas.sso.entity.*;
  12. import com.uas.sso.exception.VisibleError;
  13. import com.uas.sso.foreign.entity.ForeignInfo;
  14. import com.uas.sso.foreign.bihe.entity.BiHeInfo;
  15. import com.uas.sso.foreign.weixin.entity.OAuthInfo;
  16. import com.uas.sso.i.CountCallBack;
  17. import com.uas.sso.logging.LoggerManager;
  18. import com.uas.sso.logging.SyncBufferedLogger;
  19. import com.uas.sso.logging.UserBufferedLogger;
  20. import com.uas.sso.service.*;
  21. import com.uas.sso.support.SyncFail;
  22. import com.uas.sso.util.AccountTypeUtils;
  23. import com.uas.sso.util.CountUtils;
  24. import com.uas.sso.util.PasswordLevelUtils;
  25. import net.sf.ehcache.search.aggregator.Count;
  26. import org.springframework.beans.factory.annotation.Autowired;
  27. import org.springframework.data.domain.Page;
  28. import org.springframework.data.domain.PageRequest;
  29. import org.springframework.data.domain.Pageable;
  30. import org.springframework.data.jpa.domain.Specification;
  31. import org.springframework.stereotype.Service;
  32. import org.springframework.ui.ModelMap;
  33. import org.springframework.util.Assert;
  34. import org.springframework.util.CollectionUtils;
  35. import org.springframework.util.StringUtils;
  36. import javax.persistence.Version;
  37. import javax.persistence.criteria.*;
  38. import javax.validation.constraints.NotNull;
  39. import java.sql.Timestamp;
  40. import java.text.ParseException;
  41. import java.text.SimpleDateFormat;
  42. import java.util.*;
  43. import java.util.concurrent.ExecutorService;
  44. /**
  45. * 用户service实现类
  46. *
  47. * @author wangmh
  48. * @date 2018/1/2
  49. */
  50. @Service
  51. public class UserServiceImpl implements UserService {
  52. @Autowired
  53. private UserDao userDao;
  54. @Autowired
  55. private UserRecordDao userRecordDao;
  56. @Autowired
  57. private UserValidService userValidService;
  58. @Autowired
  59. private UserspaceService userspaceService;
  60. @Autowired
  61. private AppService appService;
  62. @Autowired
  63. private ExecutorService executorService;
  64. @Autowired
  65. private UserQuestionService userQuestionService;
  66. @Autowired
  67. private TokenService tokenService;
  68. private UserBufferedLogger userLogger = LoggerManager.getLogger(UserBufferedLogger.class);
  69. private SyncBufferedLogger syncLogger = LoggerManager.getLogger(SyncBufferedLogger.class);
  70. @Override
  71. public User findByMobile(String mobile, String mobileArea) {
  72. return userDao.findByMobileAndMobileArea(mobile, mobileArea);
  73. }
  74. @Override
  75. public User findByMobile(String mobile) {
  76. return userDao.findByMobile(mobile);
  77. }
  78. @Override
  79. public boolean mobileHasRegistered(String mobile) {
  80. User user = userDao.findByMobile(mobile);
  81. if (user == null) {
  82. return false;
  83. }
  84. return true;
  85. }
  86. @Override
  87. public boolean emailHasRegistered(String email) {
  88. List<User> users = userDao.findByEmail(email);
  89. if (CollectionUtils.isEmpty(users)) {
  90. return false;
  91. }
  92. return true;
  93. }
  94. @Override
  95. public synchronized User register(User user, String appId) {
  96. String noEncryPwd = user.getPassword();
  97. // 校验手机号是否被注册
  98. if (mobileHasRegistered(user.getMobile())) {
  99. throw new VisibleError("该手机号已被注册");
  100. }
  101. // 由于现在不考虑手机号所属区域,默认为中国大陆
  102. if (StringUtils.isEmpty(user.getMobileArea())) {
  103. user.setMobileArea(Const.CONTINENT);
  104. }
  105. if (user.getMobile() == null || !user.getMobile().matches(Const.REGEXP_MOBILE_CONTINENT)) {
  106. throw new VisibleError("请填写正确的手机号");
  107. }
  108. // 设置基本属性,手机号默认已认证
  109. user.setRegisterDate(new Timestamp(System.currentTimeMillis()));
  110. Long uu = userDao.findMaxUU();
  111. user.setUserUU(uu == null ? 1000060000L : (uu + 1));
  112. user.setSalt(String.valueOf(user.getUserUU()));
  113. user.setMobileValidCode((short) Status.AUTHENTICATED.getCode());
  114. user.setEmailValidCode((short) Status.NOT_APPLYING.getCode());
  115. user.setIdentityValidCode((short) Status.NOT_APPLYING.getCode());
  116. user.setPassword(getEncryPassword(Const.ENCRY_FORMAT, user.getPassword(), user.getSalt()));
  117. user.setFromApp(appId);
  118. user = userDao.save(user);
  119. UserRecord userRecord = new UserRecord(user.getUserUU());
  120. userRecordDao.save(userRecord);
  121. userLogger.info(user, Type.UPDATE_REGISTER.getValue());
  122. // 同步到各个应用
  123. App app = appService.findOne(appId);
  124. return syncUserInfo(user, noEncryPwd, "个人注册", app);
  125. }
  126. @Override
  127. public String getEncryPassword(String format, String noEncryPwd, String salt) {
  128. if (StringUtils.isEmpty(format)) {
  129. return noEncryPwd;
  130. }
  131. // 超过32认为是已加密过的密文
  132. if (noEncryPwd.length() >= 32) {
  133. /// 之后添加日志时恢复
  134. //logger.error("用户密码加密", String.format("传递过来的密码(%s)必须是未加密的明文", noEncryPwd));
  135. throw new VisibleError("密码过长,请重新输入");
  136. }
  137. // $password{$salt}
  138. String password = format.replace(Const.ENCRY_PARAM_PASSWORD, noEncryPwd);
  139. password = password.replace(Const.ENCRY_PARAM_SALT, salt == null ? "" : salt);
  140. return MD5.toMD5(password);
  141. }
  142. @Override
  143. public User save(User user) {
  144. user = userDao.save(user);
  145. return syncUserInfo(user, null, "修改用户信息", null);
  146. }
  147. @Override
  148. public void checkPassword(Long userUU, String password, boolean isEncry) {
  149. // 根据用户uu号找到旧数据
  150. User oldUser = userDao.findByUserUU(userUU);
  151. if (oldUser == null) {
  152. throw new VisibleError("用户名或密码错误");
  153. }
  154. // 校验密码
  155. checkPassword(oldUser, password, isEncry);
  156. }
  157. @Override
  158. public void checkPasswordByMobile(String mobile, String password, boolean isEncry) {
  159. // 找到用户
  160. User oldUser = userDao.findByMobile(mobile);
  161. if (oldUser == null) {
  162. throw new VisibleError("用户名或密码错误");
  163. }
  164. // 校验密码
  165. checkPassword(oldUser, password, isEncry);
  166. }
  167. @Override
  168. public void checkPasswordByEmail(String email, String password, boolean isEncry) {
  169. // 找到用户
  170. List<User> oldUsers = userDao.findByEmailAndEmailValidCode(email, (short) Status.AUTHENTICATED.getCode());
  171. if (CollectionUtils.isEmpty(oldUsers)) {
  172. throw new VisibleError("该邮箱未认证,请使用手机号登录");
  173. }
  174. // 校验密码
  175. for (User oldUser : oldUsers) {
  176. checkPassword(oldUser, password, isEncry);
  177. }
  178. }
  179. @Override
  180. public boolean checkPasswordByUsername(String username, String password, boolean isEncry) {
  181. Assert.hasText(username, "用户名不能为空");
  182. Assert.hasText(password, "密码不能为空");
  183. User user = findByUsername(username);
  184. checkPassword(user, password, isEncry);
  185. return true;
  186. }
  187. @Override
  188. public int getPwdErrorCount(String username) {
  189. User user = findByUsername(username);
  190. if (user == null) {
  191. throw new VisibleError("用户名不存在");
  192. }
  193. UserRecord userRecord = userRecordDao.findOne(user.getUserUU());
  194. if (userRecord == null) {
  195. return 0;
  196. }
  197. return userRecord.getPwdErrorCount();
  198. }
  199. @Override
  200. public User findByUsername(String username) {
  201. String type = AccountTypeUtils.getAccountType(username);
  202. User user = null;
  203. if (AccountTypeUtils.MOBILE.equals(type)) {
  204. // 手机号
  205. user = userDao.findByMobile(username);
  206. } else if (AccountTypeUtils.EMAIL.equals(type)) {
  207. // 邮箱
  208. List<User> users = userDao.findByEmailAndEmailValidCode(username, (short) Status.AUTHENTICATED.getCode());
  209. // 认证邮箱只有一条记录,直接选择第一个
  210. if (!CollectionUtils.isEmpty(users)) {
  211. user = users.get(0);
  212. }
  213. } else if (AccountTypeUtils.UU_NUMBER.equals(type)) {
  214. // uu号
  215. user = userDao.findByUserUU(Long.valueOf(username));
  216. }
  217. return user;
  218. }
  219. /**
  220. * 校验用户密码
  221. *
  222. * @param oldUser 用户信息
  223. * @param password 需要校验的密码
  224. * @param isEncry 需校验的密码是否被加密
  225. */
  226. private void checkPassword(User oldUser, String password, boolean isEncry) {
  227. // 密码未加密,转换成加密后的密码
  228. String encryPassword = password;
  229. if (!isEncry) {
  230. encryPassword = getEncryPassword(Const.ENCRY_FORMAT, password, oldUser.getSalt());
  231. }
  232. // 校验密码
  233. if (!encryPassword.equals(oldUser.getPassword())) {
  234. throw new VisibleError("您输入的密码与已有账号的登录密码不一致,请重新输入。");
  235. }
  236. }
  237. @Override
  238. public UserRecord save(UserRecord userRecord) {
  239. return userRecordDao.save(userRecord);
  240. }
  241. @Override
  242. public User findOne(Long userUU) {
  243. return userDao.findOne(userUU);
  244. }
  245. @Override
  246. public boolean realNameIsValid(String realName) {
  247. User user = userDao.findByRealName(realName);
  248. if (user != null && user.getIdentityValidCode() == Status.AUTHENTICATED.getCode()) {
  249. return true;
  250. }
  251. return false;
  252. }
  253. @Override
  254. public boolean idCardIsValid(String idCard) {
  255. User user = userDao.findByIdCard(idCard);
  256. if (user != null && user.getIdentityValidCode() == Status.AUTHENTICATED.getCode()) {
  257. return true;
  258. }
  259. return false;
  260. }
  261. @Override
  262. public void submitIdValidInfo(User user) {
  263. // 校验企业名和营业执照是否被认证
  264. boolean isValid = idCardIsValid(user.getIdCard());
  265. if (isValid) {
  266. throw new VisibleError("该身份证号已被认证,请确认");
  267. }
  268. User oldUser = userDao.findByUserUU(user.getUserUU());
  269. oldUser.setIdentityValidCode((short) Status.TO_BE_CERTIFIED.getCode());
  270. oldUser.setRealName(user.getRealName());
  271. oldUser.setIdCard(user.getIdCard());
  272. this.save(oldUser);
  273. // 保存日志
  274. userValidService.submitValid(user);
  275. }
  276. @Override
  277. public void updateMobile(Long userUU, String newMobile) {
  278. // 参数空校验
  279. Assert.notNull(userUU, "userUU must not be null!");
  280. Assert.hasText(newMobile, "新手机号不能为空");
  281. // 获取用户信息
  282. User user = userDao.findOne(userUU);
  283. if (user == null) {
  284. throw new VisibleError("用户不存在");
  285. }
  286. // 判断手机号是否被注册
  287. if (!newMobile.equals(user.getMobile())) {
  288. User oldUser = userDao.findByMobile(newMobile);
  289. if (oldUser != null) {
  290. throw new VisibleError("该手机号已被注册");
  291. }
  292. }
  293. // 修改手机号
  294. user.setMobile(newMobile);
  295. user.setMobileValidCode((short) Status.AUTHENTICATED.getCode());
  296. // 保存用户信息
  297. user = userDao.save(user);
  298. // 保存日志
  299. userLogger.info(user, Type.UPDATE_MOBILE.getValue());
  300. // 同步到各个应用
  301. syncUserInfo(user, null, "修改手机号", null);
  302. }
  303. @Override
  304. public void updateEmail(Long userUU, String newEmail) {
  305. // 获取用户信息
  306. User user = userDao.findOne(userUU);
  307. if (user == null) {
  308. throw new VisibleError("用户不存在");
  309. }
  310. // 修改手机号
  311. user.setEmail(newEmail);
  312. user.setEmailValidCode((short) Status.AUTHENTICATED.getCode());
  313. // 保存用户信息
  314. user = userDao.save(user);
  315. // 保存日志
  316. userLogger.info(user, Type.UPDATE_EMAIL.getValue());
  317. // 同步信息到各应用
  318. syncUserInfo(user, null, "修改邮箱", null);
  319. }
  320. @Override
  321. public Page<User> findMemberBySpaceUU(int page, int size, final Long spaceUU) {
  322. Pageable pageable = PageInfo.pageRequest(new PageRequest(page, size));
  323. Page<User> pUsers = userDao.findAll(new Specification<User>() {
  324. @Override
  325. public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
  326. List<Predicate> list = new ArrayList<>();
  327. list.add(cb.equal(root.join("userSpaces", JoinType.INNER).get("spaceUU").as(Long.class), spaceUU));
  328. Predicate[] predicates = new Predicate[list.size()];
  329. predicates = list.toArray(predicates);
  330. return cb.and(predicates);
  331. }
  332. }, pageable);
  333. return new PageInfo<User>(pUsers.getContent(), pageable, pUsers.getTotalElements());
  334. }
  335. @Override
  336. public void bindUserspace(String appId, Long userUU, Long spaceUU) {
  337. if (StringUtils.isEmpty(userUU) || StringUtils.isEmpty(spaceUU)) {
  338. throw new VisibleError("参数错误");
  339. }
  340. // 找到用户和企业
  341. User user = findOne(userUU);
  342. Userspace userspace = userspaceService.findOne(spaceUU);
  343. // 将企业添加到用户列表上
  344. Set<Userspace> userspaces = user.getUserSpaces();
  345. userspaces.add(userspace);
  346. // 保存
  347. userDao.save(user);
  348. syncUserBindSpace(userUU, spaceUU);
  349. // 保存日志
  350. userLogger.info(user, Type.BIND_USERSPACE.getValue() + spaceUU);
  351. }
  352. /**
  353. * 同步用户绑定企业关系
  354. *
  355. * @param userUU 用户uu号
  356. * @param spaceUU 企业uu号
  357. */
  358. private void syncUserBindSpace(Long userUU, Long spaceUU) {
  359. syncRelation(userUU, spaceUU, "bind");
  360. }
  361. /**
  362. * 同步用户解除绑定企业关系
  363. *
  364. * @param userUU 用户uu号
  365. * @param spaceUU 企业uu号
  366. */
  367. private void syncUserUnbindSpace(Long userUU, Long spaceUU) {
  368. syncRelation(userUU, spaceUU, "unbind");
  369. }
  370. /**
  371. * 同步用户与企业的关系
  372. *
  373. * @param userUU 用户uu号
  374. * @param spaceUU 企业uu号
  375. * @param type 类型 (bind or unbind)
  376. */
  377. private void syncRelation(final Long userUU, final Long spaceUU, final String type) {
  378. Userspace userspace = userspaceService.findOne(spaceUU);
  379. List<App> apps = userspace.getApps();
  380. final ModelMap formData = new ModelMap();
  381. formData.put("userUU", userUU);
  382. formData.put("spaceUU", spaceUU);
  383. formData.put("type", type);
  384. for (final App app : apps) {
  385. executorService.execute(new Runnable() {
  386. @Override
  387. public void run() {
  388. String url = app.getBackRelationUrl();
  389. HttpUtil.ResponseWrap res = null;
  390. try {
  391. res = HttpUtil.doPost(url, formData, 10000);
  392. if (!res.isSuccess()) {
  393. SyncLog syncLog = syncLogger.error(app.getUid(), "同步绑定信息失败", JSON.toJSONString(formData), res.getContent());
  394. SyncFail.add(syncLog.getId(), formData, url, app.getUid());
  395. } else {
  396. syncLogger.info(app.getUid(), "同步绑定信息成功", JSON.toJSONString(formData));
  397. }
  398. } catch (Exception e) {
  399. syncLogger.error(app.getUid(), "同步绑定信息失败", JSON.toJSONString(formData), e.getMessage());
  400. }
  401. }
  402. });
  403. }
  404. }
  405. @Override
  406. public void unbindUserspace(Long userUU, Long spaceUU) {
  407. if (StringUtils.isEmpty(userUU) || StringUtils.isEmpty(spaceUU)) {
  408. throw new VisibleError("参数错误");
  409. }
  410. // 找到用户和企业
  411. User user = findOne(userUU);
  412. if (user == null) {
  413. throw new VisibleError("未找到用户信息");
  414. }
  415. Userspace userspace = userspaceService.findOne(spaceUU);
  416. if (userspace == null) {
  417. throw new VisibleError("未找到企业信息");
  418. }
  419. // 将企业添加到用户列表上
  420. Set<Userspace> userspaces = user.getUserSpaces();
  421. userspaces.remove(userspace);
  422. // 保存
  423. userDao.save(user);
  424. syncUserUnbindSpace(userUU, spaceUU);
  425. // 保存日志
  426. userLogger.info(user, Type.UNBIND_USERSPACE.getValue() + spaceUU);
  427. }
  428. @Override
  429. public void setQuestion(Long userUU, List<UserQuestion> questions) {
  430. // 找到用户密保
  431. User user = userDao.findOne(userUU);
  432. List<UserQuestion> userQuestions = user.getQuestions();
  433. // 清空旧的并添加新的
  434. if (CollectionUtils.isEmpty(userQuestions)) {
  435. user.setQuestions(questions);
  436. } else {
  437. for (int i = 0; i < questions.size(); i++) {
  438. if (userQuestions.get(i) == null) {
  439. user.getQuestions().add(questions.get(i));
  440. } else {
  441. userQuestions.get(i).setQuestion(questions.get(i).getQuestion());
  442. userQuestions.get(i).setAnswer(questions.get(i).getAnswer());
  443. userQuestions.get(i).setSort(questions.get(i).getSort());
  444. }
  445. }
  446. }
  447. // 保存并添加日志
  448. user = userDao.save(user);
  449. syncUserInfo(user, null, "修改密保", null);
  450. userLogger.info(user, Type.UPDATE_QUESTION.getValue(), JSON.toJSONString(user.getQuestions()));
  451. }
  452. @Override
  453. public List<String> findRepeatEmail() {
  454. return userDao.findRepeatEmail();
  455. }
  456. @Override
  457. public List<User> findByEmail(String email) {
  458. return userDao.findByEmail(email);
  459. }
  460. @Override
  461. public User updatePassword(Long userUU, String noEncryPwd) {
  462. User user = userDao.findOne(userUU);
  463. if (user == null) {
  464. throw new VisibleError("该用户不存在");
  465. }
  466. user.setPassword(getEncryPassword(Const.ENCRY_FORMAT, noEncryPwd, user.getSalt()));
  467. user.setPasswordLevel(PasswordLevelUtils.checkPasswordLevel(noEncryPwd).getValue());
  468. user = syncUserInfo(user, noEncryPwd, "用户修改密码", null);
  469. return userDao.save(user);
  470. }
  471. @Override
  472. public List<UserSpaceDetailInfo> findUserByTels(List<String> tels) {
  473. // 获取用户列表
  474. List<User> users = userDao.findUsersByTels(tels);
  475. if (CollectionUtils.isEmpty(users)) {
  476. return null;
  477. }
  478. List<UserSpaceDetailInfo> data = new ArrayList<>(users.size());
  479. UserSpaceDetailInfo info;
  480. // 遍历用户列表取数据
  481. for (User user : users) {
  482. info = new UserSpaceDetailInfo();
  483. Set<Userspace> spaces = user.getUserSpaces();
  484. if (!CollectionUtils.isEmpty(spaces)) {
  485. // 有企业的话随便取一个,uu互联需求
  486. Iterator<Userspace> iterator = spaces.iterator();
  487. Userspace userspace = iterator.next();
  488. info.setAddress(userspace.getRegAddress());
  489. info.setCompany(userspace.getSpaceName());
  490. }
  491. info.setEmail(user.getEmail());
  492. info.setImid(user.getImId());
  493. info.setUsertel(user.getMobile());
  494. info.setUsername(user.getVipName());
  495. data.add(info);
  496. }
  497. return data;
  498. }
  499. @Override
  500. public void resetErrorCount(Long userUU) {
  501. UserRecord userRecord = userRecordDao.findOne(userUU);
  502. if (userRecord == null) {
  503. userRecord = new UserRecord(userUU);
  504. }
  505. userRecord.setPwdErrorCount(0);
  506. userRecordDao.save(userRecord);
  507. }
  508. @Override
  509. public User updateUser(@NotNull Long userUU, User newUser) {
  510. User oldUser = userDao.findOne(userUU);
  511. if (oldUser == null) {
  512. throw new VisibleError("未找到用户信息");
  513. }
  514. // 修改手机号
  515. if (!StringUtils.isEmpty(newUser.getMobile()) && !newUser.getMobile().equals(oldUser.getMobile())) {
  516. if (mobileHasRegistered(newUser.getMobile())) {
  517. throw new VisibleError("手机号已被注册");
  518. }
  519. if (!newUser.getMobile().matches(Const.REGEXP_MOBILE_CONTINENT)) {
  520. throw new VisibleError("请输入正确的手机号");
  521. }
  522. oldUser.setMobile(newUser.getMobile());
  523. oldUser.setMobileValidCode((short) Status.NOT_APPLYING.getCode());
  524. }
  525. // 修改邮箱
  526. if (!StringUtils.isEmpty(newUser.getEmail()) && !newUser.getEmail().equals(oldUser.getEmail())) {
  527. if (emailHasRegistered(newUser.getEmail())) {
  528. throw new VisibleError("邮箱已被注册");
  529. }
  530. if (!newUser.getEmail().matches(Const.REGEXP_EMAIL)) {
  531. throw new VisibleError("请输入正确的邮箱");
  532. }
  533. oldUser.setEmail(newUser.getEmail());
  534. oldUser.setEmailValidCode((short) Status.NOT_APPLYING.getCode());
  535. }
  536. // 修改用户名
  537. if (!StringUtils.isEmpty(newUser.getVipName())) {
  538. oldUser.setVipName(newUser.getVipName());
  539. }
  540. // 保存用户信息
  541. oldUser = userDao.save(oldUser);
  542. oldUser = syncUserInfo(oldUser, null, "(接口调用)修改用户信息", null);
  543. return oldUser;
  544. }
  545. @Override
  546. public long count() {
  547. return userDao.count();
  548. }
  549. @Override
  550. public Long countByLogin(String start, String end) throws ParseException {
  551. SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
  552. Date startTime = simpleDateFormat.parse(start);
  553. Date endTime = simpleDateFormat.parse(end);
  554. Calendar starttime = Calendar.getInstance();
  555. starttime.setTime(startTime);
  556. Calendar endtime = Calendar.getInstance();
  557. endtime.setTime(endTime);
  558. return userRecordDao.getCountByLogin(new Timestamp(starttime.getTimeInMillis()),new Timestamp(endtime.getTimeInMillis()));
  559. }
  560. @Override
  561. public Long countByLoginInputMonth(String startTime,String endTime, int month) throws ParseException {
  562. SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
  563. Date startToDate = simpleDateFormat.parse(startTime);
  564. Date endToDate = simpleDateFormat.parse(endTime);
  565. Calendar start = Calendar.getInstance();
  566. start.setTime(startToDate);
  567. start.add(Calendar.MONTH, -month);
  568. Calendar end = Calendar.getInstance();
  569. end.setTime(endToDate);
  570. end.add(Calendar.MONTH, -month);
  571. System.out.println(new Timestamp(start.getTimeInMillis()));
  572. System.out.println(new Timestamp(end.getTimeInMillis()));
  573. return userRecordDao.getCountByLogin(new Timestamp(start.getTimeInMillis()),new Timestamp(end.getTimeInMillis()));
  574. }
  575. @Override
  576. public long countByRegisterDate(final Calendar start, final Calendar end) {
  577. return userDao.count(new Specification<User>() {
  578. @Override
  579. public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
  580. Predicate predicate = cb.between(root.get("registerDate").as(Calendar.class), start, end);
  581. query.where(predicate);
  582. return null;
  583. }
  584. });
  585. }
  586. @Override
  587. public Map<String, Long> countByRegisterDate(Timestamp start, Timestamp end, List<String> fromApps) {
  588. Map<String, Long> data = new HashMap<>();
  589. List<Map<String, Object>> counts = userDao.getCountByRegisterDate(start, end, fromApps);
  590. for (Map<String, Object> count : counts) {
  591. data.put((String) count.get("appId"), (Long) count.get("count"));
  592. fromApps.remove(count.get("appId"));
  593. }
  594. for(String fromApp: fromApps){
  595. data.put(fromApp, 0L);
  596. }
  597. return data;
  598. }
  599. @Override
  600. public long countInCurrentMonth() {
  601. return CountUtils.countInCurrentMonth(new CountCallBack<Long>() {
  602. @Override
  603. public Long countByTime(Calendar start, Calendar end) {
  604. return countByRegisterDate(start, end);
  605. }
  606. });
  607. }
  608. @Override
  609. public long countInLastMonth() {
  610. return CountUtils.countInLastMonth(new CountCallBack<Long>() {
  611. @Override
  612. public Long countByTime(Calendar start, Calendar end) {
  613. return countByRegisterDate(start, end);
  614. }
  615. });
  616. }
  617. @Override
  618. public long countInCurrentWeek() {
  619. return CountUtils.countInCurrentWeek(new CountCallBack<Long>() {
  620. @Override
  621. public Long countByTime(Calendar start, Calendar end) {
  622. return countByRegisterDate(start, end);
  623. }
  624. });
  625. }
  626. @Override
  627. public Map<String, Long> count(final List<String> fromApps) {
  628. Map<String, Long> data = new HashMap<>();
  629. List<Map<String, Object>> counts = userDao.getCountByRegisterDate(fromApps);
  630. for (Map<String, Object> count : counts) {
  631. data.put((String) count.get("appId"), (Long) count.get("count"));
  632. }
  633. return data;
  634. }
  635. @Override
  636. public Map<String, Long> countInCurrentMonth(final List<String> fromApps) {
  637. return CountUtils.countInCurrentMonth(new CountCallBack<Map<String, Long>>() {
  638. @Override
  639. public Map<String, Long> countByTime(Calendar start, Calendar end) {
  640. return countByRegisterDate(new Timestamp(start.getTimeInMillis()), new Timestamp(end.getTimeInMillis()), fromApps);
  641. }
  642. });
  643. }
  644. @Override
  645. public Map<String, Long> countInCurrentWeek(final List<String> fromApps) {
  646. return CountUtils.countInCurrentWeek(new CountCallBack<Map<String, Long>>() {
  647. @Override
  648. public Map<String, Long> countByTime(Calendar start, Calendar end) {
  649. return countByRegisterDate(new Timestamp(start.getTimeInMillis()), new Timestamp(end.getTimeInMillis()), fromApps);
  650. }
  651. });
  652. }
  653. @Override
  654. public Map<String, Long> countInToday(List<String> fromApps) {
  655. return CountUtils.countInToday(new CountCallBack<Map<String, Long>>() {
  656. @Override
  657. public Map<String, Long> countByTime(Calendar start, Calendar end) {
  658. return countByRegisterDate(new Timestamp(start.getTimeInMillis()), new Timestamp(end.getTimeInMillis()), fromApps);
  659. }
  660. });
  661. }
  662. @Override
  663. public Map<String, Long> countInYesterday(List<String> fromApps) {
  664. return CountUtils.countInYesterday(new CountCallBack<Map<String, Long>>() {
  665. @Override
  666. public Map<String, Long> countByTime(Calendar start, Calendar end) {
  667. return countByRegisterDate(new Timestamp(start.getTimeInMillis()), new Timestamp(end.getTimeInMillis()), fromApps);
  668. }
  669. });
  670. }
  671. @Override
  672. public Map<String, Long> countgInLastMonth(List<String> fromApps) {
  673. return CountUtils.countInLastMonth(new CountCallBack<Map<String, Long>>() {
  674. @Override
  675. public Map<String, Long> countByTime(Calendar start, Calendar end) {
  676. return countByRegisterDate(new Timestamp(start.getTimeInMillis()), new Timestamp(end.getTimeInMillis()), fromApps);
  677. }
  678. });
  679. }
  680. @Override
  681. public Map<String, Long> countInInputTime(String startTime, String endTime, List<String> fromApps) throws ParseException {
  682. CountCallBack<Map<String, Long>> countCallBack = new CountCallBack<Map<String, Long>>() {
  683. @Override
  684. public Map<String, Long> countByTime(Calendar start, Calendar end) {
  685. return countByRegisterDate(new Timestamp(start.getTimeInMillis()),new Timestamp(end.getTimeInMillis()),fromApps);
  686. }
  687. };
  688. return CountUtils.countInInputTime(countCallBack,startTime,endTime);
  689. }
  690. @Override
  691. public User findByWxUnionid(String unionid) {
  692. return userDao.findByWxUnionid(unionid);
  693. }
  694. @Override
  695. public User findByBhOpenId(String openId) {
  696. return userDao.findByBhOpenId(openId);
  697. }
  698. @Override
  699. public User bindUnionId(String username, String password, String unionid) {
  700. Assert.hasText(username, "用户名不能为空");
  701. Assert.hasText(password, "密码不能为空");
  702. User user = findByUsername(username);
  703. if (user == null) {
  704. throw new IllegalArgumentException("该用户不存在");
  705. }
  706. checkPassword(user.getUserUU(), password, false);
  707. user.setWxUnionid(unionid);
  708. userDao.save(user);
  709. userLogger.info(user, Type.BIND_WEIXIN.getValue());
  710. return user;
  711. }
  712. @Override
  713. public User bindBhOpenId(String username, String password, String openId) {
  714. Assert.hasText(username, "用户名不能为空");
  715. Assert.hasText(password, "密码不能为空");
  716. User user = findByUsername(username);
  717. if (user == null) {
  718. throw new IllegalArgumentException("该用户不存在");
  719. }
  720. checkPassword(user.getUserUU(), password, false);
  721. user.setBhOpenId(openId);
  722. userDao.save(user);
  723. userLogger.info(user, Type.BIND_BIHE.getValue());
  724. return user;
  725. }
  726. @Override
  727. public User findByForeignId(ForeignInfo foreignInfo) {
  728. User user = null;
  729. if (foreignInfo instanceof OAuthInfo) {
  730. user = userDao.findByWxUnionid(foreignInfo.getForeignOpenId());
  731. } else if (foreignInfo instanceof BiHeInfo) {
  732. user = userDao.findByBhOpenId(foreignInfo.getForeignOpenId());
  733. }
  734. return user;
  735. }
  736. @Override
  737. public User bindForeignOpenId(String username, String password, ForeignInfo foreignInfo) {
  738. // 校验空参数
  739. try {
  740. Assert.hasText(username, "用户名不能为空");
  741. Assert.hasText(password, "密码不能为空");
  742. } catch (IllegalArgumentException e) {
  743. throw new VisibleError(e.getMessage());
  744. }
  745. // 校验用户名密码是否正确
  746. User user = findByUsername(username);
  747. if (user == null) {
  748. throw new VisibleError("该用户不存在");
  749. }
  750. checkPassword(user.getUserUU(), password, false);
  751. // 设置第三方openId
  752. setForeignOpenId(user, foreignInfo);
  753. userDao.save(user);
  754. userLogger.info(user, Type.BIND_FOREIGN.getValue());
  755. return user;
  756. }
  757. @Override
  758. public User bindForeignOpenId(String code, String mobile, String codeToken, ForeignInfo foreignInfo) {
  759. // 校验空参数
  760. try {
  761. Assert.hasText(code, "验证码不能为空");
  762. Assert.hasText(mobile, "手机号不能为空");
  763. Assert.hasText(codeToken, "token不能为空");
  764. } catch (IllegalArgumentException e) {
  765. throw new VisibleError(e.getMessage());
  766. }
  767. // 校验验证码是否正确
  768. Token existToken = tokenService.findOne(codeToken);
  769. if (existToken == null || existToken.isExpired()) {
  770. throw new VisibleError("验证码过期");
  771. }
  772. if (!mobile.equals(existToken.getMobile())) {
  773. throw new VisibleError("手机号已被修改,请重新获取验证码");
  774. }
  775. if (!code.equals(existToken.getBind())) {
  776. throw new VisibleError("验证码不正确,请重新输入");
  777. }
  778. // 设置第三方openId
  779. User user = userDao.findByMobile(mobile);
  780. if (user == null) {
  781. throw new VisibleError("该用户不存在");
  782. }
  783. setForeignOpenId(user, foreignInfo);
  784. userDao.save(user);
  785. userLogger.info(user, Type.BIND_FOREIGN.getValue());
  786. return user;
  787. }
  788. /**
  789. * 设置用户第三方openId,不同应用对应不同字段
  790. *
  791. * @param user 用户信息
  792. * @param foreignInfo
  793. * @return
  794. */
  795. @Override
  796. public User setForeignOpenId(User user, ForeignInfo foreignInfo) {
  797. if (user == null) {
  798. return null;
  799. }
  800. if (foreignInfo instanceof OAuthInfo) {
  801. user.setWxUnionid(foreignInfo.getForeignOpenId());
  802. } else if (foreignInfo instanceof BiHeInfo) {
  803. user.setBhOpenId(foreignInfo.getForeignOpenId());
  804. }
  805. return user;
  806. }
  807. @Override
  808. public User findByImId(String imId) {
  809. return userDao.findByImId(imId);
  810. }
  811. /**
  812. * 同步用户信息到各个应用
  813. *
  814. * @param user 用户信息
  815. * @param noEncryPwd 未加密密码,用于同步im
  816. * @param msg 同步信息描述,用户区分同步类型
  817. */
  818. private User syncUserInfo(User user, String noEncryPwd, final String msg, App otherApp) {
  819. List<App> apps = appService.findDefaultUseApp();
  820. if (otherApp != null && !apps.contains(otherApp)) {
  821. apps.add(otherApp);
  822. }
  823. try {
  824. // 其他应用可能会用到IMID,要先同步到im之后再同步到其他应用
  825. String imId = syncUserToIm(user, noEncryPwd, msg);
  826. user.setImId(imId);
  827. user = userDao.save(user);
  828. } catch (Exception e) {
  829. e.printStackTrace();
  830. }
  831. // 封装同步其他应用数据并同步
  832. boolean hasQuestion = !CollectionUtils.isEmpty(user.getQuestions());
  833. JSONObject formData = JSON.parseObject(JSON.toJSONString(user));
  834. formData.put("password", user.getPassword());
  835. formData.put("hasQuestion", hasQuestion);
  836. syncUserInfo(formData, msg, apps);
  837. return user;
  838. }
  839. private String syncUserToIm(User user, String noEncryPwd, String msg) throws Exception {
  840. String appId = "im";
  841. App app = appService.findOne(appId);
  842. if (StringUtils.isEmpty(app.getBackUserUrl())) {
  843. return null;
  844. }
  845. // 封装数据同步到im
  846. String url = app.getBackUserUrl();
  847. HttpUtil.ResponseWrap res = null;
  848. ModelMap formData = new ModelMap();
  849. formData.put("dialectUID", user.getImId());
  850. formData.put("realName", StringUtils.isEmpty(user.getRealName()) ? user.getVipName() : user.getRealName());
  851. formData.put("password", noEncryPwd);
  852. formData.put("email", StringUtils.isEmpty(user.getEmail()) ? "0" : user.getEmail());
  853. formData.put("mobile", user.getMobile());
  854. res = HttpUtil.doPost(url, formData, 10000);
  855. if (!res.isSuccess()) {
  856. syncLogger.error(appId, msg + ",同步用户信息失败", formData.toString(), res.getContent());
  857. throw new Exception(res.getContent());
  858. } else {
  859. JSONObject obj = JSON.parseObject(res.getContent());
  860. if (obj.getString("resultMsg") != null) {
  861. syncLogger.error(appId, msg + ",同步用户信息失败", formData.toString(), res.getContent());
  862. }
  863. syncLogger.info(appId, msg + ",同步用户信息成功", formData.toString(), res.getContent());
  864. return obj.getString("dialectUID");
  865. }
  866. }
  867. /**
  868. * 同步信息到指定应用
  869. *
  870. * @param formData 同步数据
  871. * @param msg 同步信息
  872. * @param apps 需要同步的应用
  873. */
  874. private void syncUserInfo(final Map<String, Object> formData, final String msg, List<App> apps) {
  875. for (final App app : apps) {
  876. executorService.execute(new Runnable() {
  877. @Override
  878. public void run() {
  879. String url = app.getBackUserUrl();
  880. if (StringUtils.isEmpty(url)) {
  881. return;
  882. }
  883. HttpUtil.ResponseWrap res;
  884. try {
  885. res = HttpUtil.doPost(url, formData, 10000);
  886. if (!res.isSuccess()) {
  887. SyncLog syncLog = syncLogger.error(app.getUid(), msg + ",同步用户信息失败", JSON.toJSONString(formData), res.getContent());
  888. SyncFail.add(syncLog.getId(), formData, url, app.getUid());
  889. } else {
  890. syncLogger.info(app.getUid(), msg + ",同步用户信息成功", JSON.toJSONString(formData));
  891. }
  892. } catch (Exception e) {
  893. syncLogger.error(app.getUid(), msg + ",同步用户信息失败", JSON.toJSONString(formData), e.getMessage());
  894. }
  895. }
  896. });
  897. }
  898. }
  899. @Override
  900. public long countByNotLogin(int month) {
  901. return CountUtils.countBeforeInputMonth(new CountCallBack<Long>() {
  902. @Override
  903. public Long countByTime(Calendar start, Calendar end) {
  904. return countBeforeTime(end);
  905. }
  906. }, month);
  907. }
  908. private long countBeforeTime(Calendar end) {
  909. return userRecordDao.count((root, query, cb) -> {
  910. Predicate lessPredicate = cb.lessThan(root.get("lastLoginTime").as(Calendar.class), end);
  911. Predicate nullPredicate = cb.isNull(root.get("lastLoginTime"));
  912. query.where(cb.or(lessPredicate, nullPredicate));
  913. return null;
  914. });
  915. }
  916. }