Commit 3a9035d7 3a9035d7a17255bd48ec74fe1718001f1361754d by xianghan@topdraw.cn

1.添加修改会员相关人员验证条件

2.转移h5登录接口
3.微信相关事件实现逻辑
1 parent 5ffd851f
......@@ -5,6 +5,8 @@ import lombok.experimental.Accessors;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
......@@ -28,6 +30,7 @@ public class MemberRelatedInfo implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
@NotNull(groups = {UpdateGroup.class})
private Long id;
// 会员id
......
package com.topdraw.business.module.member.relatedinfo.domain;
public interface UpdateGroup {
}
package com.topdraw.business.module.member.relatedinfo.rest;
import com.topdraw.annotation.AnonymousAccess;
import com.topdraw.business.module.member.relatedinfo.domain.UpdateGroup;
import com.topdraw.business.module.member.relatedinfo.service.dto.MemberRelatedInfoDTO;
import com.topdraw.business.module.member.service.MemberService;
import com.topdraw.business.module.member.service.dto.MemberDTO;
import com.topdraw.common.ResultInfo;
......@@ -7,6 +10,8 @@ import com.topdraw.annotation.Log;
import com.topdraw.business.module.member.relatedinfo.domain.MemberRelatedInfo;
import com.topdraw.business.module.member.relatedinfo.service.MemberRelatedInfoService;
import com.topdraw.business.module.member.relatedinfo.service.dto.MemberRelatedInfoQueryCriteria;
import com.topdraw.exception.BadRequestException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.util.Assert;
......@@ -20,9 +25,10 @@ import java.util.Objects;
* @author XiangHan /api/MemberRelatedInfo
* @date 2021-10-22
*/
@Slf4j
@Api(tags = "MemberRelatedInfo管理")
@RestController
@RequestMapping("/api/MemberRelatedInfo")
@RequestMapping("/ucEngine/api/MemberRelatedInfo")
@CrossOrigin
public class MemberRelatedInfoController {
......@@ -45,21 +51,29 @@ public class MemberRelatedInfoController {
return ResultInfo.success();
}
@Log
@Log("修改MemberRelatedInfo")
@PutMapping(value = "/update")
@ApiOperation("修改MemberRelatedInfo")
public ResultInfo update(@Validated @RequestBody MemberRelatedInfo resources) {
Long memberId = resources.getMemberId();
String idCard = resources.getIdCard();
Assert.notNull(memberId,"memberId can't be null");
Assert.notNull(idCard,"idCard can't be null");
MemberDTO memberDTO = this.memberService.findById(memberId);
if (Objects.nonNull(memberDTO)) {
String code = memberDTO.getCode();
Assert.notNull(code,"code can't be null");
resources.setMemberCode(code);
MemberRelatedInfoService.update(resources);
@AnonymousAccess
public ResultInfo update(@Validated(value = {UpdateGroup.class}) @RequestBody MemberRelatedInfo resources) {
Long id = resources.getId();
MemberRelatedInfoDTO memberRelatedInfoDTO = this.MemberRelatedInfoService.findById(id);
if (memberRelatedInfoDTO.getId() != null) {
Long memberId = memberRelatedInfoDTO.getMemberId();
if (Objects.isNull(memberId)) {
log.info("id ==>> [{}]",id);
throw new BadRequestException("memberId is null! please check member info");
}
MemberDTO memberDTO = this.memberService.findById(memberId);
if (Objects.nonNull(memberDTO)) {
String code = memberDTO.getCode();
Assert.notNull(code,"code can't be null");
resources.setMemberCode(code);
MemberRelatedInfoService.update(resources);
}
}
return ResultInfo.success();
}
......
......@@ -14,6 +14,9 @@ import java.time.LocalDateTime;
@Data
public class MemberDTO implements Serializable {
// iptv绑定的主会员 0:否 1:是
private Integer iptvMajor;
// vip过期时间
private LocalDateTime vipExpireTime;
......
package com.topdraw.business.module.user.weixin.service.dto;
import com.topdraw.annotation.Query;
import lombok.Data;
/**
......@@ -9,6 +10,7 @@ import lombok.Data;
@Data
public class UserWeixinQueryCriteria{
@Query()
private String unionId;
}
......
......@@ -38,7 +38,6 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
......@@ -119,6 +118,7 @@ public class UserOperationController {
@Log("大屏用户解绑")
@PutMapping(value = "/unbind")
@ApiOperation("大屏用户解绑")
@AnonymousAccess
public ResultInfo unbind(@Validated(value = {UnbindGroup.class}) @RequestBody TempIptvUser resources) {
UserTv userTv = new UserTv();
BeanUtils.copyProperties(resources,userTv);
......@@ -129,6 +129,7 @@ public class UserOperationController {
@Log("大屏更换主账号")
@PutMapping(value = "/changeMainAccount")
@ApiOperation("大屏更换主账号")
@AnonymousAccess
public ResultInfo changeMainAccount(@Validated(value = {UnbindGroup.class}) @RequestBody TempIptvUser resources) {
UserTv userTv = new UserTv();
BeanUtils.copyProperties(resources,userTv);
......@@ -136,6 +137,15 @@ public class UserOperationController {
return ResultInfo.success("update success");
}
@Log("微信服务号(H5)登录")
@PostMapping("/serviceLogin")
@ApiOperation("微信服务号(H5)登录")
@AnonymousAccess
public ResultInfo serviceLogin(@Validated @RequestBody WeiXinUserBean resources) {
Object o = this.userTvOperationService.serviceLogin(resources);
return ResultInfo.success(o);
}
@Log("微信小程序登录")
@PostMapping("/appletLogin")
@ApiOperation("微信小程序登录")
......@@ -187,7 +197,9 @@ public class UserOperationController {
throw new BadRequestException("非订阅号");
// 用户类型
JSONObject userInfo = weixinRequestUtil.getUserInfo(wxInfoMap, openId);
// JSONObject userInfo = weixinRequestUtil.getUserInfo(wxInfoMap, openId);
JSONObject userInfo = new JSONObject();
userInfo.put("unionid","oqDha5idQxR0WGPW2qHi-meHRtyg");
log.info("userInfo is : {}", userInfo.toJSONString());
unionId = userInfo.get("unionid").toString();
......@@ -212,10 +224,13 @@ public class UserOperationController {
} else {
String eventKey = subscribeBean.getEventKey();
// 用户扫描带参二维码关注。发消息
// 去除固定前缀,获取二维码参数
eventKey = eventKey.substring(8);
iptvUserInfo = com.alibaba.fastjson.JSONObject.parseObject(eventKey);
if (StringUtils.isNotBlank(eventKey)) {
// 用户扫描带参二维码关注。发消息
// 去除固定前缀,获取二维码参数
eventKey = eventKey.substring(8);
iptvUserInfo = JSONObject.parseObject(eventKey);
}
}
......@@ -224,10 +239,6 @@ public class UserOperationController {
subscribeBean.setIptvUserInfo(iptvUserInfo);
}
// 之后删除缓存信息
this.redisUtils.del(RedisKeyUtil.genSeSuSubscribeKey(unionId));
}
}
......
......@@ -12,29 +12,99 @@ import java.util.List;
public interface UserOperationService {
/**
* 保存大屏账户并创建会员
* @param resources
* @return
*/
boolean createMemberByUserTv(UserTv resources);
/**
* 大屏解绑
* @param userTv
*/
void unbind(UserTv userTv);
/**
* 大屏切换主账户(会员)
* @param userTv
*/
void changeMainAccount(UserTv userTv);
/**
* 微信小程序登录
* @param resources
* @return
*/
UserWeixinDTO appletLogin(WeiXinUserBean resources);
/**
* 微信公众号关注
* @param resources
* @return
*/
boolean subscribe(SubscribeBean resources);
/**
* 微信公众号取关
* @param resources
* @return
*/
boolean unsubscribe(SubscribeBean resources);
/**
* 保存账户
* @param data
* @return
*/
String saveUserInfo(String data);
/**
* 获取用户授权并解析、保存用户手机号
* @param resources
* @return
*/
MemberProfile saveUserWeixinPhone(WeiXinUserBean resources);
/**
*
* @param content
* @return
*/
boolean sendQrCodeMessage(String content);
/**
* 大屏删除所有收藏
* @param content
* @return
*/
boolean deleteAllCollection(String content);
/**
* 大屏删除收藏
* @param content
* @return
*/
boolean deleteCollection(String content);
/**
* 大屏收藏
* @param content
* @return
*/
boolean addCollection(String content);
/**
* 获取大屏绑定的小屏会员列表
* @param platformAccount
* @return
*/
List<MemberDTO> findBindByPlatformAccount(String platformAccount);
/**
* 服务号(H5)登录
* @param resources
* @return
*/
Object serviceLogin(WeiXinUserBean resources);
}
......
......@@ -27,6 +27,7 @@ import com.topdraw.business.module.user.weixin.collection.repository.UserCollect
import com.topdraw.business.module.user.weixin.collection.service.UserCollectionDetailService;
import com.topdraw.business.module.user.weixin.collection.service.UserCollectionService;
import com.topdraw.business.module.user.weixin.domain.UserWeixin;
import com.topdraw.business.module.user.weixin.repository.UserWeixinRepository;
import com.topdraw.business.module.user.weixin.service.UserWeixinService;
import com.topdraw.business.module.user.weixin.service.dto.UserWeixinDTO;
import com.topdraw.business.module.user.weixin.service.dto.UserWeixinQueryCriteria;
......@@ -38,8 +39,11 @@ import com.topdraw.business.process.service.UserOperationService;
import com.topdraw.business.process.service.mapper.CollectionMq2DetailMapper;
import com.topdraw.config.LocalConstants;
import com.topdraw.config.RedisKeyUtil;
import com.topdraw.config.ServiceEnvConfig;
import com.topdraw.exception.BadRequestException;
import com.topdraw.exception.EntityNotFoundException;
import com.topdraw.module.mq.DataSyncMsg;
import com.topdraw.module.mq.EntityType;
import com.topdraw.security.AESUtil;
import com.topdraw.util.IdWorker;
import com.topdraw.util.TimestampUtil;
......@@ -57,16 +61,20 @@ import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.io.IOException;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
......@@ -77,6 +85,7 @@ import java.util.stream.Collectors;
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class UserOperationServiceImpl implements UserOperationService {
@Autowired
private RedissonClient redissonClient;
@Autowired
......@@ -101,6 +110,8 @@ public class UserOperationServiceImpl implements UserOperationService {
private UserCollectionDetailRepository userCollectionDetailRepository;
@Autowired
private CollectionMq2DetailMapper collectionMq2DetailMapper;
@Autowired
private UserWeixinRepository userWeixinRepository;
......@@ -110,6 +121,7 @@ public class UserOperationServiceImpl implements UserOperationService {
private static final String SUBSCRIBE = "subscribe";
private static final String UNSUBSCRIBE = "unsubscribe";
private static final Integer[] PLATFORM_LIST = new Integer[]{0,1,2,3};
private static final Integer[] IPTV_MAJOR = new Integer[]{0,1};
private static final String QR_CODE_URL = "QR_CODE_URL_";
......@@ -151,17 +163,16 @@ public class UserOperationServiceImpl implements UserOperationService {
String appId = resources.getAppId();
String openId = resources.getOpenId();
DefaultWeiXinBeanDefinition weiXinBeanDefinition = this.parseAppletInfo(resources);
if (Objects.nonNull(weiXinBeanDefinition.getOpenId())) {
throw new RuntimeException("微信信息解析失败!");
}
// 小屏账户
UserWeixinDTO userWeixinDTO = this.findFirstByUnionIdAndAppIdAndOpenId(unionId,appId, openId);
if (Objects.isNull(userWeixinDTO.getId())) {
DefaultWeiXinBeanDefinition weiXinBeanDefinition = new DefaultWeiXinBeanDefinition();
weiXinBeanDefinition.setUnionId(unionId);
weiXinBeanDefinition.setAppid(appId);
weiXinBeanDefinition.setOpenId(openId);
// 创建会员和账户
this.doCreateUserWeiXinAndMember(weiXinBeanDefinition);
......@@ -189,7 +200,7 @@ public class UserOperationServiceImpl implements UserOperationService {
}
// 大屏账户绑定小屏会员的code
this.bondPriorityMember(userTvDTO,memberDTO_0);
this.bondPriorityMember(userTvDTO,memberDTO_0,"auto");
// 小屏会员绑定大屏账户id
MemberDTO memberDTO_1 = this.bindIptvId(memberDTO_0,userTvDTO);
......@@ -238,9 +249,6 @@ public class UserOperationServiceImpl implements UserOperationService {
// 小屏账户
UserWeixin userWeixin = this.generateUserWeiXin(weiXinBeanDefinition,SUBSCRIBE_STATUS);
if (Objects.isNull(userWeixin.getId())) {
throw new BadRequestException("创建小屏账户失败");
}
// 保存会员
Long memberId = this.doCreateMember(userWeixin,1);
......@@ -270,22 +278,6 @@ public class UserOperationServiceImpl implements UserOperationService {
}
/**
* 绑定iptvId字段并修改会员vip字段
* @param memberDTO
* @param userTvDTO
*/
private MemberDTO bindIptvIdAndUpdateVip(MemberDTO memberDTO, UserTvDTO userTvDTO) {
Integer vip = memberDTO.getVip();
if (Objects.nonNull(vip) && vip == 0) {
memberDTO.setVip(1);
return this.bindIptvId(memberDTO,userTvDTO);
}
return memberDTO;
}
/**
* 微信公众号取消关注
* @param resources
* @return
......@@ -508,7 +500,7 @@ public class UserOperationServiceImpl implements UserOperationService {
UserWeixinDTO userWeixinDTO = this.userWeixinService.findFirstByUnionId(unionid);
// 无账号,没有绑定会员
if (Objects.isNull(userWeixinDTO.getId()) || Objects.isNull(userWeixinDTO.getMemberId())) {
if (Objects.isNull(userWeixinDTO.getMemberId())) {
// 默认会员
Member member = MemberBuilder.build(LocalConstants.DEVICE_MOBILE,userWeixin.getHeadimgurl(),
userWeixin.getNickname(),vip);
......@@ -711,7 +703,7 @@ public class UserOperationServiceImpl implements UserOperationService {
MemberDTO memberDTO = this.findMemberByMemberCode(memberCode);
// 设置主会员
this.bondPriorityMember(userTvDTO, memberDTO);
this.bondPriorityMember(userTvDTO, memberDTO,"manual");
}
......@@ -720,20 +712,22 @@ public class UserOperationServiceImpl implements UserOperationService {
* @description 检查大屏账户有没有绑定小屏会员,如果没有绑定就将当前会员的code保存到大屏账户中
* @param userTvDTO
* @param memberDTO
* @param auto manual:手动 auto:自动
*/
private void bondPriorityMember(UserTvDTO userTvDTO, MemberDTO memberDTO) {
private void bondPriorityMember(UserTvDTO userTvDTO, MemberDTO memberDTO,String auto) {
// 绑定的小屏编码
String priorityMemberCode = userTvDTO.getPriorityMemberCode();
if (StringUtils.isNotEmpty(priorityMemberCode)) {
return;
if (auto.equalsIgnoreCase("auto")) {
// 绑定的小屏编码
String priorityMemberCode = userTvDTO.getPriorityMemberCode();
if (StringUtils.isNotEmpty(priorityMemberCode)) {
return;
}
}
String memberCode = memberDTO.getCode();
// 绑定了小屏,结束
if (StringUtils.isEmpty(priorityMemberCode) && StringUtils.isNotEmpty(memberCode)) {
if (StringUtils.isNotEmpty(memberCode)) {
userTvDTO.setPriorityMemberCode(memberCode);
}
......@@ -1146,12 +1140,102 @@ public class UserOperationServiceImpl implements UserOperationService {
UserTvDTO userTvDTO = this.userTvService.findByPlatformAccount(platformAccount);
if (Objects.nonNull(userTvDTO.getId())) {
Long id = userTvDTO.getId();
return this.memberService.findByUserIptvId(id);
String priorityMemberCode = userTvDTO.getPriorityMemberCode();
List<MemberDTO> memberDTOList = this.memberService.findByUserIptvId(id);
if (!CollectionUtils.isEmpty(memberDTOList)) {
for (MemberDTO memberDTO : memberDTOList) {
String code = memberDTO.getCode();
if (code.equalsIgnoreCase(priorityMemberCode)) {
memberDTO.setIptvMajor(IPTV_MAJOR[1]);
} else {
memberDTO.setIptvMajor(IPTV_MAJOR[0]);
}
}
}
return memberDTOList;
}
return null;
}
@Override
public Object serviceLogin(WeiXinUserBean resources) {
String unionId = resources.getUnionId();
String appId = resources.getAppId();
String openId = resources.getOpenId();
// 小屏账户
UserWeixinDTO userWeixinDTO = this.findFirstByUnionIdAndAppIdAndOpenId(unionId,appId, openId);
if (Objects.isNull(userWeixinDTO.getId())) {
DefaultWeiXinBeanDefinition weiXinBeanDefinition = new DefaultWeiXinBeanDefinition();
weiXinBeanDefinition.setUnionId(unionId);
weiXinBeanDefinition.setAppid(appId);
weiXinBeanDefinition.setOpenId(openId);
// 创建会员和账户
this.doCreateUserWeiXinAndMember(weiXinBeanDefinition);
} else {
// 修改账户和会员信息
this.doUpdateUserWeiXinAndMember(userWeixinDTO,appId,openId);
}
// 为了保证返回的同一用户
UserWeixinDTO userWeixinDTO_0 = this.getFirstId(userWeixinDTO);
return userWeixinDTO_0;
}
/**
* 同一用户有多个微信APP的情况下展示同一个账户信息
* 原则:那个先创建就用那个id
* @param userWeixinDTO
*/
private UserWeixinDTO getFirstId(UserWeixinDTO userWeixinDTO) {
String unionid = userWeixinDTO.getUnionid();
if (StringUtils.isNotBlank(unionid)) {
UserWeixinQueryCriteria criteria = new UserWeixinQueryCriteria();
PageRequest pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.ASC, "createTime"));
criteria.setUnionId(unionid);
List<UserWeixin> userWeixinList = this.userWeixinRepository.findAll((root, criteriaQuery, criteriaBuilder)
-> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable).getContent();
List<UserWeixin> h5AppIdList = userWeixinList.stream().filter(e -> ObjectUtil.equal(e.getAppid(), h5AppId)).collect(Collectors.toList());
List<UserWeixin> appletAppIdList = userWeixinList.stream().filter(e -> ObjectUtil.equal(e.getAppid(), appletAppid)).collect(Collectors.toList());
//没创建h5账号 返回小程序id
if (h5AppIdList.isEmpty()) {
userWeixinDTO.setId(appletAppIdList.get(0).getId());
userWeixinDTO.setAuthTime(appletAppIdList.get(0).getAuthTime());
}
//没创建小程序账号 返回h5id
if (appletAppIdList.isEmpty()) {
userWeixinDTO.setId(h5AppIdList.get(0).getId());
userWeixinDTO.setAuthTime(h5AppIdList.get(0).getAuthTime());
}
//都创建 那个先创建 用那个
if (!appletAppIdList.isEmpty() && !h5AppIdList.isEmpty()) {
if (appletAppIdList.get(0).getCreateTime().before(h5AppIdList.get(0).getCreateTime())) {
userWeixinDTO.setId(appletAppIdList.get(0).getId());
userWeixinDTO.setAuthTime(appletAppIdList.get(0).getAuthTime());
} else {
userWeixinDTO.setId(h5AppIdList.get(0).getId());
userWeixinDTO.setAuthTime(h5AppIdList.get(0).getAuthTime());
}
}
}
return userWeixinDTO;
}
/**
* 保存、修改会员加密信息
* @param resources
......