UserInfoServiceImpl.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. package com.xy.service;
  2. import cn.hutool.core.collection.CollUtil;
  3. import cn.hutool.core.text.CharSequenceUtil;
  4. import cn.hutool.core.util.IdUtil;
  5. import cn.hutool.core.util.StrUtil;
  6. import cn.hutool.json.JSONUtil;
  7. import com.alibaba.fastjson.JSON;
  8. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  9. import com.baomidou.mybatisplus.core.metadata.IPage;
  10. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  11. import com.github.yitter.idgen.YitIdHelper;
  12. import com.google.common.base.Throwables;
  13. import com.xy.annotation.Lock;
  14. import com.xy.collections.list.JArrayList;
  15. import com.xy.collections.list.JList;
  16. import com.xy.config.WeChatOfficialConfig;
  17. import com.xy.config.WebMqttConfig;
  18. import com.xy.device.EnumDeviceQrCode;
  19. import com.xy.device.EnumDeviceType;
  20. import com.xy.dto.MercDeviceQrConfigDto;
  21. import com.xy.dto.SysWorkUser.AddDto;
  22. import com.xy.dto.SysWorkUser.DelDto;
  23. import com.xy.dto.SysWorkUser.UpdateDto;
  24. import com.xy.dto.UserInfoDto;
  25. import com.xy.dto.WxServiceMsgDto;
  26. import com.xy.entity.UserInfo;
  27. import com.xy.error.CommRuntimeException;
  28. import com.xy.mapper.UserInfoMapper;
  29. import com.xy.utils.*;
  30. import io.swagger.annotations.Api;
  31. import io.swagger.annotations.ApiOperation;
  32. import lombok.AllArgsConstructor;
  33. import lombok.SneakyThrows;
  34. import lombok.extern.slf4j.Slf4j;
  35. import me.chanjar.weixin.common.api.WxConsts;
  36. import me.chanjar.weixin.mp.api.WxMpMessageHandler;
  37. import me.chanjar.weixin.mp.api.WxMpMessageRouter;
  38. import me.chanjar.weixin.mp.api.WxMpService;
  39. import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
  40. import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
  41. import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
  42. import org.springframework.beans.factory.annotation.Autowired;
  43. import org.springframework.context.ApplicationContext;
  44. import org.springframework.stereotype.Service;
  45. import org.springframework.validation.annotation.Validated;
  46. import org.springframework.web.bind.annotation.PostMapping;
  47. import org.springframework.web.bind.annotation.RequestBody;
  48. import org.springframework.web.bind.annotation.RequestMapping;
  49. import javax.servlet.http.HttpServletRequest;
  50. import java.util.List;
  51. import java.util.Map;
  52. import java.util.Objects;
  53. import static com.xy.utils.Beans.copy;
  54. import static com.xy.utils.PlusBeans.toIPage;
  55. import static com.xy.utils.PlusBeans.toPageBean;
  56. /**
  57. * <p>
  58. * 用户表 服务实现类
  59. * </p>
  60. *
  61. * @author lijin
  62. * @since 2023-01-12
  63. */
  64. @Slf4j
  65. @Service
  66. @AllArgsConstructor
  67. @Api(tags = "用户表")
  68. public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {
  69. private SysWorkUserService sysWorkUserService;
  70. private WebMqttConfig webMqttConfig;
  71. private WxMpService wxService;
  72. private WeChatOfficialConfig weChatOfficialConfig;
  73. @Override
  74. @ApiOperation("集合查询")
  75. public R<List<UserInfoDto.Vo>> list(UserInfoDto.SelectListDto selectList) {
  76. List<Long> userIds = selectList.getUserIds();
  77. UserInfoDto.Vo userVo = selectList.getUserVo();
  78. LambdaQueryWrapper<UserInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
  79. if (userVo != null) {
  80. lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(selectList.getUserVo(), UserInfo.class).build();
  81. }
  82. lambdaQueryWrapper.in(CollUtil.isNotEmpty(userIds), UserInfo::getUserId, userIds);
  83. List<UserInfo> list = list(lambdaQueryWrapper);
  84. return R.ok(copy(UserInfoDto.Vo.class, list));
  85. }
  86. @Override
  87. @ApiOperation("对象查询")
  88. public R<UserInfoDto.Vo> obj(UserInfoDto.Vo vo) {
  89. LambdaQueryWrapper<UserInfo> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(vo, UserInfo.class).build();
  90. List<UserInfo> list = list(lambdaQueryWrapper);
  91. if (Emptys.check(list)) {
  92. return R.ok(copy(UserInfoDto.Vo.class, list.get(0)));
  93. }
  94. return R.ok();
  95. }
  96. @PostMapping("page")
  97. @ApiOperation("分页查询")
  98. public R<PageBean<UserInfoDto.Vo>> page(@RequestBody UserInfoDto.Page page) {
  99. PageBean pageBean = page.getPage();
  100. LambdaQueryWrapper<UserInfo> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(page, UserInfo.class)
  101. .like(UserInfo::getTel, page.getTel())
  102. .like(UserInfo::getMail, page.getMail())
  103. .like(UserInfo::getUnionid, page.getUnionid())
  104. .ge(UserInfo::getCreateTime, page.getBeginCreateTime())
  105. .le(UserInfo::getCreateTime, page.getEndCreateTime())
  106. .build()
  107. .eq(!AuthorizeUtils.authByData(page.getSysId()), UserInfo::getCreateUser, AuthorizeUtils.getLoginId(Long.class))
  108. .orderByDesc(!Emptys.check(pageBean.getOrders()), UserInfo::getCreateTime);
  109. IPage<UserInfo> iPage = page(toIPage(pageBean), lambdaQueryWrapper);
  110. return R.ok(toPageBean(UserInfoDto.Vo.class, iPage));
  111. }
  112. @Override
  113. @ApiOperation("添加")
  114. @Lock(value = "save.tel", prefix = "user_save_")
  115. public R<UserInfoDto.Vo> save(UserInfoDto.Save save) {
  116. //添加权限用户
  117. AddDto addDto = copy(AddDto.class, save)
  118. .setEmail(save.getMail())
  119. .setPhone(save.getTel())
  120. .setRoleIds(save.getRoleIds())
  121. .setAccount(save.getAccount());
  122. R<Long> register = sysWorkUserService.register(addDto);
  123. if (register.getCode() != R.Enum.SUCCESS.getCode()) {
  124. return R.fail(register.getMsg());
  125. }
  126. Long authorizeUserId = register.getData();
  127. //添加用户
  128. Long loginId = AuthorizeUtils.getLoginId(Long.class);
  129. UserInfo saveInfo = copy(UserInfo.class, save)
  130. .createUserTime(loginId)
  131. .setUserId(YitIdHelper.nextId())
  132. .setAuthorizeUserId(authorizeUserId)
  133. .createUserTime(loginId);
  134. save(saveInfo);
  135. return R.ok(copy(UserInfoDto.Vo.class, saveInfo));
  136. }
  137. @Override
  138. @ApiOperation("修改")
  139. @Lock(value = "update.userId", prefix = "user_update_")
  140. public R update(UserInfoDto.Update update) {
  141. log.info("权限用户信息修改请求:{}", JSONUtil.toJsonPrettyStr(update));
  142. UserInfo byId = getById(update.getUserId());
  143. String account = update.getAccount();
  144. if (StrUtil.isNotEmpty(update.getTel())) {
  145. if (!update.getTel().equals(byId.getTel())) {
  146. long count = count(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getTel, update.getTel()));
  147. if (count > 0) {
  148. return R.fail("手机已存在");
  149. }
  150. }
  151. }
  152. if (StrUtil.isNotEmpty(update.getMail())) {
  153. if (!byId.getMail().equals(update.getMail())) {
  154. long count = count(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getMail, update.getMail()));
  155. if (count > 0) {
  156. return R.fail("邮箱已存在");
  157. }
  158. }
  159. }
  160. UserInfo updateInfo = copy(UserInfo.class, update)
  161. .updateUserTime(AuthorizeUtils.getLoginId(Long.class));
  162. UserInfo u = getById(update.getUserId());
  163. //修改权限用户
  164. if (Emptys.check(update.getTel()) || Emptys.check(update.getMail()) || Emptys.check(update.getStatus()) || Emptys.check(update.getPassword())) {
  165. UpdateDto updateDto = new UpdateDto()
  166. .setId(u.getAuthorizeUserId())
  167. .setAccount(account)
  168. .setPhone(update.getTel())
  169. .setEmail(update.getMail())
  170. .setPassword(update.getPassword())
  171. .setStatus(update.getStatus())
  172. .setRoleIds(update.getRoleIds());
  173. log.info("权限用户信息修改:{}", JSONUtil.toJsonPrettyStr(updateDto));
  174. sysWorkUserService.update(updateDto);
  175. }
  176. //修改用户
  177. updateById(updateInfo);
  178. return R.ok();
  179. }
  180. @ApiOperation("删除用户")
  181. @Override
  182. public R del(@RequestBody @Validated UserInfoDto.DelDto dto) {
  183. //sys_work_user 权限用户表
  184. R r = sysWorkUserService.del(copy(DelDto.class, dto));
  185. if (R.Enum.SUCCESS.getCode() != r.getCode()) {
  186. return R.fail(r.getMsg());
  187. }
  188. //user_info 用户表
  189. return R.ok(removeBatchByIds(dto.getId()));
  190. }
  191. @PostMapping("webUserMqtt")
  192. @ApiOperation("获取用户mqtt信息")
  193. public R<UserInfoDto.WebUserMqttVo> webUserMqtt(@RequestBody @Validated UserInfoDto.WebUserMqtt webUserMqtt) {
  194. Long loginId = AuthorizeUtils.getLoginId(Long.class);
  195. Integer type = webUserMqtt.getType();
  196. UserInfoDto.WebUserMqttVo webUserMqttVo = new UserInfoDto.WebUserMqttVo()
  197. .setUsername(webMqttConfig.getUsername())
  198. .setPassword(webMqttConfig.getPassword());
  199. WebMqttConfig.Protocol protocol = webMqttConfig.getProtocol();
  200. WebMqttConfig.Topic topic = webMqttConfig.getTopic();
  201. if (type == 1) {
  202. webUserMqttVo.setUrl(protocol.getPcUrl() + webMqttConfig.getIp())
  203. .setPort(webMqttConfig.getWsPort())
  204. .setClientTopic(topic.getPrefix() + topic.getPcManagePrefix() + loginId);
  205. } else if (type == 2) {
  206. webUserMqttVo.setUrl(protocol.getWxsUrl() + webMqttConfig.getIp())
  207. .setPort(webMqttConfig.getWssPort())
  208. .setClientTopic(topic.getPrefix() + topic.getWxCPrefix() + loginId);
  209. } else if (type == 3) {
  210. webUserMqttVo.setUrl(protocol.getAlisUrl() + webMqttConfig.getIp())
  211. .setPort(webMqttConfig.getWssPort())
  212. .setClientTopic(topic.getPrefix() + topic.getAlisCPrefix() + loginId);
  213. }
  214. return R.ok(webUserMqttVo);
  215. }
  216. @ApiOperation("修改微信信息")
  217. @Override
  218. public R updateByWechat(UserInfoDto.UpdateByWechat dto) {
  219. updateById(copy(UserInfo.class, dto));
  220. return R.ok();
  221. }
  222. @ApiOperation("修改支付宝信息")
  223. @Override
  224. public R updateByAli(UserInfoDto.UpdateByAli dto) {
  225. updateById(copy(UserInfo.class, dto));
  226. return R.ok();
  227. }
  228. @SneakyThrows
  229. @PostMapping("wxQrCode")
  230. @ApiOperation("获取微信服务号二维码-扫码关注公众号并绑定")
  231. public R<UserInfoDto.WxQrCodeVO> getQrCode(@RequestBody @Validated UserInfoDto.WxQrCode wxQrCode) {
  232. WxMpService wxMpService = weChatOfficialConfig.getWxMpService();
  233. if (wxMpService == null) {
  234. throw new CommRuntimeException("获取微信公众号配置信息失败!");
  235. }
  236. //指定用户
  237. String userId = wxQrCode.getUserId();
  238. if (StrUtil.isEmpty(userId)) {
  239. //当前登录用户
  240. userId = AuthorizeUtils.getLoginId(String.class);
  241. }
  242. WxMpQrCodeTicket ticket = wxService.getQrcodeService().qrCodeCreateTmpTicket(userId, 2592000);
  243. String tk = ticket.getTicket();
  244. String url = wxService.getQrcodeService().qrCodePictureUrl(tk);
  245. JList<String> contents = new JArrayList<>();
  246. contents.set(url);
  247. JList<String> text = new JArrayList<>();
  248. text.set("使用微信[扫一扫]关注");
  249. List<String> base64s = QRCodeUtils.create(contents, 400, 400, "back1.png", text).base64();
  250. UserInfoDto.WxQrCodeVO vo = new UserInfoDto.WxQrCodeVO();
  251. log.info("获取微信服务号二维码 usrId:{},tk:{}", userId, tk);
  252. return R.ok(vo.setImgList(base64s).setTicket(tk));
  253. }
  254. private WxMpMessageRouter wxMpMessageRouter;
  255. @Autowired
  256. private Map<String, WxMpMessageHandler> wxMpMessageHandlers;
  257. /**
  258. * 接收微信的事件消息
  259. * https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html
  260. *
  261. * @return
  262. */
  263. @RequestMapping(value = "/receipt", produces = {"application/xml; charset=UTF-8"})
  264. @ApiOperation("接收微信的事件消息")
  265. public String receiptMessage(@RequestBody(required = false) WxServiceMsgDto wxServiceMsgDto, HttpServletRequest request) {
  266. WxMpService wxMpService = weChatOfficialConfig.getWxMpService();
  267. if (wxMpService == null) {
  268. throw new CommRuntimeException("获取微信公众号配置信息失败!");
  269. }
  270. String echoStr = request.getParameter(WeChatOfficialConfig.ECHO_STR);
  271. // echoStr!=null,说明只是微信调试的请求
  272. if (CharSequenceUtil.isNotBlank(echoStr)) {
  273. return echoStr;
  274. }
  275. String signature = request.getParameter(WeChatOfficialConfig.SIGNATURE);
  276. String nonce = request.getParameter(WeChatOfficialConfig.NONCE);
  277. String timestamp = request.getParameter(WeChatOfficialConfig.TIMESTAMP);
  278. if (!wxService.checkSignature(timestamp, nonce, signature)) {
  279. throw new CommRuntimeException("接收微信的事件消息,验签异常!");
  280. }
  281. log.info("接收微信的事件消息:{}", wxServiceMsgDto);
  282. //处理带参数请求
  283. if (null != wxServiceMsgDto &&
  284. !StrUtil.isEmpty(wxServiceMsgDto.getMsgType()) &&
  285. !StrUtil.isEmpty(wxServiceMsgDto.getEvent()) &&
  286. !StrUtil.isEmpty(wxServiceMsgDto.getEventKey()) && !wxServiceMsgDto.getEventKey().equals("null") &&
  287. (wxServiceMsgDto.getEventKey().equals("subscribe") || wxServiceMsgDto.getEvent().equals("SCAN"))
  288. ) {
  289. //关注
  290. if (wxServiceMsgDto.getEvent().equals("subscribe")) {
  291. log.info("关注: " + wxServiceMsgDto.getFromUserName());
  292. setCacheTicket("1", wxServiceMsgDto.getFromUserName());
  293. if (wxServiceMsgDto.getEventKey().contains("FenXiangMa")) {
  294. log.info("优惠券领取");
  295. }
  296. }
  297. //扫码
  298. if (wxServiceMsgDto.getEvent().equals("SCAN")) {
  299. log.info("扫码: " + wxServiceMsgDto.getFromUserName());
  300. if (wxServiceMsgDto.getEventKey().contains("YaoQingMa")) {
  301. log.info("新用户邀请");
  302. }
  303. }
  304. log.info("参数: " + wxServiceMsgDto.getEventKey());
  305. }
  306. return "";
  307. //
  308. // String encryptType = CharSequenceUtil.isBlank(request.getParameter(WeChatOfficialConfig.ENCRYPT_TYPE)) ? WeChatOfficialConfig.RAW : request.getParameter(WeChatOfficialConfig.ENCRYPT_TYPE);
  309. // if (WeChatOfficialConfig.RAW.equals(encryptType)) {
  310. // WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(request.getInputStream());
  311. // log.info("raw inMessage:{}", JSON.toJSONString(inMessage));
  312. // WxMpXmlOutMessage outMessage = weChatOfficialConfig.getWxMpMessageRouter().route(inMessage);
  313. // return outMessage.toXml();
  314. // } else if (WeChatOfficialConfig.AES.equals(encryptType)) {
  315. // String msgSignature = request.getParameter(WeChatOfficialConfig.MSG_SIGNATURE);
  316. // WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(request.getInputStream(), weChatOfficialConfig.getConfig(), timestamp, nonce, msgSignature);
  317. // log.info("aes inMessage:{}", JSON.toJSONString(inMessage));
  318. // WxMpXmlOutMessage outMessage = weChatOfficialConfig.getWxMpMessageRouter().route(inMessage);
  319. // return outMessage.toEncryptedXml(weChatOfficialConfig.getConfig());
  320. // }
  321. // return "ok";
  322. }
  323. /**
  324. * 缓存ticket
  325. *
  326. * @param tk
  327. * @param openId
  328. */
  329. public static void setCacheTicket(String tk, String openId) {
  330. RedisService<String> redisService = SpringBeanUtils.getBean(RedisService.class);
  331. redisService.set("wechat:scan:ticket:" + tk, openId, 3600);//1h
  332. }
  333. /**
  334. * 获取tk
  335. *
  336. * @param tk
  337. * @return {@link String}
  338. */
  339. public static String getCacheTicket(String tk) {
  340. RedisService<String> redisService = SpringBeanUtils.getBean(RedisService.class);
  341. return redisService.get("wechat:scan:ticket:" + tk);
  342. }
  343. /**
  344. * 刪除ticket
  345. *
  346. * @param tk
  347. */
  348. public static void delCacheTicket(String tk) {
  349. RedisService<String> redisService = SpringBeanUtils.getBean(RedisService.class);
  350. redisService.remove("wechat:scan:ticket:" + tk);
  351. }
  352. }