package com.zzwtec.wechat.controller; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.jfinal.kit.StrKit; import com.zzwtec.jdbc.entity.ThirdUserWechat; import com.zzwtec.jdbc.service.ThirdUserWechatService; import com.zzwtec.wechat.common.ErrorMsg; import com.zzwtec.wechat.common.constant.UrlConstants; import com.zzwtec.wechat.config.WeChatConfig; import com.zzwtec.wechat.rpc.APIResponse; import com.zzwtec.wechat.rpc.Signature; import com.zzwtec.wechat.rpc.api.APIService; import com.zzwtec.wechat.rpc.inject.ProxyBuilder; import com.zzwtec.wechat.sdk.api.AccessTokenApi; import com.zzwtec.wechat.sdk.api.ApiConfigKit; import com.zzwtec.wechat.sdk.api.ApiResult; import com.zzwtec.wechat.sdk.api.TemplateMsgApi; import com.zzwtec.wechat.util.CharUtil; import com.zzwtec.wechat.util.security.MyBase64Util; import com.zzwtec.wechat.util.security.TokenUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.regex.Matcher; import java.util.regex.Pattern; import static com.zzwtec.wechat.common.enums.UserCellType.MASTER; import static com.zzwtec.wechat.common.enums.UserCellType.MEMBER; import static com.zzwtec.wechat.common.enums.UserCellType.TENANT; import static com.zzwtec.wechat.sdk.utils.RenderUtil.renderText; /** * 微信消息 * 请求微信把消息发送给用户 * @author 邓燎燕 * 2016年5月9日 */ @Controller @RequestMapping("/push") public class WechatMsgController{ private static final Logger logger = LoggerFactory.getLogger(WechatMsgController.class); private static final ExecutorService executorService = Executors.newWorkStealingPool(); @Autowired private static final APIService apiService = ProxyBuilder.build(APIService.class,WeChatConfig.weChatConfig); @Autowired private HttpServletRequest request; @Autowired private ThirdUserWechatService thirdUserWechatService; /** * 处理旧的请求 * @param body * @return */ private String oldRequest(String body){ if(body.startsWith("msg=")){ body = body.substring("msg=".length()); try { body = URLDecoder.decode(body,"UTF-8"); } catch (UnsupportedEncodingException e) { return null; } } return body; } /** * 发公告模版消息
* 请求msg 值:{"token":"token","openid":["openid"],"msgid":"公告ID","msgtitle":"公告标题","msgtime":"公告发布时间","msgcontent":"公告简述"}
* openid 微信用户的openid数组
* msgid 公告ID
* msgtitle 公告标题
* msgtime 公告发布时间 如“5月11日 18:00:00”
* msgcontent 公告简述 公告内容的请20个字加省略号 */ @RequestMapping(value = "/cmsg",produces = "application/json",method = RequestMethod.POST) @ResponseBody public JSONObject msg(@RequestBody String body) { logger.info("公告推送:"+body); // 验证数据合法性 // if (!validateSign(body)) { // return returnFail("10", ErrorMsg._10); // } // 验证数据有效性 body = oldRequest(body); if(body==null){ return returnFail(); } JSONObject json = JSONObject.parseObject(body); if (json == null) { return returnFail(); } final JSONArray openidArr = json.containsKey("openids")?json.getJSONArray("openids"):json.getJSONArray("openid"); final String msgid = json.getString("msgid"); final String msgtitle = json.getString("msgtitle"); final String msgtime = json.getString("msgtime"); final String msgcontent = json.getString("msgcontent"); if (openidArr == null || openidArr.isEmpty() || StringUtils.isEmpty(msgid) || StringUtils.isEmpty(msgtitle) || StringUtils.isEmpty(msgtime) || StringUtils.isEmpty(msgcontent)) { return returnFail(); } /* * 使用了 物业管理通知 模板 * * {{first.DATA}} * 标题:{{keyword1.DATA}} * 发布时间:{{keyword2.DATA}} * 内容:{{keyword3.DATA}} * {{remark.DATA}} */ if(WeChatConfig.weChatConfig.isPush()){ executorService.execute(() -> { JSONObject template = new JSONObject(); JSONObject data = new JSONObject(); String url, title; Pattern pattern = Pattern.compile("^\\[(.*)\\]\\((.*)\\)$"); Matcher matcher = pattern.matcher(msgtitle); if (matcher.find()) { title = matcher.group(1); url = matcher.group(2); } else { title = msgtitle; url = WeChatConfig.weChatConfig.getHost() + UrlConstants.MSG_GET_MSG + "/" + msgid; } // template.put("template_id", "uDkGCbdRYeQHEeebwYMcpFCviFhrS-VZdUFqaLgWi14"); template.put("template_id", WeChatConfig.weChatConfig.getNoticeTemplateId()); template.put("topcolor", "#E93C1F"); template.put("url", url); template.put("data", data); data.put("first", new JSONObject().fluentPut("value", "公告").fluentPut("color", "#000000")); data.put("keyword1", new JSONObject().fluentPut("value", title).fluentPut("color", "#000000")); data.put("keyword2", new JSONObject().fluentPut("value", msgtime).fluentPut("color", "#000000")); data.put("keyword3", new JSONObject().fluentPut("value", msgcontent).fluentPut("color", "#000000")); data.put("remark", new JSONObject().fluentPut("value", "点击查看公告详情。").fluentPut("color", "#000000")); for (int i = 0; i < openidArr.size(); i++) { String openid = openidArr.getString(i); template.put("touser", openid); String templateStr = template.toJSONString(); sendTemplateMsg(templateStr); } }); } return returnOk(); } /** * 发门铃呼叫模版消息
* 请求msg 值:{"token":"token","openid":["openid"],"room":"快照房间","callname":"呼叫来源","calltime":"呼叫时间"}
* openid 微信用户的openid数组
* room 快照房间
* callname 呼叫来源
* calltime 呼叫时间 如“5月11日 18:00:00” */ @RequestMapping(value = "/doorbell",produces = "application/json",method = RequestMethod.POST) @ResponseBody public JSONObject doorbell(@RequestBody String body) { logger.info("呼叫推送:"+body); // 验证数据合法性 // if (!validateSign(body)) { // // return returnFail("10", ErrorMsg._10); // } // 验证数据有效性 body = oldRequest(body); if(body==null){ return returnFail(); } JSONObject json = JSONObject.parseObject(body); if (json == null) { return returnFail(); } List openidArr = new ArrayList<>(); String room = json.getString("room"); String callname = json.getString("callname"); String calltime = json.getString("calltime"); //房间id 根据房间id查询相关用户openid String cellId = json.getString("cellId"); APIResponse userCellResponse = apiService.queryUserAndCellByCellId(cellId); if (userCellResponse.isFail()) { renderText(userCellResponse.getMsg()); return null; } // 房间住户信息 JSONArray userCells = JSONArray.parseArray(userCellResponse.getData()); if(userCells!=null){ List userIds=new ArrayList<>(); userCells.stream().forEach(obj ->{ JSONObject userCell = (JSONObject) obj; userIds.add(userCell.getString("userId")); }); List thirdUserWechats=thirdUserWechatService.queryUserWechatByUserIds(userIds); if(thirdUserWechats!=null){ thirdUserWechats.stream().forEach(thirdUserWechat ->{ openidArr.add(thirdUserWechat.getOpenid()); }); } } if (openidArr == null || openidArr.isEmpty() || StringUtils.isEmpty(room) || StringUtils.isEmpty(callname) || StringUtils.isEmpty(calltime)) { return returnFail(); } /* * 使用了 来访提醒 模板 * {{first.DATA}} * 访客:{{keyword1.DATA}} * 来访事由:{{keyword2.DATA}} * 联系电话:{{keyword3.DATA}} * 到达时间:{{keyword4.DATA}} * {{remark.DATA}} */ if(WeChatConfig.weChatConfig.isPush()){ executorService.execute(() -> { JSONObject template = new JSONObject(); JSONObject data = new JSONObject(); // template.put("template_id","FQECzlCRIk3UQb-MOfABs8Cu9vQMmR1E5hxbqrZgOKw"); template.put("template_id", WeChatConfig.weChatConfig.getVisitTemplateId()); template.put("topcolor", "#E93C1F"); template.put("data", data); data.put("first", new JSONObject().fluentPut("value", "您有一个访客到访。").fluentPut("color", "#EB4324")); data.put("keyword1", new JSONObject().fluentPut("value", "点击查看").fluentPut("color", "#EB4324")); data.put("keyword2", new JSONObject().fluentPut("value", "到访").fluentPut("color", "#000000")); data.put("keyword3", new JSONObject().fluentPut("value", "无").fluentPut("color", "#000000")); data.put("keyword4", new JSONObject().fluentPut("value", calltime).fluentPut("color", "#EB4324")); data.put("remark", new JSONObject().fluentPut("value", "点击查看访客信息,确认访客身份。").fluentPut("color", "#000000")); for (int i = 0; i < openidArr.size(); i++) { String openid = openidArr.get(i); template.put("touser", openid); template.put("url", WeChatConfig.weChatConfig.getHost()+ UrlConstants.DOORBELL_CALLROOM + "/" + room.replaceAll("-", "_") + "/" + callname.replaceAll("-", "_") + "/" + openid); String templateStr = template.toJSONString(); logger.info("发门铃呼叫模版消息: "+templateStr); sendTemplateMsg(templateStr); } }); } return returnOk(); } /** * 发开门反馈模版消息 门口机或围墙机的门铃设备调用 * e 加密信息 * token * type * opentime 开门反馈时间 * doorname 开门名称 * openres 开门结果: 开锁成功 开锁失败 */ @RequestMapping(value = "/dooropen",produces = "application/json",method = RequestMethod.POST) @ResponseBody public JSONObject pushOpenDoorMsg(String e,@RequestBody(required = false) JSONObject json) { logger.info("开门反馈推送:"+(json==null?"":json.toJSONString())); String opentime; String doorname; String openres; //兼容之前的版本,如果json为空说明客户端的提交方式是表单 if(json == null){ opentime = request.getParameter("opentime"); doorname = request.getParameter("doorname"); openres = request.getParameter("openres"); }else{ opentime = json.getString("opentime"); doorname = json.getString("doorname"); openres = json.getString("openres"); } if (StrKit.isBlank(e)) { return returnFail(); } // appId&openid&doorId&nowTime String decode = MyBase64Util.decode(e); if (decode == null) { return returnFail(); } String[] paras = decode.split(CharUtil.PARA_SEPARATE); if (paras.length != 5) { return returnFail(); } if (!paras[0].equals(ApiConfigKit.getAppId())) { return returnFail(); } if (DoorbellController.isTimeout(paras[3])) { return returnFail(); } if (TokenUtil.isValid(paras[4])) { return returnFail(); } if (StringUtils.isEmpty(opentime) || StringUtils.isEmpty(doorname) || StringUtils.isEmpty(openres)) { return returnFail(); } /* * 使用了 监控被触发提醒 模板 * * {{first.DATA}} * 触发时间:{{keyword1.DATA}} * 触发类型:{{keyword2.DATA}} * 触发详情:{{keyword3.DATA}} * {{remark.DATA}} */ String finalDoorname = doorname; String finalOpenres = openres; String finalOpentime = opentime; if(WeChatConfig.weChatConfig.isPush()){ executorService.execute(() -> { JSONObject template = new JSONObject(); JSONObject data = new JSONObject(); template.put("touser", paras[1]); // template.put("template_id", "akEk5yB02eC9-IhIzj5hpZz_asHK4_g9b-per4PzSKM"); template.put("template_id", WeChatConfig.weChatConfig.getFeedbackTemplateId()); template.put("topcolor", "#E93C1F"); template.put("url", WeChatConfig.weChatConfig.getHost()+UrlConstants.INFO_FEEDBACKDETAIL); template.put("data", data); data.put("first", new JSONObject().fluentPut("value", finalDoorname + " " + finalOpenres).fluentPut("color", "#EB4324")); data.put("keyword1", new JSONObject().fluentPut("value", finalOpentime).fluentPut("color", "#EB4324")); data.put("keyword2", new JSONObject().fluentPut("value", "开锁反馈").fluentPut("color", "#000000")); data.put("keyword3", new JSONObject().fluentPut("value", finalDoorname + " " + finalOpenres).fluentPut("color", "#000000")); data.put("remark", new JSONObject().fluentPut("value", "").fluentPut("color", "#000000")); sendTemplateMsg(template.toJSONString()); /* JSONArray news = null; try { //获取微信广告 APIResponse apiResponse = apiService.queryWechatNewsAll(); //广告列表 String newsJson = apiResponse.getData(); news = null; if(StrKit.notBlank(newsJson)){ news = JSON.parseArray(newsJson); } } catch (Exception e1) { logger.error("出现异常!",e1); } //用户OPENID String openId = paras[1]; List articleList = new ArrayList(){ { CustomServiceApi.Articles main = new CustomServiceApi.Articles(); main.setTitle("开锁成功!"); add(main); } }; if(news != null && !news.isEmpty()){ for (int i = 0; i < news.size(); i++) { JSONObject jsonObject = news.getJSONObject(i); String title = jsonObject.getString("title"); String url = jsonObject.getString("url"); String img = jsonObject.getString("img"); CustomServiceApi.Articles article = new CustomServiceApi.Articles(); article.setTitle(title); article.setUrl(url); article.setPicurl(img); articleList.add(article); } }else{ CustomServiceApi.Articles article = new CustomServiceApi.Articles(); article.setTitle("智之屋官网"); article.setUrl("http://www.zzwtec.com/"); article.setPicurl("http://wechat.zzwtec.com/images/logo.png"); articleList.add(article); } ApiResult apiResult = CustomServiceApi.sendNews(openId, articleList); if(!apiResult.isSucceed()){ logger.error("发送客服消息,出现异常!" + apiResult.getErrorMsg()); }*/ }); } return returnOk(); } /** * 发送模板消息 * * @param templateStr 消息模板 */ private static void sendTemplateMsg(String templateStr) { ApiConfigKit.setThreadLocalAppId(ApiConfigKit.getAppId()); ApiResult apiResult; int i = 0; AccessTokenApi.refreshAccessToken(); do { if (i >= 5) { break; } apiResult = TemplateMsgApi.send(templateStr); if (!apiResult.isSucceed()) { logger.error("sendTemplateMsg Faile:\nErrorCode:" +apiResult.getErrorCode()+"\nErrorMsg:"+apiResult.getErrorMsg()+"\ntemplateStr:"+templateStr); if(43004 == apiResult.getErrorCode()){ // 需要接收者关注 break; } i++; try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } else { logger.debug("sendTemplateMsg Succeed"); break; } } while (!apiResult.isSucceed()); } /** * 回复操作正常 */ private JSONObject returnOk() { JSONObject json = JSONObject.parseObject("{}"); json.put("error", "0"); json.put("errormsg", ErrorMsg._0); return json; } /** * 回复操作失败 */ private JSONObject returnFail() { JSONObject json = JSONObject.parseObject("{}"); json.put("error", "415"); json.put("errormsg", ErrorMsg._415); return json; } private JSONObject returnFail(String code, String msg) { JSONObject json = new JSONObject(); json.put("error", code); json.put("errormsg", msg); return json; } private boolean validateSign(String body) { String header = request.getHeader(Signature.ZZW_SIGN_HEADER); Signature signature = Signature.parseHeader(header); if (signature == null) { return false; } signature.setSecretKey(WeChatConfig.weChatConfig.getZzwtecSecretKey()); return signature.validateSign(body); } }