WordPress对接Google Calendar实现简易班次预约系统的方案咨询
极简班次预约工具实现方案
前期准备
- 开通Google Cloud账号,创建新项目后启用Google Calendar API,生成服务账号密钥(JSON格式),记录服务账号对应的邮箱地址
- 打开你要同步的目标Google Calendar的日历设置,在共享权限中添加上述服务账号邮箱,授予编辑权限,否则无法写入预约事件
- 记录目标日历的ID,后续API调用会用到
- 确认WordPress站点的时区与Google Calendar的时区保持一致,避免出现时间偏移问题
核心功能实现
所有代码可以直接写在当前主题的functions.php文件中,或者单独封装为自定义插件使用。
1. 接入Google Calendar API
引入Google官方API客户端,你可以通过Composer安装,也可以直接引入官方打包好的phar文件。封装获取日历忙碌时段的函数:
function get_google_busy_slots($start_time, $end_time) { // 加载服务账号密钥 $client = new Google_Client(); $client->setApplicationName('Shift Booking'); $client->setScopes(Google_Service_Calendar::CALENDAR); $client->setAuthConfig('你的服务账号密钥文件路径'); $service = new Google_Service_Calendar($client); // 查询忙碌时段 $freebusy_req = new Google_Service_Calendar_FreeBusyRequest(); $freebusy_req->setTimeMin($start_time->format(DateTime::RFC3339)); $freebusy_req->setTimeMax($end_time->format(DateTime::RFC3339)); $item = new Google_Service_Calendar_FreeBusyRequestItem(); $item->setId('你的目标日历ID'); $freebusy_req->setItems([$item]); $response = $service->freebusy->query($freebusy_req); $calendars = $response->getCalendars(); $busy_slots = $calendars['你的目标日历ID']->getBusy(); return $busy_slots; }
2. 生成可用班次列表
封装函数生成指定天数内的可选班次:
function get_available_shifts($days = 14) { $now = new DateTime(); $end_date = (clone $now)->modify("+{$days} days"); $busy_slots = get_google_busy_slots($now, $end_date); $available = []; for ($i = 0; $i < $days; $i++) { $current_date = (clone $now)->modify("+{$i} days"); $weekday = $current_date->format('N'); // 判断是工作日还是周末,设置对应时段 if ($weekday >=1 && $weekday <=5) { $shift_start = (clone $current_date)->setTime(17,0,0); $shift_end = (clone $current_date)->setTime(20,0,0); } else { $shift_start = (clone $current_date)->setTime(10,0,0); $shift_end = (clone $current_date)->setTime(13,0,0); } // 排除已过去的时段 if ($shift_start < $now) continue; // 检查是否和忙碌时段重叠 $is_busy = false; foreach ($busy_slots as $slot) { $b_start = new DateTime($slot->start); $b_end = new DateTime($slot->end); if (($shift_start < $b_end) && ($shift_end > $b_start)) { $is_busy = true; break; } } if (!$is_busy) { $available[] = [ 'start' => $shift_start->format('Y-m-d H:i:s'), 'end' => $shift_end->format('Y-m-d H:i:s'), 'label' => $shift_start->format('Y-m-d H:i') . ' - ' . $shift_end->format('H:i') ]; } } return $available; }
3. 注册预约短代码
注册短代码用于前端展示预约界面,不需要自定义页面模板的话直接在任意页面插入短代码即可使用:
add_shortcode('booking_shift', 'render_booking_shift'); function render_booking_shift() { if (!is_user_logged_in()) { return '<p>请先登录后再进行预约</p>'; } $shifts = get_available_shifts(); if (empty($shifts)) { return '<p>当前暂无可用班次,请稍后再试</p>'; } // 输出预约表单 $html = '<form method="post" action="' . admin_url('admin-post.php') . '">'; $html .= wp_nonce_field('booking_shift_action', 'booking_nonce', true, false); $html .= '<input type="hidden" name="action" value="submit_booking">'; $html .= '<label>选择可用班次:</label>'; $html .= '<select name="selected_shift" required>'; foreach ($shifts as $index => $shift) { $html .= '<option value="'.$index.'">'.$shift['label'].'</option>'; } $html .= '</select>'; $html .= '<button type="submit">确认预约</button>'; $html .= '</form>'; return $html; }
4. 处理预约提交逻辑
绑定钩子处理表单提交,自动同步事件到Google Calendar:
add_action('admin_post_submit_booking', 'handle_booking_submit'); add_action('admin_post_nopriv_submit_booking', 'handle_booking_submit'); function handle_booking_submit() { // 校验登录状态和请求合法性 if (!is_user_logged_in() || !wp_verify_nonce($_POST['booking_nonce'], 'booking_shift_action')) { wp_redirect(wp_get_referer() . '?booking_status=error'); exit; } // 获取可用班次列表,校验选中班次合法性 $shifts = get_available_shifts(); $selected_index = intval($_POST['selected_shift']); if (!isset($shifts[$selected_index])) { wp_redirect(wp_get_referer() . '?booking_status=invalid'); exit; } $selected_shift = $shifts[$selected_index]; $current_user = wp_get_current_user(); $event_name = $current_user->display_name; // 直接取用户资料的全名,用户无法修改 // 调用Google Calendar API插入事件 $client = new Google_Client(); $client->setAuthConfig('你的服务账号密钥文件路径'); $client->setScopes(Google_Service_Calendar::CALENDAR); $service = new Google_Service_Calendar($client); $event = new Google_Service_Calendar_Event([ 'summary' => $event_name, 'start' => ['dateTime' => (new DateTime($selected_shift['start']))->format(DateTime::RFC3339)], 'end' => ['dateTime' => (new DateTime($selected_shift['end']))->format(DateTime::RFC3339)], 'transparency' => 'opaque' // 标记为忙碌状态 ]); try { $service->events->insert('你的目标日历ID', $event); wp_redirect(wp_get_referer() . '?booking_status=success'); } catch (Exception $e) { wp_redirect(wp_get_referer() . '?booking_status=fail'); } exit; }
可选调整
- 如果需要用日历组件展示班次,可在短代码输出部分引入轻量日历JS库,将可用班次标注为可点击选项,无需用户下拉选择
- 可在页面中添加状态判断,根据URL的
booking_status参数展示对应成功/失败提示 - 可添加用户预约次数限制,避免恶意占用班次
内容的提问来源于stack exchange,提问作者user17604307
相关产品推荐
相关产品推荐

