2013-12-10 6 views
10

Я работаю над функцией, которая позволяет пользователям регистрироваться на моем сайте со своей учетной записью Google.Google+ Войти с вызовом обратного вызова JavaScript

Мой код основан на Google documentation (другие параметры signIn() находятся в метатегах).

function login() { 
    gapi.auth.signIn({'callback': 
    function (authResult) { 
     if (authResult['status']['signed_in']) { 
     console.log('Okay'); 
     }else { 
     console.log('Error'); 
     } 
    } 
    }); 
} 

Когда я вызываю login(), появляется всплывающее окно Google, я одобряю условия моего приложения, и все работает нормально.

Но обратного вызова вызывается дважды:

  • первый случай: Если я никогда не одобренные приложения разрешения, то обратный вызов будет звонить при открытии всплывающего И когда я буду утверждать разрешения. Поэтому он напишет «Ошибка» и «Хорошо».
  • 2-й случай: если я уже одобрил разрешения, он будет писать «ОК» два раза.

Я добавил опцию 'approvalprompt': 'force' в функцию signIn(). Функция обратного вызова больше не вызывается дважды, но заставляет пользователя утверждать разрешения приложения, даже если они были одобрены ранее. Так что это не удобно.

Есть ли удобный способ одобрить разрешения приложения один раз без двух обратных вызовов?

спасибо.

+0

