Jelajahi Sumber

Merge remote-tracking branch 'origin/V1' into V1

zhengqiang 5 tahun lalu
induk
melakukan
588a851803

+ 4 - 0
common/pom.xml

@@ -145,6 +145,10 @@
             <groupId>org.springframework</groupId>
             <artifactId>spring-web</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.tomcat.embed</groupId>
+            <artifactId>tomcat-embed-core</artifactId>
+        </dependency>
         <!-- aliyun oss end -->
     </dependencies>
 

+ 5 - 0
common/src/main/java/com/jpsoft/smart/config/WxConfig.java

@@ -14,4 +14,9 @@ import org.springframework.stereotype.Component;
 public class WxConfig {
     private String appId;
     private String appSecret;
+    private String token;
+    private String tokenUrl;
+    private String createQrCodeUrl;
+    private String showQrCodeUrl;
+    private String contentType;
 }

+ 1 - 0
common/src/main/java/com/jpsoft/smart/modules/base/service/PersonDeviceRelationService.java

@@ -13,6 +13,7 @@ public interface PersonDeviceRelationService {
 	boolean exist(String id);
 	int insert(PersonDeviceRelation model);
 	int update(PersonDeviceRelation model);
+	int updateDevicePerson(PersonDeviceRelation model) throws Exception;
 	int delete(String id);
 	List<PersonDeviceRelation> list();
 	List<PersonDeviceRelation> findByPersonId(Long personId);

+ 4 - 0
common/src/main/java/com/jpsoft/smart/modules/base/service/impl/PersonDeviceLogServiceImpl.java

@@ -117,6 +117,7 @@ public class PersonDeviceLogServiceImpl implements PersonDeviceLogService {
     public void sendTemperatureAlarmsyncTask(PersonDeviceLog personDeviceLog) {
 
         try {
+
             PersonInfo personInfo = personInfoDAO.get(personDeviceLog.getPersonId().longValue());
             if (personInfo == null) {
                 throw new Exception(personDeviceLog.getPersonId() + "对应的人员不存在");
@@ -133,6 +134,7 @@ public class PersonDeviceLogServiceImpl implements PersonDeviceLogService {
             if (warningPusherList.size() <= 0) {
                 throw new Exception("对应公司没有体温报警监管者");
             }
+
             for (WarningPusher warningPusher : warningPusherList) {
                 Map<String, Object> searchParams = new HashMap<>();
                 searchParams.put("deviceNo", personDeviceLog.getDeviceNo());
@@ -142,7 +144,9 @@ public class PersonDeviceLogServiceImpl implements PersonDeviceLogService {
                 List<Sort> sortList = new ArrayList<>();
                 sortList.add(new Sort("record_time", "desc"));
                 List<PersonDeviceLog> personDeviceLogList = personDeviceLogDAO.search(searchParams, sortList);
+
                 if (personDeviceLogList.size() >= warningPusher.getTimes()) {
+                    log.warn("开始发送模板消息");
                     WechatMessageUtil.sendTemperatureAlarmInfo(warningPusher.getOpenId(), companyInfo.getName() + "_" + deviceInfo.getAliasName(), wxConfig.getAppId(), wxConfig.getAppSecret(),personDeviceLog.getId());
                 }
             }

+ 22 - 0
common/src/main/java/com/jpsoft/smart/modules/base/service/impl/PersonDeviceRelationServiceImpl.java

@@ -6,6 +6,9 @@ import java.util.UUID;
 import javax.annotation.Resource;
 
 import com.jpsoft.smart.modules.base.entity.DeviceInfo;
+import com.jpsoft.smart.modules.lapi.service.ILapiService;
+import com.jpsoft.smart.modules.lapi.vo.LapiMsgResult;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 import com.jpsoft.smart.modules.base.dao.PersonDeviceRelationDAO;
@@ -21,6 +24,9 @@ public class PersonDeviceRelationServiceImpl implements PersonDeviceRelationServ
 	@Resource(name="personDeviceRelationDAO")
 	private PersonDeviceRelationDAO personDeviceRelationDAO;
 
+	@Autowired
+	private ILapiService lapiService;
+
 	@Override
 	public PersonDeviceRelation get(String id) {
 		// TODO Auto-generated method stub
@@ -41,6 +47,22 @@ public class PersonDeviceRelationServiceImpl implements PersonDeviceRelationServ
 		return personDeviceRelationDAO.update(model);
 	}
 
+	@Override
+	public int updateDevicePerson(PersonDeviceRelation model) throws Exception {
+
+		List<LapiMsgResult> lapiMsgResultList = lapiService.deleteDevicePerson(model.getPersonId(),model.getDeviceId());
+
+		int affectCount = 0;
+
+		if(lapiMsgResultList.size()>0){
+			LapiMsgResult lapiMsgResult = lapiMsgResultList.get(0);
+			if(lapiMsgResult.isSuccess()){
+				affectCount = personDeviceRelationDAO.update(model);
+			}
+		}
+		return affectCount;
+	}
+
 	@Override
 	public int delete(String id) {
 		// TODO Auto-generated method stub

+ 115 - 14
common/src/main/java/com/jpsoft/smart/modules/common/utils/WeixinUtil.java

@@ -1,23 +1,36 @@
 package com.jpsoft.smart.modules.common.utils;
 
+import cn.hutool.core.date.DateTime;
 import com.jpsoft.smart.modules.wechat.entity.AccessToken;
 import com.jpsoft.smart.modules.wechat.vo.UserInfo;
 import net.sf.json.JSONException;
 import net.sf.json.JSONObject;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
 
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import java.io.IOException;
 import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.stream.Collectors;
 
 /**
  * 公众平台通用接口工具类
- * 
+ *
  * @author lt
  * @date 2013-08-09
  */
 public class WeixinUtil {
 	private static Logger log = LoggerFactory.getLogger(WeixinUtil.class);
-	
+
 	// 获取access_token的接口地址(GET) 限200(次/天)
 	public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
 
@@ -35,7 +48,7 @@ public class WeixinUtil {
         result  = code.replace("APPID", appid).replace("REDIRECT_URI",url_encode).replace("SCOPE", scope);
         return result;
     }
-	
+
 	//通过code换取网页授权access_token
 	public static String accessTokenurl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
 	public static AccessToken getAccessToken(String appid, String appsecret,String code) throws Exception {
@@ -50,7 +63,7 @@ public class WeixinUtil {
 				accessToken.setOpenid(json.getString("openid"));
 				accessToken.setScope(json.getString("scope"));
 			} catch (Exception e) {
-				
+
 				// 获取token失败
 				log.error("获取token失败,返回结果result={}", json);
 				if (json.getString("errcode").equals("40163")){
@@ -62,12 +75,12 @@ public class WeixinUtil {
 		}
         return accessToken;
     }
-	
+
 	public static String jsAccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
 	public static String getJsAPI(String accessToken){
 		String formatUrl = jsAccessTokenUrl.replace("ACCESS_TOKEN", accessToken);
         JSONObject json  = HttpConnectionUtil.httpRequest(formatUrl, "GET", null);
-        
+
         if (!json.isNullObject() && !json.isEmpty()) {
 			try {
 				return json.getString("ticket");
@@ -76,13 +89,13 @@ public class WeixinUtil {
 				log.error("获取jsAPI失败,返回结果result={}", json);
 			}
 		}
-        
+
         return null;
 	}
-	
+
 	/**
 	 * 获取access_token
-	 * 
+	 *
 	 * @param appid 凭证
 	 * @param appsecret 密钥
 	 * @return
@@ -107,23 +120,23 @@ public class WeixinUtil {
 		}
 		return accessToken;
 	}
-	
+
 	// 获取用户信息
 	public static String user_info_url = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
 	public static String subscribe_user_info_url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN ";
-	
+
 	public static UserInfo getUserInfo(String openid, String accessToken) {
 		// 拼装url
 		String url = user_info_url.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openid);;
-		
+
 		JSONObject jsonObject = HttpConnectionUtil.httpRequest(url, "GET", null);
-		
+
 		UserInfo userInfo = null;
 		 if (null != jsonObject) {
 				try {
 					userInfo = new UserInfo();
 					userInfo.setOpenid(jsonObject.getString("openid").replaceAll("\"", ""));
-					
+
 					userInfo.setNickname(jsonObject.getString("nickname").replaceAll("\"", ""));
 					userInfo.setCity(jsonObject.getString("city").replaceAll("\"", ""));
 					userInfo.setProvince(jsonObject.getString("province").replaceAll("\"", ""));
@@ -136,4 +149,92 @@ public class WeixinUtil {
 			}
 		return userInfo;
 	}
+
+	public static boolean checkSignature(String token,String signature, String timestamp, String nonce) {
+		String[] arr = new String[] { token, timestamp, nonce };
+
+		String content = Arrays.stream(arr)
+				.sorted(Comparator.naturalOrder())
+				.collect(Collectors.joining());
+
+		MessageDigest md = null;
+		String tmpStr = null;
+
+		try {
+			md = MessageDigest.getInstance("SHA-1");
+			// 将三个参数字符串拼接成一个字符串进行sha1加密
+			byte[] digest = md.digest(content.getBytes("UTF-8"));
+
+			StringBuffer hexstr = new StringBuffer();
+
+			String shaHex = "";
+
+			for (int i = 0; i < digest.length; i++) {
+				shaHex = Integer.toHexString(digest[i] & 0xFF);
+				if (shaHex.length() < 2) {
+					hexstr.append(0);
+				}
+				hexstr.append(shaHex);
+			}
+
+			tmpStr = hexstr.toString();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+
+		// 将sha1加密后的字符串可与signature对比,标识该请求来源于微信
+		return signature.equals(tmpStr);
+	}
+
+	public static cn.hutool.json.JSONObject xmlToJson(ServletInputStream inputStream) throws Exception {
+		cn.hutool.json.JSONObject jsonObject = new cn.hutool.json.JSONObject();
+
+		// 创建sax解析工厂
+		SAXParserFactory factory = SAXParserFactory.newInstance();
+		// 创建sax转换工具
+		SAXParser saxParser = factory.newSAXParser();
+
+		saxParser.parse(inputStream,new DefaultHandler(){
+			private String tagName;
+
+			@Override
+			public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+				tagName = qName;
+			}
+
+			@Override
+			public void endElement(String uri, String localName, String qName) throws SAXException {
+				tagName = null;
+			}
+
+			@Override
+			public void characters(char[] ch, int start, int length) throws SAXException {
+				if(tagName!=null){
+					String content = new String(ch,start,length);
+					jsonObject.put(tagName,content);
+				}
+			}
+		});
+
+		return jsonObject;
+	}
+	public static void replyTextMessage(HttpServletResponse response, String fromUserName, String toUserName, String content){
+		StringBuilder sb = new StringBuilder();
+
+		sb.append("<xml>");
+		sb.append("<ToUserName><![CDATA[" + toUserName + "]]></ToUserName>");
+		sb.append("<FromUserName><![CDATA["+ fromUserName + "]]></FromUserName>");
+		sb.append("<CreateTime>" + DateTime.now().getTime() + "</CreateTime>");
+		sb.append("<MsgType><![CDATA[text]]></MsgType>");
+		sb.append("<Content><![CDATA[" + content + "]]></Content>");
+		sb.append("</xml>");
+
+		try {
+			response.getWriter().print(sb.toString());
+			response.getWriter().close();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
 }

+ 4 - 0
common/src/main/java/com/jpsoft/smart/modules/wechat/dao/ReplyMessageDAO.java

@@ -1,4 +1,5 @@
 package com.jpsoft.smart.modules.wechat.dao;
+import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
 import org.springframework.stereotype.Repository;
@@ -15,4 +16,7 @@ public interface ReplyMessageDAO {
 	int delete(String id);
 	List<ReplyMessage> list();
 	List<ReplyMessage> search(Map<String, Object> searchParams, List<Sort> sortList);
+    ReplyMessage findByEvent(@Param("event")String event);
+
+
 }

+ 1 - 0
common/src/main/java/com/jpsoft/smart/modules/wechat/service/ReplyMessageService.java

@@ -14,4 +14,5 @@ public interface ReplyMessageService {
 	int delete(String id);
 	List<ReplyMessage> list();
 	Page<ReplyMessage> pageSearch(Map<String, Object> searchParams, int pageNum, int pageSize,boolean count, List<Sort> sortList);
+	ReplyMessage findByEvent(String event);
 }

+ 11 - 6
common/src/main/java/com/jpsoft/smart/modules/wechat/service/impl/ReplyMessageServiceImpl.java

@@ -29,14 +29,14 @@ public class ReplyMessageServiceImpl implements ReplyMessageService {
 	public int insert(ReplyMessage model) {
 		// TODO Auto-generated method stub
 		//model.setId(UUID.randomUUID().toString());
-		
+
 		return replyMessageDAO.insert(model);
 	}
 
 	@Override
 	public int update(ReplyMessage model) {
 		// TODO Auto-generated method stub
-		return replyMessageDAO.update(model);		
+		return replyMessageDAO.update(model);
 	}
 
 	@Override
@@ -49,22 +49,27 @@ public class ReplyMessageServiceImpl implements ReplyMessageService {
 	public boolean exist(String id) {
 		// TODO Auto-generated method stub
 		int count = replyMessageDAO.exist(id);
-		
+
 		return count > 0 ? true : false;
 	}
-	
+
 	@Override
 	public List<ReplyMessage> list() {
 		// TODO Auto-generated method stub
 		return replyMessageDAO.list();
 	}
-		
+
 	@Override
 	public Page<ReplyMessage> pageSearch(Map<String, Object> searchParams, int pageNumber, int pageSize,boolean count,List<Sort> sortList) {
         Page<ReplyMessage> page = PageHelper.startPage(pageNumber,pageSize,count).doSelectPage(()->{
             replyMessageDAO.search(searchParams,sortList);
         });
-        
+
         return page;
 	}
+
+	@Override
+	public ReplyMessage findByEvent(String event) {
+		return replyMessageDAO.findByEvent(event);
+	}
 }

+ 19 - 3
common/src/main/resources/mapper/wechat/ReplyMessage.xml

@@ -1,9 +1,17 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <!-- namespace必须指向DAO接口 -->
 <mapper namespace="com.jpsoft.smart.modules.wechat.dao.ReplyMessageDAO">
-	<resultMap id="ReplyMessageMap" type="com.jpsoft.smart.modules.wechat.entity.ReplyMessage">
+    <sql id="Base_Column_List">
+    id_,
+    event_,
+    message_,
+    callback_url,
+    create_time,
+    update_time
+</sql>
+    <resultMap id="ReplyMessageMap" type="com.jpsoft.smart.modules.wechat.entity.ReplyMessage">
 		<id property="id" column="id_" />
 			<result property="event" column="event_" />
 			<result property="message" column="message_" />
@@ -56,7 +64,7 @@
 	where id_=#{id}
 	</update>
 	<select id="get" parameterType="string" resultMap="ReplyMessageMap">
-		select 
+		select
 id_,event_,message_,callback_url,create_time,update_time		from wechat_reply_message where id_=#{0}
 	</select>
 	<select id="exist" parameterType="string" resultType="int">
@@ -78,4 +86,12 @@ id_,event_,message_,callback_url,create_time,update_time		from wechat_reply_mess
 	        ${sort.name} ${sort.order}
 	 	</foreach>
 	</select>
+
+<!--auto generated by MybatisCodeHelper on 2020-03-23-->
+    <select id="findByEvent" resultMap="ReplyMessageMap">
+        select
+        <include refid="Base_Column_List"/>
+        from wechat_reply_message
+        where event_=#{event}
+    </select>
 </mapper>

+ 9 - 4
web/src/main/java/com/jpsoft/smart/modules/base/controller/PersonDeviceRelationController.java

@@ -7,6 +7,8 @@ import com.jpsoft.smart.modules.base.service.DeviceInfoService;
 import com.jpsoft.smart.modules.common.utils.PojoUtils;
 import com.jpsoft.smart.modules.common.dto.Sort;
 import com.jpsoft.smart.modules.common.dto.MessageResult;
+import com.jpsoft.smart.modules.lapi.service.ILapiService;
+import com.jpsoft.smart.modules.lapi.vo.LapiMsgResult;
 import com.jpsoft.smart.modules.sys.entity.User;
 import com.jpsoft.smart.modules.base.entity.PersonDeviceRelation;
 import com.jpsoft.smart.modules.base.service.PersonDeviceRelationService;
@@ -20,6 +22,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
@@ -44,6 +47,9 @@ public class PersonDeviceRelationController {
     @Autowired
     private DataDictionaryService dataDictionaryService;
 
+    @Autowired
+    private ILapiService lapiService;
+
     
     @ApiOperation(value="添加设备和人员绑定")
     @PostMapping("add")
@@ -255,19 +261,18 @@ public class PersonDeviceRelationController {
             personDeviceRelation.setUpdateBy(subject);
             personDeviceRelation.setUpdateTime(new Date());
 
-            int affectCount = personDeviceRelationService.update(personDeviceRelation);
+            int affectCount = personDeviceRelationService.updateDevicePerson(personDeviceRelation);
 
             if (affectCount > 0) {
                 msgResult.setResult(true);
                 msgResult.setData(affectCount);
             } else {
                 msgResult.setResult(false);
-                msgResult.setMessage("删除失败");
+                msgResult.setMessage("数据库更新失败");
             }
         }
         catch(Exception ex){
             logger.error(ex.getMessage(),ex);
-
             msgResult.setResult(false);
             msgResult.setMessage(ex.getMessage());
         }
@@ -290,7 +295,7 @@ public class PersonDeviceRelationController {
                 personDeviceRelation.setUpdateBy(subject);
                 personDeviceRelation.setUpdateTime(new Date());
 
-                affectCount += personDeviceRelationService.update(personDeviceRelation);
+                affectCount = personDeviceRelationService.updateDevicePerson(personDeviceRelation);
             }
 
             if (affectCount > 0) {

+ 19 - 3
web/src/main/java/com/jpsoft/smart/modules/base/controller/WarningPusherController.java

@@ -1,28 +1,41 @@
 package com.jpsoft.smart.modules.base.controller;
 
+import cn.hutool.json.JSONObject;
 import com.github.pagehelper.Page;
 import com.jpsoft.smart.modules.common.utils.PojoUtils;
 import com.jpsoft.smart.modules.common.dto.Sort;
 import com.jpsoft.smart.modules.common.dto.MessageResult;
 import com.jpsoft.smart.modules.base.entity.WarningPusher;
 import com.jpsoft.smart.modules.base.service.WarningPusherService;
+import com.jpsoft.smart.modules.common.utils.WeixinUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.util.EntityUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
+import java.net.URLEncoder;
 import java.text.SimpleDateFormat;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 
 @RestController
 @RequestMapping("/warningPusher")
 @Api(description = "warningPusher")
+@Slf4j
 public class WarningPusherController {
     private Logger logger = LoggerFactory.getLogger(getClass());
 
@@ -41,7 +54,7 @@ public class WarningPusherController {
 
         return msgResult;
     }
-    
+
     @ApiOperation(value="添加信息")
     @PostMapping("add")
     public MessageResult<WarningPusher> add(@RequestBody WarningPusher warningPusher,@RequestAttribute String subject){
@@ -52,7 +65,7 @@ public class WarningPusherController {
             warningPusher.setDelFlag(false);
             warningPusher.setCreateBy(subject);
             warningPusher.setCreateTime(new Date());
-            
+
             int affectCount = warningPusherService.insert(warningPusher);
 
             if (affectCount > 0) {
@@ -107,7 +120,7 @@ public class WarningPusherController {
         try {
             warningPusher.setUpdateBy(subject);
             warningPusher.setUpdateTime(new Date());
-            
+
             int affectCount = warningPusherService.update(warningPusher);
 
             if (affectCount > 0) {
@@ -278,4 +291,7 @@ public class WarningPusherController {
 
         return msgResult;
     }
+
+
+
 }

+ 273 - 0
web/src/main/java/com/jpsoft/smart/modules/wechat/controller/WxController.java

@@ -1,10 +1,13 @@
 package com.jpsoft.smart.modules.wechat.controller;
 
 import com.alibaba.fastjson.JSONObject;
+import com.jpsoft.smart.config.WxConfig;
 import com.jpsoft.smart.modules.base.entity.InformationInfo;
 import com.jpsoft.smart.modules.base.entity.OwnerInfo;
+import com.jpsoft.smart.modules.base.entity.WarningPusher;
 import com.jpsoft.smart.modules.base.service.InformationInfoService;
 import com.jpsoft.smart.modules.base.service.OwnerInfoService;
+import com.jpsoft.smart.modules.base.service.WarningPusherService;
 import com.jpsoft.smart.modules.common.dto.MessageResult;
 import com.jpsoft.smart.modules.common.service.impl.RedisServiceImpl;
 import com.jpsoft.smart.modules.common.utils.ApiUtil;
@@ -16,17 +19,36 @@ import com.jpsoft.smart.modules.common.utils.WeixinUtil;
 import com.jpsoft.smart.modules.pay.properties.WxPayProperties;
 import com.jpsoft.smart.modules.wechat.entity.AccessControl;
 import com.jpsoft.smart.modules.wechat.entity.AccessToken;
+import com.jpsoft.smart.modules.wechat.entity.ReplyMessage;
 import com.jpsoft.smart.modules.wechat.service.IAccessControlService;
+import com.jpsoft.smart.modules.wechat.service.ReplyMessageService;
 import com.jpsoft.smart.modules.wechat.vo.*;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.util.EntityUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.ValueOperations;
 import org.springframework.web.bind.annotation.*;
 
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URLEncoder;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 /**
  * @author 墨鱼_mo
@@ -42,6 +64,18 @@ public class WxController {
     @Autowired
     private ApiUtil apiUtil;
 
+    @Autowired
+    private WxConfig wxConfig;
+
+    @Autowired
+    private WarningPusherService warningPusherService;
+
+    @Autowired
+    private ReplyMessageService replyMessageService;
+
+    @Autowired
+    private ValueOperations<String,Object> valueOperations;
+
     @Autowired
     private RedisServiceImpl redisService;
 
@@ -631,4 +665,243 @@ public class WxController {
         return new MessageResult(result, message, data, code);
     }
 
+    @ApiOperation(value="验证服务器地址的有效性")
+    @GetMapping("/get")
+    @ResponseBody
+    public String index(@RequestParam(defaultValue = "") String signature,
+                        @RequestParam(defaultValue = "") String timestamp,
+                        @RequestParam(defaultValue = "") String nonce,
+                        @RequestParam(defaultValue = "") String echostr){
+        log.warn("signature=" + signature);
+        log.warn("timestamp=" + timestamp);
+        log.warn("nonce=" + nonce);
+        log.warn("echostr=" + echostr);
+
+        if (WeixinUtil.checkSignature(wxConfig.getToken(),signature,timestamp,nonce)){
+            return echostr;
+        }
+        else{
+            return "index";
+        }
+    }
+
+
+    @ResponseBody
+    @ApiOperation(value = "创建二维码")
+    @PostMapping("/qrcode/create")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name="expire_seconds", paramType="query", required=true, value="该二维码有效时间,以秒为单位。 最大不超过2592000(即30天),此字段如果不填,则默认有效期为30秒。"),
+            @ApiImplicitParam(name="action_name", paramType="query", required=true, value="二维码类型,QR_SCENE为临时的整型参数值,QR_STR_SCENE为临时的字符串参数值,QR_LIMIT_SCENE为永久的整型参数值,QR_LIMIT_STR_SCENE为永久的字符串参数值"),
+            @ApiImplicitParam(name="scene_id", paramType="query", value="场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000(目前参数只支持1--100000)"),
+            @ApiImplicitParam(name="scene_str", paramType="query", value="场景值ID(字符串形式的ID),字符串类型,长度限制为1到64")
+    })
+    public cn.hutool.json.JSONObject createQrcode(@RequestParam(name = "expire_seconds",defaultValue = "300") long expireSeconds,
+                                                  @RequestParam(name = "action_name",defaultValue = "QR_STR_SCENE") String actionName,
+                                                  @RequestParam(name = "scene_id",required = false) String sceneId,
+                                                  @RequestParam(name = "scene_str",required = false) String sceneStr){
+        cn.hutool.json.JSONObject resultObj = new cn.hutool.json.JSONObject();
+
+        try {
+            StringBuilder urlBuilder = new StringBuilder();
+            AccessToken accessToken = WeixinUtil.getAccessToken(wxConfig.getAppId(),wxConfig.getAppSecret());
+
+            urlBuilder.append(wxConfig.getCreateQrCodeUrl())
+                    .append("?access_token=")
+                    .append(URLEncoder.encode(accessToken.getToken(),"UTF-8"));
+
+            cn.hutool.json.JSONObject jsonObject = new cn.hutool.json.JSONObject();
+            jsonObject.put("expire_seconds", expireSeconds);
+            jsonObject.put("action_name", actionName);
+
+            cn.hutool.json.JSONObject actionInfo = new cn.hutool.json.JSONObject();
+            cn.hutool.json.JSONObject scene = new cn.hutool.json.JSONObject();
+
+            StringBuilder keyBuilder = new StringBuilder();
+
+            keyBuilder.append(accessToken);
+
+            if(StringUtils.isNotEmpty(sceneId)) {
+                scene.put("scene_id", sceneId);
+                keyBuilder.append(sceneId);
+            }
+
+            if(StringUtils.isNotEmpty(sceneStr)) {
+                scene.put("scene_str", sceneStr);
+                keyBuilder.append(sceneStr);
+            }
+
+            String qrcodeUrl = (String)valueOperations.get("QRCODE_" + keyBuilder.toString());
+
+            if (StringUtils.isNotEmpty(qrcodeUrl)){
+                resultObj.put("data",qrcodeUrl);
+                resultObj.put("result", true);
+            }
+            else{
+                actionInfo.put("scene",scene);
+
+                jsonObject.put("action_info", actionInfo);
+
+                StringEntity entity = new StringEntity(jsonObject.toString(), "utf-8");
+
+                entity.setContentType("application/json");//发送json数据需要设置contentType
+
+                HttpPost httpPost = new HttpPost(urlBuilder.toString());
+                CloseableHttpClient httpClient = HttpClientBuilder.create().build();
+
+                httpPost.setEntity(entity);
+
+                HttpResponse res = httpClient.execute(httpPost);
+
+                if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
+                    String content = EntityUtils.toString(res.getEntity());// 返回json格式:
+                    cn.hutool.json.JSONObject ret = new cn.hutool.json.JSONObject(content);
+
+                    if (ret.containsKey("errcode")) {
+                        resultObj.put("result", false);
+                        resultObj.put("message", ret.getStr("errmsg"));
+                        resultObj.put("code", ret.getInt("errcode"));
+                    } else {
+                        String ticket = ret.getStr("ticket");
+                        long expire_seconds = ret.getLong("expire_seconds");
+
+                        qrcodeUrl = wxConfig.getShowQrCodeUrl() + "?ticket=" + URLEncoder.encode(ticket, "UTF-8");
+
+                        valueOperations.set("QRCODE_" + keyBuilder, qrcodeUrl, expire_seconds - 5, TimeUnit.SECONDS);
+
+                        resultObj.put("data", qrcodeUrl);
+                        resultObj.put("result", true);
+                    }
+                }
+                else{
+                    resultObj.put("result", false);
+                    resultObj.put("message", "weixin服务器未正常返回!");
+                }
+            }
+        }
+        catch (Exception ex){
+            log.error(ex.getMessage(),ex);
+
+            resultObj.put("message",ex.getMessage());
+            resultObj.put("result",false);
+        }
+
+        return resultObj;
+    }
+
+    @ApiOperation(value = "处理消息事件")
+    @PostMapping("/get")
+    public void processEvent(HttpServletRequest request, HttpServletResponse response){
+        try{
+            log.warn("收到post请求");
+
+            cn.hutool.json.JSONObject requestJson = null;
+
+            if("json".equals(wxConfig.getContentType())){
+                String jsonStr = new BufferedReader(new InputStreamReader(request.getInputStream()))
+                        .lines().parallel().collect(Collectors.joining(System.lineSeparator()));
+
+                requestJson = new cn.hutool.json.JSONObject(jsonStr);
+            }
+            else {
+                requestJson = WeixinUtil.xmlToJson(request.getInputStream());
+            }
+
+            log.warn(requestJson.toString());
+
+            response.setContentType("UTF-8");
+            response.setContentType("text/html; charset=UTF-8");
+            response.setCharacterEncoding("UTF-8");
+
+            String event = requestJson.getStr("Event");
+            String eventKey = requestJson.getStr("EventKey");
+
+            /*
+            正常扫码是:"EventKey":"7000,2142006";
+            当未关注时,扫码是"EventKey":"qrscene_7000,2142006"
+            */
+            if(StringUtils.isNotEmpty(eventKey) && eventKey.indexOf("_")!=-1){
+                String[] arr = eventKey.split("_");
+
+                if(arr.length>0){
+                    eventKey = arr[1];
+                }
+            }
+
+            //微信公众号编号
+            String wechatId = requestJson.getStr("ToUserName");
+            //扫码用户openID
+            String openId = requestJson.getStr("FromUserName");
+
+
+            boolean processed = false;
+
+            if (StringUtils.isNotEmpty(eventKey) && eventKey.indexOf(",")!=-1) {
+                String[] keys = eventKey.split(",");
+                String eventCode = keys[0];
+                String id = keys[1];
+
+                ReplyMessage replyMessage = replyMessageService.findByEvent(eventCode);
+
+                if (replyMessage != null) {
+                    WarningPusher warningPusher = warningPusherService.get(id);
+                    if (warningPusher == null){
+                        WeixinUtil.replyTextMessage(response, wechatId, openId,"绑定信息不存在,请联系管理员");
+                    }
+                    else if (StringUtils.isNotBlank(warningPusher.getOpenId())){
+                        WeixinUtil.replyTextMessage(response, wechatId, openId,"此二维码已被绑定,请联系管理员");
+                    }else {
+                        warningPusher.setOpenId(openId);
+                        warningPusher.setUpdateTime(new Date());
+                        warningPusherService.update(warningPusher);
+                        WeixinUtil.replyTextMessage(response, wechatId, openId,replyMessage.getMessage());
+                    }
+
+
+
+                    processed = true;
+                }
+            }
+            //开发者在5秒内未回复任何内容
+//                for (EventCallback callback : callbackList) {
+//                    if (StringUtils.isNotEmpty(eventKey) && eventKey.startsWith(callback.getCode())) {
+//                        callback.process(wechatId, openId, eventKey);
+//
+//                        WeixinUtil.replyTextMessage(response, wechatId, openId, callback.getMessage());
+//
+//                        processed = true;
+//                        break;
+//                    }
+//                }
+//            }
+
+            if(!processed) {
+                String responseText = "success";
+
+                if("subscribe".equals(event)){
+                   /* ReplyMessage replyMessage = replyMessageService.findByEvent(wechatId,event);
+
+                    if(replyMessage!=null) {
+                        WeixinUtil.replyTextMessage(response, wechatId, openId, replyMessage.getMessage());
+                    }
+                    else{
+                        log.warn(openId + ",事件:" + event + "未设置自动回复!");
+                        response.getWriter().print(responseText);
+                    }*/
+                }
+                else {
+                    response.getWriter().print(responseText);
+                }
+            }
+        }
+        catch (Exception ex){
+            log.error(ex.getMessage(),ex);
+
+            try {
+                response.getWriter().print("fail");
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
 }

+ 8 - 3
web/src/main/resources/application-test.yml

@@ -5,9 +5,9 @@ server:
 
 spring:
   datasource:
-    url: jdbc:log4jdbc:mysql://192.168.33.20:3306/smart-community?autoReconnect=true&characterEncoding=utf8&serverTimezone=GMT%2B8
+    url: jdbc:log4jdbc:mysql://101.37.31.116:3306/smart-community?autoReconnect=true&characterEncoding=utf8&serverTimezone=GMT%2B8
     username: root
-    password: jpsoft2016
+    password: slgo^Root_!Q@W#E)P(O*I
   devtools:
     restart:
       enabled: true
@@ -28,4 +28,9 @@ springfox:
 wx:
   pay:
     appId: wx7e70eb62a8459869
-    appSecret: 909d17e353268da57c4f18cc09798049
+    appSecret: 909d17e353268da57c4f18cc09798049
+    token: weixin
+    tokenUrl: "https://api.weixin.qq.com/cgi-bin/token"
+    refreshOAuth2TokenUrl: "https://api.weixin.qq.com/sns/oauth2/refresh_token"
+    createQrCodeUrl: "https://api.weixin.qq.com/cgi-bin/qrcode/create"
+    showQrCodeUrl: "https://mp.weixin.qq.com/cgi-bin/showqrcode"