Commit 2bf05374 2bf053742d549dd4a7a4de6e74f6fc144d232311 by xianghan@topdraw.cn

V1.0.2.REALESE

1 parent dc5e7311
Showing 22 changed files with 1094 additions and 5 deletions
package com.topdraw.business.module.user.weixin.collection.domain;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* @author pengmengqing
* @date 2021-04-02
*/
@Entity
@Data
@EntityListeners(AuditingEntityListener.class)
@Accessors(chain = true)
@Table(name="uc_user_collection")
public class UserCollection implements Serializable {
// ID
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
// 应用ID
@Column(name = "app_id")
private Long appId;
// 用户ID
@Column(name = "user_id")
private Long userId;
// 收藏夹类型:1-收藏 2-播放记录 3-播放列表 4-评分 5-点赞/关注/订阅
@Column(name = "type")
private Integer type;
// 收藏夹名称
@Column(name = "name")
private String name;
// 数量
@Column(name = "count")
private Integer count;
// 创建时间
@CreatedDate
@Column(name = "create_time")
private Timestamp createTime;
// 更新时间
@LastModifiedDate
@Column(name = "update_time")
private Timestamp updateTime;
public void copy(UserCollection source){
BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true));
}
}
package com.topdraw.business.module.user.weixin.collection.domain;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* @author pengmengqing
* @date 2021-04-02
*/
@Entity
@Data
@EntityListeners(AuditingEntityListener.class)
@Accessors(chain = true)
@Table(name="uc_user_collection_detail")
public class UserCollectionDetail implements Serializable {
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "user_collection_id", insertable = false, updatable = false)
private UserCollection userCollection;
// ID
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
// 收藏夹ID
@Column(name = "user_collection_id")
private Long userCollectionId;
// 自定义收藏内容的类型CODE,默认:DEFAULT
@Column(name = "detail_folder_code")
private String detailFolderCode;
// 收藏内容的类型:MEDIA|EPISODE|CATEGORY|SUBJECT|ARTICLE|ARTIST|SCHOOL
@Column(name = "detail_type")
private String detailType;
// 收藏内容的ID
@Column(name = "detail_id")
private Long detailId;
// 收藏内容的CODE
@Column(name = "detail_code")
private String detailCode;
// 收藏内容的剧集ID
@Column(name = "detail_episode_id")
private Long detailEpisodeId;
// 收藏内容的剧集CODE
@Column(name = "detail_episode_code")
private String detailEpisodeCode;
// 收藏内容的名称
@Column(name = "detail_name")
private String detailName;
// 收藏内容的标记
@Column(name = "detail_mark")
private Integer detailMark;
// 收藏内容的图片
@Column(name = "detail_img")
private String detailImg;
// 收藏内容的剧集序号
@Column(name = "detail_index")
private Integer detailIndex;
// 收藏内容的剧集总数
@Column(name = "detail_total_index")
private Integer detailTotalIndex;
// 收藏内容的播放时间
@Column(name = "detail_play_time")
private Integer detailPlayTime;
// 收藏内容的总时间
@Column(name = "detail_total_time")
private Integer detailTotalTime;
// 收藏内容在同一folder中的顺序
@Column(name = "detail_sequence")
private Integer detailSequence;
// 收藏内容的评分
@Column(name = "detail_score")
private Float detailScore;
// 收藏内容(根据文件夹和类型的不同)的点赞/关注/订阅
@Column(name = "detail_like")
private Integer detailLike;
// 收藏内容的扩展数据
@Column(name = "detail_ext_data")
private String detailExtData;
// 创建时间
@Column(name = "create_time")
private Timestamp createTime;
// 更新时间
@Column(name = "update_time")
private Timestamp updateTime;
public void copy(UserCollectionDetail source){
BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true));
}
}
package com.topdraw.business.module.user.weixin.collection.repository;
import com.topdraw.business.module.user.weixin.collection.domain.UserCollectionDetail;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import java.util.Optional;
/**
* @author pengmengqing
* @date 2021-04-02
*/
public interface UserCollectionDetailRepository extends JpaRepository<UserCollectionDetail, Long>, JpaSpecificationExecutor<UserCollectionDetail> {
@Modifying
void deleteAllByUserCollectionId(Long userCollectionId);
Optional<UserCollectionDetail> findByDetailIdAndDetailTypeAndUserCollectionId(Long detailId, String detailType, Long userCollectionId);
}
package com.topdraw.business.module.user.weixin.collection.repository;
import com.topdraw.business.module.user.weixin.collection.domain.UserCollection;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import java.util.List;
import java.util.Optional;
/**
* @author pengmengqing
* @date 2021-04-02
*/
public interface UserCollectionRepository extends JpaRepository<UserCollection, Long>, JpaSpecificationExecutor<UserCollection> {
Optional<UserCollection> findFirstByUserIdAndTypeAndName(Long userId, Integer type, String name);
List<UserCollection> findByUserIdAndType(Long userId, Integer type);
}
package com.topdraw.business.module.user.weixin.collection.service;
import com.topdraw.business.module.user.weixin.collection.domain.UserCollectionDetail;
import com.topdraw.business.module.user.weixin.collection.service.dto.UserCollectionDetailDTO;
import com.topdraw.business.module.user.weixin.collection.service.dto.UserCollectionDetailQueryCriteria;
import org.springframework.data.domain.Pageable;
import java.util.List;
import java.util.Map;
/**
* @author pengmengqing
* @date 2021-04-02
*/
public interface UserCollectionDetailService {
/**
* 查询数据分页
* @param criteria 条件参数
* @param pageable 分页参数
* @return Map<String,Object>
*/
Map<String,Object> queryAll(UserCollectionDetailQueryCriteria criteria, Pageable pageable);
/**
* 根据ID查询
* @param id ID
* @return UserCollectionDetailDTO
*/
UserCollectionDetailDTO findById(Long id);
UserCollectionDetailDTO create(UserCollectionDetail resources);
void update(UserCollectionDetail resources);
void delete(Long id);
void deleteAllByUserCollectionId(Long id);
void deleteAll(List<UserCollectionDetail> userCollectionDetailOptional);
}
package com.topdraw.business.module.user.weixin.collection.service;
import com.topdraw.business.module.user.weixin.collection.domain.UserCollection;
import com.topdraw.business.module.user.weixin.collection.service.dto.UserCollectionDTO;
import com.topdraw.business.module.user.weixin.collection.service.dto.UserCollectionQueryCriteria;
import org.springframework.data.domain.Pageable;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* @author pengmengqing
* @date 2021-04-02
*/
public interface UserCollectionService {
/**
* 查询数据分页
* @param criteria 条件参数
* @param pageable 分页参数
* @return Map<String,Object>
*/
Map<String,Object> queryAll(UserCollectionQueryCriteria criteria, Pageable pageable);
/**
* 查询所有数据不分页
* @param criteria 条件参数
* @return List<UserCollectionDTO>
*/
List<UserCollectionDTO> queryAll(UserCollectionQueryCriteria criteria);
/**
* 根据ID查询
* @param id ID
* @return UserCollectionDTO
*/
UserCollectionDTO findById(Long id);
UserCollectionDTO create(UserCollection resources);
void update(UserCollection resources);
void delete(Long id);
void download(List<UserCollectionDTO> all, HttpServletResponse response) throws IOException;
List<UserCollection> findByUserIdAndType(Long id, Integer type);
Optional<UserCollection> findFirstByUserIdAndTypeAndName(Long id, Integer type, String name);
void save(UserCollection userCollection);
}
package com.topdraw.business.module.user.weixin.collection.service.dto;
import lombok.Data;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* @author pengmengqing
* @date 2021-04-02
*/
@Data
public class UserCollectionDTO implements Serializable {
// ID
private Long id;
// 应用ID
private Long appId;
// 用户ID
private Long userId;
// 收藏夹类型:1-收藏 2-播放记录 3-播放列表 4-评分 5-点赞/关注/订阅
private Integer type;
// 收藏夹名称
private String name;
// 数量
private Integer count;
// 创建时间
private Timestamp createTime;
// 更新时间
private Timestamp updateTime;
}
package com.topdraw.business.module.user.weixin.collection.service.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* @author pengmengqing
* @date 2021-04-02
*/
@Data
public class UserCollectionDetailDTO implements Serializable {
// ID
private Long id;
// 收藏夹ID
private Long userCollectionId;
// 自定义收藏内容的类型CODE,默认:DEFAULT
private String detailFolderCode;
// 收藏内容的类型:MEDIA|EPISODE|CATEGORY|SUBJECT|ARTICLE|ARTIST|SCHOOL
private String detailType;
// 收藏内容的ID
private Long detailId;
// 收藏内容的CODE
private String detailCode;
// 收藏内容的剧集ID
private Long detailEpisodeId;
// 收藏内容的剧集CODE
private String detailEpisodeCode;
// 收藏内容的名称
private String detailName;
// 收藏内容的标记
private Integer detailMark;
// 收藏内容的图片
private String detailImg;
// 收藏内容的剧集序号
private Integer detailIndex;
// 收藏内容的剧集总数
private Integer detailTotalIndex;
// 收藏内容的播放时间
private Integer detailPlayTime;
// 收藏内容的总时间
private Integer detailTotalTime;
// 收藏内容在同一folder中的顺序
private Integer detailSequence;
// 收藏内容的评分
private Float detailScore;
// 收藏内容(根据文件夹和类型的不同)的点赞/关注/订阅
private Integer detailLike;
// 收藏内容的扩展数据
private String detailExtData;
// 创建时间
@JsonFormat(
pattern = "MM月dd日 HH:mm",
timezone = "GMT+8"
)
private Timestamp createTime;
// 更新时间
@JsonFormat(
pattern = "MM月dd日 HH:mm",
timezone = "GMT+8"
)
private Timestamp updateTime;
}
package com.topdraw.business.module.user.weixin.collection.service.dto;
import com.topdraw.annotation.Query;
import lombok.Data;
import javax.persistence.criteria.JoinType;
/**
* @author pengmengqing
* @date 2021-04-02
*/
@Data
public class UserCollectionDetailQueryCriteria{
private Long userWeixinId;
@Query(joinType = JoinType.INNER, joinName = "userCollection")
private Long userId;
@Query(joinType = JoinType.INNER, joinName = "userCollection")
private Integer type;
private String detailType;
private String detailFolderCode = "DEFAULT";
private Long detailId;
}
package com.topdraw.business.module.user.weixin.collection.service.dto;
import lombok.Data;
/**
* @author pengmengqing
* @date 2021-04-02
*/
@Data
public class UserCollectionQueryCriteria{
}
package com.topdraw.business.module.user.weixin.collection.service.impl;
import com.topdraw.business.module.user.weixin.collection.domain.UserCollectionDetail;
import com.topdraw.business.module.user.weixin.collection.repository.UserCollectionDetailRepository;
import com.topdraw.business.module.user.weixin.collection.service.UserCollectionDetailService;
import com.topdraw.business.module.user.weixin.collection.service.dto.UserCollectionDetailDTO;
import com.topdraw.business.module.user.weixin.collection.service.dto.UserCollectionDetailQueryCriteria;
import com.topdraw.business.module.user.weixin.collection.service.mapper.UserCollectionDetailMapper;
import com.topdraw.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import java.util.*;
/**
* @author pengmengqing
* @date 2021-04-02
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class UserCollectionDetailServiceImpl implements UserCollectionDetailService {
@Autowired
private UserCollectionDetailRepository userCollectionDetailRepository;
@Autowired
private UserCollectionDetailMapper userCollectionDetailMapper;
@Override
public Map<String, Object> queryAll(UserCollectionDetailQueryCriteria criteria, Pageable pageable) {
Page<UserCollectionDetail> page = userCollectionDetailRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
return PageUtil.toPage(page.map(userCollectionDetailMapper::toDto));
}
@Override
public UserCollectionDetailDTO findById(Long id) {
UserCollectionDetail userCollectionDetail = userCollectionDetailRepository.findById(id).orElseGet(UserCollectionDetail::new);
ValidationUtil.isNull(userCollectionDetail.getId(),"UserCollectionDetail","id",id);
return userCollectionDetailMapper.toDto(userCollectionDetail);
}
@Override
@Transactional(rollbackFor = Exception.class)
public UserCollectionDetailDTO create(UserCollectionDetail resources) {
return userCollectionDetailMapper.toDto(userCollectionDetailRepository.save(resources));
}
@Override
@Transactional(rollbackFor = Exception.class)
public void update(UserCollectionDetail resources) {
UserCollectionDetail userCollectionDetail = userCollectionDetailRepository.findById(resources.getId()).orElseGet(UserCollectionDetail::new);
ValidationUtil.isNull( userCollectionDetail.getId(),"UserCollectionDetail","id",resources.getId());
userCollectionDetail.copy(resources);
userCollectionDetailRepository.save(userCollectionDetail);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void delete(Long id) {
Assert.notNull(id, "The given id must not be null!");
UserCollectionDetail userCollectionDetail = userCollectionDetailRepository.findById(id).orElseThrow(
() -> new EmptyResultDataAccessException(String.format("No %s entity " + "with id %s " + "exists!", UserCollectionDetail.class, id), 1));
userCollectionDetailRepository.delete(userCollectionDetail);
}
@Override
public void deleteAllByUserCollectionId(Long id) {
this.userCollectionDetailRepository.deleteAllByUserCollectionId(id);
}
@Override
public void deleteAll(List<UserCollectionDetail> userCollectionDetailOptional) {
this.userCollectionDetailRepository.deleteAll(userCollectionDetailOptional);
}
}
package com.topdraw.business.module.user.weixin.collection.service.impl;
import com.topdraw.business.module.user.weixin.collection.domain.UserCollection;
import com.topdraw.business.module.user.weixin.collection.repository.UserCollectionRepository;
import com.topdraw.business.module.user.weixin.collection.service.UserCollectionService;
import com.topdraw.business.module.user.weixin.collection.service.dto.UserCollectionDTO;
import com.topdraw.business.module.user.weixin.collection.service.dto.UserCollectionQueryCriteria;
import com.topdraw.business.module.user.weixin.collection.service.mapper.UserCollectionMapper;
import com.topdraw.utils.FileUtil;
import com.topdraw.utils.PageUtil;
import com.topdraw.utils.QueryHelp;
import com.topdraw.utils.ValidationUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
/**
* @author pengmengqing
* @date 2021-04-02
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class UserCollectionServiceImpl implements UserCollectionService {
@Autowired
private UserCollectionRepository userCollectionRepository;
@Autowired
private UserCollectionMapper userCollectionMapper;
@Override
public Map<String, Object> queryAll(UserCollectionQueryCriteria criteria, Pageable pageable) {
Page<UserCollection> page = userCollectionRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
return PageUtil.toPage(page.map(userCollectionMapper::toDto));
}
@Override
public List<UserCollectionDTO> queryAll(UserCollectionQueryCriteria criteria) {
return userCollectionMapper.toDto(userCollectionRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
}
@Override
public UserCollectionDTO findById(Long id) {
UserCollection userCollection = userCollectionRepository.findById(id).orElseGet(UserCollection::new);
ValidationUtil.isNull(userCollection.getId(),"UserCollection","id",id);
return userCollectionMapper.toDto(userCollection);
}
@Override
@Transactional(rollbackFor = Exception.class)
public UserCollectionDTO create(UserCollection resources) {
return userCollectionMapper.toDto(userCollectionRepository.save(resources));
}
@Override
@Transactional(rollbackFor = Exception.class)
public void update(UserCollection resources) {
UserCollection userCollection = userCollectionRepository.findById(resources.getId()).orElseGet(UserCollection::new);
ValidationUtil.isNull( userCollection.getId(),"UserCollection","id",resources.getId());
userCollection.copy(resources);
userCollectionRepository.save(userCollection);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void delete(Long id) {
Assert.notNull(id, "The given id must not be null!");
UserCollection userCollection = userCollectionRepository.findById(id).orElseThrow(
() -> new EmptyResultDataAccessException(String.format("No %s entity " + "with id %s " + "exists!", UserCollection.class, id), 1));
userCollectionRepository.delete(userCollection);
}
@Override
public void download(List<UserCollectionDTO> all, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (UserCollectionDTO userCollection : all) {
Map<String, Object> map = new LinkedHashMap<>();
map.put("应用ID", userCollection.getAppId());
// map.put("用户ID", userCollection.getSubscriberId());
// map.put("platformAccount", userCollection.getPlatformAccount());
map.put("收藏夹类型:1-收藏 2-播放记录 3-播放列表 4-评分 5-点赞/关注/订阅", userCollection.getType());
map.put("收藏夹名称", userCollection.getName());
map.put("数量", userCollection.getCount());
map.put("创建时间", userCollection.getCreateTime());
map.put("更新时间", userCollection.getUpdateTime());
list.add(map);
}
FileUtil.downloadExcel(list, response);
}
@Override
public List<UserCollection> findByUserIdAndType(Long id, Integer type) {
return this.userCollectionRepository.findByUserIdAndType(id,type);
}
@Override
public Optional<UserCollection> findFirstByUserIdAndTypeAndName(Long id, Integer type, String name) {
return Optional.empty();
}
@Override
public void save(UserCollection userCollection) {
}
}
package com.topdraw.business.module.user.weixin.collection.service.mapper;
import com.topdraw.base.BaseMapper;
import com.topdraw.business.module.user.weixin.collection.domain.UserCollectionDetail;
import com.topdraw.business.module.user.weixin.collection.service.dto.UserCollectionDetailDTO;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
/**
* @author pengmengqing
* @date 2021-04-02
*/
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface UserCollectionDetailMapper extends BaseMapper<UserCollectionDetailDTO, UserCollectionDetail> {
}
package com.topdraw.business.module.user.weixin.collection.service.mapper;
import com.topdraw.base.BaseMapper;
import com.topdraw.business.module.user.weixin.collection.domain.UserCollection;
import com.topdraw.business.module.user.weixin.collection.service.dto.UserCollectionDTO;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
/**
* @author pengmengqing
* @date 2021-04-02
*/
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface UserCollectionMapper extends BaseMapper<UserCollectionDTO, UserCollection> {
}
......@@ -109,5 +109,4 @@ public class UserWeixinServiceImpl implements UserWeixinService {
return UserWeixinMapper.toDto(userWeixin);
}
}
......
package com.topdraw.business.process.domian.weixin;
import com.alibaba.fastjson.annotation.JSONField;
import com.topdraw.annotation.Query;
import lombok.Data;
import java.sql.Timestamp;
@Data
public class UserCollectionMq {
// 应用ID
@JSONField(name = "app_id")
private Long appId;
@JSONField(name = "userId")
private Long userId;
// 收藏夹类型:1-收藏 2-播放记录 3-播放列表 4-评分 5-点赞/关注/订阅
private Integer type;
// 收藏夹名称
private String name;
// 数量
private Integer count;
private String images;
// 收藏夹ID
@JSONField(name = "user_collection_id")
@Query
private Long userCollectionId;
// 自定义收藏内容的类型CODE,默认:DEFAULT
@JSONField(name = "detail_folder_code")
@Query
private String detailFolderCode;
// 收藏内容的类型:MEDIA|EPISODE|CATEGORY|SUBJECT|ARTICLE|ARTIST|SCHOOL
@JSONField(name = "detail_type")
@Query
private String detailType;
// 收藏内容的ID
@JSONField(name = "detail_id")
@Query
private Long detailId;
// 收藏内容的CODE
@JSONField(name = "detail_code")
@Query
private String detailCode;
// 收藏内容的剧集ID
@JSONField(name = "detail_episode_id")
@Query
private Long detailEpisodeId;
// 收藏内容的剧集CODE
@JSONField(name = "detail_episode_code")
@Query
private String detailEpisodeCode;
// 收藏内容的名称
@JSONField(name = "detail_name")
@Query
private String detailName;
// 收藏内容的标记
@JSONField(name = "detail_mark")
@Query
private Integer detailMark;
// 收藏内容的图片
@JSONField(name = "detail_img")
private String detailImg;
// 收藏内容的剧集序号
@JSONField(name = "detail_index")
@Query
private Integer detailIndex;
// 收藏内容的剧集总数
@JSONField(name = "detail_total_index")
@Query
private Integer detailTotalIndex;
// 收藏内容的播放时间
@JSONField(name = "detail_play_time")
@Query
private Integer detailPlayTime;
// 收藏内容的总时间
@JSONField(name = "detail_total_time")
@Query
private Integer detailTotalTime;
// 收藏内容在同一folder中的顺序
@JSONField(name = "detail_sequence")
@Query
private Integer detailSequence;
// 收藏内容的评分
@JSONField(name = "detail_score")
@Query
private Float detailScore;
// 收藏内容(根据文件夹和类型的不同)的点赞/关注/订阅
@JSONField(name = "detail_like")
@Query
private Integer detailLike;
// 收藏内容的扩展数据
@JSONField(name = "detail_ext_data")
@Query
private String detailExtData;
// 创建时间
@JSONField(name = "create_time")
@Query
private Timestamp createTime;
// 更新时间
@JSONField(name = "update_time")
private Timestamp updateTime;
}
package com.topdraw.business.process.rest;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
......@@ -7,6 +9,8 @@ import com.topdraw.annotation.AnonymousAccess;
import com.topdraw.annotation.Log;
import com.topdraw.business.module.member.profile.domain.MemberProfile;
import com.topdraw.business.module.user.iptv.domain.UserTv;
import com.topdraw.business.module.user.iptv.service.dto.UserTvDTO;
import com.topdraw.business.module.user.weixin.domain.UserWeixin;
import com.topdraw.business.module.user.weixin.service.dto.UserWeixinDTO;
import com.topdraw.business.process.domian.TempIptvUser;
import com.topdraw.business.process.domian.UnbindGroup;
......@@ -15,8 +19,15 @@ import com.topdraw.business.process.domian.weixin.SubscribeBeanEvent;
import com.topdraw.business.process.domian.weixin.WeiXinUserBean;
import com.topdraw.business.process.service.UserOperationService;
import com.topdraw.common.ResultInfo;
import com.topdraw.config.RedisKeyUtil;
import com.topdraw.exception.BadRequestException;
import com.topdraw.module.mq.DataSyncMsg;
import com.topdraw.util.JSONUtil;
import com.topdraw.utils.RedisUtils;
import com.topdraw.utils.StringUtils;
import com.topdraw.weixin.util.WeChatConstants;
import com.topdraw.weixin.util.WeiXinRequestUtil;
import com.topdraw.weixin.util.WeixinUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
......@@ -25,6 +36,11 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@Api("账户处理")
@RestController
@RequestMapping(value = "/ucEngine/api/userOperation")
......@@ -33,6 +49,10 @@ public class UserOperationController {
@Autowired
private UserOperationService userTvOperationService;
@Autowired
private WeiXinRequestUtil weixinRequestUtil;
@Autowired
private RedisUtils redisUtils;
@Log("带参二维码")
@PostMapping(value = "/sendQrCodeMessage")
......@@ -40,7 +60,7 @@ public class UserOperationController {
@AnonymousAccess
public ResultInfo sendQrCodeMessage(@RequestBody String content) {
log.info("resources :[{}]",content);
boolean result = true;
boolean result = this.userTvOperationService.sendQrCodeMessage(content);
return ResultInfo.success(result);
}
......@@ -50,7 +70,7 @@ public class UserOperationController {
@AnonymousAccess
public ResultInfo deleteAllCollection(@RequestBody String content) {
log.info("resources :[{}]",content);
boolean result = true;
boolean result = this.userTvOperationService.deleteAllCollection(content);
return ResultInfo.success(result);
}
......@@ -60,7 +80,7 @@ public class UserOperationController {
@AnonymousAccess
public ResultInfo deleteCollection(@RequestBody String content) {
log.info("resources :[{}]",content);
boolean result = true;
boolean result = this.userTvOperationService.deleteCollection(content);
return ResultInfo.success(result);
}
......@@ -116,13 +136,88 @@ public class UserOperationController {
@PostMapping("/subscribe")
@ApiOperation("微信公众号关注")
@AnonymousAccess
public ResultInfo subscribe(@Validated @RequestBody SubscribeBeanEvent data) {
public ResultInfo subscribe(@Validated @RequestBody SubscribeBeanEvent data) throws IOException {
String content = data.getContent();
SubscribeBean subscribeBean = JSONUtil.parseMsg2Object(content, SubscribeBean.class);
this.parseSubscribe(subscribeBean);
boolean result = this.userTvOperationService.subscribe(subscribeBean);
return ResultInfo.success(result);
}
private void parseSubscribe(SubscribeBean subscribeBean) throws IOException {
if (Objects.nonNull(subscribeBean)) {
String appId = subscribeBean.getAppId();
// appId不得为空
if (StringUtils.isBlank(appId))
throw new BadRequestException("appId 不存在!");
// openId
String openId = subscribeBean.getOpenId();
if (StringUtils.isBlank(openId))
throw new BadRequestException("openId 不存在!");
// unionId
String unionId = null;
// 匹配配置文件中的微信列表信息
Map<String, String> wxInfoMap = WeixinUtil.getWeixinInfoByAppid(appId);
if (Objects.nonNull(wxInfoMap)) {
// 程序类型
String appType = wxInfoMap.get("appType");
// 非订阅号,暂不处理。返回暂不支持
if (ObjectUtil.notEqual(appType, WeChatConstants.WX_SUBSCRIPTION))
throw new BadRequestException("非订阅号");
// 用户类型
JSONObject userInfo = weixinRequestUtil.getUserInfo(wxInfoMap, openId);
log.info("userInfo is : {}", userInfo.toJSONString());
unionId = userInfo.get("unionid").toString();
if (StringUtils.isBlank(unionId))
throw new BadRequestException("unionid 不存在!");
}
// unionId不得为空
if (StringUtils.isBlank(unionId))
throw new BadRequestException("unionId 不存在!");
subscribeBean.setUnionId(unionId);
// 大屏账户信息
JSONObject iptvUserInfo = null;
// 缓存的大屏信息,使用unionid即可
String content = (String) this.redisUtils.get(RedisKeyUtil.genSeSuSubscribeKey(unionId));
if (StringUtils.isNotBlank(content)) {
// 大屏信息
iptvUserInfo = JSONObject.parseObject(content);
} else {
String eventKey = subscribeBean.getEventKey();
// 用户扫描带参二维码关注。发消息
// 去除固定前缀,获取二维码参数
eventKey = eventKey.substring(8);
iptvUserInfo = com.alibaba.fastjson.JSONObject.parseObject(eventKey);
}
// 用户自己搜索关注就没有大屏信息的话,否则表示扫码关注
if (Objects.nonNull(iptvUserInfo)) {
subscribeBean.setIptvUserInfo(iptvUserInfo);
}
// 之后删除缓存信息
this.redisUtils.del(RedisKeyUtil.genSeSuSubscribeKey(unionId));
}
}
@Log("微信公众号取关")
@PostMapping("/unsubscribe")
@ApiOperation("微信公众号取关")
......
......@@ -24,4 +24,10 @@ public interface UserOperationService {
String saveUserInfo(String data);
MemberProfile saveUserWeixinPhone(WeiXinUserBean resources);
boolean sendQrCodeMessage(String content);
boolean deleteAllCollection(String content);
boolean deleteCollection(String content);
}
......
package com.topdraw.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.List;
import java.util.Map;
@Configuration
@Data
@ConfigurationProperties(prefix = "weixin")
public class WeixinInfoConfig {
private List<Map<String, String>> list;
}
......@@ -300,6 +300,17 @@ public class WeiXinRequestUtil {
}
/**
* 公众号获取用户信息,access_token错误时,重新获取进行重试
*
* @param weixinInfo 微信参数
* @param openid 用户openid
*/
@Retryable(value = Exception.class, maxAttempts = 2, backoff = @Backoff(delay = 0L, multiplier = 0.0))
public JSONObject getUserInfo(Map<String, String> weixinInfo, String openid) throws IOException {
return this.getUserInfo(weixinInfo,openid,"");
}
/**
* @param weixinInfo
* @param nextOpenId
* @return com.alibaba.fastjson.JSONObject
......
package com.topdraw.weixin.util;
import com.topdraw.config.WeixinInfoConfig;
import com.topdraw.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@Component
@Slf4j
public class WeixinUtil {
private static WeixinInfoConfig WEIXININFOCONFIG;
@Autowired
public void setWeixinInfoConfig(WeixinInfoConfig weixinInfoConfig) {
WEIXININFOCONFIG = weixinInfoConfig;
}
public static Map<String, String> getWeixinInfoByAppid(String appid) {
if (StringUtils.isBlank(appid)) {
throw new RuntimeException("wxAppid can not be null");
}
List<Map<String, String>> list = WEIXININFOCONFIG.getList();
Optional<Map<String, String>> weixinInfoOptional = list.stream().filter(o -> o.get("appid").equals(appid)).findFirst();
if (!weixinInfoOptional.isPresent()) {
throw new RuntimeException("wxAppid error, appid is : " + appid);
}
return weixinInfoOptional.get();
}
public static Map<String, String> getWeixinInfoByIndex(Integer index) {
List<Map<String, String>> list = WEIXININFOCONFIG.getList();
if (list.size() < index + 1) {
throw new RuntimeException("wxinfo error, index out of range : {}" + index);
}
return list.get(index);
}
/**
* 使用SHA1算法对字符串数组进行加密
*
* @param strList
* @return
*/
public static String encodeUsingSHA1(String... strList) {
//将strList的值进行字典排序
Arrays.sort(strList);
StringBuilder content = new StringBuilder();
for (int i = 0; i < strList.length; i++) {
content.append(strList[i]);
}
return doEncodeUsingSHA1(content.toString());
}
/**
* SHA1实现
*
* @return sha1加密后的字符串
*/
private static String doEncodeUsingSHA1(String inStr) {
byte[] byteArray ;
try {
MessageDigest sha = MessageDigest.getInstance("SHA-1");
byteArray = sha.digest(inStr.getBytes("UTF-8"));
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("no sha-1 algorithm");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("unsupported utf-8 encoding");
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < byteArray.length; i++) {
sb.append(Integer.toString((byteArray[i] & 0xff) + 0x100, 16).substring(1));
}
return sb.toString();
}
/**
* 公众号,小程序后台配置服务器,初次检验时使用
* @throws IOException
*/
public static void doGet(HttpServletRequest request, HttpServletResponse response, Map<String, String> weixinInfo) throws IOException {
log.info("doGet receive WeChat server request parameters:{}", request.getParameterMap());
String signature = request.getParameter("signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
String echoStr = request.getParameter("echostr");
String[] arr = new String[]{weixinInfo.get("token"), timestamp, nonce};
String encrypt = WeixinUtil.encodeUsingSHA1(arr);
if (encrypt.equals(signature)) {
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(echoStr.getBytes());
outputStream.flush();
}
}
}