【微信公众平台开发】之二:高级功能开发(基于SAE)
导引:选择BAE还是SAE
*BAE3.0使用git推送每次修改非常爽,
本地修改>推送到oschina(自己留念)和BAE>点击发布>实际测试;
但是没有在线代码编辑功能!!中间出现问题就很坑爹,得重来一遍。
*SAE缺点是不能使用git,但可以在线编辑!(很多时候只是想验证新想法,在线编辑非常有用)。还有SAE可以上传多个版本的代码,比如版本1设为默认发布,版本2调试新功能a,版本3调试新功能b。而且不同版本可独立访问,调试起来非常方便。我一般先用“微信开发测试小助手”测试新功能可用,再将其添加到默认版本。
*微信开发模式页面需要填写服务器URL和Token,如果BAE可以多个版本共存,那么微信接口可以在SAE和BAE之间随意切换,而且BAE的版本回退好像有点问题。
*综上,BAE很坑,用SAE吧
0、资料
0.1、五星PHP+新浪SAE平台免费搭建微信公众帐号平台消息接口,实现查天气、无(http://coolwb.com/2460.html);
0.2、微信本地调试工具“Fiddler”(没用过)以及“微信开发测试小助手”(推荐这个);
1、对各类信息的回复以及图文回复
<?php /** * wechat php test * 主要用于本机测试 * by Jason * 2014.9.17 */ //define your token define("TOKEN", "weixin"); $wechatObj = new wechatCallbackapiTest(); //$wechatObj->valid(); 注释掉验证函数 $wechatObj->responseMsg();//调用回复信息方法 class wechatCallbackapiTest { public function valid() { $echoStr = $_GET["echostr"]; //valid signature , option if($this->checkSignature()){ echo $echoStr; exit; } } 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); $fromUsername = $postObj->FromUserName; $toUsername = $postObj->ToUserName; $keyword = trim($postObj->Content); $time = time(); //type为消息类型,customevent为事件类型 $type =$postObj->MsgType; $customevent =$postObj->Event; //经纬度 $weiDu = $postObj->Location_X; $jingDu= $postObj->Location_Y; $textTpl = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[%s]]></MsgType> <Content><![CDATA[%s]]></Content> <FuncFlag>0</FuncFlag> </xml>"; //接收事件推送,关注事件 if($type=="event" and $customevent=="subscribe"){ $msgType = "text"; $contentStr="感谢您的关注\n回复menu 查看本菜单\n回复1 查看联系方式\n回复2 查看小道消息\n回复3 查看办公地址\n回复图片查看新闻"; $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); echo $resultStr; } //单图文test,执行本句之后不再执行switch语句 //$this->replyNews1($fromUsername, $toUsername, $time); //接收普通消息 switch($type){ //文本消息 //文本消息0不适合在本地软件调试 case "text":{ if(!empty( $keyword )){ //关键词回复 if($keyword=="menu"){ $contentStr="感谢您的关注\n回复menu 查看本菜单\n回复1 查看联系方式\n回复2 查看小道消息\n回复3 查看办公地址\n回复news 查看新闻"; }else if($keyword==1){ $contentStr="联系方式:1007511108"; }else if($keyword==2){ $contentStr="小道消息正在加载,请稍候……"; }else if($keyword==3){ $contentStr="办公地址:大学城中心湖水下5米"; }else if($keyword=="news"){ $contentStr="";//设字符串为空 $this->replyNews1($fromUsername, $toUsername, $time); }else{ $contentStr="this is not a legal keyword,please try again"; } }else{ $contentStr="输入为空"; } break; } //图片消息 case "image": $contentStr="这张图真好看"; break; //语音消息 case "voice": sleep(2); $contentStr="嗯……你声音真好听"; break; //视频消息 case "video": sleep(3); $contentStr="这部片子不是我喜欢的类型"; break; //地理位置消息 case "location":{ $contentStr="你的纬度是{$weiDu},经度是{$jingDu},捕食者1号已锁定目标!"; break; } //链接消息 case "link": $contentStr="你确定发送的链接没有病毒??"; break; //消息不是以上类型 default: $contentStr="此项功能尚未开发"; break; } //统一输出 $msgType = "text"; $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); echo $resultStr; }else { echo ""; exit; } } //发送消息 //音乐回复 function replyMusic(){ } //单图文回复 function replyNews1($fromUsername, $toUsername, $time){ $newsTpl="<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[news]]></MsgType> <ArticleCount>1</ArticleCount> <Articles> <item> <Title><![CDATA[食品安全关乎人民群众的切身利益]]></Title> <Description><![CDATA[这个news很难Description]]></Description> <PicUrl><![CDATA[http://lawlietfans.duapp.com/picture/big1.png]]></PicUrl> <Url><![CDATA[http://www.baidu.com]]></Url> </item> </Articles> </xml> "; $resultStr = sprintf($newsTpl, $fromUsername, $toUsername, $time); echo $resultStr; } //多图文回复 function replyNews2(){ } private function checkSignature() { // you must define TOKEN by yourself if (!defined("TOKEN")) { throw new Exception(‘TOKEN is not defined!‘); } $signature = $_GET["signature"]; $timestamp = $_GET["timestamp"]; $nonce = $_GET["nonce"]; $token = TOKEN; $tmpArr = array($token, $timestamp, $nonce); // use SORT_STRING rule sort($tmpArr, SORT_STRING); $tmpStr = implode( $tmpArr ); $tmpStr = sha1( $tmpStr ); if( $tmpStr == $signature ){ return true; }else{ return false; } } } ?>
2、API
2.1、图灵机器人
这是我发现的最好的免费智能机器人,查看(http://www.tuling123.com)的帮助文档按照步骤做即可,很简单。
然后解析api返回的json数据即可:
$apiStr = file_get_contents($url); $apiObj =json_decode($apiStr); $contentStr = $apiObj->text;
2.2、LBS开发:百度地图
占位
3、数据库
官方文档(http://sae.sina.com.cn/doc/php/mysql.html)
试图在SAE平台使用BAE中的数据库是行不通的(我还傻傻想为什么),在那家平台就当然要用那家数据库;
首先参考(四星http://blog.csdn.net/zh379835552/article/details/39160967)
和(五星http://www.cnblogs.com/mchina/p/3332283.html)进入mysqlMyAdmin控制台;
接着创建表weixin并插入数据
CREATE TABLE IF NOT EXISTS `weixin` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`content` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
)
-- 转存表中的数据 `weixin`
INSERT INTO `weixin` (`id`, `title`, `content`) VALUES
(1, ‘中国合伙人‘, ‘导演:陈可辛;编剧:张冀‘),
(2, ‘死亡笔记‘, ‘导演:dy;编剧:bj‘);
接着编辑php代码,运行即可成功(注释详细,一看就会)
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh"> <head> <meta http-equiv="content-type" content="text/html;charset=utf-8"/> <title>database data test</title> </head> <body> <?php //echo "Welcome to Sina Cloud"; //SAE的mysql是utf8编码的所以需要在meta标签中指定页面的charset为utf-8 //从环境变量中取出数据库所要的参数 $host=getenv(‘SAE_MYSQL_HOST_M‘); $port=getenv(‘SAE_MYSQL_PORT‘); $user=getenv(‘SAE_MYSQL_USER‘); $pwd=getenv(‘SAE_MYSQL_PASS‘); /***配置数据库名称,全局名MYSQLNAME或者$dbname ***/ define("MYSQLNAME", "sNAwDmdhLkhSLCmATYsf"); $dbname=‘app_lawlietfans‘; //定义好的参数 /*接着调用mysql_connect()连接服务器,可以用上面赋值之后的host、port、user、pwd来替代这里的参数*/ $link = mysql_connect(SAE_MYSQL_HOST_M.‘:‘.SAE_MYSQL_PORT,SAE_MYSQL_USER,SAE_MYSQL_PASS); if(!$link) { die("Connect Server Failed: " . mysql_error()); } /*连接成功后立即调用mysql_select_db()选中需要连接的数据库*/ if(!mysql_select_db($dbname,$link)) { die("Select Database Failed: " . mysql_error($link)); } /*至此连接已完全建立,就可对当前数据库进行相应的操作了*/ /*!!!注意,无法再通过本次连接调用mysql_select_db来切换到其它数据库了!!!*/ /* 需要再连接其它数据库,请再使用mysql_connect+mysql_select_db启动另一个连接*/ /** * 接下来就可以使用其它标准php mysql函数操作进行数据库操作 */ //检索数据 $sql = "select * from weixin"; $rs = mysql_query($sql, $link); if ($rs === false) { die("Select Failed: " . mysql_error($link)); } else { echo "Select Succeed<br />"; while ($row = mysql_fetch_assoc($rs)) { echo "{$row[‘id‘]} {$row[‘title‘]} {$row[‘content‘]}<br />"; } } ?> </body> </html>
接着在做一个查询电影的功能也很简单。
4、超链接调用其他wap站应用
对工具类的功能来说,与其在微信中找各种接口不如直接调用其他wap站更好,(http://r2.mo.baidu.com/webapp_html.php?version=4_0&fn=webpage_flash)有一些wap站可以参考,推荐(http://m.46644.com/tool/);
有了这些链接,可以以超链接或者图文消息
(若“text”格式则需要XML转义字符:
< | < |
> | > |
& | & |
‘ | ' |
" | " |
)的形式引导用户直接访问需要的功能。(当然,如果有自己的wap站点更好。也可使用百度siteapp将普通站点一件转换为wap站)
5、缓存
如果要实现二级菜单,需要记住用户当前在菜单逻辑中的位置。微信服务器不支持cookie和session,使用数据库速度太慢,所以要使用缓存来实现此功能。
文档(http://sae.sina.com.cn/doc/php/memcache.html);
实现图灵机器人智能聊天和普通功能之间的切换;(得瑟下,效果非常好\(^o^)/)
//初始化SAE的缓存 $mem=memcache_init(); if($mmc==false) echo "mc init failed\n"; $strUser = $mem->get($fromUsername."key");//获取缓存值 //接下来修改前面代码case “text” 部分 case "text":{ if(empty($strUser)){ if($keyword=="chat"){ //设置缓存变量$fromUsername."key" $mem->set($fromUsername."key",$fromUsername."chat",$flag=0,$expire=0); $contentStr="开始和luffy君进行对话,输入#退出聊天"; }else if($keyword=="menu"){ $contentStr="回复menu 查看本菜单\n回复1、2、3、news查看消息\n回复chat和luffy君聊天"; }else if($keyword==1){ $contentStr="联系方式:1007511108"; }else if($keyword==2){ $contentStr="小道消息正在加载,请稍候……"; }else if($keyword==3){ $contentStr="办公地址:大学城中心湖水下5米"; }else if($keyword=="news"){ $contentStr="";//设字符串为空 $this->replyNews1($fromUsername, $toUsername, $time); }else{ $contentStr="回复menu 查看本菜单\n回复1、2、3、news查看消息\n回复chat和luffy君聊天"; } } else { if($keyword=="#"){ $contentStr="已经退出聊天,输入chat重新开始聊天"; $strUser=$mem->delete($fromUsername."key"); }else{ //判断是否为同一用户发送聊天请求 if($strUser==$fromUsername."chat"){ $apiKey = "你的API key"; $apiURL = "http://www.tuling123.com/openapi/api?key=KEY&info=INFO"; // 设置报文头, 构建请求报文 //header("Content-type: text/html; charset=utf-8"); $url = str_replace("INFO", $keyword, str_replace("KEY", $apiKey, $apiURL)); // 用file_get_contents 以get方式获取内容 //读取json类型数据 $apiStr = file_get_contents($url); $apiObj =json_decode($apiStr); $contentStr = $apiObj->text; } } } break; }
6、补充
学习别人的优秀框架:(http://sae.sina.com.cn/?m=appstore&category=2)
其中第一个开源到github,fork之后有空研究。在此感谢作者。