You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

479 lines
17 KiB

  1. <?php
  2. class WeChat{
  3. private $_appid;
  4. private $_appsecret;
  5. private $_accessToken;
  6. public $debug=DEBUG;
  7. public $MsgType='text';
  8. public $msg=array();
  9. /* //QRCode类型
  10. const QRCODE_TYPE_TEMP=1;
  11. const QRCODE_TYPE_LIMIT=2;
  12. const QRCODE_TYPE_LIMIT_STR=3; */
  13. public function __construct($appid,$appsecret){
  14. $this->_appid=$appid;
  15. $this->_appsecret=$appsecret;
  16. if (isset($_GET['echostr'])) {
  17. $this->valid();
  18. }
  19. if (ALWAYSCHECK==true){
  20. $check=$this->checkSignature();
  21. if (!$check){
  22. $this->writelog("checkSignature()--非法服务器");
  23. exit;
  24. }
  25. }
  26. $this->_accessToken= $this->getAccessToken();
  27. }
  28. public function getAccessToken(){
  29. $dir="./Log";
  30. if (!is_dir($dir)){
  31. mkdir($dir);
  32. }
  33. $token_file=$dir.'/access_token';
  34. if (file_exists($token_file) && time()-filemtime($token_file)<4800){
  35. $this->writelog("文件中读取的token:".file_get_contents($token_file));
  36. return file_get_contents($token_file);
  37. }
  38. $url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->_appid}&secret={$this->_appsecret}";
  39. $result=$this->_requestGet($url);
  40. if(!$result){
  41. $this->writelog("获取token出错");
  42. return false;
  43. }
  44. $result_obj=json_decode($result);
  45. file_put_contents($token_file, $result_obj->access_token);
  46. $this->writelog("url获取的token:".$result_obj->access_token);
  47. return $result_obj->access_token;
  48. }
  49. private function _requestGet($url,$ssl=true){
  50. $curl=curl_init();
  51. curl_setopt($curl, CURLOPT_URL, $url);
  52. /* $user_agent=isset($_SERVER['HTTP_USER_AGENT'])?$_SERVER['HTTP_USER_AGENT']:'';
  53. curl_setopt($curl, CURLOPT_USERAGENT, $user_agent); */
  54. curl_setopt($curl, CURLOPT_AUTOREFERER, true);
  55. if ($ssl){
  56. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  57. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
  58. }
  59. curl_setopt($curl, CURLOPT_HEADER, false);
  60. curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  61. $response=curl_exec($curl);
  62. if ($response===false){
  63. $this-> writelog('_requestGet()--返回值错误');
  64. return false;
  65. }
  66. return $response;
  67. }
  68. private function _requestPost($url,$data,$ssl=true){
  69. $curl=curl_init();
  70. curl_setopt($curl, CURLOPT_URL, $url);
  71. $user_agent=isset($_SERVER['HTTP_USER_AGENT'])?$$_SERVER['HTTP_USER_AGENT']:'';
  72. curl_setopt($curl, CURLOPT_USERAGENT, $user_agent);
  73. curl_setopt($curl, CURLOPT_AUTOREFERER, true);
  74. if ($ssl){
  75. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  76. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1);
  77. }
  78. curl_setopt($curl, CURLOPT_POST, true);
  79. curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
  80. curl_setopt($curl, CURLOPT_HEADER, false);
  81. curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  82. $response=curl_exec($curl);
  83. if ($response===false){
  84. $this->writelog('_requestPost()--返回值错误');
  85. return false;
  86. }
  87. //$error=json_decode($response,true);
  88. $this->writelog("url:".$url);
  89. $this->writelog("curl返回值为".$response);
  90. return $response;
  91. }
  92. public function valid()
  93. {
  94. $echoStr = $_GET["echostr"];
  95. //valid signature , option
  96. if($this->checkSignature()){
  97. $this->writelog( "valid()--第一次验证成功");
  98. echo $echoStr;
  99. exit;
  100. }else {
  101. $this->writelog( "valid()--第一次验证,非法服务器");
  102. exit();
  103. }
  104. }
  105. private function checkSignature()
  106. {
  107. // you must define TOKEN by yourself
  108. if (!defined("TOKEN")) {
  109. throw new Exception('TOKEN is not defined!');
  110. }
  111. $signature = $_GET["signature"];
  112. $timestamp = $_GET["timestamp"];
  113. $nonce = $_GET["nonce"];
  114. $token = TOKEN;
  115. $tmpArr = array($token, $timestamp, $nonce);
  116. // use SORT_STRING rule
  117. sort($tmpArr, SORT_STRING);
  118. $tmpStr = implode( $tmpArr );
  119. $tmpStr = sha1( $tmpStr );
  120. if( $tmpStr == $signature ){
  121. return true;
  122. }else{
  123. return false;
  124. }
  125. }
  126. private function writelog($activation){
  127. $dir="./Log";
  128. if (!is_dir($dir)){
  129. mkdir($dir);
  130. }
  131. $filename=date("Y-m-d").".txt";
  132. $open=fopen($dir."/".$filename,"a");
  133. fwrite($open,date("Y-m-d H:i:s")."\t".$activation."\r\n");
  134. fclose($open);
  135. }
  136. //获取消息
  137. public function responseMsg()
  138. {
  139. //get post data, May be due to the different environments
  140. //$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
  141. $postStr = file_get_contents("php://input");
  142. if ($this->debug){
  143. $this->writelog("function:responseMsg--接收到的消息为--".$postStr);
  144. }
  145. //extract post data
  146. if (!empty($postStr)){
  147. /* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection,
  148. the best way is to check the validity of xml by yourself */
  149. libxml_disable_entity_loader(true);
  150. $this->msg = (array)simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
  151. foreach ($this->msg as $key=>$v){
  152. $this->writelog("function:responseMsg--接收到的消息为--".$key);
  153. $this->writelog("function:responseMsg--接收到的消息为--".$v);
  154. }
  155. $this->MsgType=strtolower($this->msg['MsgType']);
  156. return $this->msg;
  157. }else {
  158. $this->writelog("消息为空");
  159. return false;
  160. }
  161. }
  162. public function eventMsg($array){
  163. switch ($array['Event']){
  164. case 'subscribe':
  165. if (!empty($array['EventKey'])){
  166. $id=substr($array['EventKey'],strpos($array['EventKey'],"qrscene_")+8);
  167. $openid=$array['FromUserName'];
  168. $time=date("Y-m-d H:i:s");
  169. $pdo = new PDO("sqlsrv:Server=".HOST.";Database=".DB, USER, PASSWORD);//5.6版本pdo连接sqlsrv
  170. $sql="SELECT id FROM qrcodeDetail WHERE qrcodeId=".$id." AND openId='".$openid."'";
  171. $selectDate=$pdo->query($sql);
  172. $selectRes=$selectDate->fetchAll(PDO::FETCH_ASSOC);
  173. if (empty($selectRes)){
  174. $sql1="INSERT INTO qrcodeDetail values($id,'$openid','subscribe','$time')";
  175. $this->writelog("eventMsg function : subscribe:result id=".$id."--sql1-".$sql1);
  176. $result=$pdo->exec($sql1);
  177. }
  178. /* $this->writelog("eventMsg function : SCAN:result id=".$id."---".json_encode($result));
  179. $errinfo=$pdo->errorInfo();
  180. if ($errinfo[0] !='00000')
  181. $this->writelog("eventMsg function : SCAN:error id=".$id."---".$errinfo[2]);
  182. else{
  183. $res=$result->fetchAll(PDO::FETCH_ASSOC);
  184. $this->writelog("eventMsg function : SCAN:res id=".$id."---".json_encode($res));
  185. $headUrl=$res[0]['url'];
  186. $this->writelog("eventMsg function : SCAN:headUrl id=".$id."---".$headUrl);
  187. header("Location: $headUrl");exit;
  188. } */
  189. // $data='{"media_id":"AuXDjP791-NMcyJajUxBLw7rLLVx_s0V9I0l_sS92c0"}';
  190. $sql2="SELECT media_id,url FROM qrcode WHERE id=".$id;
  191. $selectDate2=$pdo->query($sql2);
  192. $selectRes2=$selectDate2->fetchAll(PDO::FETCH_ASSOC);
  193. if (!empty($selectRes2)){
  194. $media_id= $selectRes2[0]['media_id'];
  195. $Rurl= $selectRes2[0]['url'];
  196. }else {
  197. $media_id="AuXDjP791-NMcyJajUxBLzhsCmTK5evvwTjASqBwmv8";
  198. $Rurl="http://xmwxc.zhizhuchuxing.cn/bookingHomePage/mdidiDetail.html?prod_code=NSPTSM01";
  199. }
  200. $data='{"media_id":"'.$media_id.'"}';
  201. $url="https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=".$this->_accessToken;
  202. $response=$this->_requestPost($url, $data);
  203. $this->writelog("返回--".$response);
  204. $media=json_decode($response,true);
  205. $mediaArray=$media['news_item'];
  206. $content = array();
  207. foreach ($mediaArray as $k=>$v){
  208. if ($k==0 || $k==1)
  209. $content[] = array("Title"=>$v['title'], "Description"=>$v['digest'], "PicUrl"=>$v['thumb_url'], "Url" =>$v['url']);
  210. else
  211. $content[] = array("Title"=>$v['title'], "Description"=>$v['digest'], "PicUrl"=>$v['thumb_url'], "Url" =>$v['content_source_url']);
  212. }
  213. $this->writelog("返回--".json_encode($content));
  214. if(is_array($content)){
  215. if (isset($content[0]['PicUrl'])){
  216. $result = $this->transmitNews($array, $content);
  217. }
  218. }
  219. }else{
  220. $data='{"media_id":"AuXDjP791-NMcyJajUxBLw7rLLVx_s0V9I0l_sS92c0"}';
  221. $url="https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=".$this->_accessToken;
  222. $response=$this->_requestPost($url, $data);
  223. $this->writelog("返回--".$response);
  224. $media=json_decode($response,true);
  225. $mediaArray=$media['news_item'];
  226. $content = array();
  227. foreach ($mediaArray as $k=>$v){
  228. if ($k==0 || $k==1)
  229. $content[] = array("Title"=>$v['title'], "Description"=>$v['digest'], "PicUrl"=>$v['thumb_url'], "Url" =>$v['url']);
  230. else
  231. $content[] = array("Title"=>$v['title'], "Description"=>$v['digest'], "PicUrl"=>$v['thumb_url'], "Url" =>$v['content_source_url']);
  232. }
  233. $this->writelog("返回--".json_encode($content));
  234. if(is_array($content)){
  235. if (isset($content[0]['PicUrl'])){
  236. $result = $this->transmitNews($array, $content);
  237. }
  238. }
  239. /* $contentStr="朋友你好,欢迎关注蜘蛛出行💐~
  240. 蜘蛛出行是专注于互联网+交通出行的科技品牌,您提供安全舒适便捷的巴士出行服务。
  241. 点击下方预订按钮开始体验吧!
  242. <a href='http://xmwxc.zhizhuchuxing.cn/bookingHomePage/mdidiDetail.html?prod_code=NSPTSM01'>点这里预订普陀山门票</a>
  243. 免去窗口排队苦恼😄
  244. 普陀山官方合作伙伴";
  245. $textTpl="
  246. <xml>
  247. <ToUserName><![CDATA[%s]]></ToUserName>
  248. <FromUserName><![CDATA[%s]]></FromUserName>
  249. <CreateTime>%s</CreateTime>
  250. <MsgType><![CDATA[%s]]></MsgType>
  251. <Content><![CDATA[%s]]></Content>
  252. </xml>";
  253. $msgType="text";
  254. $result= sprintf($textTpl, $array['FromUserName'], $array['ToUserName'], time(), $msgType, $contentStr); */
  255. }
  256. break;
  257. case 'SCAN':
  258. if (isset($array['EventKey'])){
  259. $pdo = new PDO("sqlsrv:Server=".HOST.";Database=".DB, USER, PASSWORD);//5.6版本pdo连接sqlsrv
  260. $id=$array['EventKey'];
  261. $openid=$array['FromUserName'];
  262. $time=date("Y-m-d H:i:s");
  263. $sql="SELECT id FROM qrcodeDetail WHERE qrcodeId=".$id." AND openId='".$openid."'";
  264. $selectDate=$pdo->query($sql);
  265. $selectRes=$selectDate->fetchAll(PDO::FETCH_ASSOC);
  266. if (empty($selectRes)){
  267. $sql1="INSERT INTO qrcodeDetail values($id,'$openid','SCAN','$time')";
  268. $this->writelog("eventMsg function : SCAN:result id=".$id."--sql1-".$sql1);
  269. $result=$pdo->exec($sql1);
  270. }
  271. /* $this->writelog("eventMsg function : SCAN:result id=".$id."---".json_encode($result));
  272. $errinfo=$pdo->errorInfo();
  273. if ($errinfo[0] !='00000')
  274. $this->writelog("eventMsg function : SCAN:error id=".$id."---".$errinfo[2]);
  275. else{
  276. $res=$result->fetchAll(PDO::FETCH_ASSOC);
  277. $this->writelog("eventMsg function : SCAN:res id=".$id."---".json_encode($res));
  278. $headUrl=$res[0]['url'];
  279. $this->writelog("eventMsg function : SCAN:headUrl id=".$id."---".$headUrl);
  280. header("Location: $headUrl");exit;
  281. } */
  282. // $data='{"media_id":"AuXDjP791-NMcyJajUxBLw7rLLVx_s0V9I0l_sS92c0"}';
  283. $sql2="SELECT media_id,url FROM qrcode WHERE id=".$id;
  284. $selectDate2=$pdo->query($sql2);
  285. $selectRes2=$selectDate2->fetchAll(PDO::FETCH_ASSOC);
  286. if (!empty($selectRes2)){
  287. $media_id= $selectRes2[0]['media_id'];
  288. $Rurl= $selectRes2[0]['url'];
  289. }else {
  290. $media_id="AuXDjP791-NMcyJajUxBLzhsCmTK5evvwTjASqBwmv8";
  291. $Rurl="http://xmwxc.zhizhuchuxing.cn/bookingHomePage/mdidiDetail.html?prod_code=NSPTSM01";
  292. }
  293. $data='{"media_id":"'.$media_id.'"}';
  294. $url="https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=".$this->_accessToken;
  295. $response=$this->_requestPost($url, $data);
  296. $this->writelog("返回--".$response);
  297. $media=json_decode($response,true);
  298. $mediaArray=$media['news_item'];
  299. $content = array();
  300. foreach ($mediaArray as $k=>$v){
  301. if ($k==0 || $k==1)
  302. $content[] = array("Title"=>$v['title'], "Description"=>$v['digest'], "PicUrl"=>$v['thumb_url'], "Url" =>$v['url']);
  303. elseif($k==2){
  304. $content[] = array("Title"=>$v['title'], "Description"=>$v['digest'], "PicUrl"=>$v['thumb_url'], "Url" =>$v['content_source_url']);
  305. }
  306. else
  307. $content[] = array("Title"=>$v['title'], "Description"=>$v['digest'], "PicUrl"=>$v['thumb_url'], "Url" =>$v['content_source_url']);
  308. }
  309. $this->writelog("返回--".json_encode($content));
  310. if(is_array($content)){
  311. if (isset($content[0]['PicUrl'])){
  312. $result = $this->transmitNews($array, $content);
  313. }
  314. }
  315. }
  316. break;
  317. case 'CLICK':
  318. if (isset($array['EventKey']) && $array['EventKey']=='Push-Photo-List'){
  319. $data='{"media_id":"AuXDjP791-NMcyJajUxBLw7rLLVx_s0V9I0l_sS92c0"}';
  320. $url="https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=".$this->_accessToken;
  321. $response=$this->_requestPost($url, $data);
  322. $this->writelog("返回--".$response);
  323. $media=json_decode($response,true);
  324. $mediaArray=$media['news_item'];
  325. $content = array();
  326. foreach ($mediaArray as $k=>$v){
  327. if ($k==0 || $k==1)
  328. $content[] = array("Title"=>$v['title'], "Description"=>$v['digest'], "PicUrl"=>$v['thumb_url'], "Url" =>$v['url']);
  329. else
  330. $content[] = array("Title"=>$v['title'], "Description"=>$v['digest'], "PicUrl"=>$v['thumb_url'], "Url" =>$v['content_source_url']);
  331. }
  332. $this->writelog("返回--".json_encode($content));
  333. if(is_array($content)){
  334. if (isset($content[0]['PicUrl'])){
  335. $result = $this->transmitNews($array, $content);
  336. }
  337. }
  338. }
  339. }
  340. /*
  341. $data='{"type":"news","offset":0,"count":20}';
  342. $url="https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=".$this->_accessToken;
  343. $response=$this->_requestPost($url, $data);
  344. $this->writelog("返回--".$response); */
  345. $this->writelog("回复用户event--".json_encode($result));
  346. return $result;
  347. }
  348. private function aa(){
  349. }
  350. //把openid存入数据库
  351. public function insertOpenid($data,$type){
  352. $openid=$data['FromUserName'];
  353. if ($type =='subscribe'){
  354. $sql="insert into wx_user(openid) values('{$openid}')";
  355. }else if($type =='unsubscribe'){
  356. $sql="delete from wx_user where openid='{$openid}'";
  357. }
  358. $result='';
  359. try {
  360. $pdo = new PDO("sqlsrv:Server=".HOST.";Database=".DB, USER, PASSWORD);//5.6版本pdo连接sqlsrv
  361. //$pdo=new PDO("mysql:host=".HOST.";dbname=".DB,USER,PASSWORD); //7.0版本pdo连接mysql
  362. $result=$pdo->exec($sql);
  363. $errinfo=$pdo->errorInfo();
  364. if ($errinfo[0] !='00000')
  365. $this->writelog($errinfo[2]);
  366. } catch (PDOException $e) {
  367. $this->writelog($e->getMessage());
  368. }
  369. if ($result){
  370. return true;
  371. }else {
  372. return false;
  373. }
  374. }
  375. //有用户关注的时候推送多图文消息
  376. private function transmitNews($array, $newsArray)
  377. {
  378. if(!is_array($newsArray)){
  379. return;
  380. }
  381. $itemTpl = "<item>
  382. <Title><![CDATA[%s]]></Title>
  383. <Description><![CDATA[%s]]></Description>
  384. <PicUrl><![CDATA[%s]]></PicUrl>
  385. <Url><![CDATA[%s]]></Url>
  386. </item>";
  387. $item_str = "";
  388. foreach ($newsArray as $item){
  389. $item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']);
  390. }
  391. $xmlTpl = "<xml>
  392. <ToUserName><![CDATA[%s]]></ToUserName>
  393. <FromUserName><![CDATA[%s]]></FromUserName>
  394. <CreateTime>%s</CreateTime>
  395. <MsgType><![CDATA[news]]></MsgType>
  396. <ArticleCount>%s</ArticleCount>
  397. <Articles>
  398. $item_str</Articles>
  399. </xml>";
  400. $result = sprintf($xmlTpl, $array['FromUserName'], $array['ToUserName'], time(), count($newsArray));
  401. return $result;
  402. }
  403. //获取文本
  404. public function textMsg($data){
  405. $Content=trim($data['Content']);
  406. $textTpl="
  407. <xml>
  408. <ToUserName><![CDATA[%s]]></ToUserName>
  409. <FromUserName><![CDATA[%s]]></FromUserName>
  410. <CreateTime>%s</CreateTime>
  411. <MsgType><![CDATA[%s]]></MsgType>
  412. <Content><![CDATA[%s]]></Content>
  413. </xml>";
  414. $msgType = "text";
  415. $contentStr=$this->simsimiHttp($Content);
  416. $this->writelog("textMsg有调用:".$contentStr);
  417. $resultStr = sprintf($textTpl, $data['FromUserName'], $data['ToUserName'], time(), $msgType, $contentStr);
  418. $this->writelog($resultStr);
  419. //return $resultStr;
  420. return "";
  421. }
  422. private function simsimiHttp($msg){
  423. $url="http://www.xiaodoubi.com/simsimiapi.php?msg=".$msg;
  424. $res = file_get_contents($url);
  425. file_put_contents("./demo.txt",date("Y-m-d H:i:s")." ".$res.PHP_EOL,FILE_APPEND);
  426. if (strpos($res,"xiaodouqqcom") !== false){
  427. $res="无法回答,请不要发一下奇怪的问题或字符😒";
  428. }
  429. if (strpos($msg,"主人") !== false){
  430. $res="我的主人是宇宙无敌超级大帅哥^_^人称陌帅";
  431. }
  432. return $res;
  433. }
  434. private function checkAccessToken($check){
  435. if (isset($check['errcode']) && $check['errcode'] ==40001){
  436. $url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->_appid}&secret={$this->_appsecret}";
  437. $result=$this->_requestGet($url);
  438. if(!$result){
  439. $this->writelog("获取token出错");
  440. return false;
  441. }
  442. $result_obj=json_decode($result);
  443. file_put_contents($token_file, $result_obj->access_token);
  444. $this->writelog("url获取的token:".$result_obj->access_token);
  445. return $result_obj->access_token;
  446. }
  447. }
  448. }
  449. ?>