1.www.baidu.com搜索:微信公众平台登录,输入账号密码进行登录
![](https://i-blog.csdnimg.cn/blog_migrate/5a750e7a020c8f1744bb4ffebef56428.png)
public class WeiXinServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doGet");
//验证服务器地址有效性,接受4个参数
String signature = req.getParameter("signature");//微信加密签名
String timestamp = req.getParameter("timestamp");//时间戳
String nonce = req.getParameter("nonce");//随机数
String echostr = req.getParameter("echostr");//随机字符串
PrintWriter out = resp.getWriter();
//校验的流程:
//1将token,timestamp,nonce进行字典序排序
//2将3个字符串拼接在一起进行shal加密处理
//3开发者获得加密后的字符串可与signature进行对比,标识该请求来源于微信
if (CheckUtil.checkSignature(signature, timestamp, nonce)) {
out.print(echostr);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
}
添加校验工具类
public class CheckUtil {
private static final String token = "tom";//定义一个接入的token令牌,可以由开发者随意填写
public static boolean checkSignature(String signature, String timestamp, String nonce) {
String[] arr = new String[]{token, timestamp, nonce};
Arrays.sort(arr);
StringBuffer content = new StringBuffer();
for (int i = 0; i < arr.length; i++) {
content.append(arr[i]);
}
String temp = getSha1(content.toString());
return temp.equals(signature);
}
//Sha1加密
public static String getSha1(String str) {
if (str == null || str.length() == 0) {
return null;
}
char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
try {
MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
mdTemp.update(str.getBytes("UTF-8"));
byte[] md = mdTemp.digest();
int j = md.length;
char buf[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
buf[k++] = hexDigits[byte0 & 0xf];
}
return new String(buf);
} catch (Exception e) {
// TODO Auto-generated catch block
return null;
}
}
}
4.配置web.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>WeiXinTest</display-name>
<servlet>
<!-- 设置Servlet,servlet-class是你创建的 servlet类的全路径,注意修改-->
<servlet-name>WeiXinServlet</servlet-name>
<servlet-class>com.dp.servlet.WeiXinServlet</servlet-class>
</servlet>
<servlet-mapping>
<!-- 设置拦截访问路径 -->
<servlet-name>WeiXinServlet</servlet-name>
<url-pattern>/wx.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
5.打开ngrok内网映射工具,配置微信公众号相关配置(我的是在D盘) cmd:d: cd ngrok ngrok http 8080
把这个网址配置到个人申请的微信公众平台url
注意:提交之前确保你的项目在Tomcat中已经启动,连接成功后后台出现doGet:
6.实现文本消息的响应,这里微信接入是doGet方式,回复消息是doPost方式回应,返回的是一个XML格式的数据,这里需要先写个工具类,把xml转成集合类,同样请求的时候需要把文本转换为XML,如下(需要的架包放链接里面):
/**
* xmlToMap
* @param request
* @return
* @throws IOException
* @throws DocumentException
*/
public static Map<String, String> xmlToMap(HttpServletRequest request) throws IOException, DocumentException{
Map<String, String> map = new HashMap<String, String>();
SAXReader reader = new SAXReader();
InputStream ins = request.getInputStream();
Document doc = reader.read(ins);
Element root = doc.getRootElement();
List<Element> list = root.elements();
for (Element e : list) {
map.put(e.getName(), e.getText());
}
ins.close();
return map;
}
/**
* textMessageToXml
* @param textMessage
* @return
*/
//TextMessage 为后面创建的文本消息实体类
public static String textMessageToXml(TextMessage textMessage){
XStream xstream = new XStream();
xstream.alias("xml", textMessage.getClass());
return xstream.toXML(textMessage);
}
注意看一下文本消息响应的XML文件的格式,我们根据这个格式编写一个实体Bean:
这里为了我们后面开发写重复的代码,把公用的实体类我们提取出来,先写一个公用的实体Bean CommMessage(消息父类):
public class CommMessage {
private String ToUserName;
private String FromUserName;
private long CreateTime;
private String MsgType;
set get方法略。。。。
}
在编写我们实现文本消息的实体Bean
public class TextMessage extends CommMessage {
private String Content;//文本消息内容
private String MsgId;//消息ID
set get方法略。。。。
}
7.实现文本消息回应,在servlet中doPost方法去实现,在这之前,我们先去写一个工具类,方便我们后面开发,消息分为文本,图片,视频,声音。。。
public class MessageUtil {
public static final String MESSAGE_TEXT = "text";//文本消息
public static final String MESSAGE_IMAGE = "image";//图片消息
public static final String MESSAGE_VOICE = "voice";//语音消息
public static final String MESSAGE_MUSIC = "music";//音乐消息
public static final String MESSAGE_VIDEO = "video";//视频消息
public static final String MESSAGE_LINK = "link";//链接消息
public static final String MESSAGE_LOCATION = "location";//地理位置消息
public static final String MESSAGE_EVENT = "event";//事件推送消息
public static final String MESSAGE_SUBSCRIBE = "subscribe";//关注
public static final String MESSAGE_UNSUBSCRIBE = "unsubscribe";//取消关注
public static final String MESSAGE_CLICK = "CLICK";//菜单点击
public static final String MESSAGE_VIEW = "VIEW";//菜单点击
//文本消息推送方法
public static String initText(String toUserName,String fromUserName,String content){
TextMessage text = new TextMessage();
text.setFromUserName(toUserName);
text.setToUserName(fromUserName);
text.setMsgType(MessageUtil.MESSAGE_TEXT);
text.setCreateTime(new Date().getTime());
text.setContent(content);
return textMessageToXml(text);
}
//回复文本消息内容
public static String firstMenu(){
StringBuffer sb = new StringBuffer();
sb.append("您好!这是我第一次做文本消息回复!恭喜您成功了!");
return sb.toString();
}
//关注公众号回复消息
public static String menuText(){
StringBuffer sb = new StringBuffer();
sb.append("欢迎您的关注,请按照菜单提示进行操作 : \n");
sb.append("1、感謝您的使用!\n");
sb.append("2、调出此菜单\n");
sb.append("回复?调出此菜单。");
return sb.toString();
}
}
下面代码为servlet类doPost方法实现(这里我们设置用户回复1,给用户推送文本消息):
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doPost");
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
PrintWriter out = resp.getWriter();
try {
Map<String, String> map = MessageUtil.xmlToMap(req);
String toUserName = map.get("ToUserName");
String fromUserName = map.get("FromUserName");
String msgType = map.get("MsgType");
String content = map.get("Content");
String message = null;
if (MessageUtil.MESSAGE_TEXT.equals(msgType)) {
if ("1".equals(content)) {
message = MessageUtil.initText(toUserName, fromUserName, MessageUtil.firstMenu());
} else if ("2".equals(content)) {
message = MessageUtil.initText(toUserName, fromUserName, MessageUtil.menuText());
} else if ("?".equals(content) || "?".equals(content)) {
message = MessageUtil.initText(toUserName, fromUserName, MessageUtil.menuText());
} else {
message = "";
}
// 添加关注公众号推送事件
} else if (MessageUtil.MESSAGE_EVENT.equals(msgType)) {
// 判断消息推送事件
String eventType = map.get("Event");
if (MessageUtil.MESSAGE_SUBSCRIBE.equals(eventType)) {
message = MessageUtil.initText(toUserName, fromUserName, MessageUtil.menuText());
}
}
out.print(message);
} catch (DocumentException e) {
e.printStackTrace();
} finally {
out.close();
}
}
}
8.测试文本消息的回复效果,以及用户关注公众号回复消息
9.开发所需要的jar包链接:
链接:https://pan.baidu.com/s/1nwDc1RF 密码:9wsr