如何实现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
相关产品推荐
相关产品推荐

