小的功能需求在生活的周围存在很多,这些功能需求的编程实现是学习的一种良好方式。对于给孩子读睡前故事是现阶段我这个家庭的需求,买了不少故事书,也有读,就想着将这些故事放到手机上也是一个不错的选择。
时下比较火热的「微信」是手机上呈现的一个不错的方式,于是着手规划这个小的功能需求,这个小的需求分为两部分,第一部分是服务器端对于故事的组织与管理;第二部分是服务器端与微信公众号之间的接口实现。
服务器端需要一个存储故事的数据库,用于存储故事数据,一组页面及其脚本来完成故事的管理,完成对应于数据库的ADU相关操作。剩下的就是与微信的接口部分,通过微信公众号的自定义菜单获取每日睡前故事,通过脚本依据当日信息组成微信公众号的图文信息,点击后展现故事。
最终的阅读操作如图所示「如果你也有这样的需求,可通过微信搜索smallsoftware关注即可使用,也可在微信中扫描本Blog右侧二维码直接关注」:
微信接口这部分主要是从数据库中获得数据,然后组织成图文信息即可,根据微信自定义菜单的KEY完成组装即可。
$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
if(!empty($postStr)) {
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
$fromUser = $postObj->FromUserName;
//详细请参看微信公众帐号开发接口文档
//...
$fromMsgType = $postObj->MsgType;
//...
if($fromMsgType == "event") {
$formEvent = $postObj->Event;
if($formEvent == "CLICK") {
$eventKey = $postObj->EventKey;
if($eventKey == 'YOUR_KEY') {
//取数据
//组织图文信息数据
//输出
} else { //... }
}
}
//......
服务器端包含故事的添加、修改、删除、查看,用于后台对于故事的管理。使用了Bootstrap前端框架的部分内容,具体的结构如下。
数据库类基于PDO,故事类继承数据库类,完成故事的数据相关操作封装及故事的展现,admin类完成权限和管理的封装,前端页面通过init入口完成对于数据的管理工作,init入口部分完成数据的初始化工作与上下交互操作。
没有其他可供的选择,每天一篇睡前故事,对于选择性故事的定制阅读及过往的查询不支持,对于用户阅读这部分的统计也没有完成,可以说留下了不少的坑等着填。
至于微信自定义菜单,根据其接口文档中的说明,先要由appid和secret通过一个URL用Get方式获得AccessToken,然后将准备好的菜单和获得的AccessToken通过一个URL用POST的方式提交数据,从而创建自定义菜单。
<!--?php
class WechatMenu {
private $_appid = ""; //你的appid
private $_secret = ""; //你的secret
function __construct($menu) {
//先获得AccessToken
$result = $this--->getAccessToken();
if(array_key_exists('errcode', $result)) {
throw new Exception($result['errmsg'], 1);
} else {
$url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=" . $result['access_token'];
$result = $this->Post($url, $menu);
if($result['errcode'] == 0) {
//ok
} else {
throw new Exception($result['errcode'], 1);
}
}
}
private function Post($url, $data) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
$data = curl_exec($ch);
curl_close($ch);
return json_decode($data,true);
}
private function Get($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
$data = curl_exec($ch);
curl_close($ch);
return json_decode($data,true);
}
private function getAccessToken() {
$grant_type = "client_credential";
$appid = $this->appid;
$secret = $this->secret;
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type={$grant_type}&appid={$appid}&secret={$secret}";
$result = $this->Get($url);
return $result;
}
}
?>
调用 (1) 生成json格式的菜单数据 (2)new WechatMenu($menu);
-EOF-