2015-04-22 20:30:00 hy245120020 阅读数 907
  • 安卓图灵聊天机器人接入开发

    通过本课程的学习,你将会学会图灵智能聊天机器人的接口开发,通过本次项目实战,你讲学会json数据的生成和解析,API文档的阅读和接口开发,http post 请求,动态增加View等核心知识点

    288 人正在学习 去看看 朱祚华

web.xml配置

  <servlet>
    <servlet-name>weixinServlet</servlet-name>
    <servlet-class>com.imooc.servlet.WeixinServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>weixinServlet</servlet-name>
    <url-pattern>/wx.do</url-pattern>
  </servlet-mapping>

编写java类

package com.imooc.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.dom4j.DocumentException;
import org.json.JSONException;

import com.imooc.po.TextMessage;
import com.imooc.tuling.TulingApiProcess;
import com.imooc.util.CheckUtil;
import com.imooc.util.MessageUtil;

public class WeixinServlet extends HttpServlet {
    /**
     * 接收微信平台发送的post请求
     */
    private static final long serialVersionUID = 7922920577832311647L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

        String signature = request.getParameter("signature");
        String timestamp = request.getParameter("timestamp");
        String nonce = request.getParameter("nonce");
        String echostr = request.getParameter("echostr");
        /**
        *通过检验 signature 对请求进行校验, 若校验成功则原样返回 echostr, 表示接入
        *成功,否则接入失败
        */

        PrintWriter out = response.getWriter();
        if (CheckUtil.checkSignature(signature, timestamp, nonce)) {
            out.print(echostr);
        }
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

        PrintWriter out = response.getWriter();
        try {
            Map<String, String> map = MessageUtil.xmlToMap(request);
            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)){
                TextMessage text = new TextMessage();
                text.setFromUserName(toUserName);
                text.setToUserName(fromUserName);
                text.setCreateTime(String.valueOf(new Date().getTime()));
                text.setMsgType("text");
                String reMsg = "";
                try {
                    reMsg = TulingApiProcess.getTulingMessage(content);
                } catch (JSONException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                text.setContent("阿狸:" + reMsg);
                message = MessageUtil.textMessageToXml(text);
            }
            System.out.println(message);
            out.write(message);
        } catch (DocumentException e) {
            e.printStackTrace();
        } finally{
            out.close();
        }
    }
}
package com.imooc.tuling;

import java.io.IOException;
import java.net.URLEncoder;

import org.apache.http.HttpResponse;
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;

//import net.sf.json.JSONObject;

public class TulingApiProcess {
    /**
     * 调用图灵机器人平台接口
     */
    /**
     * 调用图灵机器人平台接口 需要导入的包:commons-logging-1.0.4.jar、 httpclient-4.3.1.jar、httpcore-4.3.jar
     * @throws JSONException 
     */
    public static String getTulingMessage(String context) throws IOException, JSONException {

        String INFO = URLEncoder.encode(context, "utf-8");
        String requesturl = "http://www.tuling123.com/openapi/api?key=你的key&info=" + INFO;
        HttpGet request = new HttpGet(requesturl);
        HttpResponse response = HttpClients.createDefault().execute(request);

        String result = "";

        // 200即正确的返回码
        if (response.getStatusLine().getStatusCode() == 200) {
            result = EntityUtils.toString(response.getEntity());
            System.out.println("返回结果:" + result);
        }
        JSONObject json = new JSONObject(result);
        //以code=100000为例,参考图灵机器人api文档  
        if("100000".equals(json.getString("code"))){  
            result = json.getString("text"); 
//            System.out.println(result);
        } else{
            result = "对不起,你说的话真是太高深了……";
        }
        return result;
    }

}
package com.imooc.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

public class CheckUtil {

    private static final String token = "imooc";

    public static boolean checkSignature(String signature, String timestamp, String nonce) {
        /**
         * 验证
         */
        String[] arr = new String[] { token, timestamp, nonce };
        // 排序
        Arrays.sort(arr);

        // 生成字符串
        StringBuffer context = new StringBuffer();
        for (int i = 0; i < arr.length; i++) {
            context.append(arr[i]);
        }

        // sha1加密
        String temp = SHA1(context.toString());

        return temp.equals(signature);
    }

