微信公众号后台java开发实现自动回复机器人

微信公众号后台java开发实现自动回复机器人


1.注册微信公众号。(简单)

2.注册图灵机器人。(自己百度)

1)注册后可以拿到key  (注意  api接入里的钥匙不要打开,否则要加解密,麻烦)

3.配置微信公众号服务器验证。

1)在开发的基本配置下,填写控制器servlet访问的路径。

2)token随意写,不过要和后台一致

3)选择明文

4)随机选个字符串

然后点击提交(这里微信会发送请求和你写的验证看是否匹配,具体看微信公众号平台开发文档)  ?其实这里不用操作什么,他发送的匹配直接返回验证就过了,但是不是很安全。


4.接着是解析微信发送过来的xml格式,把他弄成map集合  

5.解析得到内容 发送httpGet请求 丢过去给图灵机器人接口,返回回复内容

6.将东西封装成xml返回回去

然后OK




涉及的包 一个都不能少(当初就是少了commons-logging)



代码如下:

[java] view plain copy
  1. package com.lin.po;  
  2.   
  3. /* 
  4.  * 文本消息 
  5. <xml> 
  6.  <ToUserName><![CDATA[toUser]]></ToUserName> 
  7.  <FromUserName><![CDATA[fromUser]]></FromUserName> 
  8.  <CreateTime>1348831860</CreateTime> 
  9.  <MsgType><![CDATA[text]]></MsgType> 
  10.  <Content><![CDATA[this is a test]]></Content> 
  11.  <MsgId>1234567890123456</MsgId> 
  12.  </xml> 
  13.  *  
  14.  */  
  15. /** 
  16.  *       参数             描述 
  17.  *  ToUserName      开发者微信号 
  18.  *  FromUserName    发送方帐号(一个OpenID) 
  19.  *  CreateTime      消息创建时间 (整型) 
  20.  *  MsgType         text 
  21.  *  Content         文本消息内容 
  22.  *  MsgId           消息id,64位整型 
  23.  * @author linxinda 
  24.  * 
  25.  */  
  26. public class TextMessage {  
  27.    private String ToUserName;  
  28.    private String FromUserName;  
  29.    private long CreateTime;  
  30.    private String MsgType;  
  31.    private String Content;  
  32.    private String MsgId;  
  33. public String getToUserName() {  
  34.     return ToUserName;  
  35. }  
  36. public void setToUserName(String toUserName) {  
  37.     ToUserName = toUserName;  
  38. }  
  39. public String getFromUserName() {  
  40.     return FromUserName;  
  41. }  
  42. public void setFromUserName(String fromUserName) {  
  43.     FromUserName = fromUserName;  
  44. }  
  45. public long getCreateTime() {  
  46.     return CreateTime;  
  47. }  
  48. public void setCreateTime(long createTime) {  
  49.     CreateTime = createTime;  
  50. }  
  51. public String getMsgType() {  
  52.     return MsgType;  
  53. }  
  54. public void setMsgType(String msgType) {  
  55.     MsgType = msgType;  
  56. }  
  57. public String getContent() {  
  58.     return Content;  
  59. }  
  60. public void setContent(String content) {  
  61.     Content = content;  
  62. }  
  63. public String getMsgId() {  
  64.     return MsgId;  
  65. }  
  66. public void setMsgId(String msgId) {  
  67.     MsgId = msgId;  
  68. }  
  69.      
  70.      
  71. }  


