PHP Facebook API Post on page's wall - php

I know, this question was asked hundred times, but none of the given solutions works for me.
I'm trying to post on the wall of every page the current user owns. So, I first get the permissions to publish_actions, read_stream, manage_pages and offline_access. Then I check via /me/permissions, that the user really granted those permissions.
Then, I try to get all pages of the user and post on the wall of the page, if the user is the admin:
$accounts = $facebook->api("/me/accounts", "GET", array("access_token"=>$facebook->getAccessToken()));
$data = $accounts["data"];
foreach ($data as $page)
{
if (isset($page["perms"]) && in_array("CREATE_CONTENT", $page["perms"])))
{
$facebook->api("/".$page["id"]."/feed", "POST", array("link"=>$link, "access_token"=>$page["access_token"]));
}
}
But, posting on the wall of the page fails, with the well known error message
Uncaught OAuthException: (#200) The user hasn't authorized the application to perform this action
Any ideas? Where's my fault?

If you can make the same call via the Graph API Explorer or cURL for one of the pages then your logic is right. So I would place a try/catch on the page/id call to see if a specific page is messing up the loop.
try {
$facebook->api("/".$page["id"]."/feed", "POST", array("link"=>$link, "access_token"=>$page["access_token"]));
} catch (FacebookApiException $e) {
error_log($e . " for: " .$page["id"] );
}
}

Related

How to identify callback from Facebook

Having an issue with the Facebook PHP API/SDK, let me begin by describing:
I made a website where you can enter 'quotes' (short messages) and then after saving the quote in the website (read; too a mysql db behind it) you can decide to share the quote with Facebook to be able to win stuff.
The flow (how it should work) is this:
User opens my site, PHP gets a login url from the Facebook PHP API/SDK
PHP reads & memorizes the 'state' url variable from the login url from the above step (which several sites mention would be a valid way to identify users)
A user saves a quote, I store the state variable from above in the db record of that quote so I can use it again later to match returning users with saved quotes.
The user decides to want to win, so he/she clicks the Facebook share button, which points their browser too the Facebook login url from step 1
The user's browser is now looking at some Facebook pages where they have to allow access for the app and allow that it can post to their wall
Once the user has given said access, they return to the callback url of my site (which happens to be the same as the 'origin url' from step 4)
PHP on my site finds the state variable in the returned url variables(?), goes trough the database to find a matching quote record, and if found, it stores some Facebook user data (userid and path to avatar) in the related db record.
PHP continues to post their earlier saved quote to the user's Facebook wall.
In essence, things work, but the most important bit, step 7, identifying who comes back via the state variable, does not. The problem is that I just get some lengthy 'code' GET variable back, and not the 'state' GET variable, and nowhere in the API docs or on StackOverflow or via Google do I find how to change it so I do get the 'state' GET variable returned again...?
So to recap, basically what I'm looking for is an ability to send some sort of identifier to Facebook that then gets included in the callback-url, and to my knowledge, that's what the 'state' variable seems best for, if it would work that is.
I'm using the currently latest API (facebook-php-sdk-v4-5.0.0.zip from this morning) Below I've shared all relevant code I use to interface with the Facebook PHP API/SDK, all this code resides in the index.php in public_html dir of my site, the callback url of my app is this same index.php
This code is pieced together from several examples, and essentially works, I just don't get the needed state variable back.
require_once __DIR__ . '<PATH-TOO-FB-API>/src/Facebook/autoload.php';
session_start();
$fbStateCode = ""; // used to memorize state code
$fbLoginUrl = ""; // user to memorize login url
// Init the API
// If you go end up testing this, dont forget too change <APP-ID> & <APP-SECRET>
$fb = new Facebook\Facebook([
'app_id' => '<APP-ID>',
'app_secret' => '<APP-SECRET>',
'default_graph_version' => 'v2.4',
'default_access_token' => isset($_SESSION['facebook_access_token']) ? $_SESSION['facebook_access_token'] : '<APP-ID>|<APP-SECRET>'
]);
// login helper
$helper = $fb->getRedirectLoginHelper();
// try get an accesstoken (wich we only have if user returned from facebook after logging in)
try {
$accessToken = $helper->getAccessToken();
} catch(Facebook\Exceptions\FacebookResponseException $e) {
//echo 'Graph returned an error: ' . $e->getMessage(); // When Graph returns an error
} catch(Facebook\Exceptions\FacebookSDKException $e) {
//echo 'Facebook SDK returned an error: ' . $e->getMessage(); // When validation fails or other local issues
}
if (isset($accessToken)) {
// User is logged in!
try {
// Now we look up some details about the user
$response = $fb->get('/me?fields=id,name');
$facebook_user = $response->getGraphUser();
exit; //redirect, or do whatever you want
} catch(Facebook\Exceptions\FacebookResponseException $e) {
//echo 'Graph returned an error: ' . $e->getMessage();
} catch(Facebook\Exceptions\FacebookSDKException $e) {
//echo 'Facebook SDK returned an error: ' . $e->getMessage();
}
// if facebook_user has an id, we assume its a user and continue
if(isset($facebook_user['id'])) {
$avatarUrl = "http://graph.facebook.com/".$facebook_user['id']."/picture";
// THE BELOW 8 LINES HANDLE LOADING A QUOTE FROM DB WITH MATCHING STATE AND SAVING
// ADDITIONAL DATA TOO IT, THE ONLY ISSUE HERE IS THAT $_GET['state'] DOESNT EXIST
// THE REST OF THIS PROCESS HAS ALREADY BEEN TESTED AND PROOFED TO BE WORKING
$curr_quote = Quotes::getQuoteByFbStateCode($_GET['state']);
$curr_quote_data = $curr_quote->getData();
$curr_quote->updateData(array(
"fb_access_token" => $accessToken,
"fb_uid" => $facebook_user['id'],
"fb_avatar_path" => $avatarUrl
));
// Save it
if($curr_quote->save()) { // Success! quote in db was updated
// Now that we are logged in and have matched the returned user with a saved quote, we can post that quote too facebook
$_SESSION['facebook_access_token'] = (string) $accessToken; // storing the access token for possible use in the FB API init
// This is the data we post too facebook
$msg_data = array (
'message' => $curr_quote_data['quote']
);
$response = $fb->post('/me/feed',$msg_data,$accessToken); // do the actual post (this, like everything else besides state variable, works)
} else { // Fail! quote in db was NOT updated?!
// handle errors
}
}
} else {
// User is NOT logged in
// So lets build up a login url
$permissions = ['public_profile','publish_actions']; // we want these permissions (note, atm im the only tester, so while the app still needs to be reviewed for the 'publish_actions' permission, it works cuz i own the app and test with same fb account)
$fbLoginUrl = $helper->getLoginUrl('http://<WEBSITE-URL>/index.php', $permissions); // get the login url from the api providing callback url and permissions array
$fbLoginUrlParams = array();
parse_str($fbLoginUrl, $fbLoginUrlParams); // store the url params in a new array so that we can (read next comment below)
$fbStateCode = $fbLoginUrlParams['state']; // read out and store the state url variable
}
Below here is logic for saving a new quote to database based on user interaction, and making use of $fbStateCode, this part of the process functions fine as well, quotes get saved with their own unique state values like they should.
So that's the story, I'm trying to do something which I'm pretty sure isn't anything special, it's just poorly documented or something?
Ended up rewriting the lot, now it works fine, not sure whats different now vs what i had, so cant really provide an awnser for others running into similair issues, sorry bout that.
#Cbroe; forwarded the headsup you gave me too the customer, got literally told 'not our problem, but the problem of the company that made the concept', so time will tell if this ever even goes online lol, still, thanks for the headsup :P
Read the docs about the state variable here:
The state parameter is a value which is provided by the client prior to the login wen redirecting to the login url. If it's available then, it get's send back in the callback url.
So, unless you provide any state variable in your step1, you won't get any from FB (and any other oAuth2 implementing API). There will not be any "magic" making that appear other than providing it with a feasable state of your PHP app in step 1.
Actually, the state parameter is to give any client the ability to restore a context, whenever the callback "happens". So the content of the state variable may be a session id, a user id or any other value which helps restoring the (php)apps context again after receiving a callback
EDIT
I assume, that the state variable needs to be added somewhere in this function here:
$helper = $fb->getRedirectLoginHelper();

