I'm trying to get friends list and I get this error:
Fatal error: Uncaught OAuthException: An active access token must be used to query information about the current user. thrown in /server/url/base_facebook.php on line 970
This is the code I'm using:
$facebook = new Facebook(array(
'appId' => $appID,
'secret' => $appSecret,
'cookie' => true, // enable optional cookie support
));
$result = $facebook->api('/me/friends/',array('access_token' => $facebook->access_token));
Here's the data I get back in the $facebook variable:
Facebook Object
(
[appId:protected] => 220........
[apiSecret:protected] => 2162e6c1b771......
[user:protected] =>
[signedRequest:protected] =>
[state:protected] => 894ad3b36c2ebdcbcf6d4f110641dd4f
[accessToken:protected] =>
[fileUploadSupport:protected] =>
)
For some reason the access_token is empty.
It worked fine and suddenly stopped...
The app already has the permissions and I'm using the latest PHP SDK v3.0.1
Please help me... I'm going crazy with this issue...
Thanks,
Bar.
it seems like u need to parse the signed request first is this an iframe app or a website?
if it's an iframe app and the user already authorized
try this.
public function parse_signed_request($signed_request)
{
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
$sig = $this->base64_url_decode($encoded_sig);
$data = json_decode($this->base64_url_decode($payload), true);
if(strtoupper($data['algorithm']) !== 'HMAC-SHA256') {
throw new Exception('bad algorithm');
}
$expected_sig = hash_hmac('sha256', $payload, $this->app_secret, $raw = true);
if($sig !== $expected_sig) {
throw new Exception('Bad signed JSON');
}
return $data;
}
this will parse the signed request.
after u get the data var_dump it and in it u will see the oauth_token....
private function base64_url_decode($input) {
return base64_decode(strtr($input, '-_', '+/'));
}
You should add $this->load->library('facebook'); in constructor .
You need to upgrade your SDK to v3.0:
https://github.com/facebook/php-sdk
Edit: Since you are using v.3.0 your construct is wrong.. there is no more $cookie parameter for constructor. I suggest revising documentation.
Related
From here: https://developers.facebook.com/docs/graph-api/reference/user/accounts/ I got to write this in my code
$request = new FacebookRequest(
$session,
'GET',
'/{user-id}/accounts'
);
$response = $request->execute();
The problem here is with version 2.8 of the API and SDK 5.0 execute() doesn't exist. How can I get a list of all the pages on a Facebook account.
#JayNCoke was correct with the approach.
$fb = new Facebook\Facebook([
'app_id' => '{app-id}',
'app_secret' => '{app-secret}',
'default_graph_version' => 'v2.5',
]);
// Sets the default fallback access token so we don't have to pass it to each request
$fb->setDefaultAccessToken('{access-token}');
$response = $fb->get('{user-id}/accounts');
$response returns a Facebook\FacebookResponse object
To get it in a usable data format, just call getDecodedBody() like below
$response = $response->getDecodedBody();
This returns an array.
You have the right endpoint, you just need to make sure you have the right call in PHP:
$fb = new Facebook\Facebook([
'app_id' => '{app-id}',
'app_secret' => '{app-secret}',
'default_graph_version' => 'v2.5',
]);
// Sets the default fallback access token so we don't have to pass it to each request
$fb->setDefaultAccessToken('{access-token}');
$response = $fb->get('{user-id}/accounts');
Also remember:
You'll need to make sure your app is asking for the manage_pages permission.
This only returns pages that the user is an Admin on. If they are of any other role, it won't return that page.
I am trying to get a page access token starting out with just a users access token stored in my database and a page id. So far I have not been using the facebook.php instead just using php's curl_* functions. So far I can send posts to the page (with a hard coded page id) but I want to impersonate the page when doing so.
Can I do this easily without facebook.php, that would be nice as it might save me from feeling like I should rewrite what I've done so far. If not, then how would I get the page access token from the facebook object - remember so far at least I don't store user ids or page ids in my db, just user access tokens and of course my app id and secret.
I've been looking at the example for getting page access tokens but I find it not quite what I need as it gets a user object and in so doing seems to force the user to login to facebook each time, but I stored the user access token to avoid exactly that from happening.
Do I need more permissions than manage_page and publish_stream? I tried adding offline_access but it doesn't seem available anymore (roadmap mentions this).
here is some of my code from my most recent attempt which uses the facebook.php file:
// try using facebook.php
require_once 'src/facebook.php';
// Create our Application instance
$facebook = new Facebook(array(
'appId' => $FB_APP_ID, // $FB_APP_ID hardcoded earlier
'secret' => $FB_APP_SECRET, // $FB_APP_SECRET hardcoded earlier
));
$facebook->setAccessToken($FB_ACCESS_TOKEN );
//got user access token $FB_ACCESS_TOKEN from database
// Get User ID -- why?
$user = $facebook->getUser();
//------ get PAGE access token
$attachment_1 = array(
'access_token' => $FB_ACCESS_TOKEN
);
$result = $facebook->api("/me/accounts", $attachment_1);
foreach($result["data"] as $page) {
if($page["id"] == $page_id) {// $page_id hardcoded earlier
$page_access_token = $page["access_token"];
break;
}
}
echo '<br/>'.__FILE__.' '.__FUNCTION__.' '.__LINE__.' $result= ' ;
var_dump($result); //this prints: array(1) { ["data"]=> array(0) { } }
$facebook->setAccessToken($page_access_token );
// Get User ID, why - re-init with new token maybe?
$user = $facebook->getUser();
//------ write to page wall
try {
$attachment = array(
'access_token' => $page_access_token,
'link' => $postLink,
'message'=> $postMessage
);
$result = $facebook->api('/me/feed','POST', $attachment);
echo '<br/>'.__FILE__.' '.__FUNCTION__.' '.__LINE__.' $result= ' ;
var_dump($result);
} catch(Exception $e) {
echo '<br/>'.__FILE__.' '.__FUNCTION__.' '.__LINE__.' $e= ' ;
var_dump($e); /*this gives : "An active access token must
be used to query information about the
current user." */
}
die;
Thanks
PS: I hardcoded the user id and started calling
$result = $facebook->api("/$user_id/accounts", $attachment_1);
and I still get an empty result.
PPS: The Graph API Explorer does not show my fan pages either even though my account is set as the Manager. My attempts to post work but show as being from my account rather than from the page.
PPPS: made a little progress by adding permissions on the graph explorer page to get an access token that way but that doesn't help as I need to the the access token programmatically. When a user with many fan pages logs in to my site I want to show them the list of their facebook fan pages to choose from. In practice aren't the permissions just granted on the app?
PPPPS: the list of permissions on my app now stands at : email, user_about_me, publish_actions
and
Extended Permissions:
manage_pages, publish_stream, create_note, status_update, share_item
do I need more? when I try now I still fail to get anything from the call to:
$facebook->api("/$user_id/accounts", $attachment_1);
Px5S: DOH!!! I see now that I was neglecting to add the manage_pages permissions to my call for a user access token when my scripts first get one and store it in the DB. But when I reuse that new access token I still get the error : "An active access token must be used to query information about the current user." So, can't such tokens be reused? Aren't they long term? will read more stuff...
Here is my functioning code, still messy but seems to work, note the scopes on the first $dialog_url, and please feel free to mock my code or even suggest improvements :
function doWallPost($postName='',$postMessage='',$postLink='',$postCaption='',$postDescription=''){
global $FB_APP_ID, $FB_APP_SECRET;
$APP_RETURN_URL=((substr($_SERVER['SERVER_PROTOCOL'],0,4)=="HTTP")?"http://":"https://").$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'].'?returnurl=1';
$code = $_REQUEST["code"];
$FB_ACCESS_TOKEN = getFaceBookAccessToken( );
$FB_ACCESS_TOKEN_OLD = $FB_ACCESS_TOKEN;
//if no code ot facebook access token get one
if( empty($code) && empty($FB_ACCESS_TOKEN) && $_REQUEST["returnurl"] != '1')
{
// if( $_REQUEST["returnurl"] == '1') die;
$dialog_url = "http://www.facebook.com/dialog/oauth?client_id=".$FB_APP_ID."&redirect_uri=".$APP_RETURN_URL."&scope=publish_stream,manage_pages";
header("Location:$dialog_url");
}
if( empty($FB_ACCESS_TOKEN) ){
if($_REQUEST['error_code'] == '200'){
return null;
}else if (!empty($code)){
$token_url = "https://graph.facebook.com/oauth/access_token?client_id=".$FB_APP_ID."&redirect_uri=".urlencode($APP_RETURN_URL)."&client_secret=".$FB_APP_SECRET."&code=".$code;
$access_token = file_get_contents($token_url);
$param1=explode("&",$access_token);
$param2=explode("=",$param1[0]);
$FB_ACCESS_TOKEN=$param2[1];
}else{
return null;
}
}
if(!empty($FB_ACCESS_TOKEN) && $FB_ACCESS_TOKEN_OLD != $FB_ACCESS_TOKEN) {
setFaceBookAccessToken( $FB_ACCESS_TOKEN);
}
$_SESSION['FB_ACCESS_TOKEN'] = $FB_ACCESS_TOKEN;
$page_name = '';
$page_id = getFaceBookPageId(); //from db
if(empty($page_id ) ) return null;
//in case there are multiple page_ids separated by commas
if(stripos($page_id, ',') !== false ){
$page_ids = explode(',', $page_id) ;// = substr($page_id, 0, stripos($page_id, ','));
}
$result = null;
foreach($page_ids as $page_id){
$page_id = trim($page_id);
if( !empty($FB_ACCESS_TOKEN)){
//get page_id
require_once 'src/facebook.php';
// Create our Application instance (replace this with your appId and secret).
$facebook = new Facebook(array(
'appId' => $FB_APP_ID,
'secret' => $FB_APP_SECRET
));
$facebook->setAccessToken($FB_ACCESS_TOKEN );
//------ get PAGE access token
$page_access_token ='';
$attachment_1 = array(
'access_token' => $FB_ACCESS_TOKEN
);
$result = $facebook->api("/me/accounts", $attachment_1);
if(count($result["data"])==0) {
return null;
}
foreach($result["data"] as $page) {
if($page["id"] == $page_id) {
$page_access_token = $page["access_token"];
break;
}
}
//------ write to page wall
try {
$attachment = array(
'access_token' => $page_access_token,
'link' => $postLink,
'message'=> $postMessage
);
$result = $facebook->api('/me/feed','POST', $attachment);
} catch(Exception $e) {
return null;
}
} //end if( !empty($FB_ACCESS_TOKEN))
}//end foreach
return $result; }
Now, I wonder if I can send the same message to several pages at once ...
Yup, just by looping over the ids, see above, it now supports multiple page ids.
And unless someone wants to contribute to the code - there's lots of ways it can be improved - I'm done.
i am trying to post to my friends' feeds using this code, but it is not working . i am stuck, any help ??
$app_url ="http://localhost.local/PMS/facebook/PostWithPHP.php";
$facebook = new Facebook(array(
'appId' => 'APPID',
'secret' => 'APPSECRET',
'cookie' => true,
));
// Get User ID
$user = $facebook->getUser();
if ($user) {
$user_friends = $facebook->api('/me/friends');
sort($user_friends['data']);
try {
// Proceed knowing you have a logged in user who's authenticated.
$access_token = $facebook->getAccessToken();
$vars = array(
'message' => 'My Message',
'name' => 'title',
'caption' => 'Caption',
'link' => 'Link',
'description' => 'Description',
'picture' => 'image'
);
foreach($user_friends['data'] as $f){
$sendTo = $f['id'];
$sendToName = $f['name'];
$result = $facebook->api("/".$sendTo ."/feed", 'post', $vars);
}
} catch (FacebookApiException $e) {
error_log($e);
$user = null;
}
}
// Login or logout url will be needed depending on current user state.
if ($user) {
$logoutUrl = $facebook->getLogoutUrl();
} else {
$loginUrl = $facebook->getLoginUrl(array('redirect_uri'=> $app_url));
echo "<script type='text/javascript'>";
echo "top.location.href = '{$loginUrl}';";
echo "</script>";
}
and another question is that using this code, but with replacing $facebook->api("/".$sendTo ."/feed", 'post', $vars); by $facebook->api("/me/feed", 'post', $vars); and of course without looping friends, posts on my timeline. how can i make it post on my wall ??
I guess for a post to a timeline you will need an accessToken from the user where to publish the content. In your case you just have the accessToken of the registered user, not of his friends. That is a restriction by FB I think.
1st check you getting the user id(place echo and check) if not try this... I think this will help you brother
$token_url = "https://graph.facebook.com/oauth/access_token?" ."client_id=" . $app_id ."&client_secret=" . $app_secret .
"&grant_type=client_credentials";
$access_token = file_get_contents($token_url);
$signed_request = $_REQUEST["signed_request"];
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
$data = json_decode(base64_decode(strtr($payload, '-_', '+/')), true);
$user_id = $data["user_id"];
There are a few things wrong with your code. First of all, make sure the link and picture parameters for the post are valid URLs. Facebook will give you a error message otherwise ((#100) link URL is not properly formatted). Also, the link must go to the Canvas or Site URL for your application.
That should solve the issues with posting to a friend's wall.
However, may I remind you that your application is in violation of the Facebook Platform Policy. Facebook doesn't allow multiple posts to the stream (whether its yours or a friends) unless there is explicit permission from the user. It also to stop common friends seeing the same message from multiple friends.
You can follow the tutorial here:
https://www.webniraj.com/2012/11/22/facebook-api-posting-a-status-update/
But, instead of making a API call to: /me/feed, you replace me with the friend's User ID, so it looks like /12345/feed
Please note that Facebook has now disabled posting to Friends' walls via the API. Instead, you should either tag the user in an action or use the Requests API.
I have been madly trying to get access token for my users since long. I read at many sites to get it somehow by using getSession() and getting access_token from it... it gives me undefined function error.. I googled that too and all solutions said to use the updated SDK but mine is updated and it still won't work... so I finally got another solution to getting access token but this seems to be giving same access token for all users... any idea where the problem lies? All users certainly can't have same token right?
$app_id = $facebook->getAppId();
$app_secret = $facebook->getApiSecret();
function callFb($url, $params)
{
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_URL => $url,
CURLOPT_POSTFIELDS => http_build_query($params),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_VERBOSE => true
));
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
$params=array('client_id'=>$app_id, 'type'=>'client_cred', 'client_secret'=>$app_secret);
$url = "https://graph.facebook.com/oauth/access_token";
$access_token = callFb($url, $params);
$access_token = substr($access_token, strpos($access_token, "=")+1, strlen($access_token));
The issue is that you are asking for type=client_cred, which tells Facebook that you don't want access token for a user, but an access token for the app. This is used for doing things like accessing insights, the realtime updates API, and public data. If you want to get user data, you should not be passing that flag.
If you really do want to roll your own access to the Graph API, you can certainly do that, following the instructions at https://developers.facebook.com/docs/authentication/ .
You say you're using the PHP SDK but I don't see any mention of it anywhere in your code.
The proper way is this:
<?php
require('facebook.php');
$fb = new Facebook(array('appId' => APP_ID, 'secret' => SECRET));
$user = $fb->getUser();
// if we have a valid user, we're logged in
if ($user)
{
// do stuff with the API using the $fb object
}
else
{
// redirect the user to the authentication page
header("Location: ".$fb->getLoginUrl());
}
Example largely paraphrased from Facebook's SDK Github.
with the old (2.x) SDK I used this to log someone with offline_access:
$session = array
(
'uid' => $userdata['fb_uid'],
'sig' => $userdata['fb_sig'],
'access_token' => $userdata['fb_access_token']
);
$facebook->setSession($session);
In the new SDK this function doesnt exist anymore. I think I need to login using:
setPersistentData($key, $value)
but this function is protected and I dont know what 'code' is? Do I need this to log the user in or not? And what's going on with 'sig'? Don't I need this anymore?
Hope someone already figured this out because the documentation really doesn't help!
With the Facebook PHP SDK v3 (see on github), it is pretty simple. To log someone with the offline_access permission, you ask it when your generate the login URL. Here is how you do that.
Get the offline access token
First you check if the user is logged in or not :
require "facebook.php";
$facebook = new Facebook(array(
'appId' => YOUR_APP_ID,
'secret' => YOUR_APP_SECRET,
));
$user = $facebook->getUser();
if ($user) {
try {
$user_profile = $facebook->api('/me');
} catch (FacebookApiException $e) {
// The access token we have is not valid
$user = null;
}
}
If he is not, you generate the "Login with Facebook" URL asking for the offline_access permission :
if (!$user) {
$args['scope'] = 'offline_access';
$loginUrl = $facebook->getLoginUrl($args);
}
And then display the link in your template :
<?php if (!$user): ?>
Login with Facebook
<?php endif ?>
Then you can retrieve the offline access token and store it. To get it, call :
$facebook->getAccessToken()
Use the offline access token
To use the offline access token when the user is not logged in :
require "facebook.php";
$facebook = new Facebook(array(
'appId' => YOUR_APP_ID,
'secret' => YOUR_APP_SECRET,
));
$facebook->setAccessToken("...");
And now you can make API calls for this user :
$user_profile = $facebook->api('/me');
Hope that helps !
With PHP SDK 2.0 (I guess), I just use it like
$data = $facebook->api( '/me', 'GET', array( 'access_token' => $userdata['fb_access_token'] ) );
This should work with the newer one to as it seems to be more of a clean approach than rather setting up sessions by ourself. Can you try?
Quentin's answer is pretty nice but incomplete, I think. It works nice, but I for example getUser() isn't working in that time because userId (which is getUser() returning) is cached.
I have created a new method to clear all caches and save it persistently.
public function setPersistentAccessToken($access_token) {
$this->setAccessToken($access_token);
$this->user = $this->getUserFromAccessToken();
$this->setPersistentData('user_id', $this->user);
$this->setPersistentData('access_token', $access_token);
return $this;
}