|
@@ -0,0 +1,636 @@
|
|
|
+package house.api.controller;
|
|
|
+
|
|
|
+
|
|
|
+import api.common.enums.IdStarterEnum;
|
|
|
+import api.common.enums.ResultCodeEnum;
|
|
|
+import api.common.exception.CommonBaseException;
|
|
|
+import api.common.model.CommonKey;
|
|
|
+import api.common.model.Result;
|
|
|
+import api.common.utils.DataUtils;
|
|
|
+import api.common.utils.JedisUtil;
|
|
|
+import api.common.utils.SHAUtils;
|
|
|
+import api.common.utils.UUidGenerator;
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
|
|
+import house.api.base.dao.TmDeveloperDao;
|
|
|
+import house.api.base.dao.TmHouseInfoDao;
|
|
|
+import house.api.base.dao.TmHouseRecommendDao;
|
|
|
+import house.api.base.dao.TmRoomIdLogDao;
|
|
|
+import house.api.base.entity.TmDeveloper;
|
|
|
+import house.api.base.entity.TmHouseInfo;
|
|
|
+import house.api.base.entity.TmHouseRecommend;
|
|
|
+import house.api.base.entity.TmRoomIdLog;
|
|
|
+import house.api.enums.DeveloperTerminalType;
|
|
|
+import io.swagger.annotations.Api;
|
|
|
+import io.swagger.annotations.ApiOperation;
|
|
|
+import lombok.extern.log4j.Log4j2;
|
|
|
+import org.apache.commons.io.IOUtils;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.stereotype.Controller;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
+import org.springframework.web.bind.annotation.PostMapping;
|
|
|
+import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
+import org.springframework.web.bind.annotation.ResponseBody;
|
|
|
+
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
+import java.io.BufferedReader;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.InputStreamReader;
|
|
|
+import java.time.Duration;
|
|
|
+import java.time.Instant;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+/**
|
|
|
+ * <p>
|
|
|
+ * 前端控制器
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @author abner
|
|
|
+ * @since 2020-06-04
|
|
|
+ */
|
|
|
+
|
|
|
+@Log4j2
|
|
|
+@Api(description = "开放api房源数据格式化相关接口")
|
|
|
+@Controller
|
|
|
+@RequestMapping("/api/vrhouse")
|
|
|
+public class TmHouseInfoController {
|
|
|
+
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private TmHouseInfoDao tmHouseInfoDao;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private TmDeveloperDao tmDeveloperDao;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private TmHouseRecommendDao tmHouseRecommendDao;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private TmRoomIdLogDao tmRoomIdLogDao;
|
|
|
+
|
|
|
+ @Value("${4dkankan.host.url}")
|
|
|
+ private String redirectVrUrl;
|
|
|
+
|
|
|
+ private static String SALT = "4dage";
|
|
|
+ private static String HOUSE_INFO_KEY = "houseInfo";
|
|
|
+ private static String REQUEST_BODY_STR_KEY = "reqBodyStr";
|
|
|
+ public static String SCENE_NUM_KEY = "SCENE_NUM";
|
|
|
+
|
|
|
+
|
|
|
+ @ApiOperation(value = "带看数据格式化接口")
|
|
|
+ @ResponseBody
|
|
|
+ @PostMapping(value = "/format")
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Result getSceneWithData(HttpServletRequest request, HttpServletResponse response) {
|
|
|
+
|
|
|
+ Instant totalStart = Instant.now();
|
|
|
+ String appId = request.getParameter(CommonKey.APP_ID);
|
|
|
+ String token = request.getParameter(CommonKey.TOKEN);
|
|
|
+ String sign = request.getParameter(CommonKey.SIGN);
|
|
|
+ Long timeStamp = DataUtils.getLongReturnNullIfNotExit(request.getParameter(CommonKey.TIME_STAMP));
|
|
|
+ log.info("获取到的appId={} ,token={} , sign={} , timeStamp={}", appId, token, sign, timeStamp);
|
|
|
+
|
|
|
+ if (!StringUtils.isNoneBlank(appId, token, sign)) {
|
|
|
+ throw new CommonBaseException(ResultCodeEnum.D3004, "appId、token、sign都不能为空");
|
|
|
+ }
|
|
|
+ if (null == timeStamp) {
|
|
|
+ throw new CommonBaseException(ResultCodeEnum.D3004, "缺失时间戳");
|
|
|
+ }
|
|
|
+ Instant stepOneStart = Instant.now();
|
|
|
+ //读取请求输入io流,解析houseInfo和请求体的字符串用于校验
|
|
|
+ Map<String ,Object> map = getAndCheckHouseInfo(request);
|
|
|
+ TmHouseInfo houseInfo = (TmHouseInfo) map.get(HOUSE_INFO_KEY);
|
|
|
+ String requestBodyStr = (String) map.get(REQUEST_BODY_STR_KEY);
|
|
|
+ //校验数据是否被篡改
|
|
|
+ checkDataModify(requestBodyStr , timeStamp , sign ,appId);
|
|
|
+
|
|
|
+ Instant stepOneEnd = Instant.now();
|
|
|
+ long stepOneDuration = Duration.between(stepOneStart , stepOneEnd).toMillis();
|
|
|
+ log.info("======{}========1、校验数据是否被篡改耗时:{}=============" ,houseInfo.getSceneNum() , stepOneDuration);
|
|
|
+ //从缓存中获取或者更新到db再更新到缓存
|
|
|
+ String roomId = houseInfo.getCommunicateRoomId();
|
|
|
+ if(StringUtils.isBlank(roomId)){
|
|
|
+ roomId = UUidGenerator.generatorUuid(IdStarterEnum.ROOM_ID.getStarter());
|
|
|
+ logRoomIdLog(roomId , houseInfo.getSceneNum());
|
|
|
+ }else{
|
|
|
+ //检查roomId是否合法
|
|
|
+ checkRoomId(roomId);
|
|
|
+ }
|
|
|
+ log.info("上送的二维码为:{}" , houseInfo.getWxAqrCode());
|
|
|
+ Instant stepTwoStart = Instant.now();
|
|
|
+ //更新db数据或者更新缓存
|
|
|
+ int insert = doDataCachedAndUpdate(houseInfo , appId , roomId);
|
|
|
+ Instant stepTwoEnd = Instant.now();
|
|
|
+ long stepTwoDuration = Duration.between(stepTwoStart , stepTwoEnd).toMillis();
|
|
|
+ log.info("======{}========2、插入房源数据耗时:{}=============" ,houseInfo.getSceneNum() , stepTwoDuration);
|
|
|
+ if (insert == 1) {
|
|
|
+ String redirectUrl = genVrLink(houseInfo);
|
|
|
+ Map<String, Object> resultMap = new HashMap<>();
|
|
|
+ resultMap.put("vrLink", redirectUrl);
|
|
|
+ resultMap.put("roomId", roomId);
|
|
|
+ //这里插入推荐房源,如果有
|
|
|
+ Instant stepThreeStart = Instant.now();
|
|
|
+ insertRecommends(houseInfo , appId ,roomId);
|
|
|
+ Instant stepThreeEnd = Instant.now();
|
|
|
+ long stepThreeDuration = Duration.between(stepThreeStart , stepThreeEnd).toMillis();
|
|
|
+ log.info("======={}========3、插入房源的推荐房源数据耗时:{}=============" ,houseInfo.getSceneNum() , stepThreeDuration);
|
|
|
+ Instant totalEnd = Instant.now();
|
|
|
+ long totalDuration = Duration.between(totalStart , totalEnd).toMillis();
|
|
|
+ log.info("======={}========格式化数据总耗时:{}=============" ,houseInfo.getSceneNum() , totalDuration);
|
|
|
+ return Result.success("成功", resultMap);
|
|
|
+ } else {
|
|
|
+ //理论上不会到这个分支
|
|
|
+ Instant totalEnd = Instant.now();
|
|
|
+ long totalDuration = Duration.between(totalStart , totalEnd).toMillis();
|
|
|
+ log.info("======={}========格式化数据总耗时:{}=============" ,houseInfo.getSceneNum() , totalDuration);
|
|
|
+ return Result.failure("数据提交失败,请重试");
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void insertRecommends(TmHouseInfo houseInfo , String appId , String roomId){
|
|
|
+ if(null != houseInfo && StringUtils.isNotBlank(houseInfo.getRecommendHouses())){
|
|
|
+ List<TmHouseInfo> recommendList = JSON.parseArray(houseInfo.getRecommendHouses() , TmHouseInfo.class);
|
|
|
+ if(!CollectionUtils.isEmpty(recommendList)){
|
|
|
+
|
|
|
+ for (TmHouseInfo recHouse : recommendList){
|
|
|
+ if(StringUtils.isBlank(recHouse.getSceneNum())){
|
|
|
+ log.warn("房源[{}]的推荐房源[{}]的场景码为空,不落库,跳过" , houseInfo.getHouseId() , recHouse.getHouseId());
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ //1、先插入推荐房源
|
|
|
+ int recInsert = doDataCachedAndUpdate(recHouse , appId , roomId);
|
|
|
+ if(recInsert != 1){
|
|
|
+ log.error("插入房源[{}]的推荐房源[{}]失败,将回滚" , houseInfo.getHouseId() , recHouse.getHouseId());
|
|
|
+ throw new CommonBaseException(ResultCodeEnum.D101 , "插入推荐房源失败");
|
|
|
+ }else{
|
|
|
+ //这里插入房源和推荐房源的关联关系
|
|
|
+ boolean needInsert = false;
|
|
|
+ if(StringUtils.isNoneBlank(houseInfo.getAgencyId() , recHouse.getAgencyId())){
|
|
|
+ if(StringUtils.equals(houseInfo.getAgencyId() , recHouse.getAgencyId())){
|
|
|
+ ///2、先插入单向 A->B
|
|
|
+ insertHouseRelation(houseInfo , recHouse);
|
|
|
+
|
|
|
+ //3、插入双向 , B->A
|
|
|
+ insertHouseRelation(recHouse , houseInfo);
|
|
|
+ needInsert = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(!needInsert){
|
|
|
+ log.warn("房源[{}]和推荐房源[{}]的经纪人不一样->[{}]-[{}],不生成关联关系" , houseInfo.getHouseId() ,recHouse.getHouseId(),
|
|
|
+ houseInfo.getAgencyId() , recHouse.getAgencyId());
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //4、除了跟主房源建立固关联关系,这五个推荐房源还要相互建立关联关系
|
|
|
+ //TODO:这里可以优化下,这个时间复杂度是0(N^2)了
|
|
|
+ for(int i = 0 ; i < recommendList.size() ; i++){
|
|
|
+ for(int j= i + 1 ; j < recommendList.size(); j++){
|
|
|
+ boolean needInsert = false;
|
|
|
+ if(StringUtils.isNoneBlank(recommendList.get(i).getAgencyId() , recommendList.get(j).getAgencyId())){
|
|
|
+ if(StringUtils.equals(recommendList.get(i).getAgencyId() , recommendList.get(j).getAgencyId())){
|
|
|
+ //A->B
|
|
|
+ insertHouseRelation(recommendList.get(i) , recommendList.get(j));
|
|
|
+ //B->A
|
|
|
+ insertHouseRelation(recommendList.get(j) , recommendList.get(i));
|
|
|
+ needInsert = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(!needInsert){
|
|
|
+ log.warn("房源[{}]和推荐房源[{}]的经纪人不一样->[{}]-[{}],不生成关联关系" , recommendList.get(i).getHouseId() ,recommendList.get(j).getHouseId(),
|
|
|
+ recommendList.get(i).getAgencyId() , recommendList.get(j).getAgencyId());
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void checkRoomId(String roomId){
|
|
|
+ QueryWrapper<TmRoomIdLog> queryWrapper = new QueryWrapper<>();
|
|
|
+ queryWrapper.eq("communicate_room_id" , roomId);
|
|
|
+ queryWrapper.eq("enable" , 1);
|
|
|
+ List<TmRoomIdLog> list = tmRoomIdLogDao.selectList(queryWrapper);
|
|
|
+ if(CollectionUtils.isEmpty(list)){
|
|
|
+ throw new CommonBaseException(ResultCodeEnum.D101 , "非法room id");
|
|
|
+ }
|
|
|
+ if(list.size() > 1){
|
|
|
+ throw new CommonBaseException(ResultCodeEnum.D101 , "一个roomId只能绑定一个场景");
|
|
|
+ }
|
|
|
+ log.info("roomId:{}合法" , roomId);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void insertHouseRelation(TmHouseInfo mainHouse , TmHouseInfo recommendHouse){
|
|
|
+ if(null == mainHouse || null == recommendHouse){
|
|
|
+ log.error("参数不够,无法建立关联关系");
|
|
|
+ }
|
|
|
+ QueryWrapper<TmHouseRecommend> recommendQueryWrapper = new QueryWrapper<>();
|
|
|
+ recommendQueryWrapper.eq("scene_num" , mainHouse.getSceneNum());
|
|
|
+ recommendQueryWrapper.eq("recommend_scene_num" , recommendHouse.getSceneNum());
|
|
|
+ recommendQueryWrapper.eq("enable" , 1);
|
|
|
+ recommendQueryWrapper.last("limit 1");
|
|
|
+ TmHouseRecommend houseRecommend = tmHouseRecommendDao.selectOne(recommendQueryWrapper);
|
|
|
+ if(null != houseRecommend){
|
|
|
+ log.info("场景码为:[{}]的房源和场景码为:[{}]的房源关联关系已经绑定,无需重复绑定" , mainHouse.getSceneNum() , recommendHouse.getSceneNum());
|
|
|
+ }else{
|
|
|
+ //新增关联关系
|
|
|
+ if(!StringUtils.isNoneBlank(mainHouse.getSceneNum() , recommendHouse.getSceneNum())){
|
|
|
+ log.warn("房源[{}]和房源[{}]的场景有一个为空:[{}]-[{}]" , mainHouse.getHouseId() ,recommendHouse.getHouseId() , mainHouse.getSceneNum() , recommendHouse.getSceneNum());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ TmHouseRecommend recommend = new TmHouseRecommend();
|
|
|
+ recommend.setRelationNo(UUidGenerator.generatorUuid(IdStarterEnum.RELATION.getStarter()));
|
|
|
+ recommend.setEnable(1);
|
|
|
+ recommend.setSceneNum(mainHouse.getSceneNum());
|
|
|
+ recommend.setRecommendSceneNum(recommendHouse.getSceneNum());
|
|
|
+ recommend.setAgencyId(mainHouse.getAgencyId());
|
|
|
+ recommend.setCreateTime(LocalDateTime.now());
|
|
|
+ recommend.setLastModifyDatetime(LocalDateTime.now());
|
|
|
+ int recommendInsert = tmHouseRecommendDao.insert(recommend);
|
|
|
+ if(recommendInsert != 1){
|
|
|
+ log.error("插入主房源:[{}]和推荐房源[{}]的关联关系失败:", mainHouse.getSceneNum() , recommendHouse.getSceneNum());
|
|
|
+ throw new CommonBaseException(ResultCodeEnum.D101 , "插入房源和推荐房源关联关系失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public int doDataCachedAndUpdate(TmHouseInfo houseInfo , String appId , String roomId){
|
|
|
+ int insert = -1;
|
|
|
+ if (!JedisUtil.exists(SCENE_NUM_KEY + ":" + houseInfo.getSceneNum() + "-" + roomId)) {
|
|
|
+ //缓存中没有此场景的数据,则需要读表,,然后再比对数据是否需要update db,再更新redis缓存
|
|
|
+ log.info("缓存中不存在key为:{}的数据" , (SCENE_NUM_KEY + ":" + houseInfo.getSceneNum() + "-" + roomId));
|
|
|
+ insert = updateOrInsertHouseInfo(houseInfo, appId , roomId);
|
|
|
+
|
|
|
+ } else {
|
|
|
+ log.info("缓存存在数据,key={}" , (SCENE_NUM_KEY + ":" + houseInfo.getSceneNum() + "-" + roomId));
|
|
|
+ //缓存中有此场景码的缓存,将校验数据是否有更新,如果没更新,则不更新db
|
|
|
+ String redisBodyStr = JedisUtil.getStringValue(SCENE_NUM_KEY + ":" + houseInfo.getSceneNum() + "-" + roomId);
|
|
|
+ //先暂存上送的houseInfo数据
|
|
|
+ TmHouseInfo toCompare = houseInfo;
|
|
|
+ /**
|
|
|
+ * 剔除request_id,create_time,last_modify_datetime,appid,communication_room_id字段
|
|
|
+ * 因为缓存中的这些字段都是被剔除的了
|
|
|
+ * **/
|
|
|
+ initCompareHouseInfo(toCompare , null);
|
|
|
+ //比较redis缓存中的数据和上送的数据是否一样,一样则表示没有数据变更,无需刷新到数据控中
|
|
|
+ if (isDataModified(redisBodyStr, JSON.toJSONString(toCompare))) {
|
|
|
+ //数据有变更了,需要更新db和缓存
|
|
|
+ log.info("数据有修改,需要更新db和redis缓存的数据");
|
|
|
+ insert = updateOrInsertHouseInfo(houseInfo, appId , roomId);
|
|
|
+ } else {
|
|
|
+ log.info("数据无修改,只更新缓存即可");
|
|
|
+ insert = 1;
|
|
|
+ //缓存续期5个小时
|
|
|
+ JedisUtil.expire(SCENE_NUM_KEY + ":" + houseInfo.getSceneNum() + "-" + roomId, 18000);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ return insert;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String ,Object> getAndCheckHouseInfo(HttpServletRequest request){
|
|
|
+ String requestBodyStr = "";
|
|
|
+ try {
|
|
|
+ InputStreamReader inputStreamReader = new InputStreamReader(request.getInputStream());
|
|
|
+ BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
|
|
|
+ requestBodyStr = IOUtils.toString(bufferedReader);
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error("读取http request的body出现异常:{}", e);
|
|
|
+ throw new CommonBaseException(ResultCodeEnum.D3008);
|
|
|
+ }
|
|
|
+ log.info("收到的请求体为:{}", requestBodyStr);
|
|
|
+ if (StringUtils.isBlank(requestBodyStr)) {
|
|
|
+ throw new CommonBaseException(ResultCodeEnum.D3004, "请求数据格式有误");
|
|
|
+ }
|
|
|
+
|
|
|
+ TmHouseInfo houseInfo = JSONObject.parseObject(requestBodyStr, TmHouseInfo.class);
|
|
|
+ if (null == houseInfo) {
|
|
|
+ throw new CommonBaseException(ResultCodeEnum.D3004, "请求数据格式有误");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (StringUtils.isBlank(houseInfo.getSceneNum())) {
|
|
|
+ throw new CommonBaseException(ResultCodeEnum.D3004, "场景码不能为空");
|
|
|
+ }
|
|
|
+ Map<String ,Object> result = new HashMap<>();
|
|
|
+ result.put(HOUSE_INFO_KEY , houseInfo);
|
|
|
+ result.put(REQUEST_BODY_STR_KEY , requestBodyStr);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void checkDataModify(String requestBodyStr ,Long timeStamp , String sign , String appId){
|
|
|
+ //校验数据是否被篡改
|
|
|
+ //TODO:这里需要改成从网关获取
|
|
|
+ QueryWrapper<TmDeveloper> developerQueryWrapper = new QueryWrapper<>();
|
|
|
+ developerQueryWrapper.eq("app_id", appId);
|
|
|
+ developerQueryWrapper.last("limit 1");
|
|
|
+ TmDeveloper tmDeveloper = tmDeveloperDao.selectOne(developerQueryWrapper);
|
|
|
+
|
|
|
+ if (tmDeveloper == null) {
|
|
|
+ throw new CommonBaseException(ResultCodeEnum.D3006);
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String , Object> requestDataMap = JSONObject.parseObject(requestBodyStr);
|
|
|
+ if(null == requestDataMap){
|
|
|
+ log.error("请求数据转换成map失败");
|
|
|
+ throw new CommonBaseException(ResultCodeEnum.D101);
|
|
|
+ }
|
|
|
+ String enCodeBodyStr = "";
|
|
|
+
|
|
|
+
|
|
|
+ Map<String , Object> sortMap = sortMapByKey(requestDataMap);
|
|
|
+ enCodeBodyStr = JSONObject.toJSONString(sortMap);
|
|
|
+
|
|
|
+ String unEnCodeSign = enCodeBodyStr + tmDeveloper.getAppSecret() + timeStamp;
|
|
|
+
|
|
|
+// log.info("待加密的数据为:{}", unEnCodeSign);
|
|
|
+ String enCodeStr = SHAUtils.getSHA256(unEnCodeSign);
|
|
|
+ log.info("解析出来的签名:{},上送的签名:{}", enCodeStr, sign);
|
|
|
+ if (!StringUtils.equals(enCodeStr, sign)) {
|
|
|
+ throw new CommonBaseException(ResultCodeEnum.D3009);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据map的key进行字典升序排序
|
|
|
+ * @param map
|
|
|
+ * @return map
|
|
|
+ */
|
|
|
+ public Map<String, Object> sortMapByKey(Map<String, Object>map) {
|
|
|
+ Map<String, Object> treemap = new TreeMap<String, Object>(map);
|
|
|
+ List<Map.Entry<String, Object>> list = new ArrayList<Map.Entry<String, Object>>(treemap.entrySet());
|
|
|
+ Collections.sort(list, new Comparator<Map.Entry<String, Object>>() {
|
|
|
+ @Override
|
|
|
+ public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) {
|
|
|
+ return StringUtils.compare(o1.getKey() , o2.getKey());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return treemap;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 校验上送的数据与数据库中的数据查看是否数据有更新,
|
|
|
+ * 如有,则更新db的数据,并更新redis缓存的数据
|
|
|
+ */
|
|
|
+ private int updateOrInsertHouseInfo(TmHouseInfo latestHouseInfo, String appId , String roomId) {
|
|
|
+ int insert = -1;
|
|
|
+ //无需刷新缓存的情况只有一个:用户做了删除房源的操作,在更新房源之前,做了缓存的清理,所以无需更新缓存
|
|
|
+ boolean noNeedUpdateRedis = false;
|
|
|
+ if (null != latestHouseInfo) {
|
|
|
+ //先存下未修改的数据,例如last_modify_datetime和request_id字段的请求数据,用于缓存
|
|
|
+ TmHouseInfo tmpHouseInfo = latestHouseInfo;
|
|
|
+ //只捞取有效的房源信息,enable= 1
|
|
|
+// TmHouseInfo dbHouseInfo = getHouseInfoFromDb(latestHouseInfo.getSceneNum(), null);
|
|
|
+ TmHouseInfo dbHouseInfo = getHouseInfoFromDb(latestHouseInfo.getSceneNum(), roomId);
|
|
|
+ if (null != dbHouseInfo) {
|
|
|
+
|
|
|
+ //非第一次插入,需要确认数据是否被修改了
|
|
|
+
|
|
|
+ //db中的数据和最新上送的数据比对,查看是否有更新
|
|
|
+ TmHouseInfo toCompare = dbHouseInfo;
|
|
|
+ //剔除可变字段
|
|
|
+ initCompareHouseInfo(toCompare , tmpHouseInfo);
|
|
|
+ if (isDataModified(JSON.toJSONString(toCompare), JSON.toJSONString(tmpHouseInfo))) {
|
|
|
+ //数据有变更了,需要更新db和缓存
|
|
|
+ //检查上送的houseId是否和数据库中的一致,一致则表示是有效的数据,否则认为是异常数据
|
|
|
+ if(!StringUtils.equals(dbHouseInfo.getHouseId() , latestHouseInfo.getHouseId())){
|
|
|
+ log.error("场景码[{}]下的有效的房源为:[{}],但是上送的为:[{}]" , latestHouseInfo.getSceneNum() ,
|
|
|
+ dbHouseInfo.getHouseId() , latestHouseInfo.getHouseId());
|
|
|
+ throw new CommonBaseException(ResultCodeEnum.D101 , "api上的房源数据没有及时删除,数据不一致");
|
|
|
+ }
|
|
|
+
|
|
|
+ //判断是否是删除房源操作
|
|
|
+ log.info("当前房源的状态为:{}" , dbHouseInfo.getEnable());
|
|
|
+ if(null != latestHouseInfo.getEnable() && latestHouseInfo.getEnable() == 0){
|
|
|
+ log.info("场景码[{}]将执行房源[{}]的删除操作" , latestHouseInfo.getSceneNum() , latestHouseInfo.getHouseId());
|
|
|
+ //如果有缓存,则先删除缓存,后面再逻辑删除
|
|
|
+ if (JedisUtil.exists(SCENE_NUM_KEY + ":" + latestHouseInfo.getSceneNum() + "-" + roomId)) {
|
|
|
+ JedisUtil.del(SCENE_NUM_KEY + ":" + latestHouseInfo.getSceneNum() + "-" + roomId);
|
|
|
+ }
|
|
|
+ //这次请求,无需更新缓存了
|
|
|
+ noNeedUpdateRedis = true;
|
|
|
+ //置空这个场景关联的推荐房源
|
|
|
+ latestHouseInfo.setRecommendHouses("");
|
|
|
+ //删除关联关系
|
|
|
+ delRecRelationBySceneNum(latestHouseInfo.getSceneNum() , dbHouseInfo.getAgencyId());
|
|
|
+
|
|
|
+ }else{
|
|
|
+ log.info("非删除操作");
|
|
|
+ }
|
|
|
+
|
|
|
+ //经纪人id变更了
|
|
|
+ if(!StringUtils.equals(dbHouseInfo.getAgencyId() , latestHouseInfo.getAgencyId())){
|
|
|
+ log.info("房源[{}]关联的经纪人由[{}]更改为[{}],需要删除原来的关联关系" , dbHouseInfo.getHouseId() , dbHouseInfo.getAgencyId() , latestHouseInfo.getAgencyId());
|
|
|
+ //删除旧的agencyId关联的关联关系
|
|
|
+ delRecRelationBySceneNum(latestHouseInfo.getSceneNum() , dbHouseInfo.getAgencyId());
|
|
|
+ }
|
|
|
+ UpdateWrapper<TmHouseInfo> houseInfoQueryWrapper = new UpdateWrapper<>();
|
|
|
+ houseInfoQueryWrapper.eq("scene_num", dbHouseInfo.getSceneNum());
|
|
|
+ houseInfoQueryWrapper.last("limit 1");
|
|
|
+ latestHouseInfo.setRequestId(dbHouseInfo.getRequestId());
|
|
|
+ initUpdateHouseInfo(latestHouseInfo, dbHouseInfo.getAppId());
|
|
|
+ insert = tmHouseInfoDao.update(latestHouseInfo, houseInfoQueryWrapper);
|
|
|
+ if (insert != 1) {
|
|
|
+ throw new CommonBaseException(ResultCodeEnum.D101, "更新houseInfo数据失败");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ //数据无变更,只更新缓存即可
|
|
|
+ log.info("数据无修改,只需要更新redis缓存的数据,并返回给调用端");
|
|
|
+ insert = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ //数据库中没有数据,属于第一次插入
|
|
|
+ initHouseInfo(latestHouseInfo, appId , roomId);
|
|
|
+ insert = tmHouseInfoDao.insert(latestHouseInfo);
|
|
|
+ if (insert != 1) {
|
|
|
+ throw new CommonBaseException(ResultCodeEnum.D101, "更新houseInfo数据失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //设置到缓存,设置缓存5个小时,这里剔除了request_id,create_time,last_modify_datetime,appid,communication_room_id字段
|
|
|
+ if(!noNeedUpdateRedis){
|
|
|
+ JedisUtil.setStringValue(SCENE_NUM_KEY + ":" + latestHouseInfo.getSceneNum() + "-" + roomId, JSON.toJSONString(tmpHouseInfo), 18000);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ return insert;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void logRoomIdLog(String roomId , String sceneNum){
|
|
|
+ if(StringUtils.isNotBlank(roomId)){
|
|
|
+ TmRoomIdLog tmRoomIdLog = new TmRoomIdLog();
|
|
|
+ tmRoomIdLog.setLogId(UUidGenerator.generatorUuid(IdStarterEnum.DEFAULT.getStarter()));
|
|
|
+ tmRoomIdLog.setCommunicateRoomId(roomId);
|
|
|
+ tmRoomIdLog.setEnable(1);
|
|
|
+ tmRoomIdLog.setSceneNum(sceneNum);
|
|
|
+ tmRoomIdLog.setCreateTime(LocalDateTime.now());
|
|
|
+ tmRoomIdLog.setUpdateTime(LocalDateTime.now());
|
|
|
+ int insert = tmRoomIdLogDao.insert(tmRoomIdLog);
|
|
|
+ if(insert != 1){
|
|
|
+ log.error("插入roomId记录失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 删除指定场景码的推荐房源的关联关系
|
|
|
+ * **/
|
|
|
+ private void delRecRelationBySceneNum(String sceneNum , String agencyId){
|
|
|
+ if(StringUtils.isNoneBlank(sceneNum , agencyId)){
|
|
|
+ QueryWrapper<TmHouseRecommend> recommendQueryWrapper = new QueryWrapper<>();
|
|
|
+ //TODO:这里去掉这个过滤,后面看看跟经纪人绑定的推荐房源如何处理
|
|
|
+// recommendQueryWrapper.eq("agency_id" , agencyId);
|
|
|
+ recommendQueryWrapper.or().eq("scene_num" , sceneNum);
|
|
|
+ recommendQueryWrapper.or().eq("recommend_scene_num" , sceneNum);
|
|
|
+ List<TmHouseRecommend> needDelRecList = tmHouseRecommendDao.selectList(recommendQueryWrapper);
|
|
|
+ if(!CollectionUtils.isEmpty(needDelRecList)){
|
|
|
+ for( TmHouseRecommend houseRecommend : needDelRecList){
|
|
|
+ QueryWrapper<TmHouseRecommend> delRecommendQuery = new QueryWrapper<>();
|
|
|
+ delRecommendQuery.eq("relation_no" , houseRecommend.getRelationNo());
|
|
|
+ delRecommendQuery.last("limit 1");
|
|
|
+ houseRecommend.setEnable(0);
|
|
|
+ int delRecResult = tmHouseRecommendDao.update(houseRecommend , delRecommendQuery);
|
|
|
+ if(delRecResult != 1){
|
|
|
+ log.error("删除关联关系失败,关联id=[{}]" , houseRecommend.getRelationNo());
|
|
|
+ throw new CommonBaseException(ResultCodeEnum.D101, "移除旧的关联关系失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 新增插入的时候初始化的字段
|
|
|
+ **/
|
|
|
+ private void initHouseInfo(TmHouseInfo houseInfo, String appId , String roomId) {
|
|
|
+ houseInfo.setRequestId(UUidGenerator.generatorUuid(IdStarterEnum.DEFAULT.getStarter()));
|
|
|
+ houseInfo.setCreateTime(LocalDateTime.now());
|
|
|
+ houseInfo.setLastModifyDatetime(LocalDateTime.now());
|
|
|
+ houseInfo.setAppId(appId);
|
|
|
+ houseInfo.setCommunicateRoomId(roomId);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void initCompareHouseInfo(TmHouseInfo houseInfo , TmHouseInfo fromSend) {
|
|
|
+ if(null != houseInfo){
|
|
|
+ houseInfo.setRequestId(null);
|
|
|
+ houseInfo.setCreateTime(null);
|
|
|
+ houseInfo.setLastModifyDatetime(null);
|
|
|
+ houseInfo.setAppId(null);
|
|
|
+ //客户第一次提交的过来的数据是没有roomId的
|
|
|
+ houseInfo.setCommunicateRoomId(null);
|
|
|
+ }
|
|
|
+
|
|
|
+ if(null != fromSend){
|
|
|
+ fromSend.setRequestId(null);
|
|
|
+ fromSend.setCreateTime(null);
|
|
|
+ fromSend.setLastModifyDatetime(null);
|
|
|
+ fromSend.setAppId(null);
|
|
|
+ //客户第一次提交的过来的数据是没有roomId的
|
|
|
+ fromSend.setCommunicateRoomId(null);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新数据的时候初始化的字段
|
|
|
+ **/
|
|
|
+ private void initUpdateHouseInfo(TmHouseInfo houseInfo, String appId) {
|
|
|
+ houseInfo.setLastModifyDatetime(LocalDateTime.now());
|
|
|
+ houseInfo.setAppId(appId);
|
|
|
+ }
|
|
|
+
|
|
|
+ private TmHouseInfo getHouseInfoFromDb(String sceneNum, String roomId) {
|
|
|
+ boolean needQuery = false;
|
|
|
+ QueryWrapper<TmHouseInfo> houseInfoQueryWrapper = new QueryWrapper<>();
|
|
|
+ if (StringUtils.isNotBlank(roomId)) {
|
|
|
+ houseInfoQueryWrapper.eq("communicate_room_id", roomId);
|
|
|
+// houseInfoQueryWrapper.eq("house_id", roomId);
|
|
|
+ needQuery = true;
|
|
|
+ }
|
|
|
+ if (StringUtils.isNotBlank(sceneNum)) {
|
|
|
+ houseInfoQueryWrapper.eq("scene_num", sceneNum);
|
|
|
+ needQuery = true;
|
|
|
+ }
|
|
|
+ TmHouseInfo dbHouseInfo = null;
|
|
|
+ if (needQuery) {
|
|
|
+ //只捞取enable=1未删除的房源
|
|
|
+ houseInfoQueryWrapper.eq("enable", 1);
|
|
|
+ List<TmHouseInfo> list = tmHouseInfoDao.selectList(houseInfoQueryWrapper);
|
|
|
+ if(!CollectionUtils.isEmpty(list)){
|
|
|
+ if(list.size() > 1){
|
|
|
+ //一个场景码下面有多个有效房源了,属于遗产情况
|
|
|
+ log.error("场景码[{}]下面有多个有效的房源信息" , sceneNum);
|
|
|
+ throw new CommonBaseException(ResultCodeEnum.D101 , "一个场景码绑定了多个有效房源");
|
|
|
+ }else if(list.size() == 1){
|
|
|
+ //理论只会有一个
|
|
|
+ dbHouseInfo = list.get(0);
|
|
|
+ }else{
|
|
|
+ log.info("场景码:{}下面再api中还没有房源" , sceneNum);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ return dbHouseInfo;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isDataModified(String src, String target) {
|
|
|
+ if (!StringUtils.equals(SHAUtils.getSHA256(src + SALT), SHAUtils.getSHA256(target + SALT))) {
|
|
|
+ //数据有更新、修改
|
|
|
+ return true;
|
|
|
+
|
|
|
+ } else {
|
|
|
+ //数据没有修改
|
|
|
+ return false;
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private String genVrLink(TmHouseInfo houseInfo) {
|
|
|
+ String terminalTypeStr = houseInfo.getTerminalType();
|
|
|
+ String userId = "";
|
|
|
+ DeveloperTerminalType terminalType = DeveloperTerminalType.getByType(terminalTypeStr);
|
|
|
+ if (null != terminalType && terminalType.equals(DeveloperTerminalType.CUSTOMER)) {
|
|
|
+ //用户端
|
|
|
+ userId = houseInfo.getUserId();
|
|
|
+ } else if (null != terminalType && terminalType.equals(DeveloperTerminalType.AGENT)) {
|
|
|
+ //经纪人端
|
|
|
+ userId = houseInfo.getAgencyId();
|
|
|
+ } else {
|
|
|
+// throw new CommonBaseException(ResultCodeEnum.D3010);
|
|
|
+ //给默认取值
|
|
|
+ userId = "";
|
|
|
+ terminalType = DeveloperTerminalType.CUSTOMER;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 样例:
|
|
|
+ * vrHouse.html?m=t-XtYfLCO&appname=vrhouse&role=customer&room_id=F8Q1&user_id=456
|
|
|
+ * vrHouse.html?m=t-XtYfLCO&appname=vrhouse&role=agent&room_id=F8Q1&user_id=456
|
|
|
+ * */
|
|
|
+ String redirectUrl = redirectVrUrl + houseInfo.getSceneNum() //场景码
|
|
|
+ + "&appname=vrhouse&role=" + terminalType.getType(); //角色名
|
|
|
+
|
|
|
+ if(StringUtils.isNotBlank(houseInfo.getCommunicateRoomId())){
|
|
|
+ redirectUrl += "&room_id=" + houseInfo.getCommunicateRoomId();//roomId
|
|
|
+ }
|
|
|
+ if(StringUtils.isNotBlank(userId)){
|
|
|
+ redirectUrl += "&user_id=" + userId; //userId
|
|
|
+ }
|
|
|
+ log.info("生成的vr链接为:{}", redirectUrl);
|
|
|
+ return redirectUrl;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|