CmsAccountServiceImpl.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. package com.cyksj.service.mange.account;
  2. import cn.hutool.core.collection.CollUtil;
  3. import cn.hutool.core.lang.Validator;
  4. import cn.hutool.core.util.RandomUtil;
  5. import cn.hutool.core.util.StrUtil;
  6. import com.baomidou.mybatisplus.core.metadata.IPage;
  7. import com.baomidou.mybatisplus.core.toolkit.Assert;
  8. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  9. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  10. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  11. import com.cyksj.common.constant.Constant;
  12. import com.cyksj.common.exception.BusinessRuntimeException;
  13. import com.cyksj.common.util.Jsons;
  14. import com.cyksj.common.util.StringUtil;
  15. import com.cyksj.mapper.AccountBlockedReplaceRecordMapper;
  16. import com.cyksj.mapper.AccountMapper;
  17. import com.cyksj.mapper.AccountUpdatePasswordRecordMapper;
  18. import com.cyksj.mapper.GoodsDonMapper;
  19. import com.cyksj.mapper.manage.AutoUpdateAccountPwdLogMapper;
  20. import com.cyksj.mapper.manage.cms.CmsUserMapper;
  21. import com.cyksj.mapper.sys.SysEmailMapper;
  22. import com.cyksj.model.entity.*;
  23. import com.cyksj.model.excel.ExcelAccountData;
  24. import com.cyksj.model.manage.views.AccountView;
  25. import com.cyksj.model.views.CmsUserVO;
  26. import com.cyksj.model.views.ExpiredAccountDataView;
  27. import com.cyksj.redis.RedisService;
  28. import com.cyksj.service.mail.CuiQiuMailService;
  29. import com.cyksj.service.mail.YhMailService;
  30. import com.cyksj.service.mange.AccountCommonService;
  31. import com.cyksj.service.mange.CmsAccountService;
  32. import com.cyksj.service.mange.CmsGroupService;
  33. import com.cyksj.service.sys.SysConfigService;
  34. import com.ejlchina.searcher.BeanSearcher;
  35. import com.ejlchina.searcher.param.Operator;
  36. import com.ejlchina.searcher.util.MapUtils;
  37. import com.google.common.collect.Lists;
  38. import lombok.RequiredArgsConstructor;
  39. import lombok.extern.slf4j.Slf4j;
  40. import org.springframework.stereotype.Service;
  41. import org.springframework.transaction.annotation.Transactional;
  42. import org.springframework.web.multipart.MultipartFile;
  43. import java.io.BufferedReader;
  44. import java.io.InputStream;
  45. import java.io.InputStreamReader;
  46. import java.util.*;
  47. /**
  48. * @author chan
  49. * @date 2022/9/27 6:23 PM
  50. */
  51. @Slf4j
  52. @Service("cms")
  53. @RequiredArgsConstructor
  54. public class CmsAccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements CmsAccountService {
  55. private final AccountMapper accountMapper;
  56. private final AccountUpdatePasswordRecordMapper accountUpdatePasswordRecordMapper;
  57. private final CmsUserMapper cmsUserMapper;
  58. private final AutoUpdateAccountPwdLogMapper autoUpdateAccountPwdLogMapper;
  59. private final BeanSearcher beanSearcher;
  60. private final CmsGroupService cmsGroupService;
  61. private final RedisService redisService;
  62. private final AccountCommonService accountCommonService;
  63. private final SysConfigService sysConfigService;
  64. private final SysEmailMapper sysEmailMapper;
  65. private final GoodsDonMapper goodsDonMapper;
  66. private final AccountBlockedReplaceRecordMapper accountBlockedReplaceRecordMapper;
  67. private final CuiQiuMailService cuiQiuMailService;
  68. private final YhMailService yhMailService;
  69. @Override
  70. public IPage<ExpiredAccountDataView> getExpiredAccountView(Boolean isCorpWx, String customerService, Long goodsId, Long skuId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer userId, String startTime, String endTime, String now, Long offset, Long limit) {
  71. return accountMapper.getExpiredAccountView(isCorpWx, customerService, goodsId, skuId, account, renewStatus, handleStatus, cnAccount, usAccount, userId, startTime, endTime, now, new Page<>(offset, limit));
  72. }
  73. @Override
  74. public List<ExcelAccountData> getExpiredAccountViewNoPage(Boolean isCorpWx, String customerService, Long goodsId, Long skuId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer userId, String startTime, String endTime, String now) {
  75. return accountMapper.getExpiredAccountViewNoPage(isCorpWx, customerService, goodsId, skuId, account, renewStatus, handleStatus, cnAccount, usAccount, userId, startTime, endTime, now);
  76. }
  77. @Override
  78. public List<OrderDon> getNoAppleOneOrderDon(List<Long> skuIds, Date yesZeroDate, Date thisZeroDate, List<String> noOrderStatus) {
  79. return accountMapper.getNoAppleOneOrderDon(skuIds, yesZeroDate, thisZeroDate, noOrderStatus);
  80. }
  81. @Override
  82. public List<AccountView> getExpiredAllAccount() {
  83. return accountMapper.getExpiredAllAccount();
  84. }
  85. @Override
  86. public void saveRecord(Long operateUserId, Long accountId, String oldPassword, String newPassword, String type) {
  87. AccountUpdatePasswordRecord record = new AccountUpdatePasswordRecord();
  88. record.setAccountId(accountId);
  89. record.setOperateUserId(operateUserId);
  90. Optional.ofNullable(cmsUserMapper.selectById(operateUserId))
  91. .ifPresent(admin -> record.setOperator(admin.getNickname()));
  92. record.setOldPassword(oldPassword);
  93. record.setNewPassword(newPassword);
  94. record.setType(type);
  95. accountUpdatePasswordRecordMapper.insert(record);
  96. }
  97. @Override
  98. public void recordAutoUpdatePwd(Long accountId, String account, String oldPwd, String newPwd, String operateIp) {
  99. AutoUpdateAccountPwdLog log = new AutoUpdateAccountPwdLog();
  100. log.setAccountId(accountId);
  101. log.setAccount(account);
  102. log.setOldPwd(oldPwd);
  103. log.setNewPwd(newPwd);
  104. log.setOperateLocation(StringUtil.getRealAddressByIP(operateIp));
  105. log.setOperateIp(operateIp);
  106. autoUpdateAccountPwdLogMapper.insert(log);
  107. }
  108. @Override
  109. public void assignDeleteCustomerAccount(Long customerServiceId) {
  110. List<AccountView> accountViews = beanSearcher.searchAll(AccountView.class, MapUtils.builder()
  111. .field(AccountView::getCustomerServiceId, customerServiceId)
  112. .build());
  113. if (accountViews.size() > 0) {
  114. List<CmsUserVO> customers = beanSearcher.searchAll(CmsUserVO.class, MapUtils.builder()
  115. .field(CmsUserVO::getId, customerServiceId).op(Operator.NotEqual)
  116. .field(CmsUserVO::getRoleNames, "客服").op(Operator.Contain)
  117. .build());
  118. if (customers.size() > 0) {
  119. log.info("删除客服id:{},分配其未修改的过期账号,账号数量:{}", customerServiceId, accountViews.size());
  120. assignCustomerAccount(customers, accountViews);
  121. }
  122. }
  123. }
  124. @Override
  125. public void assignCustomerAccount(List<CmsUserVO> customers, List<AccountView> accountViews) {
  126. int customerSize = customers.size();
  127. int accountSize = accountViews.size();
  128. if (accountSize < customerSize) {
  129. accountViews.forEach(account -> {
  130. int randomIndex = RandomUtil.randomInt(customerSize);
  131. CmsUserVO customer = customers.get(randomIndex);
  132. accountMapper.update(null, Wrappers.lambdaUpdate(Account.class)
  133. .set(Account::getCustomerServiceId, customer.getId())
  134. .eq(Account::getId, account.getId()));
  135. });
  136. return;
  137. }
  138. int num = accountSize / customerSize;
  139. int remain = accountSize % customerSize;
  140. List<List<AccountView>> partition = Lists.partition(accountViews, num);
  141. for (int i = 0; i < customerSize; i++) {
  142. List<AccountView> expiredAccounts = partition.get(i);
  143. CmsUserVO customer = customers.get(i);
  144. expiredAccounts.forEach(ea -> {
  145. Long accountId = ea.getId();
  146. accountMapper.update(null, Wrappers.lambdaUpdate(Account.class)
  147. .set(Account::getCustomerServiceId, customer.getId())
  148. .eq(Account::getId, accountId));
  149. });
  150. }
  151. if (remain > 0) {
  152. log.info("分配多余的过期账号给客服");
  153. List<AccountView> remainExpiredAccount = partition.get(customerSize);
  154. remainExpiredAccount.forEach(remainAccount -> {
  155. int randomIndex = RandomUtil.randomInt(customerSize);
  156. log.info("获取的随机下标:{}", randomIndex);
  157. CmsUserVO customer = customers.get(randomIndex);
  158. log.info("随机分配的客服是:{}", customer.getNickname());
  159. Long accountId = remainAccount.getId();
  160. accountMapper.update(null, Wrappers.lambdaUpdate(Account.class)
  161. .set(Account::getCustomerServiceId, customer.getId())
  162. .eq(Account::getId, accountId));
  163. });
  164. }
  165. }
  166. @Override
  167. @Transactional(rollbackFor = Throwable.class)
  168. public void analysisChatGPTAccount(Long goodsId, Long skuId, List<Object> accountList) {
  169. insertAccount(goodsId, skuId, accountList);
  170. }
  171. @Override
  172. public void analysisAmericaAppidAccount(Long goodsId, Long skuId, List<Object> accountList) {
  173. insertAccount(goodsId, skuId, accountList);
  174. }
  175. @Override
  176. public void readFileAndImportEmail(MultipartFile file) throws Exception {
  177. InputStream in = null;
  178. BufferedReader br = null;
  179. String regex = "----";
  180. List<SysEmail> sysEmails = new ArrayList<>();
  181. List<String> error = new ArrayList<>();
  182. try {
  183. in = file.getInputStream();
  184. br = new BufferedReader(new InputStreamReader(file.getInputStream()));
  185. String content = null;
  186. while ((content = br.readLine()) != null) {
  187. String[] split = content.split(regex);
  188. if (split.length > 1) {
  189. String email = split[0];
  190. String password = split[1];
  191. if (!StrUtil.hasEmpty(email, password)) {
  192. SysEmail sysEmail = new SysEmail();
  193. sysEmail.setEmail(email);
  194. sysEmail.setPassword(password);
  195. sysEmails.add(sysEmail);
  196. }
  197. }else {
  198. error.add(split[0]);
  199. }
  200. }
  201. if (CollUtil.isNotEmpty(sysEmails)) {
  202. Lists.partition(sysEmails, 1000).forEach(data -> {
  203. sysEmailMapper.batchInsert(data);
  204. });
  205. }
  206. } finally {
  207. if (br != null) {
  208. br.close();
  209. }
  210. if (in != null) {
  211. in.close();
  212. }
  213. }
  214. System.out.println(Jsons.toJson(error));
  215. }
  216. /**
  217. *
  218. * @param goodsId
  219. * @param skuId
  220. * @param accountList
  221. */
  222. public void insertAccount(Long goodsId, Long skuId, List<Object> accountList) {
  223. if (CollUtil.isEmpty(accountList)) {
  224. throw BusinessRuntimeException.getInstance("文件数据为空");
  225. }
  226. String cache = RedisService.key.IMPORT_ACCOUNT_CACHE_KEY.getNameFormat(goodsId);
  227. if (!redisService.setNx(cache, goodsId, RedisService.key.IMPORT_ACCOUNT_CACHE_KEY.getTimeout())) {
  228. throw BusinessRuntimeException.getInstance("后台程序正在导入账号中...");
  229. }
  230. List<Long> special_email_goods_ids = new ArrayList<>();
  231. SysConfig sysConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
  232. .eq(SysConfig::getSysKey, Constant.SPECIAL_GOODS_ACCOUNT_IMPORT_KEY).last("limit 1"));
  233. if (sysConfig != null) {
  234. try {
  235. special_email_goods_ids.addAll(Jsons.parseList(sysConfig.getSysValue(), Long.class));
  236. } catch (Exception e) {
  237. }
  238. }
  239. String regex;
  240. if (goodsId == 29l) {
  241. regex = "\\|";
  242. } else {
  243. regex = "----";
  244. }
  245. try {
  246. accountList.forEach(accountData -> {
  247. Map<String, Object> map = Jsons.toMap(accountData);
  248. Account insert = new Account();
  249. insert.setGoodsId(goodsId);
  250. if (map.keySet().size() >= 5) {
  251. String account = map.get("0").toString();
  252. String password = map.get("1").toString();
  253. String friend = map.get("2").toString();
  254. String work = map.get("3").toString();
  255. String parents = map.get("4").toString();
  256. String secret;
  257. if (map.keySet().size() == 6) {
  258. String country = map.get("5").toString();
  259. secret = String.format(Constant.NEW_APPID_SECRET, friend, work, parents, country);
  260. } else {
  261. secret = String.format(Constant.NEW_APPID_NO_COUNTRY_SECRET, friend, work, parents);
  262. }
  263. insert.setAccount(account);
  264. insert.setPassword(password);
  265. insert.setSecret(secret);
  266. } else {
  267. String[] part = map.get("0").toString().split(regex);
  268. if (part.length >= 2) {
  269. String account = part[0];
  270. String password = part[1];
  271. insert.setAccount(account);
  272. insert.setPassword(password);
  273. if (part.length > 2 && part.length < 9) {
  274. //google36、辅助邮箱
  275. //46 Google Bard
  276. if (special_email_goods_ids.contains(goodsId)) {
  277. String email = part[2];
  278. insert.setEmail(email);
  279. } else {
  280. //chatGPT 邮箱密码
  281. String gptEmailPwd = part[2];
  282. insert.setGptEmailPwd(gptEmailPwd);
  283. }
  284. }
  285. if (goodsId.equals(31l)) {
  286. if (part.length >= 9) {
  287. StringBuilder sb = new StringBuilder();
  288. String country = part[part.length - 1];
  289. if (country.contains("国")) {
  290. sb.append(part[part.length - 1]);
  291. sb.append(Constant.ONE_EMPTY);
  292. sb.append(part[part.length - 2]);
  293. sb.append(Constant.ONE_EMPTY);
  294. }
  295. for (int i = 2; i < part.length; i++) {
  296. if (part[i].contains("朋友")) {
  297. sb.append("朋友");
  298. sb.append(Constant.ONE_EMPTY);
  299. sb.append(part[i + 1]);
  300. i++;
  301. }
  302. if (part[i].contains("工作")) {
  303. sb.append("工作");
  304. sb.append(Constant.ONE_EMPTY);
  305. sb.append(part[i + 1]);
  306. i++;
  307. }
  308. if (part[i].contains("父母")) {
  309. sb.append("父母");
  310. sb.append(Constant.ONE_EMPTY);
  311. sb.append(part[i + 1]);
  312. i++;
  313. }
  314. if (part[i].contains("菜")) {
  315. sb.append("一道菜");
  316. sb.append(Constant.ONE_EMPTY);
  317. sb.append(part[i + 1]);
  318. i++;
  319. }
  320. if (part[i].contains("书")) {
  321. sb.append("一本书");
  322. sb.append(Constant.ONE_EMPTY);
  323. sb.append(part[i + 1]);
  324. i++;
  325. }
  326. if (part[i].contains("专辑")) {
  327. sb.append("一张专辑");
  328. sb.append(Constant.ONE_EMPTY);
  329. sb.append(part[i + 1]);
  330. i++;
  331. }
  332. }
  333. String string = sb.toString();
  334. if (string.contains("菜")) {
  335. StringBuilder builder = new StringBuilder();
  336. string = builder.append("生日").append(Constant.ONE_EMPTY).append(part[2]).append(Constant.ONE_EMPTY).append(string).toString();
  337. }
  338. insert.setSecret(string);
  339. } else {
  340. //密保
  341. if (part.length > 5) {
  342. String friends = part[2];
  343. String works = part[3];
  344. String parents = part[4];
  345. String birthday = part[5];
  346. String secret = String.format(Constant.NEW_APPID_NO_COUNTRY_SECRET_DATE, birthday, friends, works, parents);
  347. insert.setSecret(secret);
  348. }
  349. }
  350. }
  351. }
  352. }
  353. String account = insert.getAccount();
  354. if (StrUtil.isEmpty(account)) {
  355. return;
  356. }
  357. //重复不再重新插入
  358. if (accountCommonService.checkIsDupAccount(goodsId, account)) {
  359. return;
  360. }
  361. this.save(insert);
  362. //是否存在未发车的车队
  363. GroupsTrips waiting = cmsGroupService.getOne(Wrappers.lambdaQuery(GroupsTrips.class)
  364. .eq(GroupsTrips::getSkuId, skuId)
  365. .eq(GroupsTrips::getStatus, GroupsTrips.Status.waiting).last("limit 1"));
  366. if (waiting != null) {
  367. waiting.setAccountId(insert.getId());
  368. try {
  369. cmsGroupService.setAccount(waiting);
  370. } catch (Exception e) {
  371. //自动配置车队
  372. setGroupsTrips(skuId, insert.getId());
  373. }
  374. } else {
  375. //自动配置车队
  376. setGroupsTrips(skuId, insert.getId());
  377. }
  378. });
  379. } catch (Exception e) {
  380. log.error(StringUtil.getErrorText(e));
  381. }
  382. redisService.del(cache);
  383. }
  384. public void setGroupsTrips(Long skuId, Long accountId) {
  385. //自动配置车队
  386. GroupsTrips groupsTrips = new GroupsTrips();
  387. groupsTrips.setSkuId(skuId);
  388. groupsTrips.setAccountId(accountId);
  389. cmsGroupService.issuance(groupsTrips, null);
  390. }
  391. @Override
  392. public void batchImportBlockedAccount(Long goodsId, List<Object> accountBlockedList) {
  393. GoodsDon goodsDon = goodsDonMapper.selectById(goodsId);
  394. Assert.notNull(goodsDon, "平台不存在");
  395. List<AccountBlockedReplaceRecord> list = new ArrayList<>();
  396. accountBlockedList.forEach(accountBlocked->{
  397. Map<String, Object> map = Jsons.toMap(accountBlocked);
  398. String blockedAccount = map.get("0").toString();
  399. if (!Validator.isEmail(blockedAccount)) {
  400. return;
  401. }
  402. AccountBlockedReplaceRecord accountBlockedReplaceRecord = new AccountBlockedReplaceRecord();
  403. accountBlockedReplaceRecord.setGoodsId(goodsId);
  404. accountBlockedReplaceRecord.setAccount(blockedAccount);
  405. list.add(accountBlockedReplaceRecord);
  406. if (list.size() == 400) {
  407. accountBlockedReplaceRecordMapper.batchInsert(list);
  408. list.clear();
  409. }
  410. });
  411. if (list.size() > 0) {
  412. accountBlockedReplaceRecordMapper.batchInsert(list);
  413. }
  414. }
  415. @Override
  416. public String nfUpgradeDevice(Long accountId) throws Exception {
  417. Account at = accountMapper.selectById(accountId);
  418. if (at == null || at.getGoodsId() != 1l) {
  419. throw BusinessRuntimeException.getInstance("只支持奈飞账号");
  420. }
  421. String account = at.getAccount();
  422. String password = at.getPassword();
  423. if (StrUtil.hasEmpty(account, password)) {
  424. throw BusinessRuntimeException.getInstance("账户异常");
  425. }
  426. if (cuiQiuMailService.isCuiQiuEmail(account)) {
  427. return cuiQiuMailService.getVerifyCode(account, at.getGoodsId(), null, 1);
  428. }
  429. String code = null;
  430. try {
  431. code = yhMailService.getVerifyCode(account, at.getGoodsId(), null, 1);
  432. } catch (Exception e) {
  433. if (e.getMessage() != null && e.getMessage().contains("认证链接")) {
  434. throw BusinessRuntimeException.getInstance("请联系用户确认是否发送邮件");
  435. }
  436. throw BusinessRuntimeException.getInstance(e.getMessage());
  437. }
  438. return code;
  439. }
  440. @Override
  441. public String getAccountEmailCode(Long accountId) throws Exception {
  442. Account at = accountMapper.selectById(accountId);
  443. if (at == null || at.getGoodsId() != 1l) {
  444. throw BusinessRuntimeException.getInstance("只支持奈飞账号");
  445. }
  446. String account = at.getAccount();
  447. String password = at.getPassword();
  448. if (StrUtil.isNotEmpty(at.getRelateEmail())) {
  449. account = at.getRelateEmail();
  450. }
  451. if (StrUtil.hasEmpty(account, password)) {
  452. throw BusinessRuntimeException.getInstance("账户异常");
  453. }
  454. if (cuiQiuMailService.isCuiQiuEmail(account)) {
  455. return cuiQiuMailService.getVerifyCode(account, at.getGoodsId(), null, null);
  456. }
  457. String code = yhMailService.getVerifyCode(account, at.getGoodsId(), null, null);
  458. return code;
  459. }
  460. }