Wechat.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. <?php
  2. namespace app\admin\controller;
  3. header("Content-type:text/html;chsarset=utf-8");
  4. define("TOKEN", "ydmydm");
  5. // echo "!!!!";
  6. // use app\admin\BaseController;
  7. use think\Request;
  8. class Wechat{
  9. private $_token = "ydmydm";
  10. private $appid = "wx60064e1cac4296e6";
  11. private $secrect = "bce94d361402cc535559a9bbdb908de8";
  12. private $accessToken = '';
  13. static $qrcode_url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?";
  14. static $token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&";
  15. static $qrcode_get_url = "https://mp.weixin.qq.com/cgi-bin/showqrcode?";
  16. public function index(){
  17. // $token = "ydm2020";
  18. // $timestamp = "1623215012";
  19. // $nonce = "akdfakjdfowen";
  20. // $tmpArr = array($token, $timestamp, $nonce);
  21. // sort($tmpArr, SORT_STRING); //true
  22. // dump($tmpArr);
  23. // $tmpStr = implode( $tmpArr );
  24. // $tmpStr = sha1( $tmpStr );
  25. // echo "!!!";
  26. // dump($tmpStr);
  27. echo "!!!";
  28. // return view();
  29. }
  30. public function indexAction(){
  31. $fqid = rand(1000000, 99999999);
  32. $ACCESS_TOKEN = $this->getToken($this->appid, $this->secrect);
  33. $url = $this->getQrcodeurl($ACCESS_TOKEN, $fqid, 2);
  34. file_put_contents(LOG_PATH . '/wx.log', $fqid, FILE_APPEND);
  35. $img_url = $this->DownLoadQr($url, 'qrcode');
  36. $this->setData('qrcode_url', $img_url);
  37. $this->setView('index');
  38. }
  39. public function test(){
  40. $signature = $_GET["signature"];
  41. $timestamp = $_GET["timestamp"];
  42. $nonce = $_GET["nonce"];
  43. $echostr = $_GET["echostr"];
  44. // echo($signature);
  45. // echo($timestamp);
  46. // echo($nonce);
  47. // echo($echostr);
  48. if ($this->checkSignature($signature, $timestamp, $nonce)) {
  49. // header('Content-Type: text/html; charset=utf-8');
  50. // return Response($echostr, response_type='text/html; charset=utf-8');
  51. // echo $echostr;
  52. echo $echostr;
  53. } else {
  54. return 'Token verification failed.';
  55. }
  56. }
  57. private function checkSignature($signature, $timestamp, $nonce){
  58. // $signature = $_GET["signature"];
  59. // $timestamp = $_GET["timestamp"];
  60. // $nonce = $_GET["nonce"];
  61. // $echostr = $_GET["echostr"];
  62. // dump($signature);
  63. $token = TOKEN;
  64. // $token = $_token;
  65. $tmpArr = array($token, $timestamp, $nonce);
  66. // halt($tmpArr);
  67. sort($tmpArr, SORT_STRING);
  68. $tmpStr = implode( $tmpArr );
  69. $tmpStr = sha1( $tmpStr );
  70. if( $tmpStr == $signature ){
  71. return true;
  72. // return true;
  73. }else{
  74. return false;
  75. }
  76. }
  77. /**
  78. * 获取关注二维码ticket
  79. * @param $ACCESS_TOKEN
  80. * @param $fqid
  81. * @param int $type
  82. *
  83. * @return bool|string
  84. */
  85. protected function getQrcodeurl($ACCESS_TOKEN, $fqid, $type = 1){
  86. $url = self::$qrcode_url . 'access_token=' . $ACCESS_TOKEN;
  87. if ($type == 1) {
  88. //生成永久二维码
  89. $qrcode = '{"action_name": "QR_LIMIT_SCENE", "action_info": {"scene": {"scene_str": ' . $fqid . '}}}';
  90. } else {
  91. //生成临时二维码
  92. $qrcode = '{"expire_seconds": 604800, "action_name": "QR_STR_SCENE", "action_info": {"scene": {"scene_str": ' . $fqid . '}}}';
  93. }
  94. $result = http_post_data($url, $qrcode);
  95. $oo = json_decode($result[1]);
  96. if (empty($oo->ticket)) {
  97. return false;
  98. }
  99. if (!$oo->ticket) {
  100. $this->ErrorLogger('getQrcodeurl falied. Error Info: getQrcodeurl get failed');
  101. exit();
  102. }
  103. $url = self::$qrcode_get_url . 'ticket=' . $oo->ticket . '';
  104. echo $oo->ticket;
  105. return $url;
  106. }
  107. /**
  108. * 保存二维码到服务器
  109. * 可直接进行展示不进行存储,看业务需求
  110. *
  111. * @param $url
  112. * @param $filestring
  113. *
  114. * @return bool|string
  115. */
  116. protected function DownLoadQr($url, $filestring){
  117. if ($url == "") {
  118. return false;
  119. }
  120. $filename = $filestring . rand(0, 99999999999) . '.jpg';
  121. ob_start();
  122. readfile($url);
  123. $img = ob_get_contents();
  124. ob_end_clean();
  125. /*if (!file_exists('/public/qrcode/' . $filename)) {
  126. touch('/public/qrcode/' . $filename);
  127. }*/
  128. $file = PUBLIC_PATH . 'qrcode/' . $filename;
  129. $fp2 = fopen($file, "a");
  130. if (fwrite($fp2, $img) === false) {
  131. $this->ErrorLogger('dolwload image falied. Error Info: 无法写入图片');
  132. exit();
  133. }
  134. fclose($fp2);
  135. return '/public/qrcode/' . $filename;
  136. }
  137. /**
  138. * @param $appid
  139. * @param $appsecret
  140. *
  141. * @return mixed
  142. * 获取token
  143. */
  144. protected function getToken($appid, $appsecret){
  145. $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $appid . "&secret=" . $appsecret;
  146. $token = Request::get($url);
  147. // $url = sprintf(config('wechat.access_token_url'), config('wechat.appid'), config('wechat.appsecret'));
  148. $url = sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=", $appid, $appsecret);
  149. $access_token = json_decode(file_get_contents($url),true);
  150. halt($access_token);
  151. // $token = json_decode(stripslashes($token));
  152. // $arr = json_decode(json_encode($token), true);
  153. // $access_token = $arr['access_token'];
  154. return $access_token;
  155. }
  156. // public static function getToken(){
  157. //
  158. // $accessToken = cache(self::$_token_key);
  159. // if (!$accessToken) {
  160. // $accessTokenUrl = sprintf(config('wechat.access_token_url'), config('wechat.appid'), config('wechat.appsecret'));
  161. // $accessTokenArr = json_decode(file_get_contents($accessTokenUrl),true);
  162. // if (isset($accessTokenArr['errcode'])) {
  163. // //记录日记
  164. // Log::info($accessTokenArr['errmsg']);
  165. // return false;
  166. // } else {
  167. // $accessToken = $accessTokenArr['access_token'];
  168. // cache(self::$_token_key, $accessToken, $accessTokenArr['expires_in'] - 200);
  169. // }
  170. // }
  171. // return $accessToken;
  172. // }
  173. public function serviceAction(){
  174. $this->showPage = false;
  175. $echoStr = @$_GET["echostr"];
  176. if (!isset($echoStr)) {
  177. $this->responseMsg();
  178. } else {
  179. $this->valid();
  180. }
  181. }
  182. public function valid(){
  183. $nonce = $_GET['nonce'];
  184. $token = $this->_token;
  185. $timestamp = $_GET['timestamp'];
  186. $echostr = $_GET['echostr'];
  187. $signature = $_GET['signature'];
  188. //形成数组,然后按字典序排序
  189. $array = array($nonce, $timestamp, $token);
  190. sort($array);
  191. //拼接成字符串,sha1加密 ,然后与signature进行校验
  192. $str = sha1(implode($array));
  193. if ($str == $signature) {
  194. echo $echostr;
  195. exit;
  196. }
  197. }
  198. /**
  199. * 微信事件推送接收方法
  200. */
  201. public function responseMsg(){
  202. $postStr = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents("php://input");
  203. if (!empty($postStr)) {
  204. $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
  205. // 微信消息类型
  206. $RX_TYPE = trim($postObj->MsgType);
  207. switch ($RX_TYPE) {
  208. case "text":
  209. // 文本消息
  210. $resultStr = $this->handleText($postObj);
  211. break;
  212. case "event":
  213. // 事件推送
  214. $resultStr = $this->handleEvent($postObj);
  215. break;
  216. default:
  217. $resultStr = "Unknow msg type: " . $RX_TYPE;
  218. break;
  219. }
  220. echo $resultStr;
  221. } else {
  222. echo "";
  223. exit;
  224. }
  225. }
  226. /**
  227. * 微信文本消息
  228. * @param $postObj
  229. */
  230. public function handleText($postObj){
  231. $fromUsername = $postObj->FromUserName;
  232. $toUsername = $postObj->ToUserName;
  233. $keyword = trim($postObj->Content);
  234. $time = time();
  235. $textTpl = "<xml>
  236. <ToUserName><![CDATA[%s]]></ToUserName>
  237. <FromUserName><![CDATA[%s]]></FromUserName>
  238. <CreateTime>%s</CreateTime>
  239. <MsgType><![CDATA[%s]]></MsgType>
  240. <Content><![CDATA[%s]]></Content>
  241. <FuncFlag>0</FuncFlag>
  242. </xml>";
  243. if (!empty($keyword)) {
  244. $msgType = "text";
  245. $contentStr = "欢迎您关注";
  246. $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
  247. echo $resultStr;
  248. } else {
  249. echo "lalala";
  250. }
  251. }
  252. /**
  253. * 获取时间消息并解析相应参数
  254. * 提供数据简单推送(自动回复)
  255. * @param $object
  256. *
  257. * @return string
  258. */
  259. public function handleEvent($object){
  260. $contentStr = "";
  261. switch ($object->Event) {
  262. case "subscribe":
  263. $contentStr = "感谢您关注【测试账号】";
  264. $openid = (string)$object->FromUserName; //数据类型转换为字符串,mmp这个问题找了好久
  265. $refer_id = explode('_', $object->EventKey); //$object->EventKey返回的是qrsence_123这种类型
  266. $this->createuserinfo($openid, $refer_id[1]);//获取用户信息
  267. break;
  268. case "SCAN":
  269. $contentStr = "您已关注过,谢谢!";
  270. $openid = (string)$object->FromUserName; //数据类型转换为字符串,mmp这个问题找了好久
  271. $refer_id = explode('_', $object->EventKey); //$object->EventKey返回的是qrsence_123这种类型
  272. $this->createuserinfo($openid, $refer_id[0]);//获取用户信息
  273. break;
  274. }
  275. $resultStr = $this->responseText($object, $contentStr);
  276. return $resultStr;
  277. }
  278. /**
  279. * 消息回复模板
  280. * @param $object
  281. * @param $content
  282. * @param int $flag
  283. *
  284. * @return string
  285. */
  286. public function responseText($object, $content, $flag = 0){
  287. $textTpl = "<xml>
  288. <ToUserName><![CDATA[%s]]></ToUserName>
  289. <FromUserName><![CDATA[%s]]></FromUserName>
  290. <CreateTime>%s</CreateTime>
  291. <MsgType><![CDATA[text]]></MsgType>
  292. <Content><![CDATA[%s]]></Content>
  293. <FuncFlag>%d</FuncFlag>
  294. </xml>";
  295. $resultStr = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(), $content, $flag);
  296. return $resultStr;
  297. }
  298. /**
  299. * 获取用户详细信息
  300. * @param $openid
  301. * @param $refer_id
  302. */
  303. public function createuserinfo($openid, $refer_id){
  304. $url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" . $this->getToken($this->appid, $this->secrect) . "&openid=" . $openid;
  305. $user = request_get($url);
  306. $user = json_decode($user, true);
  307. $users = array(
  308. 'openid' => $openid,
  309. 'nickname' => $user['nickname'],
  310. 'avatar' => $user['headimgurl'],
  311. 'sex' => $user['sex'],
  312. 'unionid' => $user['unionid'],
  313. 'status' => 1,
  314. 'reg_time' => $user['subscribe_time'],//关注公众号的时间
  315. 'bind_user' => $refer_id
  316. );
  317. $user_str = date('Y-m-d H:i:s') . "\t";
  318. foreach ($users as $key => $value) {
  319. $user_str .= $key . '=' . $value . "\t";
  320. }
  321. $user_str .= "\n";
  322. file_put_contents(LOG_PATH . "wx.log", $user_str, FILE_APPEND);
  323. }
  324. }