package com.xy.service;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yitter.idgen.YitIdHelper;
import com.google.common.base.Throwables;
import com.xy.annotation.Lock;
import com.xy.collections.list.JArrayList;
import com.xy.collections.list.JList;
import com.xy.config.WeChatOfficialConfig;
import com.xy.config.WebMqttConfig;
import com.xy.device.EnumDeviceQrCode;
import com.xy.device.EnumDeviceType;
import com.xy.dto.MercDeviceQrConfigDto;
import com.xy.dto.SysWorkUser.AddDto;
import com.xy.dto.SysWorkUser.DelDto;
import com.xy.dto.SysWorkUser.UpdateDto;
import com.xy.dto.UserInfoDto;
import com.xy.dto.WxServiceMsgDto;
import com.xy.entity.UserInfo;
import com.xy.error.CommRuntimeException;
import com.xy.mapper.UserInfoMapper;
import com.xy.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static com.xy.utils.Beans.copy;
import static com.xy.utils.PlusBeans.toIPage;
import static com.xy.utils.PlusBeans.toPageBean;
/**
*
* 用户表 服务实现类
*
*
* @author lijin
* @since 2023-01-12
*/
@Slf4j
@Service
@AllArgsConstructor
@Api(tags = "用户表")
public class UserInfoServiceImpl extends ServiceImpl implements UserInfoService {
private SysWorkUserService sysWorkUserService;
private WebMqttConfig webMqttConfig;
private WxMpService wxService;
private WeChatOfficialConfig weChatOfficialConfig;
@Override
@ApiOperation("集合查询")
public R> list(UserInfoDto.SelectListDto selectList) {
List userIds = selectList.getUserIds();
UserInfoDto.Vo userVo = selectList.getUserVo();
LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>();
if (userVo != null) {
lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(selectList.getUserVo(), UserInfo.class).build();
}
lambdaQueryWrapper.in(CollUtil.isNotEmpty(userIds), UserInfo::getUserId, userIds);
List list = list(lambdaQueryWrapper);
return R.ok(copy(UserInfoDto.Vo.class, list));
}
@Override
@ApiOperation("对象查询")
public R obj(UserInfoDto.Vo vo) {
LambdaQueryWrapper lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(vo, UserInfo.class).build();
List list = list(lambdaQueryWrapper);
if (Emptys.check(list)) {
return R.ok(copy(UserInfoDto.Vo.class, list.get(0)));
}
return R.ok();
}
@PostMapping("page")
@ApiOperation("分页查询")
public R> page(@RequestBody UserInfoDto.Page page) {
PageBean pageBean = page.getPage();
LambdaQueryWrapper lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(page, UserInfo.class)
.like(UserInfo::getTel, page.getTel())
.like(UserInfo::getMail, page.getMail())
.like(UserInfo::getUnionid, page.getUnionid())
.ge(UserInfo::getCreateTime, page.getBeginCreateTime())
.le(UserInfo::getCreateTime, page.getEndCreateTime())
.build()
.eq(!AuthorizeUtils.authByData(page.getSysId()), UserInfo::getCreateUser, AuthorizeUtils.getLoginId(Long.class))
.orderByDesc(!Emptys.check(pageBean.getOrders()), UserInfo::getCreateTime);
IPage iPage = page(toIPage(pageBean), lambdaQueryWrapper);
return R.ok(toPageBean(UserInfoDto.Vo.class, iPage));
}
@Override
@ApiOperation("添加")
@Lock(value = "save.tel", prefix = "user_save_")
public R save(UserInfoDto.Save save) {
//添加权限用户
AddDto addDto = copy(AddDto.class, save)
.setEmail(save.getMail())
.setPhone(save.getTel())
.setRoleIds(save.getRoleIds())
.setAccount(save.getAccount());
R register = sysWorkUserService.register(addDto);
if (register.getCode() != R.Enum.SUCCESS.getCode()) {
return R.fail(register.getMsg());
}
Long authorizeUserId = register.getData();
//添加用户
Long loginId = AuthorizeUtils.getLoginId(Long.class);
UserInfo saveInfo = copy(UserInfo.class, save)
.createUserTime(loginId)
.setUserId(YitIdHelper.nextId())
.setAuthorizeUserId(authorizeUserId)
.createUserTime(loginId);
save(saveInfo);
return R.ok(copy(UserInfoDto.Vo.class, saveInfo));
}
@Override
@ApiOperation("修改")
@Lock(value = "update.userId", prefix = "user_update_")
public R update(UserInfoDto.Update update) {
log.info("权限用户信息修改请求:{}", JSONUtil.toJsonPrettyStr(update));
UserInfo byId = getById(update.getUserId());
String account = update.getAccount();
if (StrUtil.isNotEmpty(update.getTel())) {
if (!update.getTel().equals(byId.getTel())) {
long count = count(new LambdaQueryWrapper().eq(UserInfo::getTel, update.getTel()));
if (count > 0) {
return R.fail("手机已存在");
}
}
}
if (StrUtil.isNotEmpty(update.getMail())) {
if (!byId.getMail().equals(update.getMail())) {
long count = count(new LambdaQueryWrapper().eq(UserInfo::getMail, update.getMail()));
if (count > 0) {
return R.fail("邮箱已存在");
}
}
}
UserInfo updateInfo = copy(UserInfo.class, update)
.updateUserTime(AuthorizeUtils.getLoginId(Long.class));
UserInfo u = getById(update.getUserId());
//修改权限用户
if (Emptys.check(update.getTel()) || Emptys.check(update.getMail()) || Emptys.check(update.getStatus()) || Emptys.check(update.getPassword())) {
UpdateDto updateDto = new UpdateDto()
.setId(u.getAuthorizeUserId())
.setAccount(account)
.setPhone(update.getTel())
.setEmail(update.getMail())
.setPassword(update.getPassword())
.setStatus(update.getStatus())
.setRoleIds(update.getRoleIds());
log.info("权限用户信息修改:{}", JSONUtil.toJsonPrettyStr(updateDto));
sysWorkUserService.update(updateDto);
}
//修改用户
updateById(updateInfo);
return R.ok();
}
@ApiOperation("删除用户")
@Override
public R del(@RequestBody @Validated UserInfoDto.DelDto dto) {
//sys_work_user 权限用户表
R r = sysWorkUserService.del(copy(DelDto.class, dto));
if (R.Enum.SUCCESS.getCode() != r.getCode()) {
return R.fail(r.getMsg());
}
//user_info 用户表
return R.ok(removeBatchByIds(dto.getId()));
}
@PostMapping("webUserMqtt")
@ApiOperation("获取用户mqtt信息")
public R webUserMqtt(@RequestBody @Validated UserInfoDto.WebUserMqtt webUserMqtt) {
Long loginId = AuthorizeUtils.getLoginId(Long.class);
Integer type = webUserMqtt.getType();
UserInfoDto.WebUserMqttVo webUserMqttVo = new UserInfoDto.WebUserMqttVo()
.setUsername(webMqttConfig.getUsername())
.setPassword(webMqttConfig.getPassword());
WebMqttConfig.Protocol protocol = webMqttConfig.getProtocol();
WebMqttConfig.Topic topic = webMqttConfig.getTopic();
if (type == 1) {
webUserMqttVo.setUrl(protocol.getPcUrl() + webMqttConfig.getIp())
.setPort(webMqttConfig.getWsPort())
.setClientTopic(topic.getPrefix() + topic.getPcManagePrefix() + loginId);
} else if (type == 2) {
webUserMqttVo.setUrl(protocol.getWxsUrl() + webMqttConfig.getIp())
.setPort(webMqttConfig.getWssPort())
.setClientTopic(topic.getPrefix() + topic.getWxCPrefix() + loginId);
} else if (type == 3) {
webUserMqttVo.setUrl(protocol.getAlisUrl() + webMqttConfig.getIp())
.setPort(webMqttConfig.getWssPort())
.setClientTopic(topic.getPrefix() + topic.getAlisCPrefix() + loginId);
}
return R.ok(webUserMqttVo);
}
@ApiOperation("修改微信信息")
@Override
public R updateByWechat(UserInfoDto.UpdateByWechat dto) {
updateById(copy(UserInfo.class, dto));
return R.ok();
}
@ApiOperation("修改支付宝信息")
@Override
public R updateByAli(UserInfoDto.UpdateByAli dto) {
updateById(copy(UserInfo.class, dto));
return R.ok();
}
@SneakyThrows
@PostMapping("wxQrCode")
@ApiOperation("获取微信服务号二维码-扫码关注公众号并绑定")
public R getQrCode(@RequestBody @Validated UserInfoDto.WxQrCode wxQrCode) {
WxMpService wxMpService = weChatOfficialConfig.getWxMpService();
if (wxMpService == null) {
throw new CommRuntimeException("获取微信公众号配置信息失败!");
}
//指定用户
String userId = wxQrCode.getUserId();
if (StrUtil.isEmpty(userId)) {
//当前登录用户
userId = AuthorizeUtils.getLoginId(String.class);
}
WxMpQrCodeTicket ticket = wxService.getQrcodeService().qrCodeCreateTmpTicket(userId, 2592000);
String tk = ticket.getTicket();
String url = wxService.getQrcodeService().qrCodePictureUrl(tk);
JList contents = new JArrayList<>();
contents.set(url);
JList text = new JArrayList<>();
text.set("使用微信[扫一扫]关注");
List base64s = QRCodeUtils.create(contents, 400, 400, "back1.png", text).base64();
UserInfoDto.WxQrCodeVO vo = new UserInfoDto.WxQrCodeVO();
log.info("获取微信服务号二维码 usrId:{},tk:{}", userId, tk);
return R.ok(vo.setImgList(base64s).setTicket(tk));
}
private WxMpMessageRouter wxMpMessageRouter;
@Autowired
private Map wxMpMessageHandlers;
/**
* 接收微信的事件消息
* https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html
*
* @return
*/
@RequestMapping(value = "/receipt", produces = {"application/xml; charset=UTF-8"})
@ApiOperation("接收微信的事件消息")
public String receiptMessage(@RequestBody(required = false) WxServiceMsgDto wxServiceMsgDto, HttpServletRequest request) {
WxMpService wxMpService = weChatOfficialConfig.getWxMpService();
if (wxMpService == null) {
throw new CommRuntimeException("获取微信公众号配置信息失败!");
}
String echoStr = request.getParameter(WeChatOfficialConfig.ECHO_STR);
// echoStr!=null,说明只是微信调试的请求
if (CharSequenceUtil.isNotBlank(echoStr)) {
return echoStr;
}
String signature = request.getParameter(WeChatOfficialConfig.SIGNATURE);
String nonce = request.getParameter(WeChatOfficialConfig.NONCE);
String timestamp = request.getParameter(WeChatOfficialConfig.TIMESTAMP);
if (!wxService.checkSignature(timestamp, nonce, signature)) {
throw new CommRuntimeException("接收微信的事件消息,验签异常!");
}
log.info("接收微信的事件消息:{}", wxServiceMsgDto);
//处理带参数请求
if (null != wxServiceMsgDto &&
!StrUtil.isEmpty(wxServiceMsgDto.getMsgType()) &&
!StrUtil.isEmpty(wxServiceMsgDto.getEvent()) &&
!StrUtil.isEmpty(wxServiceMsgDto.getEventKey()) && !wxServiceMsgDto.getEventKey().equals("null") &&
(wxServiceMsgDto.getEventKey().equals("subscribe") || wxServiceMsgDto.getEvent().equals("SCAN"))
) {
//关注
if (wxServiceMsgDto.getEvent().equals("subscribe")) {
log.info("关注: " + wxServiceMsgDto.getFromUserName());
setCacheTicket("1", wxServiceMsgDto.getFromUserName());
if (wxServiceMsgDto.getEventKey().contains("FenXiangMa")) {
log.info("优惠券领取");
}
}
//扫码
if (wxServiceMsgDto.getEvent().equals("SCAN")) {
log.info("扫码: " + wxServiceMsgDto.getFromUserName());
if (wxServiceMsgDto.getEventKey().contains("YaoQingMa")) {
log.info("新用户邀请");
}
}
log.info("参数: " + wxServiceMsgDto.getEventKey());
}
return "";
//
// String encryptType = CharSequenceUtil.isBlank(request.getParameter(WeChatOfficialConfig.ENCRYPT_TYPE)) ? WeChatOfficialConfig.RAW : request.getParameter(WeChatOfficialConfig.ENCRYPT_TYPE);
// if (WeChatOfficialConfig.RAW.equals(encryptType)) {
// WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(request.getInputStream());
// log.info("raw inMessage:{}", JSON.toJSONString(inMessage));
// WxMpXmlOutMessage outMessage = weChatOfficialConfig.getWxMpMessageRouter().route(inMessage);
// return outMessage.toXml();
// } else if (WeChatOfficialConfig.AES.equals(encryptType)) {
// String msgSignature = request.getParameter(WeChatOfficialConfig.MSG_SIGNATURE);
// WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(request.getInputStream(), weChatOfficialConfig.getConfig(), timestamp, nonce, msgSignature);
// log.info("aes inMessage:{}", JSON.toJSONString(inMessage));
// WxMpXmlOutMessage outMessage = weChatOfficialConfig.getWxMpMessageRouter().route(inMessage);
// return outMessage.toEncryptedXml(weChatOfficialConfig.getConfig());
// }
// return "ok";
}
/**
* 缓存ticket
*
* @param tk
* @param openId
*/
public static void setCacheTicket(String tk, String openId) {
RedisService redisService = SpringBeanUtils.getBean(RedisService.class);
redisService.set("wechat:scan:ticket:" + tk, openId, 3600);//1h
}
/**
* 获取tk
*
* @param tk
* @return {@link String}
*/
public static String getCacheTicket(String tk) {
RedisService redisService = SpringBeanUtils.getBean(RedisService.class);
return redisService.get("wechat:scan:ticket:" + tk);
}
/**
* 刪除ticket
*
* @param tk
*/
public static void delCacheTicket(String tk) {
RedisService redisService = SpringBeanUtils.getBean(RedisService.class);
redisService.remove("wechat:scan:ticket:" + tk);
}
}