    public static String SHA1(String decript) {
        /**
         * sha1算法
         */
        try {
            MessageDigest digest = java.security.MessageDigest.getInstance("SHA-1");
            digest.update(decript.getBytes());
            byte messageDigest[] = digest.digest();
            // Create Hex String
            StringBuffer hexString = new StringBuffer();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }
}
package com.imooc.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.imooc.po.TextMessage;
import com.thoughtworks.xstream.XStream;

public class MessageUtil {
    /**
     * xml转为Map集合
     * @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;
    }
    /**
     * 将文本消息对象转化为xml
     * @return
     */
    public static String textMessageToXml(TextMessage textMessage) {
        XStream xStream = new XStream();
        xStream.alias("xml", textMessage.getClass());
        return xStream.toXML(textMessage);
    }
}
package com.imooc.po;

public class TextMessage {
    // 参数 描述
    // ToUserName 开发者微信号
    // FromUserName 发送方帐号(一个OpenID)
    // CreateTime 消息创建时间 (整型)
    // MsgType text
    // Content 文本消息内容
    // MsgId 消息id,64位整型
    private String ToUserName;
    private String FromUserName;
    private String 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 String getCreateTime() {
        return CreateTime;
    }

    public void setCreateTime(String 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;
    }

}

涉及到的lib库:
http://download.csdn.net/detail/hy245120020/8621531
end

2016-03-12 17:39:09 qq_27629109 阅读数 5767
  • 安卓图灵聊天机器人接入开发

    通过本课程的学习,你将会学会图灵智能聊天机器人的接口开发,通过本次项目实战,你讲学会json数据的生成和解析,API文档的阅读和接口开发,http post 请求,动态增加View等核心知识点

    288 人正在学习 去看看 朱祚华

准备电商比赛的时候申请了个公众号,因为之前错误地申请了订阅号,还是个人类型的,所以基本也没法开发什么功能了。于是就想到之前很火的小黄鸡聊天机器人。不过小黄鸡的接口是要收费的,所以选用了图灵机器人(http://www.tuling123.com/);也能实现自动聊天。

图灵机器人后台提供了两种接入方式,一种是API接入,一种是微信接入。使用微信接入非常简单,只要在微信后台-开发-基本配置里填写图灵机器人提供的URL和token值就可以。不过这样一来整个公众号只能实现图灵机器人的功能,几乎浪费了一个公众号。所以选择使用API接入。这里使用新浪云提供的SAE。下面是代码。

<?php
header("Content-type: text/html; charset=utf-8");
//以下为固定用法,实现和微信的对接、验证
define("TOKEN", "callTuling");

$wechatObj = new wechatCallbackapiTest();
if (isset($_GET['echostr'])) {
    $wechatObj->valid();
}else{
    $wechatObj->responseMsg();
}

class wechatCallbackapiTest
{
    public function valid()
    {
        $echoStr = $_GET["echostr"];
        if($this->checkSignature()){
            echo $echoStr;
            exit;
        }
    }

    private function checkSignature()
    {
        $signature = $_GET["signature"];
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];

        $token = TOKEN;
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr);
        $tmpStr = implode( $tmpArr );
        $tmpStr = sha1( $tmpStr );

        if( $tmpStr == $signature ){
            return true;
        }else{
            return false;
        }
    }