[java] view plain copy
  1. package com.lin.servlet;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.PrintWriter;  
  5. import java.util.Date;  
  6. import java.util.HashMap;  
  7. import java.util.Map;  
  8.   
  9. import javax.servlet.ServletException;  
  10. import javax.servlet.http.HttpServlet;  
  11. import javax.servlet.http.HttpServletRequest;  
  12. import javax.servlet.http.HttpServletResponse;  
  13.   
  14. import com.lin.po.TextMessage;  
  15. import com.lin.util.MessageUtil;  
  16. import com.lin.util.TulingApiUtil;  
  17. import com.lin.util.WeChatConnectValidateUtil;  
  18.   
  19. public class WeChatServlet extends HttpServlet {  
  20.   
  21.       
  22.     public void doPost(HttpServletRequest req, HttpServletResponse resp)  
  23.             throws ServletException, IOException {  
  24.         req.setCharacterEncoding("UTF-8");  
  25.         resp.setCharacterEncoding("UTF-8");  
  26.         PrintWriter out =resp.getWriter();  
  27.           try {  
  28.             Map<String, String> map=MessageUtil.xmlToMap(req);  
  29.             String toUserName=map.get("ToUserName");  
  30.             String fromUserName=map.get("FromUserName");  
  31.             String msgType=map.get("MsgType");  
  32.             String content=map.get("Content");  
  33.                   
  34.             String message=null;          
  35.             if("text".equals(msgType)){  
  36.             //  System.out.println("text.equals(msgType)");  
  37.                 TextMessage text =new TextMessage();  
  38.                 text.setFromUserName(toUserName);  
  39.                 text.setToUserName(fromUserName);  
  40.                 text.setMsgType("text");  
  41.                   
  42.                   
  43.                 //这里填写回复内容  
  44.                 text.setContent(TulingApiUtil.getTulingResult(content));  
  45.                   
  46.                   
  47.                 text.setCreateTime(new Date().getTime());  
  48.                 message=MessageUtil.textMessageToXml(text);  
  49.             }  
  50.         //  System.out.println(message);  
  51.             out.print(message);  
  52.         } catch (Exception e) {  
  53.             //System.out.println("doPost->try..catch");  
  54.             e.printStackTrace();  
  55.         }finally{  
  56.             out.close();  
  57.         }  
  58.     }  
  59.   
  60.       
  61.     /* 
  62.      * Get方法是微信接入请求验证时用的 其他都是post请求 
  63.      * 参数               描述 
  64.     signature   微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。 
  65.     timestamp       时间戳 
  66.     nonce           随机数 
  67.     echostr         随机字符串 
  68.      */  
  69.      //其实这里不用搞加密,直接返回echostr也行  只是不太安全  
  70.     protected void doGet(HttpServletRequest req, HttpServletResponse resp)  
  71.             throws ServletException, IOException {  
  72.             String signature=req.getParameter("signature");  
  73.             String timestamp=req.getParameter("timestamp");  
  74.             String nonce=req.getParameter("nonce");  
  75.             String echostr=req.getParameter("echostr");  
  76.               
  77.             PrintWriter out =resp.getWriter();  
  78.             if(WeChatConnectValidateUtil.checkSignature(signature,timestamp,nonce)){  
  79.                 out.print(echostr);  
  80.             }  
  81.     }  
  82. }  


[java] view plain copy
  1. package com.lin.util;  
  2. import java.io.UnsupportedEncodingException;  
  3. import java.security.MessageDigest;  
  4. import java.security.NoSuchAlgorithmException;  
  5.   
  6. /** 
  7.  * 使用Java自带的MessageDigest类 
  8.  * @author linxinda 
  9.  */  
  10. public class EncryptionUtil {  
  11.       
  12.   public static String getSha1(String source){  
  13.     // 用来将字节转换成 16 进制表示的字符  
  14.      // System.out.println("进getSha1");  
  15.         
  16.     char hexDigits[] = {'0''1''2''3''4''5''6''7''8''9''a''b''c''d''e''f'};  
  17.   
  18.     try {  
  19.       MessageDigest mdTemp = MessageDigest.getInstance("SHA1");  
  20.       mdTemp.update(source.getBytes("UTF-8")); // 通过使用 update 方法处理数据,使指定的 byte数组更新摘要  
  21.        
  22.       byte[] encryptStr = mdTemp.digest(); // 获得密文完成哈希计算,产生128 位的长整数  
  23.         
  24.       int j=encryptStr.length;  
  25.       char buf[] = new char[j * 2];   
  26.         
  27.       int k = 0// 表示转换结果中对应的字符位置  
  28.         
  29.       for (int i = 0; i < j; i++) { // 从第一个字节开始,对每一个字节,转换成 j 进制字符的转换  
  30.         byte byte0 = encryptStr[i]; // 取第 i 个字节  
  31.         buf[k++] = hexDigits[byte0 >>> 4 & 0xf]; // 取字节中高 4 位的数字转换, >>> 为逻辑右移,将符号位一起右移  
  32.         buf[k++] = hexDigits[byte0 & 0xf]; // 取字节中低 4 位的数字转换  
  33.       }  
  34.      // System.out.println(buf.toString());  
  35.       return new String(buf); // 换后的结果转换为字符串  
  36.     } catch (Exception e) {  
  37.         //System.out.println("getSha1->try...catch");  
  38.       e.printStackTrace();  
  39.     }  
  40.     return null;  
  41.   }  
  42. }  

