新增修复(默认如果删除会员后不删除关联第三方账号数据,则再次使用第三方登录后导致白屏)
/application/admin/controller/user/User.php 增加删除关联三方登录账号
/** * 删除 * @param mixed $ids */ public function del($ids = "") { appadminmodelUser::event('after_delete', function ($row) { $third = get_addon_info('third'); if($third && $third['state']==1){ addonsthirdmodelThird::where('user_id', $row['id'])->delete(); } }); parent::del($ids); }
第一步需要在微信开放平台绑定公众号并创建网站应用
注:如果不绑定公众号,通过微信公众号登录时是无法获取unionid的,则无法与微信扫码登录做同步唯一判断
第二步执行sql增加字段
ALTER TABLE `fa_third` ADD COLUMN `unionid` varchar(50) NOT NULL DEFAULT '' COMMENT '第三方唯一uid' AFTER `openid`;
第三步配置第三方登录
_scan结尾的参数值填写微信开放平台申请的网站应用参数
增加扫码登录appid和appsecret
增加3个扫码登录参数
app_id_scan
app_secret_scan
scope_scan
以下为代码修改(修改代码基础 第三方登录版本号1.1.2)
如果版本号一致直接覆盖即可
如果不一致请对比修改
搜索修改关键词 CoderRay修改
/addons/third/library/Wechat.php
<?phpnamespace addonsthirdlibrary;use fastHttp;use thinkConfig;use thinkSession;/** * 微信 */class Wechat{ const GET_AUTH_SCAN_CODE_URL = "https://open.weixin.qq.com/connect/qrconnect";//CoderRay修改 const GET_AUTH_CODE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize"; const GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token"; const GET_USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo"; /** * 配置信息 * @var array */ private $config = []; public function __construct($options = []) { if ($config = Config::get('third.wechat')) { $this->config = array_merge($this->config, $config); } $this->config = array_merge($this->config, is_array($options) ? $options : []); //CoderRay修改 start $this->isWechat = stripos(request()->server('HTTP_USER_AGENT'), 'MicroMessenger') !== false; if(!$this->isWechat){ $this->config['app_id'] = $this->config['app_id_scan']; $this->config['app_secret'] = $this->config['app_secret_scan']; $this->config['scope'] = $this->config['scope_scan']; } //CoderRay修改 end } /** * 登陆 */ public function login() { header("Location:" . $this->getAuthorizeUrl()); } /** * 获取authorize_url */ public function getAuthorizeUrl() { $state = md5(uniqid(rand(), true)); Session::set('state', $state); $queryarr = array( "appid" => $this->config['app_id'], "redirect_uri" => $this->config['callback'], "response_type" => "code", "scope" => $this->config['scope'], "state" => $state, ); request()->isMobile() && $queryarr['display'] = 'mobile'; //CoderRay修改 start if($this->isWechat){ $url = self::GET_AUTH_CODE_URL . '?' . http_build_query($queryarr) . '#wechat_redirect'; }else{ $url = self::GET_AUTH_SCAN_CODE_URL . '?' . http_build_query($queryarr) . '#wechat_redirect'; } //CoderRay修改 end return $url; } /** * 获取用户信息 * @param array $params * @return array */ public function getUserInfo($params = []) { $params = $params ? $params : request()->get(); if (isset($params['access_token']) || (isset($params['state']) && $params['state'] == Session::get('state') && isset($params['code']))) { //获取access_token $data = isset($params['code']) ? $this->getAccessToken($params['code']) : $params; $access_token = isset($data['access_token']) ? $data['access_token'] : ''; $refresh_token = isset($data['refresh_token']) ? $data['refresh_token'] : ''; $expires_in = isset($data['expires_in']) ? $data['expires_in'] : 0; if ($access_token) { $openid = isset($data['openid']) ? $data['openid'] : ''; $unionid = isset($data['unionid']) ? $data['unionid'] : ''; //CoderRay修改 start if(!$this->isWechat){ $scope = 'snsapi_login'; }else{ $scope = 'snsapi_userinfo'; } //CoderRay修改 end if (stripos($this->config['scope'], $scope) !== false) {//CoderRay修改 //获取用户信息 $queryarr = [ "access_token" => $access_token, "openid" => $openid, "lang" => 'zh_CN' ]; $ret = Http::get(self::GET_USERINFO_URL, $queryarr); $userinfo = (array)json_decode($ret, true); if (!$userinfo || isset($userinfo['errcode'])) { return []; } $userinfo = $userinfo ? $userinfo : []; $userinfo['avatar'] = isset($userinfo['headimgurl']) ? $userinfo['headimgurl'] : ''; } else { $userinfo = []; } $data = [ 'access_token' => $access_token, 'refresh_token' => $refresh_token, 'expires_in' => $expires_in, 'openid' => $openid, 'unionid' => $unionid, 'userinfo' => $userinfo ]; return $data; } } return []; } /** * 获取access_token * @param string code * @return array */ public function getAccessToken($code = '') { if (!$code) { return []; } $queryarr = array( "appid" => $this->config['app_id'], "secret" => $this->config['app_secret'], "code" => $code, "grant_type" => "authorization_code", ); $response = Http::get(self::GET_ACCESS_TOKEN_URL, $queryarr); $ret = (array)json_decode($response, true); return $ret ? $ret : []; }}
/addons/third/library/Service.php
<?phpnamespace addonsthirdlibrary;use addonsthirdmodelThird;use appcommonmodelUser;use fastRandom;use thinkDb;use thinkexceptionPDOException;/** * 第三方登录服务类 * * @author Karson */class Service{ /** * 第三方登录 * @param string $platform 平台 * @param array $params 参数 * @param array $extend 会员扩展信息 * @param int $keeptime 有效时长 * @return boolean */ public static function connect($platform, $params = [], $extend = [], $keeptime = 0) { $time = time(); $values = [ 'platform' => $platform, 'openid' => $params['openid'], 'unionid' => isset($params['unionid'])?$params['unionid']:'',//CoderRay修改 'openname' => isset($params['userinfo']['nickname']) ? $params['userinfo']['nickname'] : '', 'access_token' => $params['access_token'], 'refresh_token' => $params['refresh_token'], 'expires_in' => $params['expires_in'], 'logintime' => $time, 'expiretime' => $time + $params['expires_in'], ]; $auth = appcommonlibraryAuth::instance(); $auth->keeptime($keeptime); //CoderRay修改 start if(isset($params['unionid']) && !empty($params['unionid'])){ $third = Third::get(['platform' => $platform, 'unionid' => $params['unionid']]); if(!$third){ $third = Third::get(['platform' => $platform, 'openid' => $params['openid']]); } }else{ $third = Third::get(['platform' => $platform, 'openid' => $params['openid']]); } //CoderRay修改 end if ($third) { $user = User::get($third['user_id']); if (!$user) { return false; } $third->save($values); return $auth->direct($user->id); } else { // 先随机一个用户名,随后再变更为u+数字id $username = Random::alnum(20); $password = Random::alnum(6); $domain = request()->host(); Db::startTrans(); try { // 默认注册一个会员 $result = $auth->register($username, $password, $username . '@' . $domain, '', $extend); if (!$result) { return false; } $user = $auth->getUser(); $fields = ['username' => 'u' . $user->id, 'email' => 'u' . $user->id . '@' . $domain]; if (isset($params['userinfo']['nickname'])) { $fields['nickname'] = $params['userinfo']['nickname']; } if (isset($params['userinfo']['avatar'])) { $fields['avatar'] = htmlspecialchars(strip_tags($params['userinfo']['avatar'])); } // 更新会员资料 $user = User::get($user->id); $user->save($fields); // 保存第三方信息 $values['user_id'] = $user->id; Third::create($values); Db::commit(); } catch (PDOException $e) { Db::rollback(); $auth->logout(); return false; } // 写入登录Cookies和Token return $auth->direct($user->id); } }}
/addons/third/controller/Index.php
<?phpnamespace addonsthirdcontroller;use addonsthirdlibraryApplication;use addonsthirdlibraryService;use addonsthirdmodelThird;use thinkaddonsController;use thinkConfig;use thinkCookie;use thinkHook;use thinkLang;use thinkSession;/** * 第三方登录插件 */class Index extends Controller{ protected $app = null; protected $options = []; public function _initialize() { parent::_initialize(); $config = get_addon_config('third'); $this->app = new Application($config); } /** * 插件首页 */ public function index() { if (!appadminlibraryAuth::instance()->id) { $this->error('当前插件暂无前台页面'); } $platformList = []; if ($this->auth->id) { $platformList = Third::where('user_id', $this->auth->id)->column('platform'); } $this->view->assign('platformList', $platformList); return $this->view->fetch(); } /** * 发起授权 */ public function connect() { $platform = $this->request->param('platform'); $url = $this->request->request('url', $this->request->server('HTTP_REFERER', '/'), 'trim'); if (!$this->app->{$platform}) { $this->error(__('Invalid parameters')); } if ($url) { Session::set("redirecturl", $url); } // 跳转到登录授权页面 $this->redirect($this->app->{$platform}->getAuthorizeUrl()); return; } /** * 通知回调 */ public function callback() { $auth = $this->auth; //监听注册登录注销的事件 Hook::add('user_login_successed', function ($user) use ($auth) { $expire = input('post.keeplogin') ? 30 * 86400 : 0; Cookie::set('uid', $user->id, $expire); Cookie::set('token', $auth->getToken(), $expire); }); Hook::add('user_register_successed', function ($user) use ($auth) { Cookie::set('uid', $user->id); Cookie::set('token', $auth->getToken()); }); Hook::add('user_logout_successed', function ($user) use ($auth) { Cookie::delete('uid'); Cookie::delete('token'); }); $platform = $this->request->param('platform'); // 成功后返回之前页面 $url = Session::has("redirecturl") ? Session::pull("redirecturl") : url('index/user/index'); // 授权成功后的回调 $userinfo = $this->app->{$platform}->getUserInfo(); if (!$userinfo) { $this->error(__('操作失败'), $url); } Session::set("{$platform}-userinfo", $userinfo); //判断是否启用账号绑定 //CoderRay修改 start if(isset($userinfo['unionid']) && !empty($userinfo['unionid'])){ $third = Third::get(['platform' => $platform, 'unionid' => $userinfo['unionid']]); if(!$third){ $third = Third::get(['platform' => $platform, 'openid' => $userinfo['openid']]); } }else{ $third = Third::get(['platform' => $platform, 'openid' => $userinfo['openid']]); } //CoderRay修改 end if (!$third) { $config = get_addon_config('third'); //要求绑定账号或会员当前是登录状态 if ($config['bindaccount'] || $this->auth->id) { $this->redirect(url('index/third/prepare') . "?" . http_build_query(['platform' => $platform, 'url' => $url])); } } $loginret = Service::connect($platform, $userinfo); if ($loginret) { $this->redirect($url); } } /** * 绑定账号 */ public function bind() { $platform = $this->request->request('platform', $this->request->param('platform', '')); $url = $this->request->get('url', $this->request->server('HTTP_REFERER')); $redirecturl = url("index/third/bind") . "?" . http_build_query(['platform' => $platform, 'url' => $url]); $this->redirect($redirecturl); return; } /** * 解绑账号 */ public function unbind() { $platform = $this->request->request('platform', $this->request->param('platform', '')); $url = $this->request->get('url', $this->request->server('HTTP_REFERER')); $redirecturl = url("index/third/unbind") . "?" . http_build_query(['platform' => $platform, 'url' => $url]); $this->redirect($redirecturl); return; }}
/application/index/controller/Third.php
<?phpnamespace appindexcontroller;use addonsthirdlibraryApplication;use appcommoncontrollerFrontend;use thinkLang;use thinkSession;/** * 第三方登录控制器 */class Third extends Frontend{ protected $noNeedLogin = ['prepare']; protected $noNeedRight = ['*']; protected $app = null; protected $options = []; protected $layout = 'default'; public function _initialize() { parent::_initialize(); $config = get_addon_config('third'); $this->app = new Application($config); } /** * 准备绑定 */ public function prepare() { $platform = $this->request->request('platform'); $url = $this->request->get('url', '/'); if ($this->auth->id) { $this->redirect(url("index/third/bind") . "?" . http_build_query(['platform' => $platform, 'url' => $url])); } // 授权成功后的回调 $userinfo = Session::get("{$platform}-userinfo"); if (!$userinfo) { $this->error("操作失败,请返回重度"); } Lang::load([ APP_PATH . 'index' . DS . 'lang' . DS . $this->request->langset() . DS . 'user' . EXT, ]); $this->view->assign('userinfo', $userinfo['userinfo']); $this->view->assign('platform', $platform); $this->view->assign('url', $url); $this->view->assign('bindurl', url("index/third/bind") . '?' . http_build_query(['platform' => $platform, 'url' => $url])); $this->view->assign('captchaType', config('fastadmin.user_register_captcha')); $this->view->assign('title', "账号绑定"); return $this->view->fetch(); } /** * 绑定账号 */ public function bind() { $platform = $this->request->request('platform'); $url = $this->request->get('url', $this->request->server('HTTP_REFERER')); if (!$platform) { $this->error("参数不正确"); } // 授权成功后的回调 $userinfo = Session::get("{$platform}-userinfo"); if (!$userinfo) { $this->redirect(addon_url('third/index/connect', [':platform' => $platform]) . '?url=' . urlencode($url)); } $third = addonsthirdmodelThird::where('user_id', $this->auth->id)->where('platform', $platform)->find(); if ($third) { $this->error("已绑定账号,请勿重复绑定"); } $time = time(); $values = [ 'platform' => $platform, 'user_id' => $this->auth->id, 'unionid' => isset($userinfo['unionid'])?$userinfo['unionid']:'',//CoderRay修改 'openid' => $userinfo['openid'], 'openname' => isset($userinfo['userinfo']['nickname']) ? $userinfo['userinfo']['nickname'] : '', 'access_token' => $userinfo['access_token'], 'refresh_token' => $userinfo['refresh_token'], 'expires_in' => $userinfo['expires_in'], 'logintime' => $time, 'expiretime' => $time + $userinfo['expires_in'], ]; $third = addonsthirdmodelThird::create($values); if ($third) { $this->success("账号绑定成功", $url); } else { $this->error("账号绑定失败,请重试", $url); } } /** * 解绑账号 */ public function unbind() { $platform = $this->request->request('platform'); $third = addonsthirdmodelThird::where('user_id', $this->auth->id)->where('platform', $platform)->find(); if (!$third) { $this->error("未找到指定的账号绑定信息"); } $third->delete(); $this->success("账号解绑成功"); }}
希望以上内容对你有所帮助!如果还有其他问题,请随时提问。 各类知识收集 拥有多年CMS企业建站经验,对 iCMS, LeCMS, ClassCMS, Fastadmin, PbootCMS, PHPCMS, 易优CMS, YzmCMS, 讯睿CMS, 极致CMS, Wordpress, HkCMS, YznCMS, WellCMS, ThinkCMF, 等各类cms的相互转化,程序开发,网站制作,bug修复,程序杀毒,插件定制都可以提供最佳解决方案。