1.注册微信公众号。(简单)
2.注册图灵机器人。(自己百度)
1)注册后可以拿到key (注意 api接入里的钥匙不要打开,否则要加解密,麻烦)
3.配置微信公众号服务器验证。
1)在开发的基本配置下,填写控制器servlet访问的路径。
2)token随意写,不过要和后台一致
3)选择明文
4)随机选个字符串
然后点击提交(这里微信会发送请求和你写的验证看是否匹配,具体看微信公众号平台开发文档) ?其实这里不用操作什么,他发送的匹配直接返回验证就过了,但是不是很安全。
4.接着是解析微信发送过来的xml格式,把他弄成map集合
5.解析得到内容 发送httpGet请求 丢过去给图灵机器人接口,返回回复内容
6.将东西封装成xml返回回去
然后OK
涉及的包 一个都不能少(当初就是少了commons-logging)
代码如下:
- 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;
- }
- }
- 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);
- }
- }
- }
- 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;
- }
- }
- 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);
- }
- }
- 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);
- }
- }
- // 调用图灵机器人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;
- }
- }
- 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端口,一些忘记的命令见阿里云配置