The snippet below is supposed to get a friends list from a user's Facebook profile into my application:
<script
type="text/javascript"
src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php">
</script>
<script type="text/javascript">
FB_RequireFeatures(
["XFBML"],
function() {
FB.Facebook.init("xxxxxxxx","xd_receiver.htm");
FB.Facebook.get_sessionState().waitUntilReady(
function() {
FB.Facebook.apiClient.friends_get(
null,
function(result,ex){window.alert("friends list :" + result);}
);
}
);
}
);
</script>
Instead of the name of my friends I get some integer. I couldn't guess why. It would be nice to know why my approach doesn't work.
Your approach does work, but as Documented on the Facebook Developer Wiki, the function FB.ApiClient.Friends_get which you call doesn't return the names of friends, it returns an array of their user IDs which are large (often bigger than integer) number values. You will need to use an additional function, FB.ApiClient.users_getInfo, in order to return the name(s) of users. You also don't need to call FB.Facebook.ApiClient, you can bypass the Facebook object using FB.ApiClient directly.
Here is an example (untested, but should give you the idea):
<script type="text/javascript" src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php"></script>
<script type="text/javascript">
FB_RequireFeatures(
["XFBML"],
function() {
FB.Facebook.init("xxxxxxxx","xd_receiver.htm");
FB.Facebook.get_sessionState().waitUntilReady(
function() {
FB.ApiClient.friends_get(
null,
function(result,ex) {
FB.ApiClient.users_getInfo(result, 'name',
function(friendNames, exec) {
window.alert("first name in friends list: " + friendsNames[0]);
}
)
}
);
}
);
}
);
</script>
I believe you have to do:
FB.ApiClient.friends_get(
new Array(),
Which I saw on the developer site.
Related
I think I'm going crazy. I can't get it to work.
I simply want to check if a user has liked my page with javascript in an iFrame app.
FB.api({
method: "pages.isFan",
page_id: my_page_id,
}, function(response) {
console.log(response);
if(response){
alert('You Likey');
} else {
alert('You not Likey :(');
}
}
);
This returns: False
But I'm a fan of my page so shouldn't it return true?!
I tore my hair out over this one too. Your code only works if the user has granted an extended permission for that which is not ideal.
Here's another approach.
In a nutshell, if you turn on the OAuth 2.0 for Canvas advanced option, Facebook will send a $_REQUEST['signed_request'] along with every page requested within your tab app. If you parse that signed_request you can get some info about the user including if they've liked the page or not.
function parsePageSignedRequest() {
if (isset($_REQUEST['signed_request'])) {
$encoded_sig = null;
$payload = null;
list($encoded_sig, $payload) = explode('.', $_REQUEST['signed_request'], 2);
$sig = base64_decode(strtr($encoded_sig, '-_', '+/'));
$data = json_decode(base64_decode(strtr($payload, '-_', '+/'), true));
return $data;
}
return false;
}
if($signed_request = parsePageSignedRequest()) {
if($signed_request->page->liked) {
echo "This content is for Fans only!";
} else {
echo "Please click on the Like button to view this tab!";
}
}
You can use (PHP)
$isFan = file_get_contents("https://api.facebook.com/method/pages.isFan?format=json&access_token=" . USER_TOKEN . "&page_id=" . FB_FANPAGE_ID);
That will return one of three:
string true string false json
formatted response of error if token
or page_id are not valid
I guess the only not-using-token way to achieve this is with the signed_request Jason Siffring just posted. My helper using PHP SDK:
function isFan(){
global $facebook;
$request = $facebook->getSignedRequest();
return $request['page']['liked'];
}
You can do it in JavaScript like so (Building off of #dwarfy's response to a similar question):
<html>
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<style type="text/css">
div#container_notlike, div#container_like {
display: none;
}
</style>
</head>
<body>
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function() {
FB.init({
appId : 'YOUR_APP_ID', // App ID
channelUrl : 'http(s)://YOUR_APP_DOMAIN/channel.html', // Channel File
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});
FB.getLoginStatus(function(response) {
var page_id = "YOUR_PAGE_ID";
if (response && response.authResponse) {
var user_id = response.authResponse.userID;
var fql_query = "SELECT uid FROM page_fan WHERE page_id = "+page_id+"and uid="+user_id;
FB.Data.query(fql_query).wait(function(rows) {
if (rows.length == 1 && rows[0].uid == user_id) {
console.log("LIKE");
$('#container_like').show();
} else {
console.log("NO LIKEY");
$('#container_notlike').show();
}
});
} else {
FB.login(function(response) {
if (response && response.authResponse) {
var user_id = response.authResponse.userID;
var fql_query = "SELECT uid FROM page_fan WHERE page_id = "+page_id+"and uid="+user_id;
FB.Data.query(fql_query).wait(function(rows) {
if (rows.length == 1 && rows[0].uid == user_id) {
console.log("LIKE");
$('#container_like').show();
} else {
console.log("NO LIKEY");
$('#container_notlike').show();
}
});
} else {
console.log("NO LIKEY");
$('#container_notlike').show();
}
}, {scope: 'user_likes'});
}
});
};
// Load the SDK Asynchronously
(function(d){
var js, id = 'facebook-jssdk'; if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
d.getElementsByTagName('head')[0].appendChild(js);
}(document));
</script>
<div id="container_notlike">
YOU DON'T LIKE ME :(
</div>
<div id="container_like">
YOU LIKE ME :)
</div>
</body>
</html>
Where the channel.html file on your server just contains the line:
<script src="//connect.facebook.net/en_US/all.js"></script>
There is a little code duplication in there, but you get the idea. This will pop up a login dialog the first time the user visits the page (which isn't exactly ideal, but works). On subsequent visits nothing should pop up though.
Though this post has been here for quite a while, the solutions are not pure JS. Though Jason noted that requesting permissions is not ideal, I consider it a good thing since the user can reject it explicitly. I still post this code, though (almost) the same thing can also be seen in another post by ifaour. Consider this the JS only version without too much attention to detail.
The basic code is rather simple:
FB.api("me/likes/SOME_ID", function(response) {
if ( response.data.length === 1 ) { //there should only be a single value inside "data"
console.log('You like it');
} else {
console.log("You don't like it");
}
});
ALternatively, replace me with the proper UserID of someone else (you might need to alter the permissions below to do this, like friends_likes) As noted, you need more than the basic permission:
FB.login(function(response) {
//do whatever you need to do after a (un)successfull login
}, { scope: 'user_likes' });
i use jquery to send the data when the user press the like button.
<script>
window.fbAsyncInit = function() {
FB.init({appId: 'xxxxxxxxxxxxx', status: true, cookie: true,
xfbml: true});
FB.Event.subscribe('edge.create', function(href, widget) {
$(document).ready(function() {
var h_fbl=href.split("/");
var fbl_id= h_fbl[4];
$.post("http://xxxxxx.com/inc/like.php",{ idfb:fbl_id,rand:Math.random() } )
}) });
};
</script>
Note:you can use some hidden input text to get the id of your button.in my case i take it from the url itself in "var fbl_id=h_fbl[4];" becasue there is the id example:
url:
http://mywebsite.com/post/22/some-tittle
so i parse the url to get the id and then insert it to my databse in the like.php file.
in this way you dont need to ask for permissions to know if some one press the like button, but if you whant to know who press it, permissions are needed.
How to implement "Suggest MY-PAGE to friends" using PHP-SDK or using Javascript SDK?
First you need the Facebook SDK bundle that contains base_facebook.php, facebook.php and fb_ca_chain_bundle.crt . You will also need fbmain.php and config.php .
Next you should have a file (e.g postToWall.php) that includes fbmain.php
<?php
include_once "fbmain.php";
?>
An example of postToWall.php file.
<html>
<body id="my_body">
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function() {
FB.init({
appId: '<?php echo $facebook->getAppID() ?>',
cookie: true,
xfbml: true,
oauth: true
});
FB.Canvas.setAutoGrow();
};
(function() {
var e = document.createElement('script'); e.async = true;
e.src = document.location.protocol +
'//connect.facebook.net/en_US/all.js';
document.getElementById('fb-root').appendChild(e);
}());
</script>
<?php
if ($me)
{
$params = array('message' => "message here",
'picture' => "picture hyperlink here",
'name' => "name here",
'link' => "facebook page hyperlink here",
'description' => " description here"
);
$status = $facebook->api('/me/feed', 'POST', $params);
if (isset($status['id']))
{
//do something
}
}
?>
</body>
</html>
Credits to my tutor, Mr Zen Leow
The earlier solution I have posted is using the PHP SDK method.
Using JavaScript SDK, you can have a HTML button using onclick attribute to call a function.
<input type="button" value="Share" onclick="share();"/>
Inside share function, the method property is compulsory and the other properties (link, picture, name, caption, description) are optional. The value "feed" in method property refers to feed dialog which you need, there are other values for method property such as "apprequests" (Request Dialog) and "send" (Send Dialog). For more information, check out http://developers.facebook.com/docs/reference/dialogs/
<script>
function share()
{
var obj = {
method: "feed",
link: "Facebook page hyperlink",
picture: "Picture hyperlink",
name: "Title",
caption: "A short caption right below the title",
description: "Description"
};
function callback(response) {
document.getElementById('msg').innerHTML = "Post ID: " + response['post_id'];
}
FB.ui(obj, callback);
}
</script>
The difference between PHP SDK and JavaScript SDK
For PHP SDK, the default message specified in postToWall.php will be posted straight to the user's wall upon clicking the share button. You have to redirect user to postToWall.php first and then redirects him/her back to your application page.
For JavaScript SDK, a window will pop up upon clicking the share button and user will be able to input their own message before he/she sends it. No additional redirection will be needed after sending as user is still on the same page.
P.S.: I'm still learning Facebook and PHP at the moment, so do correct me if I am making any mistake haha. Thanks =)
Here I am using Facebook Login button plugin and javascript sdk
I am able to successfully login and logout by using above.
When a first time user has gone through authentication process I need to store user basic information i.e. Facebook login name, email in my database.
Please suggest how I can do this.
<p><fb:login-button autologoutlink="true"></fb:login-button></p>
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function () {
FB.init({ appId: '123456', status: true, cookie: true,
xfbml: true
});
};
(function () {
var e = document.createElement('script');
e.type = 'text/javascript';
e.src = document.location.protocol +
'//connect.facebook.net/en_US/all.js';
e.async = true;
document.getElementById('fb-root').appendChild(e);
} ());
</script>
Subscribe to the event auth.login. If you do this, Facebook will call your handler after a login as happened.
In that handler, use FB.api to call the Graph API to get any information you desire. For example calling /me as shown in the second example will get you basic information about the logged in user.
Now you have all the data in JavaScript. To send that up to your server, do a plain old XMLHttpRequest/AJAX request. Your JavaScript library probably makes this easy -- in jQuery this is jQuery.ajax() -- but worst case you can use XHR directly.
Now you have the data on your server and you can do whatever you want, like store it in the database. If you only want to store the data once, just check that you haven't already stored info about that user ID yet.
It's also possible to use a combination of PHP SDK and JS SDK, with the latter performing the login and the former storing data on the server. Something like:
<?php
require_once 'config.php';
require_once 'lib/facebook.php';
$facebook = new Facebook(array(
'appId' => FB_APP_ID,
'secret' => FB_APP_SECRET,
));
?>
<!DOCTYPE html>
<html xmlns:fb="http://www.facebook.com/2008/fbml">
<body>
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function () {
FB.init({
appId:'<?php echo $facebook->getAppID() ?>',
cookie:true,
xfbml:true,
oauth:true
});
FB.Event.subscribe('auth.login', function (response) {
window.location = "showUser.php"; //redirect to showUser.php on Login
});
FB.Event.subscribe('auth.logout', function (response) {
window.location.reload();
});
};
(function () {
var e = document.createElement('script');
e.async = true;
e.src = document.location.protocol +
'//connect.facebook.net/en_US/all.js';
document.getElementById('fb-root').appendChild(e);
}());
</script>
<div class="fb-login-button" data-show-faces="true" data-width="200"
data-max-rows="1"></div>
</body>
</html>
And in showUser.php you have something like:
<?php
#showUser.php
require_once 'config.php';
require_once 'lib/facebook.php';
$facebook = new Facebook(array(
'appId' => FB_APP_ID,
'secret' => FB_APP_SECRET,
));
$user = $facebook->getUser();
if($user)
{
if ($user) {
try {
// Proceed knowing you have a logged in user who's authenticated.
$user_profile = $facebook->api('/me');
var_dump($user_profile); //You can now save this data
} catch (FacebookApiException $e) {
echo '<pre>'.htmlspecialchars(print_r($e, true)).'</pre>';
$user = null;
}
}
}
?>
There's a hole in that solution -- this means the user can make up any information he wants and post an XHR back to my server. The server is going to need to check with Facebook directly.
//very simple just change this line
fb:login-button autologoutlink="true"
//with this one
fb:login-button autologoutlink="true" onlogin='your_ajax_fun_that_store_in_db()'
function your_ajax_fun_that_store_in_db(){
FB.api('/me', function(response) {
$.post( "ajax/store_user_info.php",response, function( data ) {
//write you js code here !
//you can use the (response) from facebook directly in your store_user_info.php as it will be sent in POST array
});
});
}
//last thing when you face such a problem the first thing to do is to go back to facebook reference of fun.
Building an app with the Facebook JavaScript API that will embedded into a page using the new iframe method.
I want to detect if they have liked the current page. Usually I would use print_r($_REQUEST) in PHP but that doesn't seem to work when using an iframe.
There is also this option: http://developers.facebook.com/docs/reference/fbml/visible-to-connection/ but it says its deprecated and I have never liked this method as its fairly hacky.
What is the way t do it now? Prefer to use XFBML + JavaScript API but can use PHP if required.
We've done this several times, and it seems to work pretty well. It uses XFBML to generate a Like Button widget and the JS SDK to render XFBML and subscribe to Facebook events. Code sample below:
edit: Since you're looking to detect if the user is a fan when the page loads, and FB deprecated the feature to let you get it directly from them when the canvas is loaded by passing fb_page_id to the address query string, you'll need an application install for the user to test their fan-dom of your page. It certainly adds a lot of friction to your application, but it is what it is for now - I guess.
<?php
require 'facebook.php';
// Create our Application instance (replace this with your appId and secret).
$facebook = new Facebook(array(
'appId' => 'YOUR APP ID',
'secret' => 'YOUR APP SECRET',
'cookie' => false,
));
try
{
$session = $facebook->getSession();
if (empty($session['uid']))
{
throw new Exception("User not connected to application.");
}
$is_fan = $facebook->api(array(
'method' => 'fql.query',
'query' => "SELECT uid, page_id FROM page_fan WHERE uid = {$session['uid']}"
));
if (false == $is_fan || count($is_fan) == 0) // 0 results will be returned if the user is not a fan
{
$is_fan = false;
}
else
{
$is_fan = true;
}
}
catch (FacebookApiException $e)
{
/**
* you don't have an active user session or required permissions
* for this user, so rdr to facebook to login.
**/
$loginUrl = $facebook->getLoginUrl(array(
'req_perms' => 'user_likes'
));
header('Location: ' . $loginUrl);
exit;
}
?>
<html>
<head>
</head>
<body>
<? if (empty($is_fan)): //user is not a fan. ?>
<fb:like href="http://www.facebook.com/your-facebook-page"
show_faces="true"
width="400">
</fb:like>
<? else: ?>
Yay! You're a fan!
<? endif; >?
<div id="fb-root"></div>
<script src="http://connect.facebook.net/en_US/all.js" type="text/javascript">
</script>
<script type="text/javascript">
FB.init({
appId: '<?= FB_APP_ID; ?>',
cookie: true,
status: true,
xfbml: true
});
// Subscribe to the edge creation event, from Facebook
FB.Event.subscribe('edge.create', function(response)
{
alert("Congratulations! We are so excited that you are a fan now! woot!")
});
</script>
</body>
</html>
okay, finally got got everything formatted with straight markdown. that wasn't painful at all.. (sike) :|
I have the following script which works, i.e. it goes to the facebook login page if the user is not already logged in, and asks them if they are ok with the app to post messages on their wall:
<?php
require 'facebook.php';
$facebook = new Facebook(array(
'appId' => 'removed for security reasons',
'secret' => 'removed for security reasons',
'cookie' => true,
));
$session = $facebook->getSession();
if ($session) {
if (isset($_GET[id])) {
$post = $facebook->api("/" . $_GET['id'] . "/feed", "POST", array('message' => 'Hello!'));
echo 'A message has been posted on your friends wall';
} else {
$friends = $facebook->api('/me/friends');
foreach ($friends as $key=>$value) {
echo 'You have ' . count($value) . ' friends<br />';
foreach ($value as $fkey=>$fvalue) {
echo 'friend id = ' . $fvalue[id] . ' - friend name = ' . $fvalue[name] . ' - post message<br />';
}
}
}
} else {
$loginUrl = $facebook->getLoginUrl(array(
'req_perms' => 'publish_stream',
'next' => 'http://'.$_SERVER['SERVER_NAME'].'/stage1.php',
'cancel_url' => 'http://'.$_SERVER['SERVER_NAME'].'/cancel.php',
));
header('Location: '.$loginUrl);
}
?>
How can this be improved so it does not ask for extended permissions in the start. It should only ask for basic permissions to display the friends list, and only ask for extended permissions if the user clicks on the friend to post a message.
Here's a rewrite of your code, with what I think are best practices:
<?php
require 'facebook.php';
$facebook = new Facebook(array(
'appId' => 'removed for security reasons',
'secret' => 'removed for security reasons',
'cookie' => true,
));
$session = $facebook->getSession();
// Prepare the login url with the right permission
$loginUrl = $facebook->getLoginUrl(array(
'req_perms' => 'publish_stream',
'next' => 'http://'.$_SERVER['SERVER_NAME'].'/stage1.php',
'cancel_url' => 'http://'.$_SERVER['SERVER_NAME'].'/cancel.php',
));
if ($session) {
try {
// Before processing the request
// check if we got the right permission
$perms = $facebook->api(array(
"method" => "fql.query",
"query" => "SELECT publish_stream FROM permissions WHERE uid=me()"
));
if($perms[0]['publish_stream']==='1') {
// We have the right permission
if (isset($_GET['id'])) {
// A small security measure
$id = (int) $_GET['id'];
$post = $facebook->api("/$id/feed", "POST", array('message' => 'Hello!'));
echo 'A message has been posted on your friends wall';
} else {
$friends = $facebook->api(array(
"method" => "fql.query",
"query" => "SELECT uid,name FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1=me())"
));
foreach($friends as $friend)
echo "friend id = {$friend['uid']} - friend name = {$friend['name']} - post message<br />";
}
} else {
// We don't have the right permission
header('Location: '.$loginUrl);
}
} catch (FacebookApiException $e) {
error_log($e);
}
} else {
header('Location: '.$loginUrl);
}
?>
How to check for a permission is explained here. Also I've added comments to save writing an explanation.
Quickly, there is something I want to point out regarding the following block of code:
foreach ($friends as $key=>$value) {
echo 'You have ' . count($value) . ' friends<br />';
foreach ($value as $fkey=>$fvalue) {
echo 'friend id = ' . $fvalue[id] . ' - friend name = ' . $fvalue[name] . ' - post message<br />';
}
}
Your 1st foreach loop is really misleading and not good practice at all. The Graph API isn't overly consistent in how it presents data, but the reason you are doing the foreach is to deal with the data key in the JSON object that is returned. This is generally a bad idea, because that data key is typically present along with other keys (like paging). Instead, I would check to see that $friends['data'] is not empty, and then re-assign the $friends array like so: $friends = $friends['data'];.
Example:
if (!empty($friends['data']))
{
$friends = $friends['data'];
}
else
{
$friends = array();
}
now, for your question.
You mentioned that you don't want to over-ask for permissions. That's a great thing to want, but the problem with it is that Facebook doesn't make it exceedingly easy to check for which permissions you do have or do not have. There is an FQL table that allows you check if your user has a certain set of permissions, but this table doesn't get updated with any kind of urgency. If you obtain extra permissions from a user (or if a user retracts permissions) and you then check this FQL table for the status of the permission, it can (and probably will) read the incorrect value and you will get a false positive.
You have three options to deal with this, that I can think of right off the top of my head.
Continue on your stage1.php code, as you are - there's nothing wrong with the way you're obtaining the installation and the session for the user there. You change page 2 to redirect your user through the OAuth endpoint requesting the publish-stream permission every time the user loads the page. The OAuth endpoint will not re-prompt the user to install, and will send them on their way.
The cons with this approach is, every request to post to a friends' wall turns into 3 requests.
The initial page load
The OAuth redirect / load
The redirect from OAuth back to your application
This approach also requires that you add a flag to your next key in your loginURL, which you can look for to make sure the user went through the OAuth endpoint, otherwise you're going to get an infinite redirect error.
Utilize the FB Javascript SDK to check for your users' current set of permissions. To do this, you'll utilize the FB.getLoginStatus method.
Example:
<div id="fb-root"></div>
<script src="http://code.jquery.com/jquery-1.5.2.min.js"
type="text/javascript" charset="utf-8">
</script>
<script src="http://connect.facebook.net/en_US/all.js"
type="text/javascript" charset="utf-8">
</script>
<script type="text/javascript">
(function($)
{
FB.init({
appId: '<?= FB_APP_ID; ?>',
cookie: true,
status: true,
xfbml: true
});
$('a').click(function(event)
{
var self = this;
event.preventDefault();
FB.getLoginStatus(function(session)
{
if (session.perms.match(/\"publish_stream\"/))
{
/* This user has publish stream, so we don't need
* to ask again
**/
window.location = $(self).attr('href');
}
else
{
/* This user does not have publish stream, so we need
* to ask.
**/
FB.login(function(response)
{
if (response && response.perms.match(/publish_stream/))
{
/* We now have publish stream access! */
window.location = $(self).attr('href');
}
}, {
perms: 'publish_stream'
});
}
})
return false;
})
})(jQuery);
Don't utilize any extended permissions, use the Javascript SDK (again) and give the user a publish-dialog for each user they would like to publish on the wall of. This is a relatively easy thing to do, also.
Example:
given your links for users:
Friend 1
Friend 2
Friend 3
You can do something like this:
<div id="fb-root"></div>
<script src="http://code.jquery.com/jquery-1.5.2.min.js"
type="text/javascript" charset="utf-8">
</script>
<script src="http://connect.facebook.net/en_US/all.js"
type="text/javascript" charset="utf-8">
</script>
<script type="text/javascript">
(function($)
{
$('a').click(function(event)
{
var user_id = $(this).data('id');
FB.ui({
method: 'feed',
message: 'Hello!',
to: user_id
}, function(response)
{
//this gets called whether it was successful, or not.
})
});
})(jQuery);