You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将PHPMailer get_oauth_token.php的输出加载到指定div中?

解决OAuth2授权不跳转整页的方案

1. 重构后端授权逻辑,取消直接跳转

把原get_oauth_token.php的流程拆成两个独立接口,避免用header()触发整页跳转:

接口1:生成授权链接

在MVC的Admin控制器里新增方法,负责生成谷歌授权URL和state,以JSON格式返回给前端:

public function getOAuthUrl()
{
    session_start();
    $client = new Google_Client();
    $client->setClientId('你的谷歌ClientID');
    $client->setClientSecret('你的谷歌ClientSecret');
    $client->setRedirectUri('http://localhost/Admin/oauthCallback'); // 配置回调地址
    $client->addScope('https://mail.google.com/');
    $client->setAccessType('offline');
    $client->setPrompt('select_account consent');

    $authUrl = $client->createAuthUrl();
    $_SESSION['oauth2state'] = $client->getState();
    
    header('Content-Type: application/json');
    echo json_encode([
        'authUrl' => $authUrl,
        'state' => $_SESSION['oauth2state']
    ]);
    exit;
}

接口2:处理授权回调

同样在Admin控制器里新增回调方法,接收谷歌返回的code并换取token,返回结果:

public function oauthCallback()
{
    session_start();
    if (!isset($_GET['state']) || $_GET['state'] !== $_SESSION['oauth2state']) {
        unset($_SESSION['oauth2state']);
        header('Content-Type: application/json');
        echo json_encode(['error' => '无效的state参数']);
        exit;
    }

    $client = new Google_Client();
    $client->setClientId('你的谷歌ClientID');
    $client->setClientSecret('你的谷歌ClientSecret');
    $client->setRedirectUri('http://localhost/Admin/oauthCallback');
    $client->addScope('https://mail.google.com/');

    $token = $client->fetchAccessTokenWithAuthCode($_GET['code']);
    $client->setAccessToken($token);

    // 把token存入session或数据库,供后续发信使用
    $_SESSION['gmail_oauth_token'] = $token;

    header('Content-Type: application/json');
    echo json_encode([
        'success' => true,
        'msg' => '授权成功'
    ]);
    exit;
}

2. 前端用弹窗处理授权流程

谷歌OAuth2禁止在iframe中加载授权页,所以用浏览器弹窗打开授权链接,完成后回调更新指定div:

<!-- 页面元素 -->
<button id="bindGmail">绑定谷歌邮箱</button>
<div id="oauthResult"></div>

<script>
document.getElementById('bindGmail').addEventListener('click', function() {
    // 异步请求授权链接
    fetch('/Admin/getOAuthUrl')
        .then(res => res.json())
        .then(data => {
            // 计算弹窗居中位置
            const w = 600;
            const h = 600;
            const left = (window.innerWidth - w) / 2;
            const top = (window.innerHeight - h) / 2;
            
            // 打开授权弹窗
            const authWin = window.open(
                data.authUrl,
                'GoogleOAuth',
                `width=${w},height=${h},left=${left},top=${top},scrollbars=yes`
            );

            // 定时检查弹窗状态
            const checkTimer = setInterval(() => {
                if (authWin.closed) {
                    clearInterval(checkTimer);
                    // 弹窗关闭后查询授权结果
                    fetch('/Admin/checkOAuthStatus') // 新增接口:检查session中是否存在token
                        .then(res => res.json())
                        .then(result => {
                            if (result.success) {
                                document.getElementById('oauthResult').innerHTML = '<p>谷歌邮箱绑定成功!</p>';
                            } else {
                                document.getElementById('oauthResult').innerHTML = '<p>绑定失败,请重试</p>';
                            }
                        });
                }
            }, 1000);
        })
        .catch(err => {
            document.getElementById('oauthResult').innerHTML = `<p>获取授权链接失败:${err.message}</p>`;
        });
});
</script>

3. 关键注意事项

  • 确保谷歌开发者控制台里的授权回调地址和后端配置完全一致,本地开发可填http://localhost/Admin/oauthCallback。
  • MVC架构中要确保Session正常启用,避免state验证失败。
  • 建议将获取到的token加密后存入数据库,而非仅存在Session中,方便后续调用PHPMailer发信。

内容的提问来源于stack exchange,提问作者Teo76

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 12:40:09