Facebook JS SDK渐进式网络应用程序问题

问题描述 投票:7回答:2

我有一个使用Angular 4构建的Progressive Web App。

我的问题是当从主屏幕应用程序使用时,Fb登录对话框不会自动关闭。在Chrome浏览器中打开它时工作得很好但是当我从已安装的主屏幕应用程序使用它时,对话框窗口会打开请求权限,在给出所有权限后,对话框变为空白并且不会关闭或重定向回应用程序。

看起来如果我将manifest.json中的“display”更改为“browser”,它可以工作但是当“display”处于“standalone”状态时不起作用。

我搜索了一遍但没有成功。

谢谢

facebook angular google-chrome facebook-javascript-sdk progressive-web-apps
2个回答
3
投票

当您的应用程序作为渐进式Web应用程序安装时,Facebook登录弹出窗口和父窗口(您的应用程序)无法以他们在桌面环境中的方式进行通信。

您也会在其他情况下遇到此问题,例如:当您的应用程序使用Instagram或Facebook等应用程序内浏览器启动时。

您可以按照另一个答案的建议实现基于服务器的流程。您还可以在客户端实现自定义重定向流。

自定义重定向流无需弹出窗口即可运行。当您的用户点击“登录”按钮时,他/她将被重定向到Facebook登录屏幕。登录后,将使用包含验证身份验证成功或失败所需的所有内容的URL将用户定向回应用程序。

Facebook SDK文档中的“手动构建登录流程”下描述了如何创建自定义重定向流程:

https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow

这个想法如下:

您将用户引导至Facebook登录对话框(而不是FB.login()发布的弹出窗口),例如当他们点击按钮时:

https://www.facebook.com/v2.11/dialog/oauth?
  client_id={app-id}
  &redirect_uri={redirect-uri}
  &response_type=token
  &state={state-param}

如果用户成功授予您的应用程序必要的权限,他/她将被重定向回您的应用程序(该位置由{redirect-url}确定):

{redirect-uri}?code=<facebook-code>&state={state}#_=_

然后你的应用程序需要弄清楚登录是否成功。有两种方法可以做到这一点:

A)读取当前URL的查询字符串(请参阅code=<code>部分 - 这可用于检索有关您的用户的其他信息,或者可以将其发送到您的后端服务器)。

B)使用Facebook SDK使用FB.getLoginStatus(yourCallback)检索登录状态

如果您已经在使用SDK和FB.login(yourCallback),那么您也可以将yourCallback添加到FB.getLoginStatus。您还可以根据用户的设备支持弹出流和重定向流。

我建议阅读上面发布的文档条目,以获取更多信息和选项。


0
投票

我有点想办法为FB做这个。使用FB PHP SDK生成登录URL并在子窗口上打开url,整个登录对话框和权限都发生了,它重定向到我的redirect_url,在那里我使用window.opener.postMessage将必要的数据传递给父窗口。

我的redirect_url页面设置如下:

<?php
if ( ! session_id()) {
session_start();
}

require_once "vendor/autoload.php";

$_SESSION['FBRLH_state'] = $_GET['state'];
$fb = new Facebook\Facebook([
'app_id'                => 'FBID', // Replace {app-id} with your app id
'app_secret'            => 'FBSECRET',
'default_graph_version' => 'v2.2',
]);

$helper = $fb->getRedirectLoginHelper();

try {
$accessToken = $helper->getAccessToken();
} catch (Facebook\Exceptions\FacebookResponseException $e) {
echo 'Graph returned an error: ' . $e->getMessage();
exit;
} catch (Facebook\Exceptions\FacebookSDKException $e) {
echo 'Facebook SDK returned an error: ' . $e->getMessage();
exit;
}

if ( ! isset($accessToken)) {
if ($helper->getError()) {
    header('HTTP/1.0 401 Unauthorized');
    echo "Error: " . $helper->getError() . "\n";
    echo "Error Code: " . $helper->getErrorCode() . "\n";
    echo "Error Reason: " . $helper->getErrorReason() . "\n";
    echo "Error Description: " . $helper->getErrorDescription() . "\n";
} else {
    header('HTTP/1.0 400 Bad Request');
    echo 'Bad request';
}
exit;
}

$oAuth2Client = $fb->getOAuth2Client();

$tokenMetadata = $oAuth2Client->debugToken($accessToken);
$tokenMetadata->validateAppId('FBID'); // Replace {app-id} with your app id
$tokenMetadata->validateExpiration();

if ( ! $accessToken->isLongLived()) {
try {
    $accessToken = $oAuth2Client->getLongLivedAccessToken($accessToken);
} catch (Facebook\Exceptions\FacebookSDKException $e) {
    echo "<p>Error getting long-lived access token: " . $helper->getMessage() . "</p>\n\n";
    exit;
}}

$_SESSION['fb_access_token'] = (string)$accessToken;
$tk = $_SESSION['fb_access_token']; 
?>

<?= $tk;?>
<script type="text/javascript">
window.opener.postMessage({token: '<?= $tk;?>'}, '*');
window.close();
</script>

在父窗口中,我有一个eventListener,它使用window.addEventListener("message", receiveMessage, false);and监听postMessage,receiveMessage函数根据需要处理所有数据。因此,任何使用独立模式的Web应用程序都应该能够从子窗口获取数据。

Window postmessage可用于在跨源之间传递数据。关于postMessage的更多细节在这里:https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

© www.soinside.com 2019 - 2024. All rights reserved.