    public function responseMsg()
    {
        $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
        if (!empty($postStr)){
            $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
            $RX_TYPE = trim($postObj->MsgType);

            switch ($RX_TYPE)
            {
                case "text":
                    $resultStr = $this->receiveText($postObj);
                    break;
                case "event":
                    $resultStr = $this->receiveEvent($postObj);
                    break;
            }
            echo $resultStr;
        }else {
            echo "";
            exit;
        }
    }
//处理接受到用户消息的事件
    private function receiveText($object)
    {
        $funcFlag = 0;
        $keyword = trim($object->Content);
        $contentStr = callTuling($keyword);
        $resultStr = $this->transmitText($object, $contentStr, $funcFlag);
        return $resultStr;
    }
//处理公众号被关注的事件
    private function receiveEvent($object)
    {
        $contentStr = "";
        switch ($object->Event)
        {
            case "subscribe":
                $contentStr = "你终于来了";
        }
        $resultStr = $this->transmitText($object, $contentStr);
        return $resultStr;
    }
//把图灵机器人返回的数据转换成微信使用的数据格式
    private function transmitText($object, $content, $flag = 0)
    {
        $textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[%s]]></Content>
<FuncFlag>%d</FuncFlag>
</xml>";
        $resultStr = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(), $content, $flag);
        return $resultStr;
    }
}//创建函数调用图灵机器人接口
function callTuling($keyword)
{
    $apiKey = "******"; //填写后台提供的key
    $apiURL = "http://www.tuling123.com/openapi/api?key=KEY&info=INFO"; 

    $reqInfo = $keyword; 
    $url = str_replace("INFO", $reqInfo, str_replace("KEY", $apiKey, $apiURL));
    $ch = curl_init(); 
    curl_setopt ($ch, CURLOPT_URL, $url); 
   curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); 
    $file_contents = curl_exec($ch);
    curl_close($ch); 
//获取图灵机器人返回的数据,并根据code值的不同获取到不用的数据
    $message = json_decode($file_contents,true);
    $result = "";
    if ($message['code'] == 100000){
        $result = $message['text'];
    }else if ($message['code'] == 200000){
        $text = $message['text'];
        $url = $message['url'];
        $result = $text . " " . $url;
    }else if ($message['code'] == 302000){
        $text = $message['text'];
        $url = $message['list'][0]['detailurl'];
        $result = $text . " " . $url;
    }else {
        $result = "好好说话我们还是基佬";
    }
    return $result;
}
?>


2015-05-26 10:44:45 wyx100 阅读数 5310
  • 安卓图灵聊天机器人接入开发

    通过本课程的学习,你将会学会图灵智能聊天机器人的接口开发,通过本次项目实战,你讲学会json数据的生成和解析,API文档的阅读和接口开发,http post 请求,动态增加View等核心知识点

    288 人正在学习 去看看 朱祚华

微信聊天机器人开发  java  


图灵机器人提供免费接口,并且支持java语言开发,同时提供开发说明:

图灵机器人开发说明连接:

http://www.tuling123.com/openapi/cloud/access_api.jsp


实例:

/** 调用图灵机器人平台接口 
*/ 
public static void main(String[] args) throws IOException { 

     String APIKEY = "开发者注册帐号,激活之后即可获得"; 
     String INFO = URLEncoder.encode("北京今日天气", "utf-8"); 
    String getURL = "http://www.tuling123.com/openapi/api?key=" + APIKEY + "&info=" + INFO; 
    URL getUrl = new URL(getURL); 
    HttpURLConnection connection = (HttpURLConnection) getUrl.openConnection(); 
    connection.connect(); 

    // 取得输入流,并使用Reader读取 
    BufferedReader reader = new BufferedReader(new InputStreamReader( connection.getInputStream(), "utf-8"));
    StringBuffer sb = new StringBuffer(); 
    String line = ""; 
    while ((line = reader.readLine()) != null) { 
        sb.append(line); 
    } 
    reader.close(); 
    // 断开连接 
    connection.disconnect(); 
    System.out.println(sb); 

}


2017-03-20 18:56:29 hyz301 阅读数 1175
  • 安卓图灵聊天机器人接入开发

    通过本课程的学习,你将会学会图灵智能聊天机器人的接口开发,通过本次项目实战,你讲学会json数据的生成和解析,API文档的阅读和接口开发,http post 请求,动态增加View等核心知识点

    288 人正在学习 去看看 朱祚华

此文将分两篇讲解,主要分为以下几步

  1. 签名校验;
  2. 首次提交验证申请;
  3. 接收消息;
  4. 被动响应消息(返回XML);
  5. 映射图灵消息及微信消息;

其实图灵机器人搭载微信公众号很简单,只需要把图灵的地址配到公众后台就可以了。 不过这样做之后也就没有任何扩展的可能了,因此自己实现一套!

一、签名校验

