我有以下脚本可以使用,即如果用户尚未登录则会进入Facebook登录页面,并询问他们是否可以使用该应用在墙上发布消息:
<?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] . ' - <a href="/stage2.php?id=' . $fvalue[id] . '">post message</a><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);
}
?>
如何改进,以便在开始时不要求扩展权限。它应该只要求显示朋友列表的基本权限,并且只有在用户点击该朋友发布消息时才要求扩展权限。
答案 0 :(得分:1)
以下是对您的代码的重写,我认为是最佳做法:
<?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']} - <a href=\"/stage2.php?id={$friend['uid']}\">post message</a><br />";
}
} else {
// We don't have the right permission
header('Location: '.$loginUrl);
}
} catch (FacebookApiException $e) {
error_log($e);
}
} else {
header('Location: '.$loginUrl);
}
?>
here解释了如何检查权限。此外,我添加了评论以保存解释。
答案 1 :(得分:0)
很快,我想指出以下代码块:
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] . ' - <a href="/stage2.php?id=' . $fvalue[id] . '">post message</a><br />';
}
}
你的第一个foreach循环真的是误导性的,根本不是好的练习。 Graph API在呈现数据方面并不过分一致,但您执行foreach的原因是处理返回的JSON对象中的data
键。这通常是一个坏主意,因为data
键通常与其他键(如paging
)一起出现。相反,我会检查$friends['data']
是否为空,然后重新分配$friends
数组,如下所示:$friends = $friends['data'];
。
示例:
if (!empty($friends['data']))
{
$friends = $friends['data'];
}
else
{
$friends = array();
}
现在,问你的问题。
您提到您不想过度询问权限。这是一件很棒的事情,但问题在于Facebook并没有让你检查你拥有或没有的权限变得非常容易。有一个FQL表允许您检查您的用户是否具有一组特定权限,但此表不会以任何紧急程度更新。如果您从用户那里获得额外的权限(或者如果用户撤回权限),然后您在此FQL表中检查权限的状态,它可以(并且可能会)读取不正确的值,您将得到误报。< / p>
你有三种方法可以解决这个问题,我可以想到这一点。
继续你的stage1.php代码,就像你一样 - 你在那里获得安装和会话的方式没有任何问题。每次用户加载页面时,您都会更改第2页以重定向用户通过OAuth端点请求发布流权限。 OAuth端点不会重新提示用户进行安装,并会在途中发送它们。
这种方法的缺点是,每个发送到朋友墙的请求都会变成3个请求。
此方法还要求您在loginURL中为next
键添加一个标记,您可以查找该标记以确保用户通过OAuth端点,否则您将获得无限重定向错误。
利用FB Javascript SDK检查用户当前的权限集。为此,您将使用FB.getLoginStatus方法。
示例:
<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);
不要使用任何扩展权限,使用Javascript SDK(再次)并为用户提供他们想要在墙上发布的每个用户的发布对话框。这也是一件相对容易的事情。
示例:
给出了用户链接:
<a href="#" data-id="123">Friend 1</a>
<a href="#" data-id="456">Friend 2</a>
<a href="#" data-id="789">Friend 3</a>
您可以这样做:
<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);