PHP无SDK实现Facebook登录:提取access_token问题求助
解决PHP无SDK实现Facebook登录的access_token提取问题
嘿,我一眼就瞅出问题根源了——你在get_access_token()函数里把json_decode的用法完全搞反啦!
核心问题解析
你现在写的是:
json_decode($response, $access_token);
但json_decode的第二个参数是布尔值(传true返回关联数组,false返回对象),不是用来接收结果的变量。你这写法相当于把$access_token当成布尔值传入(默认转成false),而且完全没接收函数的返回值,导致最后返回的$access_token变成了一个奇葩结构:键是完整的JSON字符串,值是空字符串,这就难怪你用isset或者array_key_exists都找不到access_token键了!
一步到位的修正方案
1. 修复get_access_token()函数
把里面的代码改成这样,正确接收json_decode的返回值:
function get_access_token(){ $app_secret = "bbbbbbbbbbbbb"; $app_id = "aaaaaaaaaaaaaa"; $redirect_uri = urlencode("https://localhost/firefly/Oauth/facebook"); $code = $_REQUEST["code"]; // 调用Facebook接口获取token响应 $response = file_get_contents("https://graph.facebook.com/oauth/access_token?client_id=".$app_id."&redirect_uri=".$redirect_uri."&client_secret=".$app_secret."&code=".$code); // 先检查请求是否成功 if($response === false){ $this->flashSession->error("ERROR:: 连接Facebook服务器失败"); return $this->response->redirect('index'); } // 把JSON字符串转成关联数组(第二个参数传true) $access_token_array = json_decode($response, true); // 检查是否拿到有效的access_token if(!isset($access_token_array['access_token'])){ $this->flashSession->error("ERROR:: 获取的令牌无效"); return $this->response->redirect('index'); } return $access_token_array; }
2. 修正facebookAction()里的调用逻辑
现在get_access_token()返回的是关联数组,所以要改成用数组键提取令牌:
elseif(isset($_REQUEST["code"])) { if(isset($_REQUEST["state"]) && $_REQUEST["state"]==$_SESSION["state"]) { // 拿到包含access_token的数组 $token_data = $this->get_access_token(); // 用['access_token']提取令牌值拼到URL里 $raw = file_get_contents("https://graph.facebook.com/me?fields=id,name,email,picture,gender&access_token=".$token_data['access_token']); $data_array = json_decode($raw,TRUE); // 额外加个用户数据有效性检查 if(!isset($data_array['id'])){ $this->flashSession->error("ERROR:: 获取用户信息失败"); return $this->response->redirect('index'); } $fbid = $data_array['id']; $fbmail = $data_array['email']; $this->session->set('id', '1000'); $this->session->set("uname", $fbmail); $this->flashSession->success("SUCCESS:: You are now flying with Phalcon!"); return $this->response->redirect('index'); }else{ $this->flashSession->error("ERROR:: Request STATE & CODE Error!"); return $this->response->redirect('index'); } }
为什么你之前的方法都没用?
isset($access_token['access_token']):你的$access_token数组的键是整个JSON字符串,根本没有access_token这个键,当然返回false。array_key_exists('access_token', $access_token):同上,键不对,白搭。parse_str($access_token, $token_array):parse_str是用来解析URL编码的字符串(比如a=1&b=2),你传的是数组,肯定无效。
额外小建议
用file_get_contents调用API有时候会因为服务器配置(比如禁用了allow_url_fopen)失败,建议换成cURL实现,兼容性更好:
// 替换get_access_token里的file_get_contents部分 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://graph.facebook.com/oauth/access_token?client_id=".$app_id."&redirect_uri=".$redirect_uri."&client_secret=".$app_secret."&code=".$code); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 本地测试可以关,生产环境建议开启 $response = curl_exec($ch); curl_close($ch);
内容的提问来源于stack exchange,提问作者Styled Bee
相关产品推荐
相关产品推荐