[java] view plain copy
  1. package com.lin.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.lin.po.TextMessage;  
  17. import com.thoughtworks.xstream.XStream;  
  18. import com.thoughtworks.xstream.io.xml.StaxDriver;  
  19.   
  20. public class MessageUtil {  
  21.     /** 
  22.      * xml转为map集合 
  23.      * @param request 
  24.      * @return 
  25.      * @throws IOException 
  26.      * @throws DocumentException 
  27.      */  
  28.       public static Map<String,String> xmlToMap(HttpServletRequest request) throws IOException, DocumentException{  
  29.           
  30.           //System.out.println("进xmlToMap");  
  31.             
  32.           Map<String,String> map=new HashMap<String, String>();  
  33.             
  34.           //dom4j saxReader解析xml  
  35.           SAXReader reader=new SAXReader();  
  36.             
  37.           //从request中获取输入流  
  38.           InputStream ins = request.getInputStream();  
  39.             
  40.           //解析xml文档  
  41.           Document doc =reader.read(ins);  
  42.             
  43.           //获得根节点  
  44.           Element root = doc.getRootElement();  
  45.             
  46.           //List存储  遍历  
  47.           List<Element> list=  root.elements();  
  48.             
  49.           for (Element e : list) {  
  50.               map.put(e.getName(), e.getText());  
  51.         }  
  52.           ins.close();  
  53.         //  System.out.println(map.toString());  
  54.         return map;    
  55.       }  
  56.         
  57.       /** 
  58.        * 将文本消息对象转换为xml 
  59.        * @param textMessage 
  60.        * @return 
  61.        */  
  62.         
  63.        //xtream jar包 ->  XStrem类提供对象转xml  
  64.       public static String textMessageToXml(TextMessage textMessage){  
  65.          // System.out.println("进textMessageToXml");  
  66.           /** 
  67.            * new StaxDriver()这个很重要 没有这个就错了 
  68.            * XStream xstream=new XStream(new StaxDriver()); 
  69.            */  
  70.         XStream xstream=new XStream(new StaxDriver());    
  71.         xstream.alias("xml", textMessage.getClass());  
  72.         // System.out.println("textMessage");  
  73.        return xstream.toXML(textMessage);       
  74.       }  
  75. }  


[java] view plain copy
  1. package com.lin.util;  
  2.   
  3. import java.util.Arrays;  
  4.   
  5. public class WeChatConnectValidateUtil {  
  6.     //Token 和微信后台接入接口的token一致  
  7.     private final static String TOKEN="linxinda";    
  8.       
  9.    public static boolean checkSignature(String signature,String timestamp,String nonce){  
  10.        //System.out.println("进checkSignature");  
  11.        String arr[]=new String[]{TOKEN,timestamp,nonce};  
  12.          
  13.        //排序  
  14.        Arrays.sort(arr);  
  15.          
  16.        //生成字符串  
  17.        StringBuffer content=new StringBuffer();  
  18.        for(int i=0;i<arr.length;i++){  
  19.            content.append(arr[i]);     
  20.        }  
  21.          
  22.        //sha1加密  
  23.        String temp=EncryptionUtil.getSha1(content.toString());  
  24.          
  25.       // System.out.println(temp+" "+signature.equals(temp));  
  26.        return signature.equals(temp);  
  27. }  
  28. }  

