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);
}
}