0

我有以下有效的脚本,即如果用户尚未登录,它会转到 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);
    }
?>

如何改进这一点,使其在开始时不要求扩展权限。它应该只请求基本权限来显示好友列表,并且只在用户点击好友发布消息时请求扩展权限。

4

2 回答 2

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);
}
?>

此处解释了如何检查权限。我还添加了评论以节省编写解释。

于 2011-04-29T16:20:50.613 回答
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 的原因是为了处理data返回的 JSON 对象中的键。这通常是一个坏主意,因为该data键通常与其他键(如paging)一起出现。相反,我会检查它$friends['data']是否为空,然后像这样重新分配$friends数组$friends = $friends['data'];

例子:

if (!empty($friends['data']))
{
    $friends = $friends['data'];
}
else
{
    $friends = array();
}

现在,对于你的问题。

您提到您不想过度要求权限。这是一件很棒的事情,但它的问题是 Facebook 并没有让检查你拥有或没有哪些权限变得非常容易。有一个 FQL 表可让您检查您的用户是否具有特定的权限集,但该表不会因任何紧急情况而更新。如果您从用户那里获得额外的权限(或者如果用户收回权限),然后您检查此 FQL 表以了解权限的状态,它可能(并且可能会)读取不正确的值,您将得到误报。

你有三个选项来处理这个问题,我可以马上想到。

  1. 继续你的 stage1.php 代码,就像你一样 - 你为那里的用户获取安装和会话的方式没有任何问题。您更改页面 2 以通过 OAuth 端点重定向您的用户,每次用户加载页面时请求发布流权限。OAuth 端点不会重新提示用户安装,并将在途中发送。

    这种方法的缺点是,每个发布到朋友墙的请求都会变成 3 个请求。

    • 初始页面加载
    • OAuth 重定向/加载
    • 从 OAuth 重定向回您的应用程序

    此方法还要求您next在 loginURL 中的密钥中添加一个标志,您可以查找该标志以确保用户通过了 OAuth 端点,否则您将收到无限重定向错误。

  2. 利用 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);
    
  3. 不要使用任何扩展权限,(再次)使用 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);
    
于 2011-04-29T15:14:45.657 回答