Возможный дубликат [Google Login Hitting Twice?] (Http://stackoverflow.com/questions/23020733/google-login-hitting-twice) –

+0

Похоже, что это общая проблема. Здесь есть ответ: stackoverflow.com/questions/23020733/... - –

ответ

4

Попробуйте зарегистрировать первый вызов в некоторой локальной переменной, а затем обработать его

Это быстрое решение помогает мне:

function login() { 
    var initializedGoogleCallback = false 
    gapi.auth.signIn({ 
    'callback': function (authResult) { 
     if (!initializedGoogleCallback) { 
     // after first call other will be ignored 
     initializedGoogleCallback = true; 
     if (authResult['status']['signed_in']) { 
      console.log('Okay'); 
     } else { 
      console.log('Error'); 
     } 
     } 
    } 
    }); 
} 

также вы можете добавить следующий код перед вызовом gapi.auth.signIn

window.removeEventListener('load') 
+0

Это хорошее решение, спасибо! Но я до сих пор не знаю, почему мы должны это делать, это как «обман». Может быть, это ошибка, или мы просто не понимаем причину. – sylvhama

+1

Я думаю, что причина в библиотеке google js. Но google не обеспечивает нормальный способ удаления всех предыдущих событий перед вызовом нового метода. Также нет источника js, чтобы полностью понять причину, и API тоже не описывают это. – Panoptik

6

Я столкнулся с одной и той же проблемой: callback callback вызывал дважды в случае, если пользователь уже предоставил разрешение; метод local variable (initializedGoogleCallback) не работает для меня, потому что он вызывает обратный вызов один раз только тогда, когда пользователь уже предоставил доступ, но не вызвал его, если пользователь является новым. После небольшого исследования (я особенно копаю на сайте, используя g + auth), я заметил, что все они используют 'approvalprompt': 'force', и у них есть уже предоставленный пользователь для повторного одобрения политики «Offline Access» каждый раз. Даже пример Google, который я выполнил для настройки моего приложения (https://developers.google.com/+/web/signin/javascript-flow), даже если он не упоминал об этом, он использует параметр «force». На данный момент это единственное решение, если вы хотите использовать поток javascript (это означает, что если вам нужна кнопка входа в личный стиль)

1

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

Не показывать кнопку входа в систему до тех пор, пока вы не получите обратный вызов - если authResult['status']['signed_in'] == true, тогда обработайте пользователя как подписанный (настройте сеанс и т. Д., Что бы вы обычно не делали). Если он неверен, тогда отобразите кнопку.

function signinCallback(authResult) { 
    if (authResult['status']['signed_in']) { 
    document.getElementById('signinButton').setAttribute('style', 'display: none'); 
    // Do sign in stuff here! 
    } else { 
    document.getElementById('signinButton').setAttribute('style', 'display: block'); 
    } 
} 

Я бы не стал использовать официальное утверждение, если вы можете!

+0

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

+0

Для javascript-метода им не нужно нажимать на него, чтобы вызвать обратный вызов - он будет запускаться, как только он будет добавлен в DOM. Если вы используете конфигурацию уровня страницы, она будет запускаться сразу после завершения загрузки страницы. Таким образом, поток будет: загрузка страницы, обратный вызов, если не подписан на кнопке дисплея. –

+0

Возможно, я чего-то не понимаю - [JS workflow] (http://developers.google.com/+/web/signin/javascript-flow). Цитата: _Вы должны использовать только инициированные пользователем события для запуска этого метода, такие как клики, чтобы блокировки всплывающих окон не препятствовали открытию диалогового окна авторизации. Кроме того, в примере _onload_ просто вызывает 'render()', что просто добавляет eventListener к кнопке. Обратный вызов не вызывается при загрузке страницы. – CRONUS

0

окончательно я решил с обходным путем; я не знаю, если это правильный способ приблизиться или я просто обман, но я делаю так:

прежде всего какой-то скрипт на странице (я использую загрузчик + JQuery)

function render() { 
    //I am not using it but kept anyway 

} 
var i; 
// Function called from a onClick on a link or button (the 'sign in with g+' button) 
function gp_login() { 
    i=0; 
    $('#alertbox').remove(); 
    var additionalParams = { 
    'callback': signinCallback, 
    /*'approvalprompt': 'force' finally removed*/ 
    }; 
    $('#gp-login').button('loading'); 
    gapi.auth.signIn(additionalParams); 
} 

function signinCallback(authResult) { //my callback function 
     var email=''; 
     var given_name=''; 
     if (authResult['status']['signed_in']) { //get some user info 
      gapi.client.load('oauth2', 'v2', function() { 
       gapi.client.oauth2.userinfo.get().execute(function(resp){ 
        email = resp.email; //get user email 
        given_name = resp.given_name; //get user email 
        family_name=resp.family_name; 
        id=resp.id; 
        if (i<2) { //execute the doLogin just one time (my cheat) 
         doLogin(email,given_name,family_name,id); //dologin does my logic with an ajax call to signup/register user to my site 
        } 
        i=2; 
       }); 
      }); 
     } else { 
     // Update the app to reflect a signed out user 
     } 

} 

этот аспект имеет часть doLogin, вызываемую всего один раз, но обратный вызов вызывается дважды (gapi.client.oauth2.userinfo.get() эта функция вызывается дважды); с немного большей настройкой с проверкой if/var, я думаю, что можно позвонить все раз. Таким образом, если пользователь уже предоставил auth, он будет автоматически подписан.

Я замечаю, что иногда Google есть всплывающий слой на дне слой, показывающий «Добро пожаловать обратно сообщение», но я не понимаю, когда он появляется, или если я должен назвать это вручную

+0

Я имею дело с той же проблемой, и я закончил реализацию аналогичного «исправления», но с переменной true/false. – Francisc0

8

Я столкнувшись с этой проблемой, но я вызываю gapi.auth.signIn() через обработчик нажатия кнопки. Обратный вызов по-прежнему вызывается дважды. Одна вещь, которую я заметил между двумя объектами authResult, заключалась в том, что authResult.status.method является «АВТО» при первом вызове (перед всплывающим окном) и является «PROMPT» во втором вызове после автоматического отклонения окна из-за предыдущего авторизации.

Решение, которое я сейчас изучаю, - это игнорировать экземпляр AUTO и обрабатывать экземпляр PROMPT обратного вызова. Не знаете, как это будет работать, когда я отменим разрешения в Google из-за отсутствия деталей в документах объекта «status».

+0

Как это сработало для вас? Я собираюсь сделать то же самое. – Dale

1

Как ответ на Дрю Тейлора, чтобы избежать двойного обратный вызова с чистым яваскриптом знаком в растворе, вы можете check the user's session state:

if (authResult["status"]["method"] == "PROMPT") {...} 

Я думаю, что обратный вызов с помощью метода AUTO обжигает в нижнем приветствии панели который появляется при первом входе в систему.

Смежные вопросы