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

如何实现WordPress网站登录用户访问个人Google日历功能

解决方案

要实现每个登录WordPress用户访问自己的私有Google日历,核心是让每个用户单独完成Google OAuth2授权,而非使用全局服务账号或仅访问公开日历。以下是具体实现步骤:

1. 配置Google Cloud OAuth2凭据

  • 登录Google Cloud Console,创建新项目并启用Google Calendar API
  • 进入「API和服务」→「凭据」,创建「OAuth客户端ID」,应用类型选择「Web应用」
  • 设置授权回调URL为你的WordPress站点内的自定义端点(例如https://你的域名.com/wp-admin/admin-ajax.php?action=google_calendar_auth_callback)
  • 配置OAuth同意屏幕,添加必要的API范围:
    • 只读权限:https://www.googleapis.com/auth/calendar.readonly
    • 读写权限:https://www.googleapis.com/auth/calendar
      同时将你的站点域名添加到「已授权的域名」列表

2. 开发用户授权流程

添加授权入口

在用户个人资料页面或自定义仪表盘添加授权按钮:

// 在用户个人中心输出授权按钮
add_action('show_user_profile', 'google_calendar_auth_button');
add_action('edit_user_profile', 'google_calendar_auth_button');
function google_calendar_auth_button($user) {
    $access_token = get_user_meta($user->ID, 'google_calendar_access_token', true);
    if (!$access_token) {
        $auth_url = 'https://accounts.google.com/o/oauth2/v2/auth?' . http_build_query([
            'client_id' => '你的Google客户端ID',
            'redirect_uri' => '你的回调URL',
            'response_type' => 'code',
            'scope' => 'https://www.googleapis.com/auth/calendar.readonly',
            'state' => wp_create_nonce('google_calendar_auth_' . $user->ID),
            'access_type' => 'offline', // 获取刷新令牌
            'prompt' => 'consent'
        ]);
        echo '<a href="' . esc_url($auth_url) . '" class="button">连接我的Google日历</a>';
    } else {
        echo '<p>已连接Google日历 | <a href="' . esc_url(add_query_arg('action', 'google_calendar_disconnect', get_edit_user_link($user->ID))) . '">断开连接</a></p>';
    }
}

处理授权回调

通过AJAX端点处理Google返回的授权码:

// 处理授权回调
add_action('wp_ajax_google_calendar_auth_callback', 'google_calendar_auth_callback');
function google_calendar_auth_callback() {
    check_admin_referer('google_calendar_auth_' . get_current_user_id(), 'state');
    
    $code = $_GET['code'];
    $token_response = wp_remote_post('https://oauth2.googleapis.com/token', [
        'body' => [
            'client_id' => '你的Google客户端ID',
            'client_secret' => '你的Google客户端密钥',
            'code' => $code,
            'redirect_uri' => '你的回调URL',
            'grant_type' => 'authorization_code'
        ]
    ]);
    
    if (!is_wp_error($token_response)) {
        $token_data = json_decode(wp_remote_retrieve_body($token_response), true);
        // 加密存储令牌,避免明文泄露
        update_user_meta(get_current_user_id(), 'google_calendar_access_token', wp_encrypt($token_data['access_token']));
        update_user_meta(get_current_user_id(), 'google_calendar_refresh_token', wp_encrypt($token_data['refresh_token']));
        update_user_meta(get_current_user_id(), 'google_calendar_token_expires', time() + $token_data['expires_in']);
    }
    
    wp_redirect(get_edit_user_link(get_current_user_id()));
    exit;
}

令牌自动刷新

访问API前检查令牌有效性,自动刷新过期令牌:

function get_valid_google_calendar_token($user_id) {
    $access_token = wp_decrypt(get_user_meta($user_id, 'google_calendar_access_token', true));
    $refresh_token = wp_decrypt(get_user_meta($user_id, 'google_calendar_refresh_token', true));
    $expires_at = get_user_meta($user_id, 'google_calendar_token_expires', true);
    
    if (time() > $expires_at) {
        $refresh_response = wp_remote_post('https://oauth2.googleapis.com/token', [
            'body' => [
                'client_id' => '你的Google客户端ID',
                'client_secret' => '你的Google客户端密钥',
                'refresh_token' => $refresh_token,
                'grant_type' => 'refresh_token'
            ]
        ]);
        
        if (!is_wp_error($refresh_response)) {
            $new_token_data = json_decode(wp_remote_retrieve_body($refresh_response), true);
            update_user_meta($user_id, 'google_calendar_access_token', wp_encrypt($new_token_data['access_token']));
            update_user_meta($user_id, 'google_calendar_token_expires', time() + $new_token_data['expires_in']);
            return $new_token_data['access_token'];
        } else {
            // 刷新失败,清除旧令牌
            delete_user_meta($user_id, 'google_calendar_access_token');
            delete_user_meta($user_id, 'google_calendar_refresh_token');
            delete_user_meta($user_id, 'google_calendar_token_expires');
            return false;
        }
    }
    
    return $access_token;
}

3. 获取并展示用户日历事件

用短代码实现前端日历展示:

// 短代码:展示用户的Google日历事件
add_shortcode('user_google_calendar', 'user_google_calendar_shortcode');
function user_google_calendar_shortcode() {
    if (!is_user_logged_in()) {
        return '<p>请登录后查看你的Google日历</p>';
    }
    
    $user_id = get_current_user_id();
    $token = get_valid_google_calendar_token($user_id);
    if (!$token) {
        return '<p>请<a href="' . esc_url(get_edit_user_link($user_id)) . '">连接你的Google日历</a></p>';
    }
    
    // 获取用户日历列表
    $calendar_response = wp_remote_get('https://www.googleapis.com/calendar/v3/users/me/calendarList', [
        'headers' => ['Authorization' => 'Bearer ' . $token]
    ]);
    
    if (is_wp_error($calendar_response)) {
        return '<p>获取日历失败,请稍后重试</p>';
    }
    
    $calendars = json_decode(wp_remote_retrieve_body($calendar_response), true);
    $output = '<h3>我的Google日历</h3><ul>';
    
    foreach ($calendars['items'] as $calendar) {
        // 获取日历最近5条事件
        $events_response = wp_remote_get('https://www.googleapis.com/calendar/v3/calendars/' . urlencode($calendar['id']) . '/events?maxResults=5', [
            'headers' => ['Authorization' => 'Bearer ' . $token]
        ]);
        
        if (!is_wp_error($events_response)) {
            $events = json_decode(wp_remote_retrieve_body($events_response), true);
            $output .= '<li><strong>' . esc_html($calendar['summary']) . '</strong>';
            if (!empty($events['items'])) {
                $output .= '<ul>';
                foreach ($events['items'] as $event) {
                    $start_date = isset($event['start']['date']) ? $event['start']['date'] : $event['start']['dateTime'];
                    $output .= '<li>' . esc_html($event['summary']) . ' - ' . date('Y-m-d H:i', strtotime($start_date)) . '</li>';
                }
                $output .= '</ul>';
            } else {
                $output .= '<p>暂无事件</p>';
            }
            $output .= '</li>';
        }
    }
    
    $output .= '</ul>';
    return $output;
}

4. 安全注意事项

  • 加密存储令牌:绝对禁止明文存储用户的访问/刷新令牌,使用WordPress内置的wp_encrypt/wp_decrypt或自定义加密逻辑
  • 权限控制:所有API请求必须验证用户登录状态,且仅能访问当前用户的令牌数据
  • 错误处理:处理令牌过期、API请求失败等场景,友好引导用户重新授权
  • 最小权限原则:仅申请必要的API权限(只读足够的话就不要申请读写权限)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 14:17:09