在开发者首次提交验证申请时,微信服务器将发送GET请求到填写的URL上,并且带上四个参数(signature、timestamp、nonce、echostr),开发者通过对签名(即signature)的效验,来判断此条消息的真实性。

此后,每次开发者接收用户消息的时候,微信也都会带上前面三个参数(signature、timestamp、nonce)访问开发者设置的URL,开发者依然通过对签名的效验判断此条消息的真实性。效验方式与首次提交验证申请一致。

根据微信开发者平台中的描述,我们在首次提交验证申请及接收用户消息时,都需要校验签名以确保消息来源真实。

参与签名的参数为timestampnoncetoken(即开发者中心中配置的Token令牌)

加密/校验流程如下:
1. 将token、timestamp、nonce三个参数进行字典序排序(此处注意:是三个参数的值,而不是按参数名排序) 
2. 将三个参数字符串拼接成一个字符串进行sha1加密
3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

由于这个东西在接收消息时是通用的,我们可以使用授权过滤器AuthorizeAttribute来实现。

 

using System.Configuration;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
using System.Linq;
using System.Web.Http.Controllers;

using Efh.Core.Security;

namespace Efh.Blog.Web.Areas.WeiXin.Filter
{
    public class WXAuthorizeAttribute : AuthorizeAttribute
    {
        /// <summary>
        /// 签名Key
        /// </summary>
        private string _wxToken = ConfigurationManager.AppSettings["WXToken"];

        /// <summary>
        /// 是否通过授权
        /// </summary>
        /// <param name="actionContext">上下文</param>
        /// <returns>是否成功</returns>
        protected override bool IsAuthorized(HttpActionContext actionContext)
        {
            var requestQueryPairs = actionContext.Request.GetQueryNameValuePairs().ToDictionary(k => k.Key, v => v.Value);
            if (requestQueryPairs.Count == 0
                || !requestQueryPairs.ContainsKey("timestamp")
                || !requestQueryPairs.ContainsKey("signature")
                || !requestQueryPairs.ContainsKey("nonce"))
            {
                return false;
            }

            string[] waitEncryptParamsArray = new[] { _wxToken, requestQueryPairs["timestamp"], requestQueryPairs["nonce"] };

            string waitEncryptParamStr = string.Join("", waitEncryptParamsArray.OrderBy(m => m));

            string encryptStr = HashAlgorithm.SHA1(waitEncryptParamStr);

            return encryptStr.ToLower().Equals(requestQueryPairs["signature"].ToLower());
        }

        /// <summary>
        /// 处理未授权请求
        /// </summary>
        /// <param name="actionContext">上下文</param>
        protected sealed override void HandleUnauthorizedRequest(HttpActionContext actionContext)
        {
            actionContext.Response = actionContext.Request.CreateResponse(
                HttpStatusCode.Unauthorized, new { status = "sign_error" });
        }
    }
}
 

 

将该特性声明在我们的微信Controller或者Action上,我们的签名校验便完成了。

二、首次提交验证申请

首次提交验证申请,微信服务器来调的时候是Get请求,而且要求我们将echostr原样返回。 注意,是原样返回。不是XML,也不是Json,<string>echostr</string>和"echostr"都是不行的!

囊中羞涩,本人使用的是虚拟主机搭载在原有的项目中,故新建微信区域(WeiXin)来实现。WeiXinAreaRegistration.cs文件如下:

 

public class WeiXinAreaRegistration : AreaRegistration
{
    public override string AreaName
    {
        get
        {
            return "WeiXin";
        }
    }

    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.Routes.MapHttpRoute(
            "WeiXinProcessor",
            "WeiXin/{controller}",
            new { controller = "Processor" }
        );
    }
}
 

 

新建Processor控制器,实现如下:

[WXAuthorize]
public class ProcessorController : ApiController
{
    public HttpResponseMessage Get()
    {
        var requestQueryPairs = Request.GetQueryNameValuePairs().ToDictionary(k => k.Key, v => v.Value);

        return new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = new StringContent(requestQueryPairs["echostr"]),
        };
    }
}

 

上述我们便实现了首次微信的验证。

三、接收消息

