Запрашивая разрешения на Facebook только тогда, когда это необходимо

StackOverflow https://stackoverflow.com/questions/5832010

Вопрос

У меня есть следующий сценарий, который работает, т.е. он переходит на страницу входа в 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);
    }
?>

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

Это было полезно?

Решение

Быстро, я хочу указать на следующий блок кода:

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 />';
    }
}

Ваш 1 -й петля Foreach действительно вводит в заблуждение и совсем не хорошая практика. График API не слишком согласован в том, как он представляет данные, но причина, по которой вы делаете предание, состоит в том, чтобы справиться с 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 Ключ в вашем логике, который вы можете найти, чтобы убедиться, что пользователь прошел через конечную точку 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 (опять же) и дайте пользователю публикацию Dialog для каждого пользователя, которого они хотели бы опубликовать на стене. Это также относительно легко сделать.

    Пример:

    Учитывая ваши ссылки для пользователей:

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

Другие советы

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top