从零开发微信公众号系列 【三】接收和自动回复消息
如果微信官方文档已能为您提供帮助,请忽略本文。
WechatController.java
package com.blacklist.cotroller; import java.io.IOException; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Scope; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import com.blacklist.enums.WechatType; import com.blacklist.server.WechatService; @RestController @SpringBootApplication @RequestMapping("/wechat") @Scope("prototype") public class WechatController { @Autowired private WechatService wechatService; @RequestMapping(method = { RequestMethod.POST, RequestMethod.GET }, produces = "text/html;charset=UTF-8") @ResponseBody public void index(HttpServletRequest request, HttpServletResponse response) throws IOException { request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); boolean isGet = request.getMethod().toLowerCase().equals("get"); if (isGet) {// 接入指引 String signature = request.getParameter("signature"); String timestamp = request.getParameter("timestamp"); String nonce = request.getParameter("nonce"); String echostr = request.getParameter("echostr"); if (wechatService.validate(signature, timestamp, nonce)) { response.getWriter().write(echostr); } } else {// 接收用户消息 Map<String, String> reqMap = wechatService.parseReq(request); if ("text".equalsIgnoreCase(reqMap.get("MsgType"))) { String input = wechatService.buildResponse(reqMap, WechatType.TEXT); response.getWriter().write(input); } else if("event".equalsIgnoreCase(reqMap.get("MsgType")) && "subscribe".equalsIgnoreCase(reqMap.get("Event"))){ String input = wechatService.buildResponse(reqMap, WechatType.EVENT); response.getWriter().write(input); }else { String input = wechatService.buildResponse(reqMap, WechatType.IMAGE); response.getWriter().write(input); } } } }
WechatService.java
package com.blacklist.server;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.blacklist.config.WechatConfig;
import com.blacklist.domain.Topic;
import com.blacklist.domain.enums.TopicEnum;
import com.blacklist.enums.WechatType;
import com.blacklist.utils.FreemarkerUtils;
import com.blacklist.utils.LuceneIKUtil;
import com.blacklist.utils.SHA1;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
@Service
public class WechatService {
private static Logger log = LoggerFactory.getLogger(WechatService.class);
public String getToken() throws IOException {
if ((System.currentTimeMillis() / 1000 - WechatConfig.expiresTime) > 7000) {
String pathUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="
+ WechatConfig.appid
+ "&secret="
+ WechatConfig.secret;
URL url = new URL(pathUrl);
HttpURLConnection httpConn = (HttpURLConnection) url
.openConnection();
httpConn.setDoOutput(true);// 使用 URL 连接进行输出
httpConn.setDoInput(true);// 使用 URL 连接进行输入
httpConn.setUseCaches(false);// 忽略缓存
httpConn.setRequestMethod("GET");// 设置URL请求方法
httpConn.setRequestProperty("Accept", "*/*"); // 设置接收数据的格式
httpConn.connect();
int length = (int) httpConn.getContentLength();// 获取长度
InputStream is = httpConn.getInputStream();
if (length != -1) {
byte[] data = new byte[length];
byte[] temp = new byte[512];
int readLen = 0;
int destPos = 0;
while ((readLen = is.read(temp)) > 0) {
System.arraycopy(temp, 0, data, destPos, readLen);
destPos += readLen;
}
String result = new String(data, "UTF-8");
JsonObject json = new JsonParser().parse(result)
.getAsJsonObject();
WechatConfig.token = json.get("access_token")
.getAsString();
WechatConfig.expiresTime = System.currentTimeMillis() / 1000;
}
}
System.out.println("wechat access token is:" + WechatConfig.token);
return WechatConfig.token;
}
public boolean validate(String signature, String timestamp, String nonce) {
List<String> list = new ArrayList<String>();
list.add(timestamp);
list.add(nonce);
list.add(WechatConfig.token);
Collections.sort(list);
String temp = String.join("", list);
if (signature.equals(SHA1.str2SHA1(temp))) {
return true;
}
return false;
}
public Map<String, String> parseReq(HttpServletRequest request) {
Map<String, String> resultMap = new HashMap<String, String>();
try {
InputStream inputStream = request.getInputStream();
SAXReader reader = new SAXReader();
Document document = reader.read(inputStream);
Element root = document.getRootElement();
@SuppressWarnings("unchecked")
List<Element> elementList = root.elements();
for (Element e : elementList) {
resultMap.put(e.getName(), cut(e.getText()));
}
inputStream.close();
inputStream = null;
} catch (IOException | DocumentException e1) {
log.error("wechat parseReq error:{}", e1.getMessage());
e1.printStackTrace();
}
return resultMap;
}
public boolean validate() {
return false;
}
private String cut(String str) {
return str.replace("<![CDATA[", "").replace("]]>", "");
}
private String baseTextResponse(Map<String, String> map) {
StringBuffer sb = new StringBuffer();
sb.append("<xml>");
sb.append("<ToUserName><![CDATA[" + map.get("FromUserName")
+ "]]></ToUserName>");
sb.append("<FromUserName><![CDATA[" + map.get("ToUserName")
+ "]]></FromUserName>");
sb.append("<CreateTime>" + System.currentTimeMillis() / 1000
+ "</CreateTime>");
sb.append("<MsgType><![CDATA[text]]></MsgType>");
sb.append("<Content><![CDATA[###MSG###]]></Content>");
sb.append("</xml>");
return sb.toString();
}
private String buildNotSupportResponse(Map<String, String> map) {
return baseTextResponse(map).replace("###MSG###", "不支持的消息!");
}
private String buildWelcome(Map<String, String> map) {
return baseTextResponse(map).replace("###MSG###", "然而,你并不知道怎么玩");
}
private String buildError(Map<String, String> map, String err) {
return baseTextResponse(map).replace("###MSG###", err);
}
private String buildResponse(Map<String, String> map) {
String content = map.get("Content");
if(WechatConfig.autoUser.equalsIgnoreCase(map.get("FromUserName"))) {
return baseTextResponse(map).replace("###MSG###", "hello,"+content);
} else {
log.info("from user is:{}", map.get("FromUserName"));
return buildNotSupportResponse(map);
}
}
public String buildResponse(Map<String, String> map,
WechatType type) {
switch (type) {
case TEXT:
return buildResponse(map);
case EVENT:
return buildWelcome(map);
default:
return buildNotSupportResponse(map);
}
}
}
SHA1.java见上一篇
附请求参数:
响应参数:
转载请注明来源【IT黑名单】