I made this PHP script that fetches messages to be posted at regular intervals to a Facebook Page that I administer.
My script is working fine, but depends on me as a user being logged into Facebook. I would like this script to run as a cron job so i fear the script will fail to work if i'm logged out.
How can i make it work even if i'm not logged into Facebook?
Note that I created a Facebook application as requested to be able to use the Facebook api. Is there a way to post as the Facebook application perhaps?
Here is my code, in case it helps.
require_once('config.inc.php');
require '_classes/facebook-php-sdk/src/facebook.php';
$homeurl = 'http://domain.com/to-facebook/index.php';
$post_url = '/'.PAGEID.'/feed';
// The message
$msg_body = array(
'message' => 'hello world',
);
// Post to Facebook
$facebook = new Facebook(array(
'appId' => FB_APP_ID,
'secret' => FB_APP_SECRET,
));
// Get User ID
$fbuser = $facebook->getUser();
if ($fbuser) {
try {
$postResult = $facebook->api($post_url, 'post', $msg_body );
} catch (FacebookApiException $e) {
echo $e->getMessage();
}
}else{
// I would like never to come to this point...
$loginUrl = $facebook->getLoginUrl(array('redirect_uri'=>$homeurl,'scope'=>'publish_stream,manage_pages,publish_actions,status_update,offline_access'));
header('Location: ' . $loginUrl);
}
if($postResult)
{
echo '<h1>Your message is posted on your facebook wall.</h1>';
}
* update *
I tried the cronjob and unfortunately, after a while I had the "Error validating access token: Session has expired at unix time" message. I'm puzzled. What am i doing wrong?
For sites connected to your app:
When you have the app get permission to manage_pages, you run an api with your user token which gives you the access tokens of all your pages. These tokens can last forever.
For users authorizing the app:
You can make the access_token last longer. The user would need to log in to refresh the extended token however. Read up more about "Facebook Extend Token".
There used to be a permissin that gave the app the ability to reuse the token forever, but it's no longer available. The best you can do nowadays is to simply run the api to extend the token each time the user log in to your app.
You can easy use CURL for this. Google something like that, "CURL login, CURL facebook login"
**update **
I tried the cronjob and unfortunately, after a while I had the "Error validating access token: Session has expired at unix time" message. I'm puzzled. What am i doing wrong?
I seem to have found a solution based on this answer Facebook Access Token for Pages .
It explains how to get an access_token to a specific page for your FB application.
I obtained it, then adapted my code. I tested it using a browser in which i'm not logged into facebook with, and it works.
Here is the updated script in case it helps.
$msg_body = array(
'message' => $message->message.' v/ #'.$message->author,
'access_token' => FB_ACCESS_TOKEN
);
try {
$postResult = $facebook->api($post_url, 'post', $msg_body );
} catch (FacebookApiException $e) {
echo $e->getMessage();
}
if($postResult)
{
echo '<h1>Your message is posted on your facebook wall.</h1>';
print_r($msg_body);
}
I'll run the cronjob for a few days and will get back to you if it proves not to work reliably.
Related
I have a Facebook app that I want to use to post on my customer's Facebook Page Walls on their behalf. I have it setup now so that when they authenticate my app I get the Access token, but when I go to post to the wall I am getting the following error: "OAuthException: Error validating access token: The session is invalid because the user logged out."
How can I post from my script without being logged in?
Here is my code:
include_once('fb-php-sdk/src/facebook.php');
$facebook = new Facebook(array(
'appId' => 'XXX',
'secret' => 'XXX',
));
try {
$page_id = '215133535279290'; //page id of the customer's facebook page
$args = array(
'access_token' => 'XXX', //access token received when user authenticated app
'message' => 'A test message'
);
$post_id = $facebook->api("/$page_id/feed","post",$args);
} catch (FacebookApiException $e) {
echo "Error:" . $e;
}
The new facebook API has what is called an extended access token (it replaces offline access: https://developers.facebook.com/roadmap/offline-access-removal/ I think) which I believe lasts upto 60 days (or something like that). To use it simply get the access token when the logs in through your website:
$token = $facebook->getAccessToken();
Save it to Db and use this token later:
$facebook = new Facebook();
$facebook->setAccessToken($accessTokenFromDB);
Then you should be able to continue as though the user is logged in.
As for the user being logged out part, make sure you are using the latest version of the API and not an old version and also make sure the stuff under the "Scenario 2: If you have been previously requesting offline_access - updated 4/30/2012" heading of the page I linked.
You could carry on using offline_access until 3rd of October, but then why if it's being turned off for real in 2 months time and would have to rewrite your code.
Get the publish_stream extended permission. Once you have this permission you can post feed stories using your app access token while the user is offline. There is no need for offline_access permissions or saving and using a user access token in this scenario.
I'm writing a facebook application in PHP with the facebook SDK.
The important parts in my code are:
$facebook = new Facebook(array(
'appId' => $ApplicationID,
'secret' => $ApplicationSecret,
'cookie' => true, // enable optional cookie support
));
$user = $facebook->getUser();
$post = $facebook->api('/' . $user . '/feed', 'post', array(
stuff
));
$_SESSION['finish'] = false;
$_SESSION['inside'] = 'yes';
$_SESSION['uid'] = $user;
$token = $facebook->getAccessToken();
echo 'Access token: ' .$token;
$_SESSION['friends'] = $facebook->api('/me/friends?access_token'.$token);
You can see I am echoing the access token.
At first, I haven't added the access_token into the query - I just added it for checking.
The problem is that the last like (with the /me/friends/) throws an exception:
OAuthException: An active access token must be used to query information about the current user.
Although I did a login, and the feed post did work (I checked at my wall, it's there). Then, my try catch block handles the exception by redirecting to the login link, this way:
catch(Exception $e) {
$login_url_params = array(
'scope' => 'stuff',
'fbconnect' => 1,
'redirect_uri' => $ApplicationURL
);
$login_url = $facebook->getLoginUrl($login_url_params);
//redirect to the login URL on facebook
echo ("EXCPETION! " . $e . "<script> top.location.href='" . $login_url . "'</script>");
exit();
}
The code writing the exception is obviously only for debugging purposes.
Well, the first time I run the application a similar code is executed by a if(!$user) condition. Then it asks for my permission and I give it. Then, again, it says the access token is invalid (but does post to my wall).
Please note that I've compared the access_tokens, and even after removing the application and doing it all again - it stayed the same.
This is very awkward behavior and I fail to understand it. May anyone please shred some light on this?
Edit: For some weird reason, the token doesn't change even after going to a different user. But the post on the wall is still made... (And the exception thrown when accessing the friends list)
For some weird reason, the token doesn't change even after going to a different user. But the post on the wall is still made... (And the exception thrown when accessing the friends list)
That sounds to me as if you don’t actually have a user currently logged in, so the SDK is just using your app access token, which is always the default token it will use before it receives another, more “specific” one.
What format does your access token have – does is look something like your_app_id|your_app_secret or your_app_id|some_random_characters? If it’s starting with your app id, it’s most definitively an app access token.
I'm having some strange issues building an iframe app for Facebook. The app seems to get stuck in an infinite loop on the Go To App page.
After the user authorizes the app in the Go To App page, and returns to the app, the /me api call throws the "Error validating access token" exception. I checked and there is a valid access token in the Signed Request (tested with the facebook access token debuggin tool). I tried setting that with the setAccessToken() method unsuccessfully.
The getUser() method successfully returns the user ID, but it still hangs on the /me api call.
This doesn't happen in every browser, i'm just seeing it in Chrome sometimes in a no clear pattern. I fixed it in IE using the P3P header. It works fine in Firefox.
I pretty much stuck and i'm out of hair to pull out so any ideas are welcome. Thanks a lot.
The full error message: "Error validating access token: You cannot access the app till you log in to www.facebook.com and follow the instructions given."
Some code below.
$this->_facebook = new Facebook(
array(
'appId' => $this->_config['appId'],
'secret' => $this->_config['secret'],
'cookie' => true,
'fileUpload' => true
)
);
$this->_signedRequest = $this->_facebook->getSignedRequest();
// Doing something with signed request, not FB related
$this->_userId = $this->_facebook->getUser();
if($this->_userId) {
try{
// At this line the "Error validating access token" error shows up
$this->_user = $this->_facebook->api('/me');
// Some more irrelevant code here
} catch (Exception $e){
$this->_facebook->destroySession();
$this->_facebookLogin(false);
}
} else {
$this->_facebook->destroySession();
$this->_facebookLogin(false);
}
// The _facebookLogin method
public function _facebookLogin($perms = 'email,user_birthday,publish_stream,video_upload'){
$data = array(
'fbconnect' => 0,
'redirect_uri' => 'aredirecturl.com'
);
if(!empty($perms)) {
$data['scope'] = $perms;
}
echo '<script type="text/javascript">window.top.location.href = "'.$this->_facebook->getLoginUrl($data).'";</script>';
exit;
}
Edit this part
// At this line the "Error validating access token" error shows up
$this->_user = $this->_facebook->api('/me');
to this
// At this line the "Error validating access token" error shows up
$this->_user = $this->facebook->api('/me','GET');
What about destroying your session by hand? Did you debug these parameters?
unset($_SESSION['fb_'.$YOUR_API_KEY.'_code']);
unset($_SESSION['fb_'.$YOUR_API_KEY.'_access_token']);
unset($_SESSION['fb_'.$YOUR_API_KEY.'_user_id']);
unset($_SESSION['fb_'.$YOUR_API_KEY.'_state']);
I am almost using the same code as you,but I'm not using fileUpload and cookie parameters.
This is a rather infuriating problem. We had code that was working perfectly fine for months and now, all of the sudden, it doesn't. The code just used this url to grab the wall posts we were making on our fan page and showed them on our site. http://graph.facebook.com/[our number]/feed?limit=10
Now it doesn't work and I've spent a ridiculous number of hours sifting through search results on this issue. Unfortunately, everything I find seems to be referring to Facebook apps and not fan pages. I can't stop seeing how I need to authenticate it using my secret key, but I can't find anything that shows me what my fan page's secret key is or if one even exists. I can't, for the life of me, get this thing working and I can't figure out why it just randomly stopped working in the first place.
Here's the error we get:
{
"error": {
"type": "OAuthException",
"message": "An access token is required to request this resource."
}
}
EDIT: So thanks much to Frank Farmer for finding that post, the problem is needing an access token, which I can't find ANY solution to getting ANYWHERE.
The way that I was able to do this was by:
Creating a new facebook application
Logged into Facebook with the user that is an admin for the Facebook Page
Opened up a request for permissions for the application
https://www.facebook.com/dialog/oauth?client_id='the_application_id'&redirect_uri=http://your_redirect_uri/&scope=email,read_stream,user_birthday,user_about_me,user_likes,read_stream,user_education_history,user_work_history,user_groups,user_hometown,user_religion_politics,user_location,user_online_presence,user_relationships,user_status,user_website,read_friendlists,offline_access,manage_pages,ads_management,publish_stream
Your redirect URI MUST match what you have set into the application settings in your facebook application.
I basically granted access to everything for this application, the main thing you need to make sure of is 'manage_pages'
-After that you will need to copy the 'code=xxxxxx' portion of the link that you are forwarded onto after accepting the permissions request. You can THEN request an access_code for the user, once you have that, you can get the Facebook page posts that the user is an admin to.
https://graph.facebook.com/oauth/access_token?client_id='the_application_id'&redirect_uri=http://your_redirect_uri/&client_secret='the_code_from_above'
It will then respond with an access code!
https://graph.facebook.com/feed?access_token='your_access_token'
Below is some sample code you can use with the PHP facebook SDK:
define('APP_ID', 'your_app_id');
define('APP_API_KEY', 'your_app_api_key');
define('APP_SECRET', 'your_app_secret');
$fb = new Facebook(array(
'appId' => APP_ID,
'secret' => APP_SECRET,
'cookie' => false
));
$fb_user_id = 'user_id_of_person_that_has_page_admin_rights';
$access_token = urlencode('your_access_token_you_received');
try {
$user = $fb->api('/'.$fb_user_id,'GET',array('access_token'=>$access_token));
$accounts = $fb->api('/'.$fb_user_id.'/accounts','GET',array('access_token'=>$access_token));
} catch (FacebookApiException $e) {
echo $e->getMessage();
}
echo "<strong>User Details:</strong><br />";
foreach($user as $key => $value){
echo ucwords(str_replace("_"," ",$key)).": ".$value."<br />";
$fb->api('/feed','POST',array('access_token'=>$access_token,'id'=>$user_id,'message'=>'Add a post to the user's wall'));
}
echo "<br /><strong>Accounts Details:</strong><br />";
foreach($accounts['data'] as $account){
foreach($account as $key => $value){
echo ucwords(str_replace("_"," ",$key)).": ".$value."<br />";
}
try {
$posts = $fb->api('/'.$account['id'].'/posts','GET',array('access_token'=>$account['access_token']));
} catch (FacebookApiException $e) {
echo $e->getMessage();
}
echo "<br /><strong>-- Posts for this account:</strong><br />";
foreach($posts['data'] as $post){
foreach($post as $key => $value){
echo ucwords(str_replace("_"," ",$key)).": ".$value."<br />";
}
echo "<br />";
}
}
Yeah, it requires a token now. They announced this via their blog.
http://developers.facebook.com/blog/post/509/
Breaking change: Graph API PROFILE_ID/feed and PROFILE_ID/posts requires access_token
The Graph API PROFILE_ID/feed/ for a Page, Application, User or Group and PROFILE_ID/posts for a Page or User will now require a vaild access_token to access the wall or posts of the corresponding object (where previously no access_token was required).
Looks like they only gave a week notice.
You should subscribe to the RSS feed for their dev blog. They pull stuff like this all the time, although usually they give a little more notice.
After you have your personal access token, run:
https://graph.facebook.com/me/accounts?access_token=token
where 'token' is your access token. This will show you all the access tokens for the pages you have access to. Now use that page access token to post to:
'/page_username_id/feed'
where page_username_id is either the page id or the url username.
Hope this helps.
Skye
The URL
https://graph.facebook.com/oauth/access_token?client_id='the_application_id'&redirect_uri=http://your_redirect_uri/&client_secret='the_code_from_above'
is not true. the Client Secret is your App Secret. You need a extra argument, for example:
https://graph.facebook.com/oauth/access_token?client_id=[YOUR-APP-ID]&redirect_uri=http://your-uri(like in the app config)/&client_secret=[your-app-secret]&code=[code-from-above]
How do I go about combining examples from both
https://github.com/facebook/php-sdk/blob/master/examples/example.php and
https://github.com/facebook/connect-js/blob/master/examples/jquery/login.html
The end goal is so that we can use jQuery to sign in, and somehow the following line would still work
$user = $facebook->getUser();
What I currently notice is that when I sign in with JavaScript, it doesn't set the session with PHP, hence, it is incompatible with PHP based SDK (so $user in this case would still be null)
I am not a big fan of Login with Facebook,
because it causes the browser to load a different page (the facebook login) and then redirects back to the web app. It is far more ideal if I can load up a popup box for user to signin, and then transparently redirects back to my web app. So any suggestions on how I can go about implementing this user experience would be greatly appreciated. Thank you!
Not sure if you got this working. The current JS API has a configuration to save the cookie so the server may read it:
FB.init({
appId : 'YOUR APP ID',
cookie : true
});
Now, in PHP, you can do the following to use the session from the JS:
// Read the cookie created by the JS API
$cookie = preg_replace("/^\"|\"$/i", "", $_COOKIE['fbs_' . FB_APP_ID]);
parse_str($cookie, $data);
// Startup the Facebook object
$fb = new Facebook(array(
'appId' => FB_APP_ID,
'secret' => FB_APP_SECRET
));
// Say we are using the token from the JS
$fb->setAccessToken($data['access_token']);
// It should work now
var_dump($fb->getUser());
Hope it helped.
I just use the Facebook login button - https://developers.facebook.com/docs/reference/plugins/login/
Once the user has used that to login (if they weren't already) and grant access to your app (site), the PHP-SDK should have no trouble using the Facebook session and APIs.
Update
I just tried this with the new version 3.0 PHP SDK and it is definitely not working. Found this on the developer blog
If you are using the JavaScript SDK for login in conjunction with the PHP SDK, you will want to wait for the JavaScript SDK upgrade (coming in 4 weeks). Version 3.0.0 of the PHP SDK won’t cooperate with the current JavaScript SDK due to the cookie format changing.
In other words, use the v2 PHP SDK until the JS SDK is updated.
it's sound like facebook didn't fix this problem at the right time(as they talk https://developers.facebook.com/blog/post/503).
this is newest infomation about js sdk
https://developers.facebook.com/blog/post/525/
After long hours of searching, I found this fixed my problem where the PHP SDK did not pick up the Facebook session. Apparently, the Javascript SDK is not setting the session the right way. Add this to your auth.login eventlistener:
FB.Event.subscribe('auth.login', function(response) {
FB._oauth = false;
FB.Cookie.setEnabled(true);
FB.Auth.setSession(response.authResponse, response.status);
FB._oauth = true;
window.location.reload();
});
Also, make sure you set the App Domain to match your cookie domain. After fixing these items, it finally worked.
Edit:
This morning, everything was working fine. When I was testing some more just now, I found that I had to edit base_facebook.php to make sure the requests to Facebook would not time-out. My guess is that because I am testing on my local machine, the connection would not be fast enough to make it in time. This explains the strange behaviour where sometimes it would and sometimes it would not work.
Alter the connecttimeout in the $CURL_OPTS array on line 128:
public static $CURL_OPTS = array(
CURLOPT_CONNECTTIMEOUT => 20,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_USERAGENT => 'facebook-php-3.1',
);
In version 4 of the SDK it works automatically with the JavaScript SDK. You just need to use FacebookJavaScriptLoginHelper:
$helper = new FacebookJavaScriptLoginHelper(); // Get access token from JS SDK
try {
$session = $helper->getSession();
} catch(FacebookRequestException $e) {
// When Facebook returns an error
echo "Exception occured, code: " . $e->getCode();
echo " with message: " . $e->getMessage();
} catch(\Exception $e) {
// When validation fails or other local issues
echo "Exception occured, code: " . $e->getCode();
echo " with message: " . $e->getMessage();
}
// If logged in
if($session) {
// Get user profile
try {
$user_profile = (new FacebookRequest(
$session, 'GET', '/me'
))->execute()->getGraphObject(GraphUser::className());
print_r($user_profile);
} catch(FacebookRequestException $e) {
echo "Exception occured, code: " . $e->getCode();
echo " with message: " . $e->getMessage();
}
}
No need to mess around with cookies!