Запрашивать разрешения на Facebook только при необходимости - PullRequest
0 голосов
/ 29 апреля 2011

У меня есть следующий скрипт, который работает, то есть он переходит на страницу входа в Facebook, если пользователь еще не вошел в систему, и спрашивает, в порядке ли он с приложением, чтобы публиковать сообщения на своей стене:*

Как это можно улучшить, чтобы не запрашивать расширенные разрешения при запуске.Он должен запрашивать только основные разрешения для отображения списка друзей и запрашивать расширенные разрешения только в том случае, если пользователь нажимает на друга, чтобы опубликовать сообщение.

Ответы [ 2 ]

1 голос
/ 29 апреля 2011

Вот переписывание вашего кода, с которым я считаю лучшими практиками:

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

Как проверить разрешение, объяснено здесь .Также я добавил комментарии, чтобы сохранить написание объяснения.

0 голосов
/ 29 апреля 2011

Вкратце, я хочу отметить кое-что в отношении следующего блока кода:

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);
    
...