司开星的博客

SAE 上使用PHP搭建微信公众号后台

准备阶段

SAE准备

SAE的应用平台提供了一个语言环境。比如提供了PHP环境的应用即可运行PHP代码。当然环境中也可以放HTML和CSS,将要展示的页面命名为index.html即可。

SAE的申请略过。创建一个PHP5.6空应用,代码管理中打开git。本地文件就可以通过Git命令上传到SAE上了。具体命令SAE页面有写。
应用有个地址,记下来,需要填到微信中。

微信准备

申请微信公众号略过。在后台的开发项中修改配置。其中:

  • URL:填刚刚SAE中创建的应用地址
  • Token:自己想填什么都可以
  • EncodingAESKey:可以随机生成的加密密钥
  • 加解密方式:一开始建议明文,熟悉了之后可以使用密文模式

之后需要在SAE的应用端验证一下这个地址可用才能启用开发者模式。
参考微信官方文档:http://mp.weixin.qq.com/wiki/8/f9a0b8382e0b77d87b3bcc1ce6fbc104.html ,直接把PHP示例代码下载下来,代码里的TOKEN填刚刚配置中填的,文件名修改为index.php。
接着通过Git上传到SAE中。
确定上传完成后即可点击微信后台中的启用,如果SAE上正常运行了刚刚上传的php的话就能够启用成功。

开始写后台

官方代码

刚刚下载的示例代码不仅有验证函数,还有一个用于响应公众号用户消息的函数responseMsg()。我们先试着用示例代码写一些功能。
将刚刚修改的本地index.php文件中的$wechatObj->valid();注释掉,在下面添加一行$wechatObj->responseMsg(); 再次上传修改 git commit,git push。如果代码正常上传的话你给这个公众号发消息应该都能收到回复了。

写一个获取天气的功能

通过API获取天气信息并返回

网上搜索得到一个简单的天气查询网址:http://mobile.weather.com.cn/data/sk/101340101.htmlhttp://mobile.weather.com.cn/data/sk/101340101.html ,其中101340101表示weather.com.cn使用的城市编码,所有对应编码可见参考资料2。这里我们将参考资料2的所有对应编码保存到本地weathercode.xml中。
更新:weather.com.cn的接口无法使用了。使用http://www.heweather.com代替。(先在官网申请账户,API https://api.heweather.com/x3/weather?cityid=城市ID&key=你的认证key)

此处我们选择使用cURL的方式获取网页返回,因为这种方式比较方便且SAE官方声明支持cURL(http://www.sinacloud.com/doc/sae/php/fetchurl.html?highlight=curl)

根据参考资料5的示例代码可以写出获取台北天气的代码如下:

1
2
3
4
5
6
7
<?php
//$wt = curl_init("http://mobile.weather.com.cn/data/sk/101340101.html");
$wt = curl_init("https://api.heweather.com/x3/weather?cityid=CN101340101&key=你的认证key
curl_setopt($wt,CURLOPT_RETURNTRANSFER,1);
$weatherjson = curl_exec($wt);
curl_close($wt);
?>

要获取指定城市的天气需要读取xml。但读取xml较麻烦(见参考资料6),于是将weathercode.xml手动转换为json格式。读取文件并转换为数组的代码如下:

1
2
$jsoncontent = file_get_contents('weathercode.json');
$weatherarray = json_decode($jsoncontent);

对于获取的json由于层数太多使用PHP处理太复杂,直接使用正则表达式获取需要的内容:

1
2
3
4
<?php
preg_match("/\"now\":{.*?{.*?}.*?}.*?}/",$json,$matches);
echo $matches[0];
?>

实现功能的完整的代码部分如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
if(!empty( $keyword ))
{
if(strpos($keyword,"天气")!==false)
{
//get weather by user input
$location = str_ireplace("天气", "",$keyword);
$jsoncontent = file_get_contents('weathercode.json');
$locationarray = json_decode($jsoncontent, true);
$locationcode = $locationarray[$location];
$cncode = "CN" . $locationcode;

//weather can't use,use heweather instead
//$wt = curl_init("http://mobile.weather.com.cn/data/sk/$locationcode.html");
$wt = curl_init("https://api.heweather.com/x3/weather?cityid=$cncode&key=你的认证key");

curl_setopt($wt,CURLOPT_RETURNTRANSFER,1);
//curl_setopt($wt,CURLOPT_REFERER,'http://mobile.weather.com.cn/');
$weatherjson = curl_exec($wt);
//the limit of word
//$weatherarray = json_decode($weatherjson);
//$weathernow = $weatherarray->{'HeWeather data service 3.0'};
curl_close($wt);
preg_match("/\"now\":({.*?{.*?}.*?}.*?})/",$weatherjson,$matches);
$weathernow = $matches[1];
$msgType = "text";
$contentStr = $weathernow;
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;

}

格式化返回的数据

返回的数据类似于:

1
"now":{"cond":{"code":"101","txt":"多云"},"fl":"11","hum":"46","pcpn":"0","pres":"1021","tmp":"12","vis":"10","wind":{"deg":"120","dir":"东风","sc":"3-4","spd":"11"}}

根据官方API说明,通过正则获取内容,即可获得格式化的内容。

添加对错误城市的处理

有些时候用户会输入不存在的城市天气查询,这样返回的结果比较不好看。可以加一个判断部分,在输入不存在的城市时提示检查输入:

1
2
3
4
5
6
7
8
9
if($locationcode) {

……

}
else {
$contentStr = "没有找到这个城市哦~ 请确认城市或区名。示例1: 南京天气; 示例2: 海淀天气";
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;

这样天气查询的代码就算完成了~

参考资料:

  1. 《中国天气网 天气预报API 国家气象局 根据城市名称抓取城市ID,XML格式、JSON格式、图片代码》
  2. 《中国天气网天气预报API接口城市代码,XML格式,数据具体到县、区级别》
  3. 《【荐】怎么用PHP发送HTTP请求(POST请求、GET请求)?》
  4. 《curl网站开发指南》
  5. 《http://php.net/manual/zh/book.curl.php》
  6. 《PHP通过SimpleXML访问xml文档》
  7. 《json_decode》
  8. 《PHP创建和解析JSON数据的方法》
  9. 《在PHP语言中使用JSON》
  10. 《PHP高级特性一之正则表达式用法》