Querying the photos of a facebook page with age restriction

I am the administrator of a Facebook page which needs to have an age restriction of 17+ on it.
On my website, I am making some Graph API queries, like querying photo albums and linking to them on Facebook. I am using the PHP Facebook API.
I can't seem to get to grips around the page access tokens and when they expire and when not.
I tried to follow this answer here, which was highly voted, but it isn't clear what you do with the first access_token after you copy it. I am not sure if this is even valid any more.
I tried to access the page using the access token I get when I do me/accounts in Graph Explorer and it works, but after some time it expires and I get an exception that the token expired. I need something that stays working and doesn't expire and need me to go in and update it.
This is the code I have so far:
$fbconfig = array();
$fbconfig['appId'] = DEF_APP_ID;
$fbconfig['secret'] = DEF_APP_SECRET;
$fbconfig['fileUpload'] = false;
Facebook::$CURL_OPTS[CURLOPT_SSL_VERIFYPEER] = false;
$facebook = new Facebook($fbconfig);
//I am not sure if the following is the right way
$facebook->setAccessToken(DEF_ACCESS_TOKEN);
$facebook->setExtendedAccessToken();
...
try
{
$albums_resp = $facebook->api('/'.$id.'/albums','GET');
...
}
catch (FacebookApiException $ex)
{
error_log($ex);
}
What is the right way to achieve this?

Facebook sdk how to get page like using scoped_user_id

Im creating a Facebook application which will ask to like page before continue with the app. But after changing Facebook api platform to version 2, I cant get Facebook user id, I get scoped user id instead. Using scoped_user_id i cant get users who liked my page. Heres my code
if ($fb_scope_id){
try {
$user_like = $facebook->api('/'.$fb_scope_id.'/likes/');
} catch (FacebookApiException $e) {
$user_like = null;
}
}
It returns an empty array. Any solution?

