标签:
1.申请一个微信公众号(个人订阅号即可)
2.申请成为开发者,并打开开发者模式
注:开发者模式和编辑模式 两者互斥,不能同时开启
3.外网映射工具ngrok,下载地址:http://pan.baidu.com/s/1o6mXNDK
4.验证服务器的有效性
1).获取get请求携带的四个参数
1 package com.weinxin.servlet; 2 3 import java.io.IOException; 4 import java.io.PrintWriter; 5 import java.util.Date; 6 import java.util.Map; 7 8 import javax.servlet.ServletException; 9 import javax.servlet.http.HttpServlet; 10 import javax.servlet.http.HttpServletRequest; 11 import javax.servlet.http.HttpServletResponse; 12 13 import com.weinxin.util.CheckUtils; 14 import com.weinxin.util.MessageUtil; 15 import com.weixin.entity.TextMessage; 16 17 /** 18 * 微信接入 19 * @author chen 20 * 21 */ 22 public class GetWxServlet extends HttpServlet{ 23 24 private static final long serialVersionUID = 1L; 25 26 /** 27 * 验证服务器地址的有效性 28 */ 29 @Override 30 @SuppressWarnings("static-access") 31 protected void doGet(HttpServletRequest requset, HttpServletResponse response) 32 throws ServletException, IOException { 33 34 //微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数 35 String signature = requset.getParameter("signature"); 36 //时间戳 37 String timestamp = requset.getParameter("timestamp"); 38 //随机数 39 String nonce = requset.getParameter("nonce"); 40 //随机字符串 41 String echostr = requset.getParameter("echostr"); 42 43 CheckUtils cu = new CheckUtils(); 44 45 PrintWriter pw = response.getWriter(); 46 47 if(cu.checkSignature(signature, timestamp, nonce)){ 48 pw.println(echostr); 49 } 50 51 } 52 53 }
2).校验此次get请求是否来自微信服务器
1 package com.weinxin.util; 2 3 import java.io.UnsupportedEncodingException; 4 import java.security.MessageDigest; 5 import java.security.NoSuchAlgorithmException; 6 import java.util.Arrays; 7 8 /** 9 * 校验此次get请求是否来自微信服务器 10 * 加密/校验流程如下: 11 * 1. 将token、timestamp、nonce三个参数进行字典序排序 12 * 2. 将三个参数字符串拼接成一个字符串进行sha1加密 13 * 3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信 14 * @author chen 15 * 16 */ 17 public class CheckUtils { 18 19 private static final String token = "***";//此处的token必须与服务器配置页面填写的token一致 20 21 public static boolean checkSignature(String signature, String timestamp, String nonce){ 22 23 String[] arr = new String[]{token, timestamp, nonce}; 24 //排序 25 Arrays.sort(arr); 26 //生成字符串 27 StringBuffer content = new StringBuffer(); 28 //将需要的数值追加到content中 29 for(int i = 0; i < arr.length; i++){ 30 content.append(arr[i]); 31 } 32 //sha1加密 33 String temp = getSha1(content.toString()); 34 //返回结果 35 return temp.equals(signature); 36 37 } 38 39 /** 40 * sha1加密算法 41 * @param str 42 * @return 43 */ 44 private static String getSha1(String str){ 45 46 if(str == null || str.length() == 0){ 47 return null; 48 } 49 //十六进制数组 50 char hexDigits[] = {‘0‘, ‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘, ‘6‘, ‘7‘, ‘8‘, ‘9‘, 51 ‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘, ‘f‘}; 52 try { 53 //创建具有指定算法名称的MessageDigest实例对象 54 MessageDigest mdTemp = MessageDigest.getInstance("SHA1"); 55 //通过调用update方法向MessageDigest对象传送要计算的数据,然后调用以下某个digest方法来计算摘要,即生成散列码 56 mdTemp.update(str.getBytes("UTF-8")); 57 //生成散列码 58 byte[] md = mdTemp.digest(); 59 //计算散列码的长度 60 int i = md.length; 61 char buf[] = new char[i * 2]; 62 int j = 0; 63 for(int k = 0; k < i; k++){ 64 byte byte0 = md[k]; 65 buf[j++] = hexDigits[byte0 >>> 4 & 0xf]; 66 buf[j++] = hexDigits[byte0 & 0xf]; 67 } 68 return new String(buf); 69 } catch (NoSuchAlgorithmException e) { 70 e.printStackTrace(); 71 } catch (UnsupportedEncodingException e) { 72 e.printStackTrace(); 73 } 74 return null; 75 76 } 77 78 }
3).打开外网映射工具,在cmd中将当前目前切换至ngrok所在目录,然后执行ngrok -config ngrok.cfg -subdomain example 8080example自定义,执行成功后入下图:
4).配置web.xml
通过配置web.xml,正确的将请求转发到相应的处理类中,配置如下:
5).配置服务器配置(开发者中心->服务器配置->修改配置)
URL:填写上一步骤中ngrok生成的地址(比如:http://example.tunnel.mobi),再加上项目名和请求名(比如:weixin/weixin.do)
weixin.do即为web.xml中的url-pattern中的请求名
完整的URL即为http://example.tunnel.mobi/weixin/weixin.do
token:可以随机填写,但此处填写的token必须与CheckUtils.java中的token保持一致
EncodingAESKey:随机生成即可
消息加解密方式:明文即可
点击提交,若一切无误则提交成功!如果出现token验证失败,则检查此处的token是否与CheckUtils.java中的token一致。此时微信接入已成功!
5.消息自动回复
?当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。
其中文本消息的格式为:
1).创建文本消息的实体类
1 package com.weixin.entity; 2 3 public class TextMessage { 4 5 private String ToUserName;//开发者微信号 6 private String FromUserName;//发送方账号 7 private long CreateTime;//消息创建时间 8 private String MsgType;//text 9 private String Content;//文本消息内容 10 private String MsgId;//消息id,64位整形 11 12 public String getToUserName() { 13 return ToUserName; 14 } 15 public void setToUserName(String toUserName) { 16 ToUserName = toUserName; 17 } 18 public String getFromUserName() { 19 return FromUserName; 20 } 21 public void setFromUserName(String fromUserName) { 22 FromUserName = fromUserName; 23 } 24 public long getCreateTime() { 25 return CreateTime; 26 } 27 public void setCreateTime(long l) { 28 CreateTime = l; 29 } 30 public String getMsgType() { 31 return MsgType; 32 } 33 public void setMsgType(String msgType) { 34 MsgType = msgType; 35 } 36 public String getContent() { 37 return Content; 38 } 39 public void setContent(String content) { 40 Content = content; 41 } 42 public String getMsgId() { 43 return MsgId; 44 } 45 public void setMsgId(String msgId) { 46 MsgId = msgId; 47 } 48 49 }
2).创建格式转换类
1 package com.weinxin.util; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.util.HashMap; 6 import java.util.List; 7 import java.util.Map; 8 9 import javax.servlet.http.HttpServletRequest; 10 11 import org.dom4j.Document; 12 import org.dom4j.DocumentException; 13 import org.dom4j.Element; 14 import org.dom4j.io.SAXReader; 15 16 import com.thoughtworks.xstream.XStream; 17 import com.weixin.entity.TextMessage; 18 19 /** 20 * 类型转换类 21 * @author chen 22 * 23 */ 24 public class MessageUtil { 25 26 /** 27 * 将xml中转化为map 28 * @param request 29 * @return 30 */ 31 @SuppressWarnings("unchecked") 32 public static Map<String, String> xmlToMap(HttpServletRequest request){ 33 34 Map<String, String> map = new HashMap<String, String>(); 35 SAXReader reader = new SAXReader(); 36 try { 37 //从request中获取输入流 38 InputStream is = request.getInputStream(); 39 //获取document对象,即文档对象 40 Document doc = reader.read(is); 41 //获取根节点 42 Element root = doc.getRootElement(); 43 //将根节点下的数据写入list中 44 List<Element> list = root.elements(); 45 //遍历list,将数据放入map中 46 for(Element e: list){ 47 map.put(e.getName(), e.getText()); 48 } 49 //关闭输入流 50 is.close(); 51 } catch (IOException e) { 52 e.printStackTrace(); 53 } catch (DocumentException e) { 54 e.printStackTrace(); 55 } 56 return map; 57 58 } 59 60 /** 61 * 将文本对象转化为xml 62 * @param textMessage 63 * @return 64 */ 65 public static String textMessageToXml(TextMessage textMessage){ 66 67 XStream stream = new XStream(); 68 //将序列化中的类全量名称,用别名替换 69 //即将根节点由"com.weixin.entity.TextMessage"转化为"xml" 70 stream.alias("xml", textMessage.getClass()); 71 return stream.toXML(textMessage); 72 73 } 74 75 }
3).消息回复
1 package com.weinxin.servlet; 2 3 import java.io.IOException; 4 import java.io.PrintWriter; 5 import java.util.Date; 6 import java.util.Map; 7 8 import javax.servlet.ServletException; 9 import javax.servlet.http.HttpServlet; 10 import javax.servlet.http.HttpServletRequest; 11 import javax.servlet.http.HttpServletResponse; 12 13 import com.weinxin.util.CheckUtils; 14 import com.weinxin.util.MessageUtil; 15 import com.weixin.entity.TextMessage; 16 17 /** 18 * 微信接入 19 * @author chen 20 * 21 */ 22 public class GetWxServlet extends HttpServlet{ 23 24 private static final long serialVersionUID = 1L; 25 26 /** 27 * 验证服务器地址的有效性 28 */ 29 @Override 30 @SuppressWarnings("static-access") 31 protected void doGet(HttpServletRequest requset, HttpServletResponse response) 32 throws ServletException, IOException { 33 34 //微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数 35 String signature = requset.getParameter("signature"); 36 //时间戳 37 String timestamp = requset.getParameter("timestamp"); 38 //随机数 39 String nonce = requset.getParameter("nonce"); 40 //随机字符串 41 String echostr = requset.getParameter("echostr"); 42 43 CheckUtils cu = new CheckUtils(); 44 45 //获取response的输出流 46 PrintWriter pw = response.getWriter(); 47 48 if(cu.checkSignature(signature, timestamp, nonce)){ 49 pw.println(echostr); 50 } 51 52 } 53 54 /** 55 * 自动回复用户发送的消息 56 */ 57 @SuppressWarnings("static-access") 58 @Override 59 protected void doPost(HttpServletRequest requset, HttpServletResponse response) throws ServletException, IOException { 60 61 //设置编码格式 62 requset.setCharacterEncoding("UTF-8"); 63 response.setCharacterEncoding("UTF-8"); 64 65 MessageUtil mu = new MessageUtil(); 66 TextMessage tm = new TextMessage(); 67 68 PrintWriter pw = response.getWriter(); 69 70 Map<String, String> map = mu.xmlToMap(requset); 71 String fromUserName = map.get("FromUserName"); 72 String toUserName = map.get("ToUserName"); 73 String msgType = map.get("MsgType"); 74 String content = map.get("Content"); 75 String message = null; 76 77 if("text".equals(msgType)){//文本消息 78 tm.setFromUserName(toUserName); 79 tm.setToUserName(fromUserName); 80 tm.setMsgType("text"); 81 tm.setCreateTime(new Date().getTime()); 82 tm.setContent("您发送的消息是:" + content); 83 message = mu.textMessageToXml(tm); 84 } 85 pw.write(message); 86 pw.close(); 87 88 } 89 90 }
然后关注该公众号,发送消息测试即可。
此处只是大致介绍,更多内容请参考官方文档:http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html
标签:
原文地址:http://www.cnblogs.com/jinjiyese/p/4788221.html