小的功能需求在生活的周围存在很多,这些功能需求的编程实现是学习的一种良好方式。对于给孩子读睡前故事是现阶段我这个家庭的需求,买了不少故事书,也有读,就想着将这些故事放到手机上也是一个不错的选择。
时下比较火热的「微信」是手机上呈现的一个不错的方式,于是着手规划这个小的功能需求,这个小的需求分为两部分,第一部分是服务器端对于故事的组织与管理;第二部分是服务器端与微信公众号之间的接口实现。
服务器端需要一个存储故事的数据库,用于存储故事数据,一组页面及其脚本来完成故事的管理,完成对应于数据库的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-