您的位置:首页 > 移动开发 > 微信开发

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

2016-11-30 14:29 746 查看

微信公众号后台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





package com.lin.po;  
  
/* 
 * 文本消息 
<xml> 
 <ToUserName><![CDATA[toUser]]></ToUserName> 
 <FromUserName><![CDATA[fromUser]]></FromUserName> 
 <CreateTime>1348831860</CreateTime> 
 <MsgType><![CDATA[text]]></MsgType> 
 <Content><![CDATA[this is a test]]></Content> 
 <MsgId>1234567890123456</MsgId> 
 </xml> 
 *  
 */  
/** 
 *       参数             描述 
 *  ToUserName      开发者微信号 
 *  FromUserName    发送方帐号(一个OpenID) 
 *  CreateTime      消息创建时间 (整型) 
 *  MsgType         text 
 *  Content         文本消息内容 
 *  MsgId           消息id,64位整型 
 * @author linxinda 
 * 
 */  
public class TextMessage {  
   private String ToUserName;  
   private String FromUserName;  
   private long CreateTime;  
   private String MsgType;  
   private String Content;  
   private String MsgId;  
public String getToUserName() {  
    return ToUserName;  
}  
public void setToUserName(String toUserName) {  
    ToUserName = toUserName;  
}  
public String getFromUserName() {  
    return FromUserName;  
}  
public void setFromUserName(String fromUserName) {  
    FromUserName = fromUserName;  
}  
public long getCreateTime() {  
    return CreateTime;  
}  
public void setCreateTime(long createTime) {  
    CreateTime = createTime;  
}  
public String getMsgType() {  
    return MsgType;  
}  
public void setMsgType(String msgType) {  
    MsgType = msgType;  
}  
public String getContent() {  
    return Content;  
}  
public void setContent(String content) {  
    Content = content;  
}  
public String getMsgId() {  
    return MsgId;  
}  
public void setMsgId(String msgId) {  
    MsgId = msgId;  
}  
     
     
}  

[java]
view plain
copy





package com.lin.servlet;  
  
import java.io.IOException;  
import java.io.PrintWriter;  
import java.util.Date;  
import java.util.HashMap;  
import java.util.Map;  
  
import javax.servlet.ServletException;  
import javax.servlet.http.HttpServlet;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
  
import com.lin.po.TextMessage;  
import com.lin.util.MessageUtil;  
import com.lin.util.TulingApiUtil;  
import com.lin.util.WeChatConnectValidateUtil;  
  
public class WeChatServlet extends HttpServlet {  
  
      
    public void doPost(HttpServletRequest req, HttpServletResponse resp)  
            throws ServletException, IOException {  
        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("text".equals(msgType)){  
            //  System.out.println("text.equals(msgType)");  
                TextMessage text =new TextMessage();  
                text.setFromUserName(toUserName);  
                text.setToUserName(fromUserName);  
                text.setMsgType("text");  
                  
                  
                //这里填写回复内容  
                text.setContent(TulingApiUtil.getTulingResult(content));  
                  
                  
                text.setCreateTime(new Date().getTime());  
                message=MessageUtil.textMessageToXml(text);  
            }  
        //  System.out.println(message);  
            out.print(message);  
        } catch (Exception e) {  
            //System.out.println("doPost->try..catch");  
            e.printStackTrace();  
        }finally{  
            out.close();  
        }  
    }  
  
      
    /* 
     * Get方法是微信接入请求验证时用的 其他都是post请求 
     * 参数               描述 
    signature   微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。 
    timestamp       时间戳 
    nonce           随机数 
    echostr         随机字符串 
     */  
     //其实这里不用搞加密,直接返回echostr也行  只是不太安全  
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)  
            throws ServletException, IOException {  
            String signature=req.getParameter("signature");  
            String timestamp=req.getParameter("timestamp");  
            String nonce=req.getParameter("nonce");  
            String echostr=req.getParameter("echostr");  
              
            PrintWriter out =resp.getWriter();  
            if(WeChatConnectValidateUtil.checkSignature(signature,timestamp,nonce)){  
                out.print(echostr);  
            }  
    }  
}  

[java]
view plain
copy





package com.lin.util;  
import java.io.UnsupportedEncodingException;  
import java.security.MessageDigest;  
import java.security.NoSuchAlgorithmException;  
  
