选择BAE还是SAE?
* BAE3.0使用git推送每次修改非常爽,
1> 本地修改
2> 推送到oschina(自己留念)和BAE
3> 点击发布>实际测试;
但是没有在线代码编辑功能!!中间出现问题就很坑爹,得重来一遍。
* SAE缺点是不能使用git,但可以在线编辑!(很多时候只是想验证新想法,在线编辑非常有用)。
还有SAE可以上传多个版本的代码,比如版本1设为默认发布,版本2调试新功能a,版本3调试新功能b。而且不同版本可独立访问,调试起来非常方便。
我一般先用“微信开发测试小助手”测试新功能可用,再将其添加到默认版本。
* 微信开发模式页面需要填写服务器URL和Token,如果BAE可以多个版本共存,那么微信接口可以在SAE和BAE之间随意切换,而且BAE的版本回退好像有点问题。
*综上,BAE很坑,用SAE吧
本地测试推荐“微信开发测试小助手”
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="联系方式:666";
}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开发:百度地图
http://my.oschina.net/SnifferApache/blog/317701
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,使用数据库速度太慢,所以要使用缓存来实现此功能。(see also 文档)
实现图灵机器人智能聊天和普通功能之间的切换;
//初始化SAE的缓存
$mem=memcache_init();
if($mem==false)
echo "mem cache 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="联系方式:666";
}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;
}