api.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  1. <?php
  2. /**
  3. * [WeEngine System] Copyright (c) 2014 WE7.CC
  4. * WeEngine is NOT a free software, it under the license terms, visited http://www.we7.cc/ for more details.
  5. */
  6. define('IN_API', true);
  7. require_once './framework/bootstrap.inc.php';
  8. load()->model('reply');
  9. load()->model('attachment');
  10. load()->model('visit');
  11. load()->app('common');
  12. load()->classs('wesession');
  13. $hash = $_GPC['hash'];
  14. if(!empty($hash)) {
  15. $id = pdo_fetchcolumn("SELECT acid FROM " . tablename('account') . " WHERE hash = :hash", array(':hash' => $hash));
  16. }
  17. if(!empty($_GPC['appid'])) {
  18. $appid = ltrim($_GPC['appid'], '/');
  19. if ($appid == 'wx570bc396a51b8ff8') {
  20. $_W['account'] = array(
  21. 'type' => '3',
  22. 'key' => 'wx570bc396a51b8ff8',
  23. 'level' => 4,
  24. 'token' => 'platformtestaccount'
  25. );
  26. } else {
  27. $id = pdo_fetchcolumn("SELECT acid FROM " . tablename('account_wechats') . " WHERE `key` = :appid", array(':appid' => $appid));
  28. }
  29. }
  30. if(empty($id)) {
  31. $id = intval($_GPC['id']);
  32. }
  33. if (!empty($id)) {
  34. $uniacid = pdo_getcolumn('account', array('acid' => $id), 'uniacid');
  35. $_W['account'] = uni_fetch($uniacid);
  36. }
  37. if(empty($_W['account'])) {
  38. exit('initial error hash or id');
  39. }
  40. if(empty($_W['account']['token'])) {
  41. exit('initial missing token');
  42. }
  43. $_W['debug'] = intval($_GPC['debug']);
  44. $_W['acid'] = $_W['account']['acid'];
  45. $_W['uniacid'] = $_W['account']['uniacid'];
  46. $_W['uniaccount'] = uni_fetch($_W['uniacid']);
  47. $_W['account']['groupid'] = $_W['uniaccount']['groupid'];
  48. $_W['account']['qrcode'] = $_W['attachurl'].'qrcode_'.$_W['acid'].'.jpg?time='.$_W['timestamp'];
  49. $_W['account']['avatar'] = $_W['attachurl'].'headimg_'.$_W['acid'].'.jpg?time='.$_W['timestamp'];
  50. $_W['attachurl'] = attachment_set_attach_url();
  51. visit_update_today('web', 'we7_api');
  52. $engine = new WeEngine();
  53. if (!empty($_W['setting']['copyright']['status'])) {
  54. $engine->died('抱歉,站点已关闭,关闭原因:' . $_W['setting']['copyright']['reason']);
  55. }
  56. if (!empty($_W['uniaccount']['endtime']) && TIMESTAMP > $_W['uniaccount']['endtime']) {
  57. $engine->died('抱歉,您的公众号已过期,请及时联系管理员');
  58. }
  59. if($_W['isajax'] && $_W['ispost'] && $_GPC['flag'] == 1) {
  60. $engine->encrypt();
  61. }
  62. if($_W['isajax'] && $_W['ispost'] && $_GPC['flag'] == 2) {
  63. $engine->decrypt();
  64. }
  65. load()->func('compat.biz');
  66. $_W['isajax'] = false;
  67. $engine->start();
  68. class WeEngine {
  69. private $account = null;
  70. private $modules = array();
  71. public $keyword = array();
  72. public $message = array();
  73. public function __construct() {
  74. global $_W;
  75. $this->account = WeAccount::create($_W['account']);
  76. if(strtolower($_SERVER['REQUEST_METHOD']) == 'post') {
  77. $_W['modules'] = uni_modules();
  78. $this->modules = array_keys($_W['modules']);
  79. $this->modules[] = 'cover';
  80. $this->modules[] = 'default';
  81. $this->modules[] = 'reply';
  82. $this->modules = array_unique ($this->modules);
  83. }
  84. }
  85. public function encrypt() {
  86. global $_W;
  87. if(empty($this->account)) {
  88. exit('Miss Account.');
  89. }
  90. $timestamp = TIMESTAMP;
  91. $nonce = random(5);
  92. $token = $_W['account']['token'];
  93. $signkey = array($token, TIMESTAMP, $nonce);
  94. sort($signkey, SORT_STRING);
  95. $signString = implode($signkey);
  96. $signString = sha1($signString);
  97. $_GET['timestamp'] = $timestamp;
  98. $_GET['nonce'] = $nonce;
  99. $_GET['signature'] = $signString;
  100. $postStr = file_get_contents('php://input');
  101. if(!empty($_W['account']['encodingaeskey']) && strlen($_W['account']['encodingaeskey']) == 43 && !empty($_W['account']['key']) && $_W['setting']['development'] != 1) {
  102. $data = $this->account->encryptMsg($postStr);
  103. $array = array('encrypt_type' => 'aes', 'timestamp' => $timestamp, 'nonce' => $nonce, 'signature' => $signString, 'msg_signature' => $data[0], 'msg' => $data[1]);
  104. } else {
  105. $data = array('', '');
  106. $array = array('encrypt_type' => '', 'timestamp' => $timestamp, 'nonce' => $nonce, 'signature' => $signString, 'msg_signature' => $data[0], 'msg' => $data[1]);
  107. }
  108. exit(json_encode($array));
  109. }
  110. public function decrypt() {
  111. global $_W;
  112. if(empty($this->account)) {
  113. exit('Miss Account.');
  114. }
  115. $postStr = file_get_contents('php://input');
  116. if(!empty($_W['account']['encodingaeskey']) && strlen($_W['account']['encodingaeskey']) == 43 && !empty($_W['account']['key']) && $_W['setting']['development'] != 1) {
  117. $resp = $this->account->local_decryptMsg($postStr);
  118. } else {
  119. $resp = $postStr;
  120. }
  121. exit($resp);
  122. }
  123. public function start() {
  124. global $_W;
  125. if(empty($this->account)) {
  126. exit('Miss Account.');
  127. }
  128. if(!$this->account->checkSign()) {
  129. exit('Check Sign Fail.');
  130. }
  131. if(strtolower($_SERVER['REQUEST_METHOD']) == 'get') {
  132. $row = array();
  133. $row['isconnect'] = 1;
  134. pdo_update('account', $row, array('acid' => $_W['acid']));
  135. cache_delete("uniaccount:{$_W['uniacid']}");
  136. exit(htmlspecialchars($_GET['echostr']));
  137. }
  138. if(strtolower($_SERVER['REQUEST_METHOD']) == 'post') {
  139. $postStr = file_get_contents('php://input');
  140. if(!empty($_GET['encrypt_type']) && $_GET['encrypt_type'] == 'aes') {
  141. $postStr = $this->account->decryptMsg($postStr);
  142. }
  143. WeUtility::logging('trace', $postStr);
  144. $message = $this->account->parse($postStr);
  145. $this->message = $message;
  146. if(empty($message)) {
  147. WeUtility::logging('waring', 'Request Failed');
  148. exit('Request Failed');
  149. }
  150. $_W['openid'] = $message['from'];
  151. $_W['fans'] = array('from_user' => $_W['openid']);
  152. $this->booking($message);
  153. if($message['event'] == 'unsubscribe') {
  154. $this->receive(array(), array(), array());
  155. exit();
  156. }
  157. $sessionid = md5($message['from'] . $message['to'] . $_W['uniacid']);
  158. session_id($sessionid);
  159. WeSession::start($_W['uniacid'], $_W['openid']);
  160. $_SESSION['openid'] = $_W['openid'];
  161. $pars = $this->analyze($message);
  162. $pars[] = array(
  163. 'message' => $message,
  164. 'module' => 'default',
  165. 'rule' => '-1',
  166. );
  167. $hitParam['rule'] = -2;
  168. $hitParam['module'] = '';
  169. $hitParam['message'] = $message;
  170. $hitKeyword = array();
  171. $response = array();
  172. foreach($pars as $par) {
  173. if(empty($par['module'])) {
  174. continue;
  175. }
  176. $par['message'] = $message;
  177. $response = $this->process($par);
  178. if($this->isValidResponse($response)) {
  179. $hitParam = $par;
  180. if(!empty($par['keyword'])) {
  181. $hitKeyword = $par['keyword'];
  182. }
  183. break;
  184. }
  185. }
  186. $response_debug = $response;
  187. $pars_debug = $pars;
  188. if($hitParam['module'] == 'default' && is_array($response) && is_array($response['params'])) {
  189. foreach($response['params'] as $par) {
  190. if(empty($par['module'])) {
  191. continue;
  192. }
  193. $response = $this->process($par);
  194. if($this->isValidResponse($response)) {
  195. $hitParam = $par;
  196. if(!empty($par['keyword'])) {
  197. $hitKeyword = $par['keyword'];
  198. }
  199. break;
  200. }
  201. }
  202. }
  203. WeUtility::logging('params', var_export($hitParam, true));
  204. WeUtility::logging('response', $response);
  205. $resp = $this->account->response($response);
  206. if(!empty($_GET['encrypt_type']) && $_GET['encrypt_type'] == 'aes') {
  207. $resp = $this->account->encryptMsg($resp);
  208. $resp = $this->account->xmlDetract($resp);
  209. }
  210. if($_W['debug']) {
  211. $_W['debug_data'] = array(
  212. 'resp' => $resp,
  213. 'is_default' => 0
  214. );
  215. if(count($pars_debug) == 1) {
  216. $_W['debug_data']['is_default'] = 1;
  217. $_W['debug_data']['params'] = $response_debug['params'];
  218. } else {
  219. array_pop($pars_debug);
  220. $_W['debug_data']['params'] = $pars_debug;
  221. }
  222. $_W['debug_data']['hitparam'] = $hitParam;
  223. $_W['modules']['cover'] = array('title' => '入口封面', 'name' => 'cover');
  224. load()->web('template');
  225. $process = template('utility/emulator', TEMPLATE_FETCH);
  226. echo json_encode(array('resp' => $resp, 'process' => $process));
  227. exit();
  228. }
  229. if ($resp !== 'success') {
  230. $mapping = array(
  231. '[from]' => $this->message['from'],
  232. '[to]' => $this->message['to'],
  233. '[rule]' => $this->params['rule']
  234. );
  235. $resp = str_replace(array_keys($mapping), array_values($mapping), $resp);
  236. }
  237. ob_start();
  238. echo $resp;
  239. ob_start();
  240. $this->receive($hitParam, $hitKeyword, $response);
  241. ob_end_clean();
  242. exit();
  243. }
  244. WeUtility::logging('waring', 'Request Failed');
  245. exit('Request Failed');
  246. }
  247. private function isValidResponse($response) {
  248. if ($response === 'success') {
  249. return true;
  250. }
  251. if(is_array($response)) {
  252. if($response['type'] == 'text' && !empty($response['content'])) {
  253. return true;
  254. }
  255. if($response['type'] == 'news' && !empty($response['items'])) {
  256. return true;
  257. }
  258. if(!in_array($response['type'], array('text', 'news', 'image'))) {
  259. return true;
  260. }
  261. }
  262. return false;
  263. }
  264. private function booking($message) {
  265. global $_W;
  266. if ($message['event'] == 'unsubscribe' || $message['event'] == 'subscribe') {
  267. $todaystat = pdo_get('stat_fans', array('date' => date('Ymd'), 'uniacid' => $_W['uniacid']));
  268. if ($message['event'] == 'unsubscribe') {
  269. if (empty($todaystat)) {
  270. $updatestat = array(
  271. 'new' => 0,
  272. 'uniacid' => $_W['uniacid'],
  273. 'cancel' => 1,
  274. 'cumulate' => 0,
  275. 'date' => date('Ymd'),
  276. );
  277. pdo_insert('stat_fans', $updatestat);
  278. } else {
  279. $updatestat = array(
  280. 'cancel' => $todaystat['cancel'] + 1,
  281. );
  282. $updatestat['cumulate'] = 0;
  283. pdo_update('stat_fans', $updatestat, array('id' => $todaystat['id']));
  284. }
  285. } elseif ($message['event'] == 'subscribe') {
  286. if (empty($todaystat)) {
  287. $updatestat = array(
  288. 'new' => 1,
  289. 'uniacid' => $_W['uniacid'],
  290. 'cancel' => 0,
  291. 'cumulate' => 0,
  292. 'date' => date('Ymd'),
  293. );
  294. pdo_insert('stat_fans', $updatestat);
  295. } else {
  296. $updatestat = array(
  297. 'new' => $todaystat['new'] + 1,
  298. 'cumulate' => 0,
  299. );
  300. pdo_update('stat_fans', $updatestat, array('id' => $todaystat['id']));
  301. }
  302. }
  303. }
  304. load()->model('mc');
  305. $setting = uni_setting($_W['uniacid'], array('passport'));
  306. $fans = mc_fansinfo($message['from']);
  307. $default_groupid = cache_load("defaultgroupid:{$_W['uniacid']}");
  308. if (empty($default_groupid)) {
  309. $default_groupid = pdo_fetchcolumn('SELECT groupid FROM ' .tablename('mc_groups') . ' WHERE uniacid = :uniacid AND isdefault = 1', array(':uniacid' => $_W['uniacid']));
  310. cache_write("defaultgroupid:{$_W['uniacid']}", $default_groupid);
  311. }
  312. if(!empty($fans)) {
  313. if ($message['event'] == 'unsubscribe') {
  314. cache_build_memberinfo($fans['uid']);
  315. pdo_update('mc_mapping_fans', array('follow' => 0, 'unfollowtime' => TIMESTAMP), array('fanid' => $fans['fanid']));
  316. pdo_delete('mc_fans_tag_mapping', array('fanid' => $fans['fanid']));
  317. } elseif ($message['event'] != 'ShakearoundUserShake' && $message['type'] != 'trace') {
  318. $rec = array();
  319. if (empty($fans['follow'])) {
  320. $rec['follow'] = 1;
  321. $rec['followtime'] = $message['time'];
  322. }
  323. $member = array();
  324. if(!empty($fans['uid'])){
  325. $member = mc_fetch($fans['uid']);
  326. }
  327. if (empty($member)) {
  328. if (!isset($setting['passport']) || empty($setting['passport']['focusreg'])) {
  329. $data = array(
  330. 'uniacid' => $_W['uniacid'],
  331. 'email' => md5($message['from']).'@we7.cc',
  332. 'salt' => random(8),
  333. 'groupid' => $default_groupid,
  334. 'createtime' => TIMESTAMP,
  335. );
  336. $data['password'] = md5($message['from'] . $data['salt'] . $_W['config']['setting']['authkey']);
  337. pdo_insert('mc_members', $data);
  338. $rec['uid'] = pdo_insertid();
  339. }
  340. }
  341. if(!empty($rec)){
  342. pdo_update('mc_mapping_fans', $rec, array('openid' => $message['from']));
  343. }
  344. }
  345. } else {
  346. if ($message['event'] == 'subscribe' || $message['type'] == 'text' || $message['type'] == 'image') {
  347. load()->model('mc');
  348. $force_init_member = false;
  349. if (!isset($setting['passport']) || empty($setting['passport']['focusreg'])) {
  350. $force_init_member = true;
  351. }
  352. mc_init_fans_info($message['from'], $force_init_member);
  353. }
  354. }
  355. }
  356. private function receive($par, $keyword, $response) {
  357. global $_W;
  358. fastcgi_finish_request();
  359. $subscribe = cache_load('module_receive_enable');
  360. $modules = uni_modules();
  361. $obj = WeUtility::createModuleReceiver('core');
  362. $obj->message = $this->message;
  363. $obj->params = $par;
  364. $obj->response = $response;
  365. $obj->keyword = $keyword;
  366. $obj->module = 'core';
  367. $obj->uniacid = $_W['uniacid'];
  368. $obj->acid = $_W['acid'];
  369. if(method_exists($obj, 'receive')) {
  370. @$obj->receive();
  371. }
  372. load()->func('communication');
  373. if (empty($subscribe[$this->message['type']])) {
  374. $subscribe[$this->message['type']] = $subscribe[$this->message['event']];
  375. }
  376. if (!empty($subscribe[$this->message['type']])) {
  377. foreach ($subscribe[$this->message['type']] as $modulename) {
  378. $params = array(
  379. 'i' => $GLOBALS['uniacid'],
  380. 'modulename' => $modulename,
  381. 'request' => json_encode($par),
  382. 'response' => json_encode($response),
  383. 'message' => json_encode($this->message),
  384. );
  385. $response = ihttp_request(wurl('utility/subscribe/receive'), $params, array(), 10);
  386. if (is_error($response) && $response['errno'] == '7') {
  387. $response = ihttp_request($_W['siteroot'] . 'web/' . wurl('utility/subscribe/receive'), $params, array(), 10);
  388. }
  389. }
  390. }
  391. }
  392. private function analyze(&$message) {
  393. $params = array();
  394. if(in_array($message['type'], array('event', 'qr'))) {
  395. $params = call_user_func_array(array($this, 'analyze' . $message['type']), array(&$message));
  396. if(!empty($params)) {
  397. return (array)$params;
  398. }
  399. }
  400. if(!empty($_SESSION['__contextmodule']) && in_array($_SESSION['__contextmodule'], $this->modules)) {
  401. if($_SESSION['__contextexpire'] > TIMESTAMP) {
  402. $params[] = array(
  403. 'message' => $message,
  404. 'module' => $_SESSION['__contextmodule'],
  405. 'rule' => $_SESSION['__contextrule'],
  406. 'priority' => $_SESSION['__contextpriority'],
  407. 'context' => true
  408. );
  409. return $params;
  410. } else {
  411. unset($_SESSION);
  412. session_destroy();
  413. }
  414. }
  415. if(method_exists($this, 'analyze' . $message['type'])) {
  416. $temp = call_user_func_array(array($this, 'analyze' . $message['type']), array(&$message));
  417. if(!empty($temp) && is_array($temp)){
  418. $params += $temp;
  419. }
  420. } else {
  421. $params += $this->handler($message['type']);
  422. }
  423. return $params;
  424. }
  425. private function analyzeSubscribe(&$message) {
  426. global $_W;
  427. $params = array();
  428. $message['type'] = 'text';
  429. $message['redirection'] = true;
  430. if(!empty($message['scene'])) {
  431. $message['source'] = 'qr';
  432. $sceneid = trim($message['scene']);
  433. $scene_condition = '';
  434. if (is_numeric($sceneid)) {
  435. $scene_condition = " `qrcid` = '{$sceneid}'";
  436. }else{
  437. $scene_condition = " `scene_str` = '{$sceneid}'";
  438. }
  439. $qr = pdo_fetch("SELECT `id`, `keyword` FROM " . tablename('qrcode') . " WHERE {$scene_condition} AND `uniacid` = '{$_W['uniacid']}'");
  440. if(!empty($qr)) {
  441. $message['content'] = $qr['keyword'];
  442. if (!empty($qr['type']) && $qr['type'] == 'scene') {
  443. $message['msgtype'] = 'text';
  444. }
  445. $params += $this->analyzeText($message);
  446. return $params;
  447. }
  448. }
  449. $message['source'] = 'subscribe';
  450. $setting = uni_setting($_W['uniacid'], array('welcome'));
  451. if(!empty($setting['welcome'])) {
  452. $message['content'] = $setting['welcome'];
  453. $params += $this->analyzeText($message);
  454. }
  455. return $params;
  456. }
  457. private function analyzeQR(&$message) {
  458. global $_W;
  459. $params = array();
  460. $message['type'] = 'text';
  461. $message['redirection'] = true;
  462. if(!empty($message['scene'])) {
  463. $message['source'] = 'qr';
  464. $sceneid = trim($message['scene']);
  465. $scene_condition = '';
  466. if (is_numeric($sceneid)) {
  467. $scene_condition = " `qrcid` = '{$sceneid}'";
  468. }else{
  469. $scene_condition = " `scene_str` = '{$sceneid}'";
  470. }
  471. $qr = pdo_fetch("SELECT `id`, `keyword` FROM " . tablename('qrcode') . " WHERE {$scene_condition} AND `uniacid` = '{$_W['uniacid']}'");
  472. }
  473. if (empty($qr) && !empty($message['ticket'])) {
  474. $message['source'] = 'qr';
  475. $ticket = trim($message['ticket']);
  476. if(!empty($ticket)) {
  477. $qr = pdo_fetchall("SELECT `id`, `keyword` FROM " . tablename('qrcode') . " WHERE `uniacid` = '{$_W['uniacid']}' AND ticket = '{$ticket}'");
  478. if(!empty($qr)) {
  479. if(count($qr) != 1) {
  480. $qr = array();
  481. } else {
  482. $qr = $qr[0];
  483. }
  484. }
  485. }
  486. }
  487. if(!empty($qr)) {
  488. $message['content'] = $qr['keyword'];
  489. if (!empty($qr['type']) && $qr['type'] == 'scene') {
  490. $message['msgtype'] = 'text';
  491. }
  492. $params += $this->analyzeText($message);
  493. }
  494. return $params;
  495. }
  496. public function analyzeText(&$message, $order = 0) {
  497. global $_W;
  498. $pars = array();
  499. $order = intval($order);
  500. if(!isset($message['content'])) {
  501. return $pars;
  502. }
  503. $cachekey = 'we7:' . $_W['uniacid'] . ':keyword:' . md5($message['content']);
  504. $keyword_cache = cache_load($cachekey);
  505. if (!empty($keyword_cache) && $keyword_cache['expire'] > TIMESTAMP) {
  506. return $keyword_cache['data'];
  507. }
  508. $condition = <<<EOF
  509. `uniacid` IN ( 0, {$_W['uniacid']} )
  510. AND
  511. (
  512. ( `type` = 1 AND `content` = :c1 )
  513. or
  514. ( `type` = 2 AND instr(:c2, `content`) )
  515. or
  516. ( `type` = 3 AND :c3 REGEXP `content` )
  517. or
  518. ( `type` = 4 )
  519. )
  520. AND `status`=1
  521. EOF;
  522. $params = array();
  523. $params[':c1'] = $message['content'];
  524. $params[':c2'] = $message['content'];
  525. $params[':c3'] = $message['content'];
  526. if (intval($order) > 0) {
  527. $condition .= " AND `displayorder` > :order";
  528. $params[':order'] = $order;
  529. }
  530. $keywords = reply_keywords_search($condition, $params);
  531. if(empty($keywords)) {
  532. return $pars;
  533. }
  534. foreach($keywords as $keyword) {
  535. $params = array(
  536. 'message' => $message,
  537. 'module' => $keyword['module'],
  538. 'rule' => $keyword['rid'],
  539. 'priority' => $keyword['displayorder'],
  540. 'keyword' => $keyword,
  541. 'reply_type' => $keyword['reply_type']
  542. );
  543. $pars[] = $params;
  544. }
  545. $cache = array(
  546. 'data' => $pars,
  547. 'expire' => TIMESTAMP + 5 * 60,
  548. );
  549. cache_write($cachekey, $cache);
  550. return $pars;
  551. }
  552. private function analyzeEvent(&$message) {
  553. if (strtolower($message['event']) == 'subscribe') {
  554. return $this->analyzeSubscribe($message);
  555. }
  556. if (strtolower($message['event']) == 'click') {
  557. $message['content'] = strval($message['eventkey']);
  558. return $this->analyzeClick($message);
  559. }
  560. if (in_array($message['event'], array('pic_photo_or_album', 'pic_weixin', 'pic_sysphoto'))) {
  561. pdo_query("DELETE FROM ".tablename('menu_event')." WHERE createtime < '".($GLOBALS['_W']['timestamp'] - 100)."' OR openid = '{$message['from']}'");
  562. if (!empty($message['sendpicsinfo']['count'])) {
  563. foreach ($message['sendpicsinfo']['piclist'] as $item) {
  564. pdo_insert('menu_event', array(
  565. 'uniacid' => $GLOBALS['_W']['uniacid'],
  566. 'keyword' => $message['eventkey'],
  567. 'type' => $message['event'],
  568. 'picmd5' => $item,
  569. 'openid' => $message['from'],
  570. 'createtime' => TIMESTAMP,
  571. ));
  572. }
  573. } else {
  574. pdo_insert('menu_event', array(
  575. 'uniacid' => $GLOBALS['_W']['uniacid'],
  576. 'keyword' => $message['eventkey'],
  577. 'type' => $message['event'],
  578. 'picmd5' => $item,
  579. 'openid' => $message['from'],
  580. 'createtime' => TIMESTAMP,
  581. ));
  582. }
  583. $message['content'] = strval($message['eventkey']);
  584. $message['source'] = $message['event'];
  585. return $this->analyzeText($message);
  586. }
  587. if (!empty($message['eventkey'])) {
  588. $message['content'] = strval($message['eventkey']);
  589. $message['type'] = 'text';
  590. $message['redirection'] = true;
  591. $message['source'] = $message['event'];
  592. return $this->analyzeText($message);
  593. }
  594. return $this->handler($message['event']);
  595. }
  596. private function analyzeClick(&$message) {
  597. if(!empty($message['content']) || $message['content'] !== '') {
  598. $message['type'] = 'text';
  599. $message['redirection'] = true;
  600. $message['source'] = 'click';
  601. return $this->analyzeText($message);
  602. }
  603. return array();
  604. }
  605. private function analyzeImage(&$message) {
  606. load()->func('communication');
  607. if (!empty($message['picurl'])) {
  608. $response = ihttp_get($message['picurl']);
  609. if (!empty($response)) {
  610. $md5 = md5($response['content']);
  611. $event = pdo_fetch("SELECT keyword, type FROM ".tablename('menu_event')." WHERE picmd5 = '$md5'");
  612. if (!empty($event['keyword'])) {
  613. pdo_delete('menu_event', array('picmd5' => $md5));
  614. } else {
  615. $event = pdo_fetch("SELECT keyword, type FROM ".tablename('menu_event')." WHERE openid = '{$message['from']}'");
  616. }
  617. if (!empty($event)) {
  618. $message['content'] = $event['keyword'];
  619. $message['eventkey'] = $event['keyword'];
  620. $message['type'] = 'text';
  621. $message['event'] = $event['type'];
  622. $message['redirection'] = true;
  623. $message['source'] = $event['type'];
  624. return $this->analyzeText($message);
  625. }
  626. }
  627. return $this->handler('image');
  628. }
  629. }
  630. private function analyzeVoice(&$message) {
  631. $params = $this->handler('voice');
  632. if (empty($params) && !empty($message['recognition'])) {
  633. $message['type'] = 'text';
  634. $message['redirection'] = true;
  635. $message['source'] = 'voice';
  636. $message['content'] = $message['recognition'];
  637. return $this->analyzeText($message);
  638. } else {
  639. return $params;
  640. }
  641. }
  642. private function handler($type) {
  643. if(empty($type)) {
  644. return array();
  645. }
  646. global $_W;
  647. $params = array();
  648. $setting = uni_setting($_W['uniacid'], array('default_message'));
  649. $default_message = $setting['default_message'];
  650. if(is_array($default_message) && !empty($default_message[$type]['type'])) {
  651. if ($default_message[$type]['type'] == 'keyword') {
  652. $message = $this->message;
  653. $message['type'] = 'text';
  654. $message['redirection'] = true;
  655. $message['source'] = $type;
  656. $message['content'] = $default_message[$type]['keyword'];
  657. return $this->analyzeText($message);
  658. } else {
  659. $params[] = array(
  660. 'message' => $this->message,
  661. 'module' => is_array($default_message[$type]) ? $default_message[$type]['module'] : $default_message[$type],
  662. 'rule' => '-1',
  663. );
  664. return $params;
  665. }
  666. }
  667. return array();
  668. }
  669. private function process($param) {
  670. global $_W;
  671. if(empty($param['module']) || !in_array($param['module'], $this->modules)) {
  672. return false;
  673. }
  674. if ($param['module'] == 'reply') {
  675. $processor = WeUtility::createModuleProcessor('core');
  676. } else {
  677. $processor = WeUtility::createModuleProcessor($param['module']);
  678. }
  679. $processor->message = $param['message'];
  680. $processor->rule = $param['rule'];
  681. $processor->reply_type = $param['reply_type'];
  682. $processor->priority = intval($param['priority']);
  683. $processor->inContext = $param['context'] === true;
  684. $response = $processor->respond();
  685. if(empty($response)) {
  686. return false;
  687. }
  688. return $response;
  689. }
  690. public function died($content = '') {
  691. global $_W, $engine;
  692. if (empty($content)) {
  693. exit('');
  694. }
  695. $response['FromUserName'] = $engine->message['to'];
  696. $response['ToUserName'] = $engine->message['from'];
  697. $response['MsgType'] = 'text';
  698. $response['Content'] = htmlspecialchars_decode($content);
  699. $response['CreateTime'] = TIMESTAMP;
  700. $response['FuncFlag'] = 0;
  701. $xml = array2xml($response);
  702. if(!empty($_GET['encrypt_type']) && $_GET['encrypt_type'] == 'aes') {
  703. $resp = $engine->account->encryptMsg($xml);
  704. $resp = $engine->account->xmlDetract($resp);
  705. } else {
  706. $resp = $xml;
  707. }
  708. exit($resp);
  709. }
  710. }