123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- <?php
- namespace app\common\controller;
- use think\Config;
- use think\Db;
- use think\Exception;
- use think\exception\DbException;
- use think\exception\PDOException;
- class Wechat
- {
- public $appid = 'wx81f7b48cef8b4cfb';
- public $appsecret = 'e5d87a1aed0a553838286012a5685800';
- private $access_token = '54_XqfLmdbsNdBLQlCbxMNto2vBcDnQjUf9Uxt_U6CHXiPgtdlwP2ju3KP5DqK0UT6wsxKAHhw0bGcI5og1K25RFGH9v0AT7hnN-WFcJa0vaQJgcXzqqE75zbWHn5qG6HdNq-rFbGn60AK9peTwLYReAGAVIB';
- private $expires_time = 72000;
- private $_error = '';
-
- public function __construct($refreshToken = false)
- {
- $config = $this->getConfig();
- if (empty($config)) {
- exit($this->_error);
- }
-
- if (empty($config['appid']) || empty($config['appsecret'])) {
- exit('微信配置为空');
- }
- $this->appid = $config['appid'];
- $this->appsecret = $config['appsecret'];
-
- if ($refreshToken || empty($config['access_token']) || $config['access_token_expire_time'] < strtotime('+5 minute')) {
- if (!$this->refreshAccessToken()) {
- exit($this->_error);
- }
- } else {
- $this->access_token = $config['access_token'];
- $this->expires_time = $config['access_token_expire_time'];
- }
- }
-
- private function getConfig()
- {
-
- try {
- $config = Db::name('wechat')->column('value', 'name');
- } catch (PDOException $e) {
-
- if ('1146' == $e->getData()['PDO Error Info']['Driver Error Code']) {
-
- $prefix = Config::get('database.prefix');
- $sqlCreateTable = "CREATE TABLE `{$prefix}wechat` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',`name` varchar(100) CHARACTER SET utf8mb4 NOT NULL COMMENT '数据名',`value` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '值',`description` text CHARACTER SET utf8mb4 COMMENT '描述',`updatetime` int(10) DEFAULT NULL COMMENT '更新时间',PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='微信配置表';";
- $sqlInsertData = "insert into `{$prefix}wechat` (`id`, `name`, `value`, `description`, `updatetime`) values ('1','appid','','APPID',NULL),('2','appsecret','','APP SECRET',NULL),('3','access_token','','SCCESS TOKEN',NULL),('4','access_token_expire_time','','SCCESS TOKEN过期时间',NULL),('5','qrcode','','二维码',NULL);";
- try {
- Db::query($sqlCreateTable);
- Db::query($sqlInsertData);
- return Db::name('wechat')->column('value', 'name');
- } catch (Exception $e) {
- $this->_error = '微信配置表不存在,创建失败';
- return false;
- }
- }
- $this->_error = $e->getMessage();
- return false;
- } catch (DbException $e) {
- $this->_error = $e->getMessage();
- return false;
- }
- return $config;
- }
-
- private function refreshAccessToken()
- {
-
- $data = $this->wechatRequest('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $this->appid . '&secret=' . $this->appsecret);
- if (empty($data['access_token'])) {
- $this->_error = 'access_token获取失败';
- return false;
- }
- $this->access_token = $data['access_token'];
- $this->expires_time = time() + $data['expires_in'];
- try {
- Db::name('wechat')->where('name', 'access_token')->update(['value' => $this->access_token, 'updatetime' => time()]);
- Db::name('wechat')->where('name', 'access_token_expire_time')->update(['value' => $this->expires_time, 'updatetime' => time()]);
- } catch (Exception $e) {
- $this->_error = $e->getMessage();
- return false;
- }
- return true;
- }
-
- public function http_request($url, $method = 'GET', $data = [])
- {
- $addHeader = [];
- $curl = curl_init();
- curl_setopt_array($curl, [
- CURLOPT_ACCEPT_ENCODING => 'gzip,deflate',
- CURLOPT_URL => $url,
- CURLOPT_CUSTOMREQUEST => strtoupper($method),
- CURLOPT_USERAGENT => "Mozilla / 5.0 (Windows NT 10.0; Win64; x64)",
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_SSL_VERIFYPEER => false,
- CURLOPT_SSL_VERIFYHOST => false,
- CURLOPT_MAXREDIRS => 10,
- CURLOPT_CONNECTTIMEOUT => 10,
- CURLOPT_TIMEOUT => 30,
- ]);
-
- if ($data) {
- $data = json_encode($data, JSON_UNESCAPED_UNICODE);
- array_push($addHeader, 'Content-type:application/json');
- curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
- }
- curl_setopt($curl, CURLOPT_HTTPHEADER, $addHeader);
- $response = curl_exec($curl);
- $err = curl_error($curl);
- curl_close($curl);
- if ($err) throw new \Exception($err);
- return $response;
- }
-
- public function getError()
- {
- return $this->_error;
- }
-
- public function wechatRequest($url, $data = null, $callback = false)
- {
- $url = $url . (strpos($url, '?') ? '&' : '?') . 'access_token=' . $this->access_token;
- try {
- if (!empty($data)) {
- $res = $this->http_request($url, 'POST', $data);
- } else {
- $res = $this->http_request($url);
- }
- } catch (\Exception $e) {
- $this->_error = $e->getMessage();
- return false;
- }
- $res = json_decode($res, true);
-
- if (!empty($res['errcode'])) {
- $log = [
- 'url' => $url,
- 'data' => $data,
- 'response' => $res
- ];
-
- if (!$callback && '40001' == $res['errcode'] && !empty($res['errmsg']) && strpos($res['errmsg'], 'access_token is invalid')) {
-
- if (!$this->refreshAccessToken()) {
- return false;
- }
- dta($log, '微信接口请求出错,AccessToken失效所致,正在尝试修复');
-
- return $this->wechatRequest($url, $data, true);
- }
- dta($log, '微信接口请求出错');
- if (!empty($res['errmsg'])) {
- $this->_error = $res['errmsg'];
- }
- return false;
- }
- return $res;
- }
-
- public function serverValidation()
- {
- $TOKEN = 'milingerfuyelkdoywb';
- $signature = $_GET["signature"] ?? "";
- $timestamp = $_GET["timestamp"] ?? "";
- $nonce = $_GET["nonce"] ?? "";
- $tmpArr = array($TOKEN, $timestamp, $nonce);
- sort($tmpArr, SORT_STRING);
- $tmpStr = implode($tmpArr);
- $tmpStr = sha1($tmpStr);
- if ($tmpStr == $signature) {
- return $_GET["echostr"] ?? '';
- }
- return 'error';
- }
-
- public function bootToUrl($url = '')
- {
- $redirect_uri = request()->domain() . '/index/wechat/wechatRedirect?redirect=' . $url;
- $appid = $this->wechat->appid;
- $redirect_uri = urlencode($redirect_uri);
- $scope = 'snsapi_base';
- $wechat_authorize = "http://2.ipfsfil168.com/get-weixin-code.html?appid={$appid}&redirect_uri={$redirect_uri}&response_type=code&scope={$scope}&state=123#wechat_redirect";
- $this->redirect($wechat_authorize);
- }
-
- public function wechatRedirect()
- {
- $code = input('code');
- $redirect = input('redirect');
-
- if ($code) {
- $wechat_url = 'https://api.weixin.qq.com/sns/oauth2/access_token' .
- '?appid=' . $this->wechat->appid .
- '&secret=' . $this->wechat->appsecret .
- '&code=' . input('code') .
- '&grant_type=authorization_code';
- try {
- $res = $this->wechat->http_request($wechat_url);
- } catch (\Exception $e) {
- $this->error($e->getMessage());
- }
- $res = json_decode($res, true);
- if (empty($res['openid'])) {
- $this->error('登录失败');
- }
- $redirect = base64_decode($redirect);
- $redirect = htmlspecialchars_decode($redirect);
- $query = parse_url(strstr($redirect, '?'), PHP_URL_QUERY);
- parse_str($query, $params);
-
- if ('snsapi_userinfo' == $res['scope']) {
- $userinfo = file_get_contents("https://api.weixin.qq.com/sns/userinfo?access_token={$res['access_token']}&openid={$res['openid']}&lang=zh_CN");
- $userinfo = json_decode($userinfo, true);
- if (!empty($userinfo['errcode']) && !empty($userinfo['errmsg'])) {
- exit($userinfo['errmsg']);
- }
-
-
-
-
-
-
-
-
- $invite_code = $params['sharecode'] ?? '';
-
-
- $token = 'abcdefg';
- if (false === $token) {
- exit($this->_error ?: '登录失败');
- }
- } else {
- exit('仅支持snsapi_userinfo');
- }
- $redirect = $redirect . (strpos($redirect, '?') ? '&' : '?') . 'token=' . $token;
- $this->redirect($redirect ? urldecode($redirect) : '/');
- }
- $this->error('授权失败');
- }
- }
|