我已将博客放到csdn平台了,后面也是打算在csdn上编写博客,本文在csdn博客的地址:http://blog.csdn.net/wsa518/article/details/51112020
上一篇博客我介绍了如何申请一个新浪云,并创建一个云应用,应用的开发语言为PHP。这篇博客将详细介绍编码实现微信公众号智能聊天功能。
大家先打开微信公众号的开发文档:https://mp.weixin.qq.com/wiki,找到“接入指南”
将官方的PHP代码文件下载下来:
解压缩后修改文件名并拷贝到我们的项目(从新浪云svn上Check Out下来的项目)中,如下图所示(这里我删除了“config.yaml”文件和替换了“index.php”文件):
紧接着修改下代码中的TOKEN值:
现在我们通过svn将代码提交到新浪云上,去微信公众号后台的“开发” -> “基本配置”中修改下配置:
修改配置中的URL就是新浪云应用的地址,Token就是代码中定义的TOKEN常量,EncodingAESKey随机生成就行了(主要用来加密使用,这篇博客不讲解),点击“提交”按钮,正常情况下应该是配置成功的,如果有人没有配置成功可以尝试网上搜索下解决方案,实在没辙,发邮箱wsa518@yeah.net或者博客私聊我都行:
好了,和微信对接上后,我们要开始写代码咯:
先创建一个名叫TuringRobot类,用来处理图灵机器人的逻辑,这里我暂时只实现了图灵机器人的文本、链接、新闻和菜谱消息的处理,有兴趣的可以再深入研究下其他类型的回复:
<?php
/**
* Created by PhpStorm.
* User: Ainsworth
* Date: 16/4/9
* Time: 下午5:20
*/
define("TURING_API_URL", "http://www.tuling123.com/openapi/api");
define("TURING_API_KEY", "您申请的图灵机器人Api Key");
class TuringRobot
{
/**
* 获取图灵机器人的回复
*
* @param $content
* @param $user_id
* @return string
*/
public function getInfo($content, $user_id)
{
$url = TURING_API_URL . "?key=" . TURING_API_KEY . "&info=" . $content . "&userid=" . $user_id;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
return json_decode($output, true);
}
/**
* 回复文本消息
*
* @param $info
* @return mixed
*/
public function textInfo($info)
{
return $info["text"];
}
/**
* 回复链接消息
*
* @param $info
* @return string
*/
public function linkInfo($info)
{
return $info["text"] . "\n" . $info["url"];
}
/**
* 回复新闻消息
*
* @param $info
* @return string
*/
public function newsInfo($info)
{
$news = $info["text"] . "\n\n";
$list = $info["list"];
foreach ($list as $l) {
error_log($l["icon"]);
$news .= $l["article"] . "\n" . $l["detailurl"] . "\n";
}
return $news;
}
/**
* 回复菜谱消息
*
* @param $info
* @return array
*/
public function cookbookInfo($info)
{
$new_list = array();
$list = $info["list"];
for ($i = 0; $i < count($list); $i++) {
// 由于微信图文消息最多发8条, 所以这边限制下
if ($i > 8) break;
$new_list[$i] = array("title" => $list[$i]["name"],
"description" => $list[$i]["info"],
"picurl" => $list[$i]["icon"],
"url" => $list[$i]["detailurl"]);
}
error_log(serialize($new_list));
return $new_list;
}
}
接下来我们回到index.php文件中,在wechatCallbackapiTest类中加入文本和图片消息的微信回复格式处理:
/**
* 回复文本消息模板
*
* @param $obj
* @param $content
* @return string
*/
private function textTemplate($obj, $content)
{
$time = time();
return "<xml>
<ToUserName><![CDATA[$obj->FromUserName]]></ToUserName>
<FromUserName><![CDATA[$obj->ToUserName]]></FromUserName>
<CreateTime>$time</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[$content]]></Content>
</xml>";
}
/**
* 回复图文消息模板
*
* @param $obj
* @param $news
* @return string
*/
private function newsTemplate($obj, $news)
{
$time = time();
$num = count($news);
$textTpl = "<xml>
<ToUserName><![CDATA[$obj->FromUserName]]></ToUserName>
<FromUserName><![CDATA[$obj->ToUserName]]></FromUserName>
<CreateTime>$time</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<ArticleCount>$num</ArticleCount>
<Articles>";
foreach ($news as $new) {
$textTpl .= $this->transmitNewItem($new["title"], $new["description"], $new["picurl"], $new["url"]);
}
$textTpl .= "</Articles></xml>";
return $textTpl;
}
private function transmitNewItem($title, $description, $picurl, $url)
{
return "<item>
<Title><![CDATA[$title]]></Title>
<Description><![CDATA[$description]]></Description>
<PicUrl><![CDATA[$picurl]]></PicUrl>
<Url><![CDATA[$url]]></Url>
</item>";
}
写好后,加入一个处理文本消息的函数(即我们在微信公众号里发送聊天的文本内容,根据发送过来的内容做一些处理):
/**
* 接受文本消息并处理
*
* @param $obj
* @return string
*/
private function receiveText($obj)
{
$content = $obj->Content;
// 图灵机器人消息处理
$robot = new TuringRobot();
$info = $robot->getInfo($content, $obj->FromUserName);
switch ($info["code"]) {
case 100000: // 文本类
return $this->textTemplate($obj, $robot->textInfo($info));
case 200000: // 链接类
return $this->textTemplate($obj, $robot->linkInfo($info));
case 302000: // 新闻类
return $this->textTemplate($obj, $robot->newsInfo($info));
case 308000: // 菜谱类
return $this->newsTemplate($obj, $robot->cookbookInfo($info));
case 313000: // 儿歌类(儿童版)
case 314000: // 诗歌类(儿童版)
default:
return "亲,你能说的再简单点吗?我有点理解不过来啦!";
}
}
在responseMsg函数中调用(这里我删除了一些暂时不使用的代码,大家按照我写的来即可),这里我也只处理了文本消息,如果你对公众号发送图片或者语音什么的,我这边默认是统一回复“亲,你说的是啥,我只能理解文字啊!”:
public function responseMsg()
{
//get post data, May be due to the different environments
$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
//extract post data
if (!empty($postStr)) {
/* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection,
the best way is to check the validity of xml by yourself */
libxml_disable_entity_loader(true);
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
$result = '';
switch ($postObj->MsgType) {
case 'event':
// 关注后自动回复
if ($postObj->Event == 'subscribe') {
$result = $this->textTemplate($postObj, 'hi,你怎么才关注我,我都等你一万年了!');
}
break;
case 'text': // 文本消息
$result = $this->receiveText($postObj);
break;
case 'image': // 图片消息
case 'voice': // 语言消息
case 'video': // 视频消息
case 'shortvideo': // 小视频消息
case 'link': // 链接消息
default:
$result = $this->textTemplate($postObj, '亲,你说的是啥,我只能理解文字啊!');
break;
}
echo $result;
} else {
echo '';
exit;
}
}
最后,把index.php头部位置的代码改下:
$wechatObj = new wechatCallbackapiTest();
$wechatObj->valid();
改为:
$wechat = new wechatCallbackapiTest();
if (isset($_GET["echostr"])) {
$wechat->valid();
} else {
$wechat->responseMsg();
}
还有别忘了引入TuringRobot.php哦!
include 'TuringRobot.php';
将所有的代码提交至新浪云上,回到微信公众平台点击“启用”:
下面我们来测试一下:
最后的最后呢,我放上我的公众号二维码,大家可以测试看看!(最后我建议如果公众号已经在运营阶段,最好是开发的时候本地测试,可以去看我的这篇博客:http://my.oschina.net/wanggong/blog/648671)