微信将请求的消息分为六种:文本消息、图片消息、语音消息、视频消息、地理位置消息、链接消息,其实我们还可以将事件推送也理解为其中一种。

将响应的消息分为六种: 1. 回复文本消息 2. 回复图片消息 3. 回复语音消息 4. 回复视频消息 5. 回复音乐消息 6. 回复图文消息 。我们在这儿主要使用文本消息和图文消息。

分析后我们发现,ToUserNameFromUserNameCreateTimeMsgType是所有消息共有的参数。同时也是我们响应时必需的参数。

我们创建消息基类和消息类型枚举如下

public class BaseMsg
{
    public string ToUserName { get; set; }

    public string FromUserName { get; set; }

    public long CreateTime { get; set; }

    public MsgType MsgType { get; set; }
}

public enum MsgType
{
    [XmlEnum("event")]
    Event,
    [XmlEnum("text")]
    Text,
    [XmlEnum("image")]
    Image,
    [XmlEnum("voice")]
    Voice,
    [XmlEnum("video")]
    Video,
    [XmlEnum("music")]
    Music,
    [XmlEnum("news")]
    News
}

 

此处枚举字段标注的XmlEnum稍候解释。

而后按照各消息类型的非共有的参数,分别创建对应消息的实体类

文本消息:

[XmlRoot("xml")]
public class TextMsg : BaseMsg
{
    public string Content { get; set; }
}

 图文消息:

[XmlRoot("xml")]
public class NewsMsg : BaseMsg
{
    public int ArticleCount { get; set; }

    [XmlArray("Articles")]
    [XmlArrayItem("item")]
    public List<NewsInfo> Articles { get; set; }
}

public class NewsInfo
{
    public string Title { get; set; }

    public string Description { get; set; }

    public string PicUrl { get; set; }

    public string Url { get; set; }
}

 等等。

接下来我们就可以开始接收微信的消息了

微信是通过Post,从正文中以XML的格式将参数传递过来的

var requestContent = Request.Content.ReadAsStreamAsync().Result;

 将正文参数读取出来后,转为Xml

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(requestContent);

 这样,我们便可以读取到我们需要的内容了

string msgTypeStr = xmlDoc.SelectSingleNode("xml/MsgType").InnerText;//消息类型
string userName = xmlDoc.SelectSingleNode("xml/FromUserName").InnerText;//来源用户标识
string efhName = xmlDoc.SelectSingleNode("xml/ToUserName").InnerText;//我们的用户标识

 而后,我们根据消息类型,进行进一步的处理。

转下一篇

第二篇:使用web api开发微信公众号,调用图灵机器人接口(二)

原文链接:http://efenghuo.com/blog/2498.aspx

2015-12-28 15:47:14 YYlxid 阅读数 1872
  • 安卓图灵聊天机器人接入开发

    通过本课程的学习,你将会学会图灵智能聊天机器人的接口开发,通过本次项目实战,你讲学会json数据的生成和解析,API文档的阅读和接口开发,http post 请求,动态增加View等核心知识点

    288 人正在学习 去看看 朱祚华

注意,微信在发送xml消息时,是通过post方式传递参数的

1、申请图灵机器人api

http://www.tuling123.com/

申请账号,接入虚拟机器人,获取api接入地址和api key


如果是直接填写到微信公众平台开发基本配置的 url和token里,则填写内容为


详见api使用文档


参考 http://blog.csdn.net/pamchen/article/details/38718947

http://www.jikexueyuan.com/course/445_3.html

所需包

Dom4j.jar (一个java的xml api,用来读写xml文件)

Httpcore.jar(用于http请求)

Httpclient.jar

Commons-logging.jar(否则执行“HttpClients.createDefault().execute(request);”会报错)

所涉及的类

 

TulingApiProcess 根据请求内容,访问图灵对应网页,获得结果

WeChat  微信xml消息处理

ReceiveXmlProcess对xml消息进行解析,

FormatXmlProcess将结果转换为xml格式

ReceiveXmlEntityxml消息实体类

首先获取xml消息,解析xml消息,判断消息类型,若为text则提交给图灵api处理,将处理结果转换为xml格式,在返回。

没有更多推荐了,返回首页