package com.zzwtec.wechat.controller; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.jfinal.kit.StrKit; import com.xiaoleilu.hutool.util.StrUtil; import com.zzwtec.jdbc.entity.ThirdUserWechat; import com.zzwtec.jdbc.service.ThirdUserWechatService; import com.zzwtec.wechat.common.constant.UrlConstants; import com.zzwtec.wechat.common.enums.CallType; import com.zzwtec.wechat.common.enums.DoorType; import com.zzwtec.wechat.config.WeChatConfig; import com.zzwtec.wechat.rpc.APIResponse; import com.zzwtec.wechat.rpc.api.APIService; import com.zzwtec.wechat.rpc.inject.ProxyBuilder; import com.zzwtec.wechat.sdk.api.ApiConfigKit; import com.zzwtec.wechat.sdk.inlet.MsgController; import com.zzwtec.wechat.sdk.kit.HttpKit; import com.zzwtec.wechat.sdk.msg.out.OutNewsMsg; import com.zzwtec.wechat.service.LoginService; import com.zzwtec.wechat.util.CharUtil; import com.zzwtec.wechat.util.CommonUtil; import com.zzwtec.wechat.util.TimeUtil; import com.zzwtec.wechat.util.security.MyBase64Util; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Controller; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import static com.xiaoleilu.hutool.util.StrUtil.isEmpty; import static com.zzwtec.wechat.config.WeChatConfig.weChatConfig; import static com.zzwtec.wechat.sdk.api.ApiConfigKit.getAppId; import static com.zzwtec.wechat.util.CharUtil.PARA_SEPARATE; /** * 门铃呼叫信息控制器
* 用户点击门铃呼叫模版消息后有这个控制显示 * * @author 邓燎燕 * 2016年5月9日 */ @Controller @RequestMapping("/doorbell") public class DoorbellController { private static ThirdUserWechatService thirdUserWechatService; @Autowired private HttpServletRequest request; private static StringRedisTemplate redisTemplate; @Autowired private LoginService loginService; private static final String CODE_KEY = "wechat-code-"; private static final String DOOR_INFO_KEY = "wechat-door-"; private static final APIService apiService = ProxyBuilder.build(APIService.class, WeChatConfig.weChatConfig); private static final Logger logger = LoggerFactory.getLogger(DoorbellController.class); @Autowired public void setStringRedisTemplate(StringRedisTemplate redisTemplate) { DoorbellController.redisTemplate = redisTemplate; } @Autowired public void setThirdUserWechatService(ThirdUserWechatService thirdUserWechatService) { DoorbellController.thirdUserWechatService = thirdUserWechatService; } /** * 进入呼叫页面 * v0 room * v1 callName * v2 openid */ @RequestMapping("/callroom/{_room}/{_callName}/{openid}") public String callroom(@PathVariable("_room") String room, @PathVariable("_callName") String callName, @PathVariable("openid") String openid) { room = StrUtil.isBlank(room) ? null : room.replaceAll("_", "-"); callName = StrUtil.isBlank(callName) ? null : CharUtil.decode(callName).replaceAll("_", "-"); String res = HttpKit.get(weChatConfig.getWsHost() + "/capture-" + room + "/1"); request.setAttribute("room", room); request.setAttribute("callName", callName); request.setAttribute("res", res); if (openid != null) { APIResponse response = apiService.findUserByAppidAndOpenid(ApiConfigKit.getAppId(), openid,apiService); if (response.isSuccess()) { request.setAttribute("userId", JSONObject.parseObject(response.getData()).getString("id")); } } return "/door/view/callroom.html"; } /** * 查看呼叫历史 * v0 userId * v1 page */ @RequestMapping("/callhistory/{userId}/{page}") public String callHistory(@PathVariable("userId") String userId, @PathVariable("page") int page) { if (StrKit.isBlank(userId)) { return "/door/view/nocallhistory.html"; } // 查询呼叫历史 APIResponse response = apiService.getCallLog(userId, page, 20); if (APIResponse.isFail(response)) { return "/common/view/failure_tips.html"; } if (StrKit.isBlank(response.getData())) { return "/door/view/nocallhistory.html"; } // 处理呼叫历史 JSONObject pageJson = JSONObject.parseObject(response.getData()); List> callLogList = toCallLogList(pageJson.getJSONArray("data")); if (callLogList == null || callLogList.isEmpty()) { return "/door/view/nocallhistory.html"; } request.setAttribute("appId", ApiConfigKit.getAppId()); request.setAttribute("total", pageJson.getIntValue("total")); request.setAttribute("logArr", callLogList); return "/door/view/callhistory.html"; } /** * 查看呼叫快照 * v0 captureKey */ @RequestMapping(value = "/getcallcapture",produces = "application/json") @ResponseBody public String getCallCapture(String captureKey) { APIResponse response = apiService.queryCaptureURLById(captureKey); if (!APIResponse.isSuccess(response)) { return APIResponse.toJSONObject(response).toJSONString(); } JSONObject jsonObject = new JSONObject(); jsonObject.put("url",response.getData()); return jsonObject.toJSONString(); } /** * 获取门列表 * v0 openid * v1 communityId * v2 buildId * v3 nowTime */ @RequestMapping("/getdoorlist") public ModelAndView getDoorList(String e) { ModelAndView modelAndView = new ModelAndView(); if (StrKit.isBlank(e)) { // 操作超时 重新点击“开门”菜单获取 request.setAttribute("tips", "操作超时 重新点击“开门”菜单获取"); modelAndView.setViewName("/door/view/opendoor.html"); return modelAndView; } // openid&communityId&buildId×tamp String decode = MyBase64Util.decode(e); if (decode == null) { // 操作无效 重新点击“开门”菜单获取 request.setAttribute("tips", "操作无效 重新点击“开门”菜单获取"); modelAndView.setViewName("/door/view/opendoor.html"); return modelAndView; } String[] paras = decode.split(PARA_SEPARATE); if (paras.length != 4) { // 操作无效 重新点击“开门”菜单获取 request.setAttribute("tips", "操作无效 重新点击“开门”菜单获取"); modelAndView.setViewName("/door/view/opendoor.html"); return modelAndView; } if (isTimeout(paras[3])) { // 操作超时 重新点击“开门”菜单获取 request.setAttribute("tips", "操作超时 重新点击“开门”菜单获取"); modelAndView.setViewName("/door/view/opendoor.html"); return modelAndView; } String tokenId=loginService.getLoginToken(); String doorListView = getDoorList(this, request, paras[0], paras[1], paras[2],tokenId); if (StrKit.notBlank(doorListView)){ modelAndView.setViewName(doorListView); }else{ modelAndView = null; } return modelAndView; } /** * 开门 * v0 openid * v1 doorId * v2 nowTime */ @RequestMapping("/opendoor") public String opendoor(String e) { APIResponse response = thridOpenDoor(e); request.setAttribute("tips", response.getMsg()); return "/door/view/opendoor.html"; } /** * 开门 * v0 openid * v1 doorId * v2 nowTime */ @RequestMapping(value = "/opendoor2",produces = "application/json") @ResponseBody public JSONObject opendoor2(String e) { APIResponse response = thridOpenDoor(e); return APIResponse.toJSONObject(response); } public static String getDoorList(Object target, HttpServletRequest request, String openid, String communityId, String buildId,String tokenId) { MsgController msgController = null; if (target instanceof MsgController) { msgController = (MsgController) target; } APIResponse re = apiService.getDoorList(communityId, buildId, tokenId); if (re == null || re.getCode() != 0) { if (msgController != null) { ((MsgController) target).renderOutTextMsg("请求失败,请重新操作"); return null; } else { return "/common/view/failure_tips.html"; } } JSONArray doorArr = JSONArray.parseArray(re.getData()); //该房产没有门 if(CollectionUtils.isEmpty(doorArr) && msgController != null){ msgController.renderOutTextMsg("暂无对应的门!"); return null; } if (msgController != null && doorArr.size() == 1) { // 只有一个门 JSONObject doorJson = doorArr.getJSONObject(0); Boolean remote = doorJson.getBoolean("remote"); if(remote != null && remote){ logger.info("门的json数据--->{}",doorJson.toJSONString()); APIResponse response = openCheck(openid, communityId, buildId); if(response!=null){ msgController.renderOutTextMsg(response.getMsg()); return null; } response = apiService.thridOpenDoor(openid, doorJson.getString("doorId"),apiService); boolean fail = response.isFail(); if(fail){ msgController.renderOutTextMsg("服务器繁忙,开门失败!请稍后重试!"); return null; } msgController.renderOutTextMsg("开门成功!"); return null; }else { msgController.renderOutTextMsg("暂无对应的门!"); return null; } } else { // 多个门 JSONArray doorbells = JSONArray.parseArray("[]"); JSONArray enclosures = JSONArray.parseArray("[]"); for (int i = 0; i < doorArr.size(); i++) { JSONObject doorJson = doorArr.getJSONObject(i); Boolean remote = doorJson.getBoolean("remote"); if(remote != null && remote){ //0表示楼栋门,1表示小区门 if (doorJson.getIntValue("type") == DoorType.getDoorType(DoorType.BUILD_DOOR)) { doorbells.add(doorJson); } else if(doorJson.getIntValue("type") == DoorType.getDoorType(DoorType.COMMUNITY_DOOR)) { enclosures.add(doorJson); } String itemDoorId = doorJson.getString("doorId"); String itemCommunityId = doorJson.containsKey("communityId") ? doorJson.getString("communityId") : communityId; String itemBuildId = "0"; if (doorJson.getIntValue("type") == DoorType.getDoorType(DoorType.BUILD_DOOR)) { itemBuildId = doorJson.containsKey("buildId") ? doorJson.getString("buildId") : buildId; } redisTemplate.opsForValue().set(DOOR_INFO_KEY+itemDoorId,itemCommunityId+PARA_SEPARATE+itemBuildId,5,TimeUnit.MINUTES); } } int wxArticleCount = Integer.MAX_VALUE; int maxShow = Integer.MAX_VALUE; OutNewsMsg outNewsMsg = null; List> list = null; if (msgController == null) { list = new ArrayList<>(); } else { outNewsMsg = new OutNewsMsg(msgController.getInMsg()); wxArticleCount = weChatConfig.getWxArticleCount(); maxShow = weChatConfig.getWxArticleCount(); if (doorArr.size() > wxArticleCount) { maxShow = wxArticleCount-1; } logger.info("wxArticleCount:{} maxShow:{} doorbells.size:{} enclosures.size:{}", wxArticleCount, maxShow, doorbells.size(), enclosures.size()); } String appId = ApiConfigKit.getAppId(); int i = 0; long nowTime = System.currentTimeMillis(); for (int j = 0; j < doorbells.size(); j++, i++) { if (i < maxShow) { JSONObject doorJson = doorbells.getJSONObject(j); String doorId = doorJson.getString("doorId"); String title = doorJson.getString("name"); String encode = getDoorEncode(openid, doorId, title, nowTime); if (list != null) { Map map = new HashMap<>(); map.put("title", title); map.put("e", encode); list.add(map); } else { String url = weChatConfig.getHost() + UrlConstants.DOORBELL_OPEN_DOOR + "?appId=" + appId + "&e=" + encode; outNewsMsg.addNews(title, "楼栋门", null, url); } } else { break; } } if (list != null && list.size() > 0) { request.setAttribute("doorbells", list); list = new ArrayList<>(); } for (int j = 0; j < enclosures.size(); i++, j++) { if (i < maxShow) { JSONObject doorJson = enclosures.getJSONObject(j); String doorId = doorJson.getString("doorId"); String title = doorJson.getString("name"); String encode = getDoorEncode(openid, doorId, title, nowTime); if (list != null) { Map map = new HashMap<>(); map.put("title", title); map.put("e", encode); list.add(map); } else { String url = weChatConfig.getHost() + UrlConstants.DOORBELL_OPEN_DOOR + "?appId=" + appId + "&e=" + encode; outNewsMsg.addNews(title, "小区门", null, url); } } else { break; } } if (list != null && list.size() > 0) { request.setAttribute("enclosures", list); } if (msgController == null) { request.setAttribute("appId", ApiConfigKit.getAppId()); return "/door/view/doorlist.html"; } else { if(doorArr.size() > wxArticleCount){ String encode = MyBase64Util.encode(openid + PARA_SEPARATE + communityId + PARA_SEPARATE + buildId + PARA_SEPARATE + nowTime); String url = weChatConfig.getHost() + UrlConstants.DOORBELL_GET_DOOR_LIST + "?e=" + encode; outNewsMsg.addNews("点击选择要开锁的门", "门列表", null, url); } msgController.render(outNewsMsg); } return null; } } private static String getDoorEncode(String openid, String doorId, String title, long nowTime) { return MyBase64Util.encode(openid + PARA_SEPARATE + doorId + PARA_SEPARATE + title + PARA_SEPARATE + nowTime); } private List> toCallLogList(JSONArray callLogJson) { if (callLogJson == null || callLogJson.size() == 0) { return null; } List> callLogList = new ArrayList<>(callLogJson.size()); for (int i = 0; i < callLogJson.size(); i++) { JSONObject item = callLogJson.getJSONObject(i); Map map = new HashMap<>(); boolean isCallee = isCallee(item.getIntValue("calleeType")); String[] calltimeStr = TimeUtil.timeLong2Str(item.getLong("calltime")).split(" "); map.put("isCallee", isCallee); map.put("tips", isCallee ? "访客呼叫" : "呼叫管理员"); map.put("date", calltimeStr[0].replaceAll("\\-", "/")); map.put("time", calltimeStr[1]); map.put("callname", item.getString("callName")); map.put("calleename", item.getString("calleeName")); map.put("captureKey", item.containsKey("img") ? item.getString("img") : ""); callLogList.add(map); } return callLogList; } private boolean isCallee(int calleeType) { CallType calledType = CallType.findType(calleeType); return calledType == CallType.CELL || calledType == CallType.PHONE; } private APIResponse thridOpenDoor(String e) { if (StrKit.isBlank(e)) { return new APIResponse(415, "操作无效 重新点击“开门”菜单获取"); } String decode = MyBase64Util.decode(e); if (decode == null) { return new APIResponse(415, "操作无效 重新点击“开门”菜单获取"); } // openid&doorId&title&nowTime String[] paras = decode.split(PARA_SEPARATE); if (paras.length != 4) { return new APIResponse(415, "操作无效 重新点击“开门”菜单获取"); } String openid = paras[0]; String doorId = paras[1]; String time = paras[3]; if (isTimeout(time)) { return new APIResponse(415, "操作超时 重新点击“开门”菜单获取"); } APIResponse response = openCheck(openid, doorId); if(response!=null){ return response; } String code = getCode(e); String result = redisTemplate.opsForValue().get(code); if(StringUtils.isEmpty(result)){ redisTemplate.opsForValue().set(code,e,2,TimeUnit.MINUTES); return apiService.thridOpenDoor(openid, doorId, apiService); }else{ return new APIResponse(415, "门锁已开!"); } } /** * 开门权限检查 * @param openid * @param doorId * @return */ private static APIResponse openCheck(String openid, String doorId) { // communityId&buildId String communityIdBuildId = redisTemplate.opsForValue().get(DOOR_INFO_KEY+doorId); if(communityIdBuildId == null){ return new APIResponse(415, "操作超时 重新点击“开门”菜单获取"); } String[] communityIdBuildIds = communityIdBuildId.split(PARA_SEPARATE); String communityId = communityIdBuildIds[0]; String buildId = communityIdBuildIds[1]; return openCheck(openid, communityId, buildId); } private static APIResponse openCheck(String openid, String communityId, String buildId) { // 查询微信关绑定系失败 ThirdUserWechat thirdUserWechat = thirdUserWechatService.queryUserWechatByOpenid(openid); // 没有绑定账号 if (thirdUserWechat==null || isEmpty(thirdUserWechat.getUserId())) { return new APIResponse(310, "查询不到您的用户信息"); } APIResponse userCellResponse = apiService.queryUserAndCellByUserId(thirdUserWechat.getUserId()); if(userCellResponse.isFail()){ return new APIResponse(415, "操作超时 重新点击“开门”菜单获取"); } JSONArray userCells = JSONArray.parseArray(userCellResponse.getData()); if(userCells == null || userCells.isEmpty()){ return new APIResponse(415, "您没有房产"); } boolean has = false; boolean disable = false; for(int i=0; i (2 * 60 * 1000); } private static long getTimestamp(String timestamp) { char last = timestamp.charAt(timestamp.length() - 1); if (last < '0' || last > '9') { timestamp = timestamp.substring(0, timestamp.length() - 1); } return Long.parseLong(timestamp); } private String getCode(String e){ return CODE_KEY + CommonUtil.getMD5(e.getBytes()); } }