/** 
 * 使用Java自带的MessageDigest类 
 * @author linxinda 
 */  
public class EncryptionUtil {  
      
  public static String getSha1(String source){  
    // 用来将字节转换成 16 进制表示的字符  
     // System.out.println("进getSha1");  
        
    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(source.getBytes("UTF-8")); // 通过使用 update 方法处理数据,使指定的 byte数组更新摘要  
       
      byte[] encryptStr = mdTemp.digest(); // 获得密文完成哈希计算,产生128 位的长整数  
        
      int j=encryptStr.length;  
      char buf[] = new char[j * 2];   
        
      int k = 0; // 表示转换结果中对应的字符位置  
        
      for (int i = 0; i < j; i++) { // 从第一个字节开始,对每一个字节,转换成 j 进制字符的转换  
        byte byte0 = encryptStr[i]; // 取第 i 个字节  
        buf[k++] = hexDigits[byte0 >>> 4 & 0xf]; // 取字节中高 4 位的数字转换, >>> 为逻辑右移,将符号位一起右移  
        buf[k++] = hexDigits[byte0 & 0xf]; // 取字节中低 4 位的数字转换  
      }  
     // System.out.println(buf.toString());  
      return new String(buf); // 换后的结果转换为字符串  
    } catch (Exception e) {  
        //System.out.println("getSha1->try...catch");  
      e.printStackTrace();  
    }  
    return null;  
  }  
}  

[java]
view plain
copy





package com.lin.util;  
  
import java.io.IOException;  
import java.io.InputStream;  
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 com.lin.po.TextMessage;  
import com.thoughtworks.xstream.XStream;  
import com.thoughtworks.xstream.io.xml.StaxDriver;  
  
public class MessageUtil {  
    /** 
     * xml转为map集合 
     * @param request 
     * @return 
     * @throws IOException 
     * @throws DocumentException 
     */  
      public static Map<String,String> xmlToMap(HttpServletRequest request) throws IOException, DocumentException{  
          
          //System.out.println("进xmlToMap");  
            
          Map<String,String> map=new HashMap<String, String>();  
            
          //dom4j saxReader解析xml  
          SAXReader reader=new SAXReader();  
            
          //从request中获取输入流  
          InputStream ins = request.getInputStream();  
            
          //解析xml文档  
          Document doc =reader.read(ins);  
            
          //获得根节点  
          Element root = doc.getRootElement();  
            
          //List存储  遍历  
          List<Element> list=  root.elements();  
            
          for (Element e : list) {  
              map.put(e.getName(), e.getText());  
        }  
          ins.close();  
        //  System.out.println(map.toString());  
        return map;    
      }  
        
      /** 
       * 将文本消息对象转换为xml 
       * @param textMessage 
       * @return 
       */  
        
       //xtream jar包 ->  XStrem类提供对象转xml  
      public static String textMessageToXml(TextMessage textMessage){  
         // System.out.println("进textMessageToXml");  
          /** 
           * new StaxDriver()这个很重要 没有这个就错了 
           * XStream xstream=new XStream(new StaxDriver()); 
           */  
        XStream xstream=new XStream(new StaxDriver());    
        xstream.alias("xml", textMessage.getClass());  
        // System.out.println("textMessage");  
       return xstream.toXML(textMessage);       
      }  
}  

[java]
view plain
copy





package com.lin.util;  
  
import java.util.Arrays;  
  
public class WeChatConnectValidateUtil {  
    //Token 和微信后台接入接口的token一致  
    private final static String TOKEN="linxinda";    
      
   public static boolean checkSignature(String signature,String timestamp,String nonce){  
       //System.out.println("进checkSignature");  
       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]);     
       }  
         
       //sha1加密  
       String temp=EncryptionUtil.getSha1(content.toString());  
         
      // System.out.println(temp+" "+signature.equals(temp));  
       return signature.equals(temp);  
}  
}  

[java]
view plain
copy





// 调用图灵机器人api接口,获取智能回复内容:  
package com.lin.util;  
  
import java.io.IOException;  
import java.io.UnsupportedEncodingException;  
import java.net.URLEncoder;  
  
