【发布时间】:2013-04-19 20:24:39
【问题描述】:
我正在尝试开发一个 PHP 应用程序,当我处于离线状态且根本没有登录 Facebook 时,它可以让我通过 cronjob 在我的页面上自动发布新帖子。我知道 offline_access 权限早已不复存在,但Removal of offline_access permission 文章明确指出以下内容:
场景 5:页面访问令牌
当用户授予应用 manage_pages 权限时,应用能够 获取用户管理的页面的页面访问令牌 查询 [User ID]/accounts Graph API 端点。随着迁移 启用,当使用短期用户访问令牌查询此 端点,获得的页面访问令牌也是短暂的。
将短期用户访问令牌交换为长期访问 使用前面解释的端点和步骤的令牌。通过使用 长期用户访问令牌,查询 [User ID]/accounts 端点 现在将为以下页面提供不会过期的页面访问令牌 用户管理。这也适用于使用非过期查询 通过已弃用的 offline_access 获得的用户访问令牌 权限。
... 这让我觉得像我想的那样的自动化 PHP 解决方案确实可以设计。所以我继续创建了一个新的应用程序并授予 manage_pages 权限,以及 publish_actions 权限。
但是我的代码:
<?php
require_once("sdk/facebook.php");
$config = array();
$config['appId'] = MY_APP_ID;
$config['secret'] = MY_APP_SECRET;
$config['fileUpload'] = false; // optional
$facebook = new Facebook($config);
$accountID = MY_ACCOUNT_ID;
$pages = $facebook->api("/$accountID/accounts/");
var_dump($pages);
?>
...返回以下错误:
致命错误: 未捕获的 OAuthException:需要用户访问令牌 请求此资源。
我做错了什么?
更令人困惑的是——同时,这里的这段代码毫无问题地向我的 Wall 发布了状态更新(我仍然没有登录 Facebook 或其他任何东西)
<?php
require_once("sdk/facebook.php");
$config = array();
$config['appId'] = MY_APP_ID;
$config['secret'] = MY_APP_SECRET;
$config['fileUpload'] = false; // optional
$token_url = "https://graph.facebook.com/oauth/access_token?" .
"client_id=" . $config['appId'] .
"&client_secret=" . $config['secret'] .
"&grant_type=client_credentials";
$app_token = str_replace('access_token=','',file_get_contents($token_url));
$facebook = new Facebook($config);
$args = array(
'access_token' => $app_token,
'message' => 'test post via app access token'
);
$accountID = MY_ACCOUNT_ID;
$post_id = $facebook->api("/$accountID/feed", "post", $args);
?>
...如果我这样做了
$post_id = $facebook->api("/$myPageID/feed", "post", $args);
...相反,我得到:
致命错误: Uncaught OAuthException: (#200) 用户没有 授权应用程序执行此操作
解决方案
在先生的帮助下。 Mohammed Alghbari,我能够在这个问题上取得合理的进展并最终找到解决方案。
按照他的建议,我需要先生成一个用户访问令牌,发出这样的请求:
https://graph.facebook.com/me/accounts?access_token=USER_ACCESS_TOKEN
为了检索实际的页面访问令牌并发布到页面。所以我意识到当我通过 PHP SDK 生成的登录链接登录时,一个 USER_ACCESS_TOKEN 为我存储在一个 $_SESSION 变量中。我拿到了那个令牌,向https://graph.facebook.com/me/accounts?access_token=USER_ACCESS_TOKEN 发出了一个请求,检索了 PAGE_ACCESS_TOKEN 并使用它来成功地将测试消息发布到我的页面。
但是,我随后注销并发出了session_destroy(); 令我惊讶的是,在我这样做的那一刻,我的代码又开始抛出A user access token is required to request this resource. 异常。我很沮丧。
然后,我决定手动请求https://graph.facebook.com/MY_ACCOUNT_ID/accounts/?MY_USER_ACCESS_TOKEN 看看会发生什么。更令我惊讶的是 - GRAPH API 接受了 USER_ACCESS_TOKEN 并返回了所有有效的页面令牌。我很沮丧为什么我在 SDK 中遇到异常,但是当我直接向 GRAPH API 发出请求时没有错误,所以我决定开始调试 base_facebook.php。我使用的 PHP SDK 是 3.2.2 版本。
经过数小时的搜索,发现位于 base_facebook.php 第 899 行的这段代码无缘无故地抛出异常(有点)
if (!isset($params['access_token'])) {
$params['access_token'] = $this->getAccessToken();
}
当我注释掉 $params['access_token'] = $this->getAccessToken(); 行时,我的 PHP SDK 请求再次开始返回有效令牌。
很奇怪。我想知道这是 PHP SDK 中的错误,还是我的代码有问题。我的最终代码大致如下:
<?php
require_once("sdk/facebook.php");
$config = array();
$config['appId'] = MY_APP_ID;
$config['secret'] = MY_APP_SECRET;
$config['fileUpload'] = false; // optional
$facebook = new Facebook($config);
$token = MY_USER_TOKEN; // extracted from $_SESSION
$response = $facebook->api("/MY_ACCOUNT_ID/accounts/?access_token=$token");
// code that extracts the page token from $response goes here
$args = array(
'access_token' => MY_PAGE_TOKEN,
'message' => 'test post via app access token'
);
$post_id = $facebook->api("/MY_PAGE_ID/feed", "post", $args); // It works!!
?>
编辑#2
经过一些进一步的测试,结果证明你可以修改而不是注释掉第 899 行
$facebook->api("/MY_ACCOUNT_ID/accounts/?access_token=MY_ACCESS_TOKEN');
到
$facebook->api("/MY_ACCOUNT_ID/accounts/", 'get', array('access_token' => 'MY_ACCESS_TOKEN'));
【问题讨论】:
标签: php facebook-graph-api facebook-php-sdk facebook-apps facebook-access-token