How to check if user/app can post on target group wall?

I can post on group / page and user wall, but i don't want my app to show error when posting on selected wall, if the selected wall doesn't allow posting so is there any way to know that are we able to post on target wall?
Note: I found two similar questions but they do not pertain to exactly what i want
1 Application able to post on user's Wall
2 How to check the permission whether a friend allow me to post on his wall or not using php sdk
Please discuss in comment before taking any negative action.
Thanks.
AFAIK, there's no way to check exactly the way you want, coz the privacy varies, as you have already said. The only privacy setting that can be queried is the OPEN, CLOSED, or SECRET of group, which can be done by calling the graph api:
`http://graph.facebook.com/$Group_id`
That returns json data that has a field privacy, which will be one of OPEN, CLOSED, or SECRET.
But on top of that you have settings for groups where you can restrict posting to only group admins. And that permission can not be checked.
So i think what you'll have to do is check the returned value, i.e $response after making the post. If the permission is not given, then the returned data looks like this:
{
"error": {
"type": "Exception",
"message": "You do not have permission to post in this group."
}
}
Hence you can check if $response has "error" field, and inform the user accordingly. Somewhat like this: if(isset($response['error'])).
Also check the fql table that represents groups for more info, if you haven't already.
Do you mean how to check if a user has given permission to post on their wall?
try {
// Get the permissions this user has
$call = $this->facebook->api("/me/permissions");
// If they have the permission we require ('publish_stream')
if($call['data'][0]['publish_actions']){
try{
// Do your magic here...
// Also include your access token in the array
$params = array('message'=> 'hello world');
$call = $this->facebook->api('/me/feed','POST',$params);
}catch(FacebookApiException $e) {
$result = $e->getResult(); // prob no permissions
}
}
} catch(FacebookApiException $e) {
$result = $e->getResult();
}
So basically, first check to see if the user has permissions for a particular action, then if they do $call[data][0]['publish_action'] will be a set to 1 (int).
Example output of $call = $this->facebook->api("/me/permissions");
[installed] => (int) 1
[email] => (int) 1
[publish_actions] => (int) 1
I have the above permissions from the user through facebook.

Why am I getting Error message saying I've logged out even though my app seems to work fine?

I've made a simple app for the purpose of posting to a Facebook Page using PHP scripts from my personal web site.
After much trial and error, it seems to work just fine. I can log in to my app via my web site, post something, and it returns to my web site. So all is good.
The one oddity is that despite everything working, I am getting this error in my logs:
OAuthException: Error validating access token: The session is invalid
because the user logged out.
I've Googled the error, and from what I've seen, most people are experiencing time outs or being unexpectedly logged out. Solutions range within terms of how to maintain a logged in session.
However, I think my case is different from other questions I've seen because, despite the error, I seem to remain logged in. I can post to my Page wall as many times as I want.
The error does not seem to be generated every time I post to the wall. It seems to come up one out of every three or four, but it is not consistent, and I have not been able to determine a pattern.
Since everything is working, I could just ignore the error message, but that seems to me to be bad practise. I don't want anything sneaking up to bite me later.
Any help or advice would be much appreciated.
The code that drives the Facebook interaction is integrated with my CMS, so some parts of it are spread around, and/or might be obscure because of the parts I had to customize. However, I believe this function has the meat of the PHP interaction. Please let me know if this is sufficient to help determine the source of the problem:
private function executeFacebookPost()
{
// Facebook posts are limited to 420 characters. Links and pictures
// are separate.
$bodyOption = $this->mention->getOption(Action::$BODY);
if (count($bodyOption) == 0)
{
$fbPost = '';
}
else
{
$fbPost = $bodyOption[1];
}
$linkOption = $this->mention->getOption(Action::$LINK_TO);
if (count($linkOption) == 0)
{
$link = '';
}
else
{
$link = $linkOption[1];
}
// Use require_once() and not require() because you might be doing
// some facebook action elsewhere, and this script will die a sad
// death if it's asked to require more than once.
require_once('+facebook/facebook.php');
// Create our Application instance
$facebook = new Facebook(array(
'appId' => Site::getFacebookAppID(),
'secret' => Site::getFacebookSecret(),
));
$fbUser = $facebook->getUser();
if ($fbUser)
{
try
{
$page_id = Site::getFacebookPage();
$page_info = $facebook->api("/$page_id?fields=access_token");
if (!empty($page_info['access_token']))
{
$args = array(
'access_token' => $page_info['access_token'],
'message' => $fbPost,
'link' => $link,
//'description' => "aaaaaaaasdfsfsdf",
//'picture' => "http://cdn1.kingdomsofcamelot.com/fb/e2/src/img/fte/army_troop.png",
);
$post_id = $facebook->api("/$page_id/feed", "post", $args);
}
}
catch (FacebookApiException $e)
{
error_log($e, 1, 'ebisudave#gmail.com');
}
}
}
When you get your access_token, request offline_access and then your token won't expire.
it's not possible to give help without accessing code.
but i think an application(from cellphone,browser,...) changed current token trying to get updates from your facebook account.
test it again with this devices logged out.

Categories