├── screenshot
├── hotest.png
├── menu.png
├── random.png
├── recent.png
├── search.png
├── visit_wp.png
├── weishequ.png
└── custom_menu.png
├── LICENSE
├── README.md
├── functions.php
├── wechat-robot.php
└── wechat.php
/screenshot/hotest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangvsa/wechat-robot/HEAD/screenshot/hotest.png
--------------------------------------------------------------------------------
/screenshot/menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangvsa/wechat-robot/HEAD/screenshot/menu.png
--------------------------------------------------------------------------------
/screenshot/random.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangvsa/wechat-robot/HEAD/screenshot/random.png
--------------------------------------------------------------------------------
/screenshot/recent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangvsa/wechat-robot/HEAD/screenshot/recent.png
--------------------------------------------------------------------------------
/screenshot/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangvsa/wechat-robot/HEAD/screenshot/search.png
--------------------------------------------------------------------------------
/screenshot/visit_wp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangvsa/wechat-robot/HEAD/screenshot/visit_wp.png
--------------------------------------------------------------------------------
/screenshot/weishequ.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangvsa/wechat-robot/HEAD/screenshot/weishequ.png
--------------------------------------------------------------------------------
/screenshot/custom_menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangvsa/wechat-robot/HEAD/screenshot/custom_menu.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 王辰
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Wechat Robot
2 | ============
3 | Wechat Robot是一个WordPress插件,实现了WP站点和微信公众号的连接,支持自动回复、文章搜索、订阅回复、微社区入口等功能。
4 | Wechat Robot使用PHP语言,稍作改动可以即可以在非Wordpress环境下使用。
5 |
6 |
7 |
8 | ## 功能列表
9 | - 自定义菜单
10 | - 访问WP网站
11 | - 查看最新文章
12 | - 查看随机文章
13 | - 查看热门文章
14 | - 关键字搜索
15 | - 访问FB社区
16 | - 订阅时显示欢迎菜单
17 |
18 |
19 |
20 | ## 功能截图
21 | 本插件原为[Freebuf](http://www.freebuf.com)编写,在这直接用Freebuf公众号演示,大家也可以微信关注Freebuf自己体验。
22 |
23 | - 自定义菜单
24 | 
25 | - 显示欢迎菜单,输入任何不被识别的字符串均可
26 | 
27 | - 回复0可以访问主站
28 | 
29 | - 回复1查看最新文章
30 | )
31 | - 回复2查看随机文章
32 | 
33 | - 回复3查看热门文章(本月)
34 | 
35 | - 回复4+关键字进行搜索
36 | 
37 | - 回复5访问FB社区
38 | 
39 |
40 |
41 |
42 | ## 安装使用
43 | 1. 下载本插件,编辑文件wechat-robot.php
44 | * 修改WechatRobot构造函数参数中的`appid`和`secret`
45 | * 若支持菜单则参照[微信API](http://mp.weixin.qq.com/wiki/index.php?title=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95%E5%88%9B%E5%BB%BA%E6%8E%A5%E5%8F%A3)填写`create_menu`中的菜单参数,然后按需修改`onClick`函数来响应菜单点击事件。
46 | * 若不支持菜单,则注释掉`create_menu`调用即可。
47 | * 按需修改`onText`函数和`onSubscribe`函数,响应用户信息和订阅事件。
48 | 2. 将wechat-robot目录上传到WP目录`/wp-content/plugins/`,然后在WP后台开启本插件。
49 | 3. 进入微信公众账号后台,开启高级功能->开发模式,填写token和url
50 | token填写`wechat`,url填写`你的网站地址/?wechat`,比如`http://www.freebuf.com/?wechat`,注意不要省略`http://`
51 |
52 | ## 详细文档
53 | 见[API wiki](https://github.com/wangvsa/wechat-robot/wiki/API文档)
54 |
55 |
--------------------------------------------------------------------------------
/functions.php:
--------------------------------------------------------------------------------
1 | ID);
38 | if ( $thumbnail_id ) {
39 | $thumb = wp_get_attachment_image_src($thumbnail_id, $size);
40 | $thumb = $thumb[0];
41 | }
42 |
43 | if (empty($thumb)) {
44 | $thumb = 'http://www.freebuf.com/buf/themes/freebuf/images/logo2.jpg';
45 | }
46 |
47 | return $thumb;
48 | }
49 |
50 | /**
51 | * GET 请求
52 | * @param string $url
53 | * @return string $result
54 | */
55 |
56 | function http_get($url) {
57 | $oCurl = curl_init();
58 | if(stripos($url,"https://")!==FALSE) {
59 | curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, false);
60 | curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
61 | }
62 |
63 | curl_setopt($oCurl, CURLOPT_URL, $url);
64 | curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
65 |
66 | $result = curl_exec($oCurl);
67 | $status = curl_getinfo($oCurl);
68 | curl_close($oCurl);
69 |
70 | if(intval($status["http_code"])==200)
71 | return $result;
72 | return $status["http_code"];
73 | }
74 |
75 |
76 | /**
77 | * POST 请求
78 | * @param string $url
79 | * @param array $param
80 | * @return string $result
81 | */
82 | function http_post($url, $param) {
83 |
84 | $oCurl = curl_init();
85 |
86 | if(stripos($url,"https://")!==FALSE){
87 | curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, false);
88 | curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
89 | }
90 |
91 | if (is_string($param)) {
92 | $strPOST = $param;
93 | } else {
94 | $aPOST = array();
95 | foreach($param as $key=>$val) {
96 | $aPOST[] = $key."=".urlencode($val);
97 | }
98 | $strPOST = join("&", $aPOST);
99 | }
100 |
101 | curl_setopt($oCurl, CURLOPT_URL, $url);
102 | curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );
103 | curl_setopt($oCurl, CURLOPT_POST,true);
104 | curl_setopt($oCurl, CURLOPT_POSTFIELDS,$strPOST);
105 |
106 | $result = curl_exec($oCurl);
107 | $status = curl_getinfo($oCurl);
108 | curl_close($oCurl);
109 | if(intval($status["http_code"])==200)
110 | return $result;
111 | return $status["http_code"];
112 | }
113 | ?>
114 |
--------------------------------------------------------------------------------
/wechat-robot.php:
--------------------------------------------------------------------------------
1 | create_menu('{
19 | "button":[
20 | {
21 | "name":"阅读文章",
22 | "sub_button":[
23 | {
24 | "type":"click",
25 | "name":"最新文章",
26 | "key":"MENU_RECENT_POSTS"
27 | },
28 | {
29 | "type":"click",
30 | "name":"随机文章",
31 | "key":"MENU_RANDOM_POSTS"
32 | },
33 | {
34 | "type":"click",
35 | "name":"热门文章",
36 | "key":"MENU_HOTEST_POSTS"
37 | }
38 | ]
39 | },
40 | {
41 | "type":"view",
42 | "name":"FB主页",
43 | "url":"http://www.freebuf.com"
44 | },
45 | {
46 | "type":"view",
47 | "name":"微社区",
48 | "url":"http://wx.wsq.qq.com/187329269"
49 | }]
50 | }');
51 | $robot->run();
52 | }
53 | }
54 |
55 |
56 | class WechatRobot extends Wechat {
57 |
58 | protected function queryAndResponse( $arg ) {
59 | $the_query = new WP_Query( $arg );
60 | if( $the_query->have_posts() ) {
61 |
62 | $counter = 0;
63 | $items = array();
64 |
65 | while( $the_query->have_posts() ) {
66 | $the_query->the_post();
67 | global $post;
68 |
69 | $title = get_the_title();
70 | $link = get_permalink();
71 | $excerpt = wechat_get_excerpt( get_the_excerpt() );
72 |
73 | if ( $counter == 0 ) {
74 | $thumb = wechat_get_thumb($post, array(640, 320));
75 | } else {
76 | $thumb = wechat_get_thumb($post, array(80, 80));
77 | }
78 |
79 | $new_item = new NewsResponseItem($title, $excerpt, $thumb, $link);
80 | array_push($items, $new_item);
81 |
82 | // 最多显示3篇
83 | if ( ++$counter == 3 )
84 | break;
85 | }
86 |
87 | $this->responseNews($items);
88 |
89 | } else {
90 | $this->responseText("不好意思~没有找到您想要的东东~请换个关键字再试试?");
91 | }
92 |
93 | wp_reset_postdata();
94 |
95 | }
96 |
97 | protected function searchPosts( $key ) {
98 | $arg = array( 's' => $key );
99 | $this->queryAndResponse( $arg );
100 | }
101 |
102 | protected function recentPosts() {
103 | $arg = array( 'ignore_sticky_posts'=>1, 'showposts' => 3 );
104 | $this->queryAndResponse( $arg );
105 | }
106 |
107 | protected function randomPosts() {
108 | $arg = array ( 'ignore_sticky_posts' => 1, 'orderby' => 'rand' );
109 | $this->queryAndResponse( $arg );
110 | }
111 |
112 | protected function hotestPosts() { // 本月最热门
113 | $arg = array (
114 | 'ignore_sticky_posts' => 1,
115 | 'orderby' => 'comment_count',
116 | 'year' => date('Y'),
117 | 'monthnum' => date('m')
118 | );
119 | $this->queryAndResponse( $arg );
120 | }
121 |
122 |
123 | protected function onText() {
124 | $msg = $this->getRequest('content');
125 | if( $msg == '0' ) {
126 | $this->responseText("访问FreeBuf黑客与极客,请点击下面连接:\n http://www.freebuf.com ");
127 | } else if( $msg == '5' ) {
128 | $this->responseText("访问FB社区,请点击下面连接:\n http://wx.wsq.qq.com/187329269 ");
129 | } else if( $msg == '1' ) {
130 | $this->recentPosts();
131 | } else if ( $msg == '2' ) {
132 | $this->randomPosts();
133 | } else if ( $msg == '3' ) {
134 | $this->hotestPosts();
135 | } else if ( strncmp($msg, '4', 1)==0 ) { // starts with '4'
136 | if( strlen($msg) == 1 ) {
137 | $this->responseText("您没有输入关键字,要输入[4关键字]进行搜索哦,比如 4黑客 ");
138 | } else {
139 | $this->searchPosts( substr($msg, 1, strlen($msg)-1) );
140 | }
141 | } else {
142 | $this->responseText("欢迎关注FreeBuf黑客与极客\n 回复[0]访问FreeBuf\n 回复[1]查看最新文章".
143 | "\n 回复[2]查看随机文章\n 回复[3]查看热门文章\n 回复[4关键字]搜索文章\n 回复[5]访问FB社区\n 回复其他内容查看本菜单");
144 | }
145 | }
146 |
147 | protected function onSubscribe() {
148 | $this->responseText("欢迎关注FreeBuf黑客与极客\n 回复[0]访问FreeBuf\n 回复[1]查看最新文章".
149 | "\n 回复[2]查看随机文章\n 回复[3]查看热门文章\n 回复[4关键字]搜索文章\n 回复[5]访问FB社区 回复其他内容查看本菜单");
150 | }
151 |
152 | // 点击菜单
153 | protected function onClick() {
154 | $key = $this->getRequest('EventKey');
155 | if($key=="MENU_RECENT_POSTS") {
156 | $this->recentPosts();
157 | } else if($key=="MENU_RANDOM_POSTS") {
158 | $this->randomPosts();
159 | } else if($key=="MENU_HOTEST_POSTS") {
160 | $this->hotestPosts();
161 | }
162 | }
163 |
164 | }
165 |
--------------------------------------------------------------------------------
/wechat.php:
--------------------------------------------------------------------------------
1 | appid = $appid;
35 | $this->secret = $secret;
36 | if (!$this->validateSignature($token)) {
37 | exit('签名验证失败');
38 | }
39 |
40 | if ($this->isValid()) {
41 | // 网址接入验证
42 | exit($_GET['echostr']);
43 | }
44 |
45 | if (!isset($GLOBALS['HTTP_RAW_POST_DATA'])) {
46 | exit('缺少数据');
47 | }
48 |
49 | $this->debug = $debug;
50 | set_error_handler(array(&$this, 'errorHandler'));
51 | // 设置错误处理函数,将错误通过文本消息回复显示
52 |
53 | $xml = (array) simplexml_load_string($GLOBALS['HTTP_RAW_POST_DATA'], 'SimpleXMLElement', LIBXML_NOCDATA);
54 |
55 | $this->request = array_change_key_case($xml, CASE_LOWER);
56 | // 将数组键名转换为小写,提高健壮性,减少因大小写不同而出现的问题
57 | }
58 |
59 | /**
60 | * 判断此次请求是否为验证请求
61 | *
62 | * @return boolean
63 | */
64 | private function isValid() {
65 | return isset($_GET['echostr']);
66 | }
67 |
68 | /**
69 | * 验证此次请求的签名信息
70 | *
71 | * @param string $token 验证信息
72 | * @return boolean
73 | */
74 | private function validateSignature($token) {
75 | $signature = $_GET["signature"];
76 | $timestamp = $_GET["timestamp"];
77 | $nonce = $_GET["nonce"];
78 |
79 | $tmpArr = array($token, $timestamp, $nonce);
80 | sort($tmpArr, SORT_STRING);
81 | $tmpStr = implode( $tmpArr );
82 | $tmpStr = sha1( $tmpStr );
83 |
84 | if( $tmpStr == $signature ){
85 | return true;
86 | } else {
87 | return false;
88 | }
89 | }
90 |
91 | /**
92 | * 获取本次请求中的参数,不区分大小
93 | *
94 | * @param string $param 参数名,默认为无参
95 | * @return mixed
96 | */
97 | protected function getRequest($param = FALSE) {
98 | if ($param === FALSE) {
99 | return $this->request;
100 | }
101 |
102 | $param = strtolower($param);
103 |
104 | if (isset($this->request[$param])) {
105 | return $this->request[$param];
106 | }
107 |
108 | return NULL;
109 | }
110 |
111 | /**
112 | * 获取token,使用文件缓存机制
113 | * 首先检查文件是否存在,存在则检查token是否过期
114 | * 若过期或文件不存在,则向服务器请求,然后存入文件
115 | *
116 | */
117 | public function get_access_token() {
118 | $path = WEIXIN_ROBOT_PLUGIN_DIR."/access_token.json";
119 | // 检查文件并查看token是否过期
120 | if(file_exists($path)) {
121 | $json = file_get_contents($path);
122 | if(!isset($json['access_token']) || !isset($json['time']) || !isset($json['expires_in']))
123 | return false;
124 |
125 | $array = json_decode($json, true);
126 | $expires_time = intval($array["time"]) + intval($array["expires_in"]) - 100;
127 | $now = time();
128 | if($now < $expires_time)
129 | return $array["access_token"];
130 | }
131 |
132 | // 如果文件不存在或者token已经过期则向服务器请求
133 | $result = $this->http_get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$this->appid."&secret=".$this->secret);
134 | if($result) {
135 | $json = json_decode($result, true);
136 | if(!$json || isset($json['errcode']))
137 | return false;
138 |
139 | $json["time"] = time();
140 | $json = json_encode($json);
141 |
142 | // 写入文件
143 | $file = fopen($path, "wb");
144 | if($file!==false) {
145 | fwrite($file, $json);
146 | fclose($file);
147 | }
148 | return $json["access_token"];
149 | }
150 | return false;
151 |
152 | }
153 |
154 |
155 | /**
156 | * 使用curl实现GET请求
157 | */
158 | private function http_get($url) {
159 | $oCurl = curl_init();
160 | if(stripos($url, "https://")!==FALSE) {
161 | curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
162 | curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);
163 | }
164 | curl_setopt($oCurl, CURLOPT_URL, $url);
165 | curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
166 | $content = curl_exec($oCurl);
167 | $status = curl_getinfo($oCurl);
168 | curl_close($oCurl);
169 | if(intval($status["http_code"])==200)
170 | return $content;
171 | else
172 | return false;
173 | }
174 |
175 |
176 | // 创建菜单,根据微信api传入菜单json
177 | public function create_menu($menu_json) {
178 | $access_token = $this->get_access_token();
179 | $res = http_post("https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$access_token, $menu_json);
180 | return $res;
181 | }
182 |
183 | public function fetch_menu() {
184 | $access_token = $this->get_access_token();
185 | $res = http_get("https://api.weixin.qq.com/cgi-bin/menu/get?access_token=".$access_token);
186 | return $res;
187 | }
188 |
189 |
190 |
191 | /**
192 | * 用户关注时触发,用于子类重写
193 | *
194 | * @return void
195 | */
196 | protected function onSubscribe() {}
197 |
198 | /**
199 | * 用户取消关注时触发,用于子类重写
200 | *
201 | * @return void
202 | */
203 | protected function onUnsubscribe() {}
204 |
205 | /**
206 | * 收到文本消息时触发,用于子类重写
207 | *
208 | * @return void
209 | */
210 | protected function onText() {}
211 |
212 | /**
213 | * 收到图片消息时触发,用于子类重写
214 | *
215 | * @return void
216 | */
217 | protected function onImage() {}
218 |
219 | /**
220 | * 收到地理位置消息时触发,用于子类重写
221 | *
222 | * @return void
223 | */
224 | protected function onLocation() {}
225 |
226 | /**
227 | * 收到链接消息时触发,用于子类重写
228 | *
229 | * @return void
230 | */
231 | protected function onLink() {}
232 |
233 | /**
234 | * 收到自定义菜单消息时触发,用于子类重写
235 | *
236 | * @return void
237 | */
238 | protected function onClick() {}
239 |
240 | /**
241 | * 收到地理位置事件消息时触发,用于子类重写
242 | *
243 | * @return void
244 | */
245 | protected function onEventLocation() {}
246 |
247 | /**
248 | * 收到语音消息时触发,用于子类重写
249 | *
250 | * @return void
251 | */
252 | protected function onVoice() {}
253 |
254 | /**
255 | * 扫描二维码时触发,用于子类重写
256 | *
257 | * @return void
258 | */
259 | protected function onScan() {}
260 |
261 | /**
262 | * 收到未知类型消息时触发,用于子类重写
263 | *
264 | * @return void
265 | */
266 | protected function onUnknown() {}
267 |
268 | /**
269 | * 回复文本消息
270 | *
271 | * @param string $content 消息内容
272 | * @param integer $funcFlag 默认为0,设为1时星标刚才收到的消息
273 | * @return void
274 | */
275 | protected function responseText($content, $funcFlag = 0) {
276 | exit(new TextResponse($this->getRequest('fromusername'), $this->getRequest('tousername'), $content, $funcFlag));
277 | }
278 |
279 | /**
280 | * 回复音乐消息
281 | *
282 | * @param string $title 音乐标题
283 | * @param string $description 音乐描述
284 | * @param string $musicUrl 音乐链接
285 | * @param string $hqMusicUrl 高质量音乐链接,Wi-Fi 环境下优先使用
286 | * @param integer $funcFlag 默认为0,设为1时星标刚才收到的消息
287 | * @return void
288 | */
289 | protected function responseMusic($title, $description, $musicUrl, $hqMusicUrl, $funcFlag = 0) {
290 | exit(new MusicResponse($this->getRequest('fromusername'), $this->getRequest('tousername'), $title, $description, $musicUrl, $hqMusicUrl, $funcFlag));
291 | }
292 |
293 | /**
294 | * 回复图文消息
295 | * @param array $items 由单条图文消息类型 NewsResponseItem() 组成的数组
296 | * @param integer $funcFlag 默认为0,设为1时星标刚才收到的消息
297 | * @return void
298 | */
299 | protected function responseNews($items, $funcFlag = 0) {
300 | exit(new NewsResponse($this->getRequest('fromusername'), $this->getRequest('tousername'), $items, $funcFlag));
301 | }
302 |
303 | /**
304 | * 分析消息类型,并分发给对应的函数
305 | *
306 | * @return void
307 | */
308 | public function run() {
309 | switch ($this->getRequest('msgtype')) {
310 | case 'event':
311 | switch ($this->getRequest('event')) {
312 | case 'subscribe':
313 | $this->onSubscribe();
314 | break;
315 |
316 | case 'unsubscribe':
317 | $this->onUnsubscribe();
318 | break;
319 |
320 | case 'SCAN':
321 | $this->onScan();
322 | break;
323 |
324 | case 'LOCATION':
325 | $this->onEventLocation();
326 | break;
327 |
328 | case 'CLICK':
329 | $this->onClick();
330 | break;
331 | }
332 | break;
333 |
334 | case 'text':
335 | $this->onText();
336 | break;
337 |
338 | case 'image':
339 | $this->onImage();
340 | break;
341 |
342 | case 'location':
343 | $this->onLocation();
344 | break;
345 |
346 | case 'link':
347 | $this->onLink();
348 | break;
349 |
350 | case 'voice':
351 | $this->onVoice();
352 | break;
353 |
354 | default:
355 | $this->onUnknown();
356 | break;
357 | }
358 | }
359 |
360 |
361 | /**
362 | * 自定义的错误处理函数,将 PHP 错误通过文本消息回复显示
363 | * @param int $level 错误代码
364 | * @param string $msg 错误内容
365 | * @param string $file 产生错误的文件
366 | * @param int $line 产生错误的行数
367 | * @return void
368 | */
369 | protected function errorHandler($level, $msg, $file, $line) {
370 | if ( ! $this->debug) {
371 | return;
372 | }
373 |
374 | $error_type = array(
375 | // E_ERROR => 'Error',
376 | E_WARNING => 'Warning',
377 | // E_PARSE => 'Parse Error',
378 | E_NOTICE => 'Notice',
379 | // E_CORE_ERROR => 'Core Error',
380 | // E_CORE_WARNING => 'Core Warning',
381 | // E_COMPILE_ERROR => 'Compile Error',
382 | // E_COMPILE_WARNING => 'Compile Warning',
383 | E_USER_ERROR => 'User Error',
384 | E_USER_WARNING => 'User Warning',
385 | E_USER_NOTICE => 'User Notice',
386 | E_STRICT => 'Strict',
387 | E_RECOVERABLE_ERROR => 'Recoverable Error',
388 | E_DEPRECATED => 'Deprecated',
389 | E_USER_DEPRECATED => 'User Deprecated',
390 | );
391 |
392 | $template = <<responseText(sprintf($template,
401 | $error_type[$level],
402 | $msg,
403 | $file,
404 | $line
405 | ));
406 | }
407 |
408 | }
409 |
410 | /**
411 | * 用于回复的基本消息类型
412 | */
413 | abstract class WechatResponse {
414 |
415 | protected $toUserName;
416 | protected $fromUserName;
417 | protected $funcFlag;
418 | protected $template;
419 |
420 | public function __construct($toUserName, $fromUserName, $funcFlag) {
421 | $this->toUserName = $toUserName;
422 | $this->fromUserName = $fromUserName;
423 | $this->funcFlag = $funcFlag;
424 | }
425 |
426 | abstract public function __toString();
427 | }
428 |
429 | /**
430 | * 用于回复的文本消息类型
431 | */
432 | class TextResponse extends WechatResponse {
433 |
434 | protected $content;
435 |
436 | public function __construct($toUserName, $fromUserName, $content, $funcFlag = 0) {
437 | parent::__construct($toUserName, $fromUserName, $funcFlag);
438 |
439 | $this->content = $content;
440 | $this->template = <<
442 |
443 |
444 | %s
445 |
446 |
447 | %s
448 |
449 | XML;
450 | }
451 |
452 | public function __toString() {
453 | return sprintf($this->template,
454 | $this->toUserName,
455 | $this->fromUserName,
456 | time(),
457 | $this->content,
458 | $this->funcFlag
459 | );
460 | }
461 |
462 | }
463 |
464 | /**
465 | * 用于回复的音乐消息类型
466 | */
467 | class MusicResponse extends WechatResponse {
468 |
469 | protected $title;
470 | protected $description;
471 | protected $musicUrl;
472 | protected $hqMusicUrl;
473 |
474 | public function __construct($toUserName, $fromUserName, $title, $description, $musicUrl, $hqMusicUrl, $funcFlag) {
475 | parent::__construct($toUserName, $fromUserName, $funcFlag);
476 |
477 | $this->title = $title;
478 | $this->description = $description;
479 | $this->musicUrl = $musicUrl;
480 | $this->hqMusicUrl = $hqMusicUrl;
481 | $this->template = <<
483 |
484 |
485 | %s
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 | %s
494 |
495 | XML;
496 | }
497 |
498 | public function __toString() {
499 | return sprintf($this->template,
500 | $this->toUserName,
501 | $this->fromUserName,
502 | time(),
503 | $this->title,
504 | $this->description,
505 | $this->musicUrl,
506 | $this->hqMusicUrl,
507 | $this->funcFlag
508 | );
509 | }
510 |
511 | }
512 |
513 | /**
514 | * 用于回复的图文消息类型
515 | */
516 | class NewsResponse extends WechatResponse {
517 |
518 | protected $items = array();
519 |
520 | public function __construct($toUserName, $fromUserName, $items, $funcFlag) {
521 | parent::__construct($toUserName, $fromUserName, $funcFlag);
522 |
523 | $this->items = $items;
524 | $this->template = <<
526 |
527 |
528 | %s
529 |
530 | %s
531 |
532 | %s
533 |
534 | %s
535 |
536 | XML;
537 | }
538 |
539 | public function __toString() {
540 | return sprintf($this->template,
541 | $this->toUserName,
542 | $this->fromUserName,
543 | time(),
544 | count($this->items),
545 | implode($this->items),
546 | $this->funcFlag
547 | );
548 | }
549 |
550 | }
551 |
552 | /**
553 | * 单条图文消息类型
554 | */
555 | class NewsResponseItem {
556 |
557 | protected $title;
558 | protected $description;
559 | protected $picUrl;
560 | protected $url;
561 | protected $template;
562 |
563 | public function __construct($title, $description, $picUrl, $url) {
564 | $this->title = $title;
565 | $this->description = $description;
566 | $this->picUrl = $picUrl;
567 | $this->url = $url;
568 | $this->template = <<
570 |
571 |
572 |
573 |
574 |
575 | XML;
576 | }
577 |
578 | public function __toString() {
579 | return sprintf($this->template,
580 | $this->title,
581 | $this->description,
582 | $this->picUrl,
583 | $this->url
584 | );
585 | }
586 |
587 | }
588 |
589 | ?>
590 |
--------------------------------------------------------------------------------