オフラインで Facebook にまったくログインしていないときに、cronjob を使用してページに新しい投稿を自動的に作成できる PHP アプリケーションを開発しようとしています。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: このリソースを要求するには、ユーザー アクセス トークンが必要です。
私は何を間違っていますか?
さらに紛らわしい - 同時に、ここにあるこのコードは、問題なく私のウォールにステータスの更新を投稿します (そして、私はまだ 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 Alaghbari 氏の親切な助けにより、私はこの問題を適切に進めることができ、最終的に解決策にたどり着きました。
彼が提案したように、最初にユーザー アクセス トークンを生成し、次のようなリクエストを発行する必要がありました。
https://graph.facebook.com/me/accounts?access_token=USER_ACCESS_TOKEN
実際のページ アクセス トークンを取得し、ページに投稿するため。そのため、PHP SDK によって生成されたログイン リンクからログインすると、$_SESSION 変数内に USER_ACCESS_TOKEN が格納されていることに気付きました。私はそのトークンを取得し、にリクエストを発行し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'));