我正在尝试开发一个 PHP 应用程序,它可以让我通过 cronjob 在我的页面上自动发布新帖子,而我处于离线状态并且根本没有登录 Facebook。我知道offline_access权限早就没有了,但是删除offline_access 权限一文清楚地说明了以下内容:
场景 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);
...相反,我得到:
致命错误:未捕获的 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'));