微信公众平台,监听用户输入及事件
微信消息类
/** * */ package com.xianquan.wx.model; import java.io.Serializable; import java.util.Date; import com.thoughtworks.xstream.annotations.XStreamOmitField; /** * @ClassName: Message * @Description: 微信收到的消息 * @author coil * @date 2020年1月10日 下午4:13:20 * */ @Data public class WechatMessage implements Serializable{ private static final long serialVersionUID = 1L; public static final String TEXT = "text"; public static final String IMAGE = "image"; public static final String LOCATION = "location"; public static final String LINK = "link"; public static final String EVENT = "event"; @XStreamOmitField private Integer id;//数据库存储的id // 开发者微信号 private String toUserName; // 发送方帐号(一个OpenID) private String fromUserName; // 消息创建时间 private Date createTime; // 消息类型(text/image/location/link) private String msgType; // 消息id,64位整型 private String msgId; // 消息内容 (文本消息专有) private String content; //图片链接 (图片消息专有) private String picUrl; // 消息标题 (链接消息专有) private String title; // 消息描述 (链接消息专有) private String description; // 消息链接 (链接消息专有) private String url; //地理位置纬度 Location_X(地理位置专有) private String locationX; //地理位置经度 Location_Y(地理位置专有) private String locationY; // 地图缩放大小 (地理位置专有) private String scale; // 地理位置信息 (地理位置专有) private String label; //事件类型,subscribe(订阅)、unsubscribe(取消订阅)、CLICK(自定义菜单点击事件) (事件推送专有) private String event; //事件KEY值,与自定义菜单接口中KEY值对应(事件推送专有) private String eventKey; //头像 private String headImgUrl; //标记图片的ID private String mediaId; //用户名称 private String userName; //用户昵称 private String remark; }
天气查询工具类
package com.xianquan.wx.weixin.sdk.weather; import com.xianquan.wx.weixin.sdk.propertie.WeixinGlobal; import com.google.gson.Gson; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; /** * @ClassName: PM25 * @Description: TODO * @author coil * @date 2020年1月14日 下午6:24:29 * */ public class PM25 { /**获取pm2.5的返回字符串*/ public static String getPM25Data(String city){ String result = ""; city = HanyuPinyinUtil.toHanyuPinyin(city); StringBuffer buf = new StringBuffer(); buf.append("city="); buf.append(city); buf.append("&token="); buf.append(WeixinGlobal.PM25_TOKEN); buf.append("&stations=no"); String param = buf.toString(); String urlName = WeixinGlobal.PM25_API + param; URL realUrl; try { realUrl = new URL(urlName); // 打开和URL之间的连接 URLConnection conn = realUrl.openConnection(); conn.setDoInput(true); BufferedReader br = new BufferedReader(new InputStreamReader( conn.getInputStream(),"UTF-8")); String line = br.readLine(); while (line != null) { result += line; line = br.readLine(); } br.close(); } catch (Exception e) { e.printStackTrace(); } return result; } /**解析返回数据类型*/ public static Object analysisPMData(String strPM){ Gson gson = new Gson(); if(strPM.contains("error")){ PM25Error error = gson.fromJson(strPM, PM25Error.class); return error; }else{ strPM = strPM.replace("[", "").replace("]", ""); PM25Result pm25Result = gson.fromJson(strPM,PM25Result.class); return pm25Result; } } }
监听用户对微信服务号的操作
1 package com.xianquan.wx.web.controller; 2 3 import com.xianquan.wx.model.*; 4 import com.xianquan.wx.weixin.sdk.message.Image; 5 import com.xianquan.wx.weixin.sdk.message.ImageMessage; 6 import com.xianquan.wx.weixin.sdk.model.reply.TextMessage; 7 import com.xianquan.wx.weixin.sdk.propertie.WeixinGlobal; 8 import com.xianquan.wx.weixin.sdk.util.AccessTokenUtil; 9 import com.xianquan.wx.weixin.sdk.util.MessageUtil; 10 import com.xianquan.wx.weixin.sdk.util.WeixinUtil; 11 import com.xianquan.wx.weixin.sdk.weather.*; 12 import org.springframework.beans.factory.annotation.Autowired; 13 import org.springframework.stereotype.Controller; 14 import org.springframework.web.bind.annotation.RequestMapping; 15 import org.springframework.web.bind.annotation.RequestMethod; 16 import org.springframework.web.bind.annotation.ResponseBody; 17 import org.springframework.web.servlet.mvc.support.RedirectAttributes; 18 19 import javax.annotation.Resource; 20 import javax.servlet.http.HttpServletRequest; 21 import java.util.Date; 22 import java.util.List; 23 import java.util.Map; 24 25 26 @Controller() 27 public class WeixinController { 28 29 public static int pagesize = 10; 30 31 32 //接收微信公众号接收的消息,处理后再做相应的回复 33 @RequestMapping(value="/weixin",method=RequestMethod.POST,produces="text/html;charset=UTF-8") 34 @ResponseBody 35 public String replyMessage(HttpServletRequest request, RedirectAttributes attr){ 36 //仅处理微信服务端发的请求 37 if (checkWeixinReques(request)) { 38 Date date = new Date(); 39 Map<String, String> requestMap = WeixinUtil.parseXml(request); 40 Message message = WeixinUtil.mapToMessage(requestMap); 41 WechatMessage wechatMessage = WeixinUtil.mapToWechatMessage(requestMap); 42 wechatMessage.setCreateTime(date); 43 String type = message.getMsgType(); 44 String openId = message.getFromUserName(); 45 String msg = ""; 46 WechatUser user = null; 47 String msgType = requestMap.get("MsgType"); 48 if(type != WechatMessage.EVENT){ 49 /** 50 * 保存接受消息到数据库 51 */ 52 } 53 if(type.equals(WechatMessage.EVENT)){ 54 String eventType = requestMap.get("Event"); 55 String accessToken = AccessTokenUtil.queryAccessToken(); 56 if(wechatMessage.getEvent().equals("unsubscribe")){//取消关注公众号事件监听 57 /** 58 * 59 */ 60 } 61 if(wechatMessage.getEvent().equals("subscribe")){//关注公众号事件监听 62 /** 63 * 64 */ 65 } 66 // 自定义菜单点击事件 67 else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) { 68 WechatUser wechatUser = wechatUserService.getByOpenId(openId); 69 String remark = wechatUser.getRemark(); 70 String studentName = wechatUser.getStudentName(); 71 Integer studentId = wechatUser.getStudentId(); 72 // 事件KEY值,与创建自定义菜单时指定的KEY值对应 73 TextMessage textMessage = new TextMessage(); 74 textMessage.setMsgType(Message.TEXT); 75 textMessage.setCreateTime(date.getTime()); 76 textMessage.setFromUserName(message.getToUserName()); 77 textMessage.setToUserName(message.getFromUserName()); 78 String eventKey = requestMap.get("EventKey"); 79 String respContent = "请求处理异常,请稍候尝试!"; 80 if (eventKey.equals("11")) { 81 82 }else if (eventKey.equals("14")) { 83 respContent = "14菜单项被点击,功能开发中!"; 84 } else if (eventKey.equals("21")) { 85 respContent = "21菜单项被点击,功能开发中!"; 86 } else if (eventKey.equals("32")) { 87 respContent = "32菜单项被点击!"; 88 } else if (eventKey.equals("33")) { 89 respContent = "33菜单项被点击!"; 90 } 91 textMessage.setContent("您好,"+user.getName()+" 我的微信平台通知您:"+ respContent 92 ); 93 msg = MessageUtil.textMessageToXml(textMessage); 94 return msg; 95 } 96 } 97 if (type.equals(Message.TEXT)) {//仅处理文本回复内容 98 String content = message.getContent();//消息内容 99 TextMessage textMessage = new TextMessage(); 100 textMessage.setFromUserName(message.getToUserName()); 101 textMessage.setToUserName(message.getFromUserName()); 102 textMessage.setMsgType(Message.TEXT); 103 textMessage.setCreateTime(date.getTime()); 104 if(validateWechatContent(content)){ 105 String unbundling = null; 106 String idCard = content.split("\+")[0]; 107 String remark = content.split("\+")[1]; 108 if( content.split("\+").length == 3){ 109 unbundling = content.split("\+")[2]; 110 } 111 }else if(content.endsWith("天气")){ 112 String keyWord = content.replaceAll("天气", "").trim(); 113 String weather = BaiduWeather.getSend(keyWord); 114 textMessage.setContent("您好,"+user.getName()+" 我的微信平台通知您: 【"+keyWord+"】"+weather); 115 }else if(content.endsWith("空气质量")){ 116 String city = content.replaceAll("空气质量", "").trim(); 117 String strPM = PM25.getPM25Data(city); 118 Object param = PM25.analysisPMData(strPM); 119 if(param instanceof PM25Result){ 120 textMessage.setContent("您好,"+user.getName()+" 我的微信平台通知您: "+((PM25Result) param).getArea()+ 121 "今日空气质量指数(AQI):"+((PM25Result) param).getAqi()+ 122 " 空气质量指数类别:"+((PM25Result) param).getQuality()+ 123 " 首要污染物:"+((PM25Result) param).getPrimary_pollutant()+ 124 " pm2_5:"+((PM25Result) param).getPm2_5()+ 125 " pm2_5_24h:"+((PM25Result) param).getPm2_5_24h()); 126 }else if(param instanceof PM25Error){ 127 textMessage.setContent("您好,"+user.getName()+" 我的微信平台通知您: "+((PM25Error) param).getError()); 128 } 129 130 }else{ 131 textMessage.setContent("您好,"+user.getName()+" 我的微信平台通知您: 不能识别您发出的指令!"); 132 133 } 134 msg = MessageUtil.textMessageToXml(textMessage); 135 return msg; 136 }else if(type.equals(Message.IMAGE)){ 137 ImageMessage imageMessage = new ImageMessage(); 138 imageMessage.setToUserName(message.getFromUserName()); 139 imageMessage.setFromUserName(message.getToUserName()); 140 imageMessage.setCreateTime(date.getTime()); 141 imageMessage.setMsgType(Message.IMAGE); 142 Image image = new Image(); 143 image.setMediaId(message.getMediaId()); 144 imageMessage.setImage(image); 145 msg = MessageUtil.imageMessageToXml(imageMessage); 146 return msg; 147 }else if(type.equals(Message.LOCATION)){ 148 TextMessage textMessage = new TextMessage(); 149 textMessage.setFromUserName(message.getToUserName()); 150 textMessage.setToUserName(message.getFromUserName()); 151 textMessage.setMsgType(Message.TEXT); 152 textMessage.setCreateTime(date.getTime()); 153 textMessage.setContent("您好,"+user.getName()+" 我的微信平台通知您: 您发送的是位置, 纬度为:"+message.getLocationX()+ 154 "; 经度为:"+message.getLocationY()+"; 位置为:"+message.getLabel()+"."); 155 msg = MessageUtil.textMessageToXml(textMessage); 156 return msg; 157 } 158 159 } 160 return Reply.WELCOME_CONTENT; 161 } 162 163 164 //微信公众平台验证url是否有效使用的接口 165 @RequestMapping(value="/weixin",method=RequestMethod.GET,produces="text/html;charset=UTF-8") 166 @ResponseBody 167 public String initWeixinURL(HttpServletRequest request){ 168 String echostr = request.getParameter("echostr"); 169 if (checkWeixinReques(request) && echostr != null) { 170 System.out.println(echostr); 171 return echostr; 172 }else{ 173 return "error"; 174 } 175 } 176 177 178 /** 179 * 根据token计算signature验证是否为weixin服务端发送的消息 180 */ 181 private static boolean checkWeixinReques(HttpServletRequest request){ 182 String signature = request.getParameter("signature"); 183 String timestamp = request.getParameter("timestamp"); 184 String nonce = request.getParameter("nonce"); 185 if (signature != null && timestamp != null && nonce != null ) { 186 String[] strSet = new String[] { WeixinGlobal.TOKEN, timestamp, nonce }; 187 java.util.Arrays.sort(strSet); 188 String key = ""; 189 for (String string : strSet) { 190 key = key + string; 191 } 192 String pwd = WeixinUtil.sha1(key); 193 return pwd.equals(signature); 194 }else { 195 return false; 196 } 197 } 198 199 /** 200 * @Title: validateWechatContent 201 * @Description: 验证用户通过微信发送来的文本消息是否匹配格式 202 * @param content 203 * @return 204 */ 205 private boolean validateWechatContent(String content){ 206 if(content.contains("+") && content.split("\+").length == 2 ||content.split("\+").length == 3){ 207 String str[] = content.split("\+"); 208 if(IdCardUtil.is18ByteIdCardComplex(str[0])){ 209 return true; 210 } 211 return false; 212 } 213 return false; 214 } 215 }