import org.apache.http.HttpResponse;  
import org.apache.http.client.ClientProtocolException;  
import org.apache.http.client.methods.HttpGet;  
import org.apache.http.impl.client.HttpClients;  
import org.apache.http.util.EntityUtils;  
import org.json.JSONException;  
import org.json.JSONObject;  
  
  
/** 
 * 调用图灵机器人api接口,获取智能回复内容 
 * @author pamchen-1 
 * 
 */  
public class TulingApiUtil {  
    /** 
     * 调用图灵机器人api接口,获取智能回复内容,解析获取自己所需结果 
     * @param content 
     * @return 
     */  
      
    private static final String KEY="这里填自己的key";  
      
    public static String getTulingResult(String content){  
        //System.out.println("传入的内容->"+content);  
          
          
        /** 此处为图灵api接口,参数key需要自己去注册申请,先以11111111代替 */  
         String apiUrl = "http://www.tuling123.com/openapi/api?key="+KEY+"&info=";  
        String param = "";  
          
        //System.out.println("!!!!!!!");  
          
        try {  
            param = apiUrl+URLEncoder.encode(content,"utf-8");  
        } catch (UnsupportedEncodingException e1) {  
            System.out.println("UnsupportedEncodingException");  
            e1.printStackTrace();  
        } //将参数转为url编码  
          
          
        //System.out.println("?????????");  
          
        /** 发送httpget请求 */  
        HttpGet request = new HttpGet(param);  
        String result = "";  
        try {  
               
            HttpResponse response = HttpClients.createDefault().execute(request);  
        /** 
         * 特别注意  这一步一定要加commons-logging 这个jar包  否则会没反应,调试了好久!! 
         * 似乎这个jar包是打印信息的     
         */  
            int code =response.getStatusLine().getStatusCode();  
            if(code==200){  
                result = EntityUtils.toString(response.getEntity());  
            }  
            else {  
            //  System.out.println("code="+code);  
            }  
        } catch (ClientProtocolException e) {  
            System.out.println("ClientProtocolException");  
            e.printStackTrace();  
        } catch (IOException e) {  
            System.out.println("IOException");  
            e.printStackTrace();  
        }  
          
          
        /** 请求失败处理 */  
        if(null==result){  
        //  System.out.println("null==result");  
            return "对不起,你说的话真是太高深了……";  
        }  
          
        //  
          
        //System.out.println("...........");  
        try {  
            StringBuffer bf=new StringBuffer();  
            String s="";  
            JSONObject json = new JSONObject(result);  
            //以code=100000为例,参考图灵机器人api文档  
            /** 
             *   code   说明 
                100000  文本类 
                200000  链接类 
                302000  新闻类 
                308000  菜谱类 
             */  
            if(100000==json.getInt("code")){  
                s = json.getString("text");  
                bf.append(s);  
            }  
            else if(200000==json.getInt("code")){  
                s = json.getString("text");  
                bf.append(s);  
                bf.append("\n");  
                s = json.getString("url");  
                bf.append(s);  
            }  
            else if(302000==json.getInt("code")){  
                //s = json.getString("text");  
                s="待开发有点麻烦!\n";  
                bf.append(s);  
            }  
            else if(308000==json.getInt("code")){  
                //s = json.getString("text");  
                s="待开发有点麻烦!\n";  
                bf.append(s);  
            }  
            result=bf.toString();  
        } catch (JSONException e) {   
            System.out.println("JSONException");  
            e.printStackTrace();  
        }  
        //System.out.println("机器人回复->"+result);  
        return result;  
    }  
}  

[java]
view plain
copy





package com.lin.test;  
  
import java.io.BufferedInputStream;  
import java.util.Scanner;  
  
import com.lin.util.TulingApiUtil;  
  
public class Test {  
  
    public static void main(String[] args) {  
        Scanner scanner=new Scanner(new BufferedInputStream(System.in));  
            while(scanner.hasNext()){  
                String content=scanner.next();  
                 System.out.println(TulingApiUtil.getTulingResult(content));  
            }  
            scanner.close();  
    }  
  
}  

最后总结自己遇到的问题,便于日后查看:
1. 图灵机器人的加密钥匙要关闭,否则就得进行加解密操作,他的api里有详细说明。

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

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

service tomcat6/httpd/iptable restart

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

 
 
上一篇Web Service调用
下一篇linux下shell显示-bash-4.1#不显示路径解决方法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: