Commit 2bf05374 2bf053742d549dd4a7a4de6e74f6fc144d232311 by xianghan@topdraw.cn

V1.0.2.REALESE

1 parent dc5e7311
Showing 22 changed files with 1291 additions and 99 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);
}
......
......@@ -20,12 +20,18 @@ import com.topdraw.business.module.user.iptv.domain.UserConstant;
import com.topdraw.business.module.user.iptv.domain.UserTv;
import com.topdraw.business.module.user.iptv.service.UserTvService;
import com.topdraw.business.module.user.iptv.service.dto.UserTvDTO;
import com.topdraw.business.module.user.weixin.collection.domain.UserCollection;
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.UserCollectionService;
import com.topdraw.business.module.user.weixin.domain.UserWeixin;
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;
import com.topdraw.business.process.domian.weixin.BuyVipBean;
import com.topdraw.business.process.domian.weixin.SubscribeBean;
import com.topdraw.business.process.domian.weixin.UserCollectionMq;
import com.topdraw.business.process.domian.weixin.WeiXinUserBean;
import com.topdraw.business.process.service.UserOperationService;
import com.topdraw.config.LocalConstants;
......@@ -35,14 +41,16 @@ import com.topdraw.exception.EntityNotFoundException;
import com.topdraw.security.AESUtil;
import com.topdraw.util.IdWorker;
import com.topdraw.util.TimestampUtil;
import com.topdraw.utils.QueryHelp;
import com.topdraw.utils.RedisUtils;
import com.topdraw.utils.StringUtils;
import com.topdraw.weixin.beans.DefaultWeiXinBeanDefinition;
import com.topdraw.weixin.beans.WeiXinBeanDefinition;
import com.topdraw.weixin.beans.*;
import com.topdraw.weixin.beans.config.WeiXinAppListConfig;
import com.topdraw.weixin.util.WeChatConstants;
import com.topdraw.weixin.util.WeiXinRequestUtil;
import com.topdraw.weixin.util.WeixinUtil;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -58,10 +66,9 @@ import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Service
@Slf4j
......@@ -79,11 +86,19 @@ public class UserOperationServiceImpl implements UserOperationService {
@Autowired
private RedisUtils redisUtils;
@Autowired
private WeiXinRequestUtil weixinRequestUtil;
@Autowired
private WeiXinAppListConfig weiXinAppListConfig;
@Autowired
private MemberProfileService memberProfileService;
@Autowired
private WeiXinRequestUtil weixinRequestUtil;
@Autowired
private UserCollectionService userCollectionService;
@Autowired
private UserCollectionDetailService userCollectionDetailService;
@Autowired
private UserCollectionDetailRepository userCollectionDetailRepository;
/** 取消关注 */
private static final Integer UNSUBSCRIBE_STATUS = 0;
......@@ -92,6 +107,8 @@ public class UserOperationServiceImpl implements UserOperationService {
private static final String UNSUBSCRIBE = "unsubscribe";
private static final Integer[] PLATFORM_LIST = new Integer[]{0,1,2,3};
private static final String QR_CODE_URL = "QR_CODE_URL_";
@Value("${uc.service.platform:}")
private String platform;
......@@ -114,6 +131,12 @@ public class UserOperationServiceImpl implements UserOperationService {
/**
* 微信公众号关注
* 1.未扫描大屏二维码
* 1). 保存、修改小屏账户,创建小屏账户会员
* 2.扫描大屏二维码
* 1). 从redis中获取大屏信息
* 2). 大屏账户保存小屏会员的code
* 3). 小屏会员中保存大屏的id
* @description 大小屏绑定,大屏账户保存小屏会员编码
* @param resources
* @return
......@@ -130,29 +153,38 @@ public class UserOperationServiceImpl implements UserOperationService {
throw new RuntimeException("微信信息解析失败!");
}
UserWeixinDTO userWeixinDTO = this.findUserWeiXinByOpenIdAndAppId(appId, openId);
// 小屏账户
UserWeixinDTO userWeixinDTO = this.findFirstByUnionIdAndAppIdAndOpenId(unionId,appId, openId);
if (Objects.isNull(userWeixinDTO.getId())) {
// 创建会员和账户
this.doCreateUserWeiXinAndMember(weiXinBeanDefinition,userWeixinDTO);
this.doCreateUserWeiXinAndMember(weiXinBeanDefinition);
} else {
// 修改会员和会员信息
// 修改账户和会员信息
this.doUpdateUserWeiXinAndMember(userWeixinDTO,appId,openId);
}
// 小屏会员
MemberDTO memberDTO_0 = this.findMemberByAppIdAndOpenId(appId,openId);
// 大屏信息
JSONObject iptvUserInfo = resources.getIptvUserInfo();
if (Objects.nonNull(iptvUserInfo)) {
// 从redis中获取大屏信息
UserTvDTO userTvDTO = this.findUserTvFromRedis(unionId);
// 小屏会员
MemberDTO memberDTO_0 = this.findMemberByAppIdAndOpenId(appId,openId);
// 携带了大屏信息
if (Objects.nonNull(userTvDTO) && StringUtils.isNotEmpty(memberDTO_0.getCode())) {
// 绑定主账号会员
// 账户
String platformAccount = iptvUserInfo.getString("platformAccount");
// 大屏账户
UserTvDTO userTvDTO = this.userTvService.findByPlatformAccount(platformAccount);
if (Objects.isNull(userTvDTO)) {
throw new BadRequestException("大屏信息不存在!");
}
// 大屏账户绑定小屏会员的code
this.bondPriorityMember(userTvDTO,memberDTO_0);
// 小屏会员绑定大屏账户id
......@@ -160,6 +192,7 @@ public class UserOperationServiceImpl implements UserOperationService {
// 修改会员
this.doUpdateMemberByMemberDTO(memberDTO_1);
}
return true;
......@@ -167,6 +200,17 @@ public class UserOperationServiceImpl implements UserOperationService {
}
/**
* 获取小屏账户
* @param unionId
* @param appId
* @param openId
* @return
*/
private UserWeixinDTO findFirstByUnionIdAndAppIdAndOpenId( String unionId,String appId, String openId) {
return this.userWeixinService.findFirstByUnionIdAndAppIdAndOpenId(unionId,appId,openId);
}
/**
*
* @param userWeixinDTO
* @param appId
......@@ -185,11 +229,10 @@ public class UserOperationServiceImpl implements UserOperationService {
/**
* 创建会员和账户
* @param weiXinBeanDefinition
* @param userWeixinDTO
*/
private void doCreateUserWeiXinAndMember(DefaultWeiXinBeanDefinition weiXinBeanDefinition,UserWeixinDTO userWeixinDTO) {
private void doCreateUserWeiXinAndMember(DefaultWeiXinBeanDefinition weiXinBeanDefinition) {
// 创建小屏
// 小屏账户
UserWeixin userWeixin = this.generateUserWeiXin(weiXinBeanDefinition,SUBSCRIBE_STATUS);
if (Objects.isNull(userWeixin.getId())) {
throw new BadRequestException("创建小屏账户失败");
......@@ -223,46 +266,6 @@ public class UserOperationServiceImpl implements UserOperationService {
}
/**
* 从redis中获取大屏信息
* @param unionId
* @return
*/
private UserTvDTO findUserTvFromRedis(String unionId) {
// 解析大屏信息
JSONObject iptvUserInfo = this.parseUserTvContent(unionId);
if (Objects.nonNull(iptvUserInfo)) {
String platformAccount = iptvUserInfo.getString("platformAccount");
UserTvDTO userTvDTO = this.findByPlatformAccount(platformAccount);
if (Objects.nonNull(userTvDTO.getId()))
userTvDTO.setPlatformAccount(platformAccount);
return userTvDTO;
}
return null;
}
/**
* 解析大屏用户
* @param unionId
* @return
*/
private JSONObject parseUserTvContent(String unionId) {
// 缓存的信息,使用unionid即可
String content = (String) this.redisUtils.get(RedisKeyUtil.genSeSuSubscribeKey(unionId));
// 之后删除缓存信息
redisUtils.del(RedisKeyUtil.genSeSuSubscribeKey(unionId));
JSONObject iptvUserInfo = com.alibaba.fastjson.JSONObject.parseObject(content);
return iptvUserInfo;
}
/**
* 绑定iptvId字段并修改会员vip字段
* @param memberDTO
* @param userTvDTO
......@@ -618,20 +621,6 @@ public class UserOperationServiceImpl implements UserOperationService {
}
}
/*if (StringUtils.isNotBlank(resources.getEncryptedData())) {
String decrypt = AESUtil.decrypt(resources.getEncryptedData(), key);
if (decrypt != null) {
encryptedData = decrypt.substring(16);
}
}*/
/*if (StringUtils.isNotBlank(resources.getIv())) {
String decrypt = AESUtil.decrypt(iv, key);
if (decrypt != null) {
iv = decrypt.substring(16);
}
}*/
String appId_ = weixinInfoMap.get("appid");
String secret = weixinInfoMap.get("secret");
......@@ -751,15 +740,6 @@ public class UserOperationServiceImpl implements UserOperationService {
}
/**
* 通过账户获取大屏账户
* @param platformAccount
* @return
*/
private UserTvDTO findByPlatformAccount(String platformAccount) {
return this.userTvService.findByPlatformAccount(platformAccount);
}
/**
* 通过编码获取会员
* @param memberCode
* @return
......@@ -838,16 +818,6 @@ public class UserOperationServiceImpl implements UserOperationService {
}
/**
* 通过大屏账户id查询大屏信息
* @param userTvId
* @return
*/
private UserTvDTO findByUserTvId(Long userTvId) {
UserTvDTO userTvDTO = this.userTvService.findById(userTvId);
return userTvDTO;
}
/**
* 通过大屏账户查询大屏信息
* @param resources
* @return
......@@ -974,6 +944,139 @@ public class UserOperationServiceImpl implements UserOperationService {
return this.doSaveOrUpdateMemberProfile(weiXinBeanDefinition,resources);
}
@Override
public boolean sendQrCodeMessage(String content) {
try {
log.info("receive get qrCode message, content {}", content);
JSONObject jsonObject = JSONObject.parseObject(content);
String appid = jsonObject.getString("appid");
String IPTVappid = jsonObject.getString("IPTVappid");
String platformAccount = jsonObject.getString("platformAccount");
String sessionId = jsonObject.getString("sessionId");
String key = QR_CODE_URL + appid + "_" + platformAccount + "_" + sessionId;
String url = (String) this.redisUtils.get(key);
if (StringUtils.isBlank(url)) {
Map<String, String> wxInfo = WeixinUtil.getWeixinInfoByAppid(appid);
String appType = wxInfo.get("appType");
// 订阅号不支持带参二维码,直接返回
if (StrUtil.isNotEmpty(appType) && ObjectUtil.equals(appType, WeChatConstants.WX_SUBSCRIPTION)) {
log.error("订阅号不支持带参二维码 || {} || {}", appid, content);
return false;
}
QrCode qrCode = new QrCode();
qrCode.setActionName(WeChatConstants.QR_STR_SCENE);
if (StringUtils.isNotBlank(wxInfo.get("qrCodeExpireSeconds"))) {
qrCode.setExpireSeconds(Integer.valueOf(wxInfo.get("qrCodeExpireSeconds")));
}
ActionInfo actionInfo = new ActionInfo();
Scene scene = new Scene();
scene.setSceneStr(content);
actionInfo.setScene(scene);
qrCode.setActionInfo(actionInfo);
JSONObject jsonQrCode = this.weixinRequestUtil.getQrCode(wxInfo, qrCode);
url = jsonQrCode.getString("url");
Integer expireSeconds = jsonQrCode.getInteger("expire_seconds");
this.redisUtils.set(key, url, expireSeconds, TimeUnit.SECONDS);
}
/* HashMap<String, Object> map = new HashMap<>();
map.put("sessionId", sessionId);
map.put("url", url);
map.put("appid", appid);
map.put("IPTVappid", IPTVappid);
map.put("platformAccount", platformAccount);
map.put("extraInfo", content);
messageProducer.sendQrCodeMessage(JSONObject.toJSONString(map));*/
} catch (Exception e) {
log.error("GetQrCodeConsumer || get qrCode error || {}", e.toString(), e);
}
return true;
}
@Override
public boolean deleteAllCollection(String content) {
try {
log.info("receive UserCollection delete all message, content {}", content);
JSONObject jsonObject = JSONObject.parseObject(content);
String platformAccount = jsonObject.getString("platformAccount");
Integer type = jsonObject.getInteger("collectionType");
UserTvDTO userTvDTO = this.userTvService.findByPlatformAccount(platformAccount);
Long id = userTvDTO.getId();
List<UserCollection> userCollections = this.userCollectionService.findByUserIdAndType(id, type);
if (userCollections == null || userCollections.isEmpty()) {
return false;
}
for (UserCollection userCollection : userCollections) {
this.userCollectionDetailService.deleteAllByUserCollectionId(userCollection.getId());
}
} catch (Exception e) {
log.error("CollectionDeleteConsumer || UserCollection delete all error || {}", e.toString(), e);
}
return true;
}
@Override
public boolean deleteCollection(String content) {
try {
log.info("receive UserCollection delete message, content {}", content);
JSONObject jsonObject = JSONObject.parseObject(content);
String platformAccount = jsonObject.getString("platformAccount");
String data = jsonObject.getString("data");
if (StringUtils.isBlank(data) || !data.startsWith("[")) {
return false;
}
UserTvDTO userTvDTO = this.userTvService.findByPlatformAccount(platformAccount);
Long id = userTvDTO.getId();
List<UserCollectionMq> userCollectionMqList = JSONObject.parseArray(data, UserCollectionMq.class);
if (userCollectionMqList == null || userCollectionMqList.isEmpty()) {
return false;
}
Map<Long, List<UserCollectionMq>> collect = userCollectionMqList.stream()
.collect(Collectors.groupingBy(UserCollectionMq::getUserCollectionId));
for (Map.Entry<Long, List<UserCollectionMq>> entry : collect.entrySet()) {
List<UserCollectionMq> value = entry.getValue();
UserCollectionMq userCollectionMq = value.get(0);
if (StringUtils.isBlank(userCollectionMq.getName())) {
userCollectionMq.setName("DEFAULT");
}
Optional<UserCollection> userCollectionOptional =
this.userCollectionService.findFirstByUserIdAndTypeAndName(id, userCollectionMq.getType(),
userCollectionMq.getName());
UserCollection userCollection = userCollectionOptional.orElseGet(UserCollection::new);
int count = 0;
for (UserCollectionMq collectionMq : value) {
collectionMq.setUserCollectionId(userCollection.getId());
List<UserCollectionDetail> userCollectionDetailOptional =
this.userCollectionDetailRepository.findAll((root, criteriaQuery, criteriaBuilder) ->
QueryHelp.getPredicate(root, collectionMq, criteriaBuilder));
if (!userCollectionDetailOptional.isEmpty()) {
this.userCollectionDetailService.deleteAll(userCollectionDetailOptional);
count++;
}
}
userCollection.setAppId(userCollectionMq.getAppId())
.setUserId(id)
.setName(userCollectionMq.getName())
.setType(userCollectionMq.getType())
.setCount(userCollection.getCount() - count);
this.userCollectionService.save(userCollection);
}
} catch (Exception e) {
log.error("CollectionDeleteConsumer || UserCollection delete error || {}", e.toString(), e);
}
return true;
}
/**
* 保存、修改会员加密信息
* @param resources
......
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();
}
}
}