[java] view plain copy
  1. // 调用图灵机器人api接口,获取智能回复内容:  
  2. package com.lin.util;  
  3.   
  4. import java.io.IOException;  
  5. import java.io.UnsupportedEncodingException;  
  6. import java.net.URLEncoder;  
  7.   
  8. import org.apache.http.HttpResponse;  
  9. import org.apache.http.client.ClientProtocolException;  
  10. import org.apache.http.client.methods.HttpGet;  
  11. import org.apache.http.impl.client.HttpClients;  
  12. import org.apache.http.util.EntityUtils;  
  13. import org.json.JSONException;  
  14. import org.json.JSONObject;  
  15.   
  16.   
  17. /** 
  18.  * 调用图灵机器人api接口,获取智能回复内容 
  19.  * @author pamchen-1 
  20.  * 
  21.  */  
  22. public class TulingApiUtil {  
  23.     /** 
  24.      * 调用图灵机器人api接口,获取智能回复内容,解析获取自己所需结果 
  25.      * @param content 
  26.      * @return 
  27.      */  
  28.       
  29.     private static final String KEY="这里填自己的key";  
  30.       
  31.     public static String getTulingResult(String content){  
  32.         //System.out.println("传入的内容->"+content);  
  33.           
  34.           
  35.         /** 此处为图灵api接口,参数key需要自己去注册申请,先以11111111代替 */  
  36.          String apiUrl = "http://www.tuling123.com/openapi/api?key="+KEY+"&info=";  
  37.         String param = "";  
  38.           
  39.         //System.out.println("!!!!!!!");  
  40.           
  41.         try {  
  42.             param = apiUrl+URLEncoder.encode(content,"utf-8");  
  43.         } catch (UnsupportedEncodingException e1) {  
  44.             System.out.println("UnsupportedEncodingException");  
  45.             e1.printStackTrace();  
  46.         } //将参数转为url编码  
  47.           
  48.           
  49.         //System.out.println("?????????");  
  50.           
  51.         /** 发送httpget请求 */  
  52.         HttpGet request = new HttpGet(param);  
  53.         String result = "";  
  54.         try {  
  55.                
  56.             HttpResponse response = HttpClients.createDefault().execute(request);  
  57.         /** 
  58.          * 特别注意  这一步一定要加commons-logging 这个jar包  否则会没反应,调试了好久!! 
  59.          * 似乎这个jar包是打印信息的     
  60.          */  
  61.             int code =response.getStatusLine().getStatusCode();  
  62.             if(code==200){  
  63.                 result = EntityUtils.toString(response.getEntity());  
  64.             }  
  65.             else {  
  66.             //  System.out.println("code="+code);  
  67.             }  
  68.         } catch (ClientProtocolException e) {  
  69.             System.out.println("ClientProtocolException");  
  70.             e.printStackTrace();  
  71.         } catch (IOException e) {  
  72.             System.out.println("IOException");  
  73.             e.printStackTrace();  
  74.         }  
  75.           
  76.           
  77.         /** 请求失败处理 */  
  78.         if(null==result){  
  79.         //  System.out.println("null==result");  
  80.             return "对不起,你说的话真是太高深了……";  
  81.         }  
  82.           
  83.         //  
  84.           
  85.         //System.out.println("...........");  
  86.         try {  
  87.             StringBuffer bf=new StringBuffer();  
  88.             String s="";  
  89.             JSONObject json = new JSONObject(result);  
  90.             //以code=100000为例,参考图灵机器人api文档  
  91.             /** 
  92.              *   code   说明 
  93.                 100000  文本类 
  94.                 200000  链接类 
  95.                 302000  新闻类 
  96.                 308000  菜谱类 
  97.              */  
  98.             if(100000==json.getInt("code")){  
  99.                 s = json.getString("text");  
  100.                 bf.append(s);  
  101.             }  
  102.             else if(200000==json.getInt("code")){  
  103.                 s = json.getString("text");  
  104.                 bf.append(s);  
  105.                 bf.append("\n");  
  106.                 s = json.getString("url");  
  107.                 bf.append(s);  
  108.             }  
  109.             else if(302000==json.getInt("code")){  
  110.                 //s = json.getString("text");  
  111.                 s="待开发有点麻烦!\n";  
  112.                 bf.append(s);  
  113.             }  
  114.             else if(308000==json.getInt("code")){  
  115.                 //s = json.getString("text");  
  116.                 s="待开发有点麻烦!\n";  
  117.                 bf.append(s);  
  118.             }  
  119.             result=bf.toString();  
  120.         } catch (JSONException e) {   
  121.             System.out.println("JSONException");  
  122.             e.printStackTrace();  
  123.         }  
  124.         //System.out.println("机器人回复->"+result);  
  125.         return result;  
  126.     }  
  127. }  


[java] view plain copy
  1. package com.lin.test;  
  2.   
  3. import java.io.BufferedInputStream;  
  4. import java.util.Scanner;  
  5.   
  6. import com.lin.util.TulingApiUtil;  
  7.   
  8. public class Test {  
  9.   
  10.     public static void main(String[] args) {  
  11.         Scanner scanner=new Scanner(new BufferedInputStream(System.in));  
  12.             while(scanner.hasNext()){  
  13.                 String content=scanner.next();  
  14.                  System.out.println(TulingApiUtil.getTulingResult(content));  
  15.             }  
  16.             scanner.close();  
  17.     }  
  18.   
  19. }  




最后总结自己遇到的问题,便于日后查看:

1. 图灵机器人的加密钥匙要关闭,否则就得进行加解密操作,他的api里有详细说明。

2.可以多写些测试类方便调试,不要每次都传到服务器上调试,好麻烦。


最后记下自己服务器的一些信息

service tomcat6/httpd/iptable restart

微信要80端口,一些忘记的命令见阿里云配置


 
 

你可能感兴趣的:(微信公众号后台java开发实现自动回复机器人)