wechatcallbackapi.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. <?php
  2. /**
  3. * Created by 上海风车教育科技有限公司.
  4. * User: 刘红伟
  5. * Date: 15-11-23
  6. * Email: 454303753@qq.com
  7. * File:wechatcallbackapi.php
  8. */
  9. class wechatcallbackapi {
  10. protected $echostr;
  11. protected $signature;
  12. protected $timestamp;
  13. protected $nonce;
  14. protected $_POST_DATA;
  15. protected $_POST;
  16. private $toUserName; // 开发者微信号
  17. private $fromUserName; // 发送方帐号(一个OpenID)
  18. private $token;
  19. public function __construct($nonce,$timestamp,$signature,$echostr){
  20. $this->echostr=$echostr;
  21. $this->signature=$signature;
  22. $this->timestamp=$timestamp;
  23. $this->nonce =$nonce;
  24. $this->_POST_DATA = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents("php://input");
  25. }
  26. public function valid($token){
  27. $this->token=$token;
  28. if($this->checkSignature()){
  29. // echo $this->checkSignature();
  30. libxml_disable_entity_loader(TRUE);
  31. $this->_POST = simplexml_load_string($this->_POST_DATA, 'SimpleXMLElement', LIBXML_NOCDATA);
  32. if($this->_POST){
  33. $this->toUserName = strval($this->_POST->ToUserName);
  34. $this->fromUserName = strval($this->_POST->FromUserName);
  35. $this->msgType = $this->_POST->MsgType;
  36. }
  37. switch($this->msgType){
  38. case 'event':
  39. $this->_parseEvent();
  40. break;
  41. }
  42. }else{
  43. echo '';exit;
  44. }
  45. }
  46. public function get($field){
  47. $arr = (array)$this->_POST;
  48. if (isset($arr[$field]))
  49. {
  50. $result = $arr[$field];
  51. }
  52. return $result;
  53. }
  54. public function _parseEvent(){
  55. $this->event = $this->get('Event');
  56. if($this->event){
  57. $this->responseMsg($this->event);
  58. }
  59. }
  60. public function responseMsg($method='')
  61. {
  62. switch($method){
  63. case 'subscribe':
  64. $this->_subscribe();
  65. break;
  66. case 'SCAN':
  67. $this->_scan();
  68. break;
  69. case 'CLICK':
  70. $this->_click($method);
  71. break;
  72. case 'VIEW':
  73. $this->_view();
  74. break;
  75. }
  76. }
  77. /**
  78. * 用户直接关注的消息
  79. *
  80. */
  81. public function _text(){
  82. $fromUsername = $this->fromUserName;
  83. $toUsername = $this->toUserName;
  84. $time = time();
  85. $tpl= new wechattemplate('text');
  86. $textTpl=$tpl->getTpl();
  87. $contentStr = "欢迎关注漫行旅游租车,在这里您可以与我们分享您的骑行感受,或对我们的服务提出宝贵意见和建议,谢谢!";
  88. $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $contentStr);
  89. echo $resultStr;
  90. }
  91. private function setText($contentStr){
  92. $fromUsername = $this->fromUserName;
  93. $toUsername = $this->toUserName;
  94. $time = time();
  95. $tpl= new wechattemplate('text');
  96. $textTpl=$tpl->getTpl();
  97. $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $contentStr);
  98. echo $resultStr;
  99. }
  100. private function _view(){
  101. $this->_text();
  102. }
  103. private function _click($method){
  104. $fromUsername = $this->fromUserName;
  105. $toUsername = $this->toUserName;
  106. $time = time();
  107. $tpl= new wechattemplate('text');
  108. $textTpl=$tpl->getTpl();
  109. $contentStr = "欢迎关注漫行旅游租车,在这里您可以与我们分享您的骑行感受,或对我们的服务提出宝贵意见和建议,谢谢!".$method;
  110. $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $contentStr);
  111. echo $resultStr;
  112. }
  113. private function _scan(){
  114. $fromUsername = $this->fromUserName;
  115. $EventKey=$this->get('EventKey');
  116. if($EventKey){
  117. $inform_config= $this->msg_config($fromUsername,$EventKey);
  118. switch($inform_config['status']){
  119. case 20:
  120. $temapi= new wechattemplateapi($this->token,$inform_config['inform_config'],3);
  121. $temapi->send();//通知不成功,未做记录
  122. break;
  123. case 21:
  124. $this->setText('此车已被借走,请借其它辆!');
  125. break;
  126. case 22:
  127. $this->setText('此车不在锁柱,请借其它辆!');
  128. break;
  129. case 30:
  130. $this->setText('此车属于你,请误借给他人使用!');
  131. break;
  132. case 31:
  133. $this->setText('此车不属于你,请借其它辆或找回自己的车!');
  134. break;
  135. case 40:
  136. $this->setText('此车不在借的状态,请借其它辆!');
  137. break;
  138. case 60:
  139. $this->setText('此锁柱已坏,请借其它辆!');
  140. break;
  141. case 61:
  142. $this->setText('非法锁柱,请借其它辆!');
  143. break;
  144. case 62:
  145. $this->setText('此锁柱无自行车,请借其它辆!');
  146. break;
  147. case 98:
  148. $temapi= new wechattemplateapi($this->token,$inform_config['inform_config'],3);
  149. $temapi->send();//通知不成功,未做记录
  150. break;
  151. case 99:
  152. $this->setText('未找到此车!请借其它辆!');
  153. break;
  154. default :
  155. $this->setText('未找到此车!请借其它辆!');
  156. }
  157. }else{
  158. $this->_text();
  159. }
  160. }
  161. private function _subscribe(){
  162. $fromUsername = $this->fromUserName;
  163. $toUsername = $this->toUserName;
  164. $EventKey=$this->get('EventKey');
  165. $time = time();
  166. if($EventKey){
  167. $EventKey=$this->get('EventKey');
  168. $key_arr=explode('_',$EventKey);
  169. if(isset($key_arr[2])){
  170. $EventKey=$key_arr[1].'_'.$key_arr[2];
  171. }else{
  172. $EventKey=$key_arr[1];
  173. }
  174. $inform_config= $this->msg_config($fromUsername,$EventKey);
  175. switch($inform_config['status']){
  176. case 20:
  177. $temapi= new wechattemplateapi($this->token,$inform_config['inform_config'],3);
  178. $temapi->send();//通知不成功,未做记录
  179. break;
  180. case 21:
  181. $this->setText('此车已被借走,请借其它辆!');
  182. break;
  183. case 22:
  184. $this->setText('此车不在锁柱,请借其它辆!');
  185. break;
  186. case 30:
  187. $this->setText('此车属于你,请误借给他人使用!');
  188. break;
  189. case 31:
  190. $this->setText('此车不属于你,请借其它辆或找回自己的车!');
  191. break;
  192. case 40:
  193. $this->setText('此车不在借的状态!请借其它辆!');
  194. break;
  195. case 60:
  196. $this->setText('此锁柱已坏,请借其它辆!');
  197. break;
  198. case 61:
  199. $this->setText('非法锁柱,请借其它辆!');
  200. break;
  201. case 62:
  202. $this->setText('此锁柱无自行车,请借其它辆!');
  203. break;
  204. case 98:
  205. $temapi= new wechattemplateapi($this->token,$inform_config['inform_config'],3);
  206. $temapi->send();//通知不成功,未做记录
  207. break;
  208. case 99:
  209. $this->setText('未找到此车!请借其它辆!');
  210. break;
  211. default :
  212. $this->setText('未找到此车!请借其它辆!');
  213. }
  214. }else{
  215. $tpl= new wechattemplate('text');
  216. $textTpl=$tpl->getTpl();
  217. $contentStr = "欢迎关注漫行旅游租车,在这里您可以与我们分享您的骑行感受,或对我们的服务提出宝贵意见和建议,谢谢!";
  218. $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $contentStr);
  219. echo $resultStr;
  220. }
  221. }
  222. /*
  223. * 文本消息
  224. *
  225. * ToUserName: 开发者微信号
  226. * FromUserName: 发送方帐号(一个OpenID)
  227. * CreateTime: 消息创建时间 (整型)
  228. * MsgType: text
  229. * Content: 文本消息内容
  230. * MsgId: 消息id,64位整型
  231. */
  232. private function checkSignature()
  233. {
  234. // you must define TOKEN by yourself
  235. if (!defined("TOKEN")) {
  236. throw new Exception('TOKEN is not defined!');
  237. }
  238. $signature = $this->signature;
  239. $timestamp = $this->timestamp;
  240. $nonce = $this->nonce;
  241. $token = TOKEN;
  242. $tmpArr = array($token, $timestamp, $nonce);
  243. // use SORT_STRING rule
  244. sort($tmpArr, SORT_STRING);
  245. $tmpStr = implode( $tmpArr );
  246. $tmpStr = sha1( $tmpStr );
  247. if( $tmpStr == $signature ){
  248. return true;
  249. }else{
  250. return false;
  251. }
  252. }
  253. private function msg_config($fromUsername,$EventKey){
  254. /**
  255. * 现在只有自行车编号
  256. */
  257. $data=array();
  258. $bike_name='未知自行车';
  259. $location_name='未知网点';
  260. $bike_user_status=0;
  261. $bike_status=0;
  262. $lock_id=0;
  263. $bike_no='';
  264. $lock_code='';
  265. if($EventKey){
  266. $type =explode('_',$EventKey);
  267. if(isset($type[1])){
  268. if($type[0]=='L'){
  269. //查锁柱
  270. $lock_no= $type[1];
  271. //查看锁柱是否存在。并查看锁柱状态
  272. $l_lock_data= Yii::app()->db->createCommand()->from('lock_cylinder')->where('lock_cylinder_no=:lock_cylinder_no',array(':lock_cylinder_no'=>$lock_no))->queryRow();
  273. //存在
  274. if($l_lock_data){
  275. $lock_id=$l_lock_data['lock_cylinder_id'];
  276. //锁柱已坏时
  277. if($l_lock_data['status']==1){
  278. $data=array();
  279. $data['status']=60;
  280. $data['inform_config']=array();
  281. return $data;
  282. }
  283. }else{
  284. //不存在
  285. $data=array();
  286. $data['status']=61;
  287. $data['inform_config']=array();
  288. return $data;
  289. }
  290. //锁柱存在时,查看锁上可有车
  291. $l_bike_lock_data= Yii::app()->db->createCommand()->from('bike_lock_relation')->where('lock_cylinder_id=:lock_cylinder_id',array(':lock_cylinder_id'=>$lock_id))->queryRow();
  292. if($l_bike_lock_data){
  293. //存在时
  294. $l_bike_data= Yii::app()->db->createCommand()->select('bike_id,bike_no,bike_category_id,status')->from('bike')->where('bike_id=:bike_id',array(':bike_id'=>$l_bike_lock_data['bike_id']))->queryRow();
  295. if(!$l_bike_data){
  296. $data=array();
  297. $data['status']=99;
  298. $data['inform_config']=array();
  299. return $data;
  300. }
  301. $bike_no=$l_bike_data['bike_no'];
  302. }else{
  303. //不存在时
  304. //获取管理器
  305. $local_c_data= Yii::app()->db->createCommand()->select('location_controller_id,location_controller_no,status')->from('location_controller')->where('location_controller_id=:location_controller_id',array(':location_controller_id'=>$l_lock_data['location_controller_id']))->queryRow();
  306. if($local_c_data){
  307. $w_json= $this->getData(Yii::app()->params['hardware_api_url'].'query_state?code='.$local_c_data['location_controller_no']);
  308. $w_data=json_decode($w_json,1);
  309. if($w_data){
  310. if(isset($w_data['stations'][0]['docks'])){
  311. $docks=$w_data['stations'][0]['docks'];
  312. foreach($docks as $v) {
  313. if (isset($v['status']) && $v['status'] == 1) {
  314. if (isset($v['dockno']) && ($v['dockno'] == $lock_no)) {
  315. if(isset($v['bikecode']) && !empty($v['bikecode'])){
  316. $bike_no = $v['bikecode'];
  317. }
  318. }
  319. }
  320. }
  321. if(empty($bike_no)){
  322. $data=array();
  323. $data['status']=62;
  324. $data['inform_config']=array();
  325. return $data;
  326. }
  327. }else{
  328. $data=array();
  329. $data['status']=62;
  330. $data['inform_config']=array();
  331. return $data;
  332. }
  333. }else{
  334. $data=array();
  335. $data['status']=62;
  336. $data['inform_config']=array();
  337. return $data;
  338. }
  339. }else{
  340. $data=array();
  341. $data['status']=62;
  342. $data['inform_config']=array();
  343. return $data;
  344. }
  345. }
  346. }else{
  347. $bike_no=$type[1];
  348. }
  349. }else{
  350. $bike_no=$type[0];
  351. }
  352. }
  353. $bike_data= Yii::app()->db->createCommand()->select('bike_id,bike_no,bike_category_id,status')->from('bike')->where('bike_no=:bike_no',array(':bike_no'=>$bike_no))->queryRow();
  354. if($bike_data){
  355. $bike_category_data= Yii::app()->db->createCommand()->select('category_name')->from('bike_category')->where('category_id=:category_id',array(':category_id'=>$bike_data['bike_category_id']))->queryRow();
  356. if($bike_category_data){
  357. $bike_name=$bike_category_data['category_name'];
  358. }
  359. /**
  360. * 车的状态
  361. */
  362. if($bike_data['status']==20){
  363. //取出锁柱ID
  364. $bike_lock_data= Yii::app()->db->createCommand()->from('bike_lock_relation')->where('bike_id=:bike_id',array(':bike_id'=>$bike_data['bike_id']))->queryRow();
  365. if($bike_lock_data){
  366. //取网点id
  367. $lock_data= Yii::app()->db->createCommand()->select('lock_cylinder_id,lock_cylinder_no,location_id')->from('lock_cylinder')->where('lock_cylinder_id=:lock_cylinder_id',array(':lock_cylinder_id'=>$bike_lock_data['lock_cylinder_id']))->queryRow();
  368. }
  369. if($lock_data){
  370. $location_data= Yii::app()->db->createCommand()->select('location_id,location_no,location_name')->from('location')->where('location_id=:location_id',array(':location_id'=>$lock_data['location_id']))->queryRow();
  371. if($location_data){
  372. $location_name = $location_data['location_name'];
  373. }
  374. $url=Yii::app()->params['weixin_realm'].Yii::app()->createUrl('lend/index',array('openId'=>$fromUsername,'eventkey'=>$bike_no,'expires_time'=>time()));
  375. $account=$location_name;
  376. $data['status']=20;
  377. $data['inform_config']=array(
  378. 'url'=>$url,
  379. 'openId'=>$fromUsername,
  380. 'first'=>'恭喜您扫描成功',
  381. 'location'=>$location_name,
  382. 'bike_name'=>$bike_name,
  383. 'remark'=>'请在5分钟内完成租车,否则此链接将失效'
  384. );
  385. }else{
  386. $data['status']=22;
  387. $data['inform_config']=array();
  388. }
  389. }elseif($bike_data['status']==30){
  390. //判断
  391. $w_json= $this->getData(Yii::app()->params['hardware_api_url'].'bike?bikecode='.$bike_no);
  392. $w_result=json_decode($w_json,1);
  393. if($w_result && isset($w_result['errcode']) && $w_result['errcode']){
  394. $data['status']=21;
  395. }
  396. if($w_result && isset($w_result['isout']) && $w_result['isout']){
  397. $lock_code=$w_result['dockno'];
  398. $location_no=$w_result['sitecode'];
  399. //
  400. $b_lock_data= Yii::app()->db->createCommand()->select('lock_cylinder_id,lock_cylinder_no,location_id')->from('lock_cylinder')->where('lock_cylinder_no=:lock_cylinder_no',array(':lock_cylinder_no'=>$lock_code))->queryRow();
  401. if($b_lock_data){
  402. $b_location_data= Yii::app()->db->createCommand()->select('location_id,location_no,location_name')->from('location')->where('location_id=:location_id',array(':location_id'=>$b_lock_data['location_id']))->queryRow();
  403. }
  404. if($b_location_data){
  405. $location_name=$b_location_data['location_name'];
  406. $url=Yii::app()->params['weixin_realm'].Yii::app()->createUrl('lend/index',array('openId'=>$fromUsername,'eventkey'=>$bike_no,'expires_time'=>time()));
  407. $account=$location_name;
  408. $data['status']=98;
  409. $data['inform_config']=array(
  410. 'url'=>$url,
  411. 'openId'=>$fromUsername,
  412. 'first'=>'恭喜您扫描成功',
  413. 'location'=>$location_name,
  414. 'bike_name'=>$bike_name,
  415. 'remark'=>'请在5分钟内完成租车,否则此链接将失效'
  416. );
  417. }
  418. }else{
  419. $data['status']=21;
  420. }
  421. }else{
  422. $data['status']=40;
  423. $data['inform_config']=array();
  424. }
  425. }else{
  426. $data['status']=99;
  427. $data['inform_config']=array();
  428. }
  429. /**
  430. * 验证人
  431. */
  432. $auth_data= Yii::app()->db->createCommand()->select('auth_id,auth_uid')->from('user_auth')->where('auth_uid=:auth_uid',array(':auth_uid'=>$fromUsername))->queryRow();
  433. if($auth_data){
  434. $user_auth_data= Yii::app()->db->createCommand()->from('user_auth_relation')->where('auth_id=:auth_id',array(':auth_id'=>$auth_data['auth_id']))->queryRow();
  435. if($user_auth_data){
  436. $bike_user_data= Yii::app()->db->createCommand()->from('bike_user_relation')->where('user_id=:user_id',array(':user_id'=>$user_auth_data['user_id']))->queryRow();
  437. if($bike_user_data){
  438. /**
  439. * 判断此车是否属于本人
  440. *
  441. */
  442. if($bike_data['bike_id']==$bike_user_data['bike_id']){
  443. $data['status']=30;
  444. $data['inform_config']=array();
  445. }else{
  446. $data['status']=31;
  447. $data['inform_config']=array();
  448. }
  449. }else{
  450. $a_bike_data= Yii::app()->db->createCommand()->from('abnormal_bike_relation')->where('user_id=:user_id',array(':user_id'=>$user_auth_data['user_id']))->queryRow();
  451. if($a_bike_data){
  452. if($bike_data['bike_id']==$a_bike_data['bike_id']){
  453. $data['status']=30;
  454. $data['inform_config']=array();
  455. }else{
  456. $data['status']=31;
  457. $data['inform_config']=array();
  458. }
  459. }
  460. }
  461. }
  462. }
  463. //验检是否在锁柱上
  464. return $data;
  465. }
  466. private function getData($url){
  467. $ch = curl_init();
  468. curl_setopt($ch, CURLOPT_URL, $url);
  469. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  470. curl_setopt($ch, CURLOPT_HEADER, 0);
  471. $output = curl_exec($ch);
  472. curl_close($ch);
  473. return $output;
  474. }
  475. }