You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:34:33