无法连接Microsoft Bookings API:WordPress集成403权限问题
解决Microsoft Bookings数据拉取的403权限错误
核心问题分析
你遇到的403 ErrorAccessDenied错误主要来自三个方面:权限配置不匹配、代码语法错误、API端点使用不当。
分步解决方案
1. 修正权限配置
/me/calendar/getSchedule接口需要委派权限:
- 必须为应用添加
Calendars.Read或Calendars.ReadWrite权限(不能仅添加Bookings相关权限) - 确保管理员已对该权限授予租户级同意(密码流需要显式的管理员同意)
- 注意:密码流仅支持工作/学校账户,个人微软账户无法使用此授权方式,且账户不能启用MFA。
2. 修复代码语法错误
你的getAccessToken函数中,Guzzle客户端实例化存在语法错误:
// 错误写法 $client = new GuzzleHttp Client(); // 正确写法 $client = new GuzzleHttp\Client();
3. 调整API端点(针对Bookings业务日历)
如果要拉取的是Microsoft Bookings的业务日历数据,而非用户个人日历,应该使用Bookings专属API端点,而非getSchedule:
// 替换原端点 $bookingsEndpoint = "https://graph.microsoft.com/v1.0/bookings/businesses/{$businessId}/calendarView?startDateTime={$start}&endDateTime={$end}"; // 请求方式改为GET $response = $client->request('GET', $bookingsEndpoint, [ 'headers' => [ 'Authorization' => "Bearer $accessToken", 'Content-Type' => 'application/json' ] ]);
完整修正后的代码
<?php require 'vendor/autoload.php'; use GuzzleHttp\Client; use GuzzleHttp\Exception\RequestException; function bookings_init($calendar){ $clientId = "MY_CLIENT_ID"; $clientSecret = "MY_SECRET_ID"; $tenantId = "MY_TENANT_ID"; $username = "MY_USER_EMAIL"; $password = "MY_PASSWORD"; $accessToken = getAccessToken($clientId, $clientSecret, $tenantId, $username, $password); if ($accessToken) { $businessId = "BUSINESS_ID"; $start = urlencode("2023-09-25T08:00:00Z"); $end = urlencode("2023-10-25T17:00:00Z"); $bookingsData = retrieveBookingsData($accessToken, $businessId, $start, $end); if ($bookingsData) { var_dump($bookingsData); } } } function getAccessToken($clientId, $clientSecret, $tenantId, $username, $password){ try { $client = new GuzzleHttp\Client(); $response = $client->post("https://login.microsoftonline.com/{$tenantId}/oauth2/v2.0/token", [ 'form_params' => [ 'grant_type' => 'password', 'client_id' => $clientId, 'client_secret' => $clientSecret, 'scope' => 'https://graph.microsoft.com/.default', 'username' => $username, 'password' => $password ], ]); $body = $response->getBody(); $data = json_decode($body, true); return $data['access_token'] ?? null; } catch (RequestException $e) { echo "获取Token失败:{$e->getMessage()}"; return null; } } function retrieveBookingsData($accessToken, $businessId, $start, $end) { $bookingsEndpoint = "https://graph.microsoft.com/v1.0/bookings/businesses/{$businessId}/calendarView?startDateTime={$start}&endDateTime={$end}"; $client = new GuzzleHttp\Client(); try { $response = $client->request('GET', $bookingsEndpoint, [ 'headers' => [ 'Authorization' => "Bearer {$accessToken}", 'Content-Type' => 'application/json' ] ]); $body = $response->getBody(); return json_decode($body->getContents(), true); } catch (RequestException $e) { $errorResponse = $e->getResponse() ? $e->getResponse()->getBody()->getContents() : "无响应内容"; echo "HTTP请求失败,状态码{$e->getCode()}。响应:{$errorResponse}"; return false; } }
额外注意事项
- 密码流(Resource Owner Password Credentials)是Microsoft不推荐的授权方式,建议后续切换为授权码流(Authorization Code Flow)以提升安全性
- 确保使用的账户拥有访问目标Bookings业务日历的权限(需在Bookings中添加该用户为业务成员)
内容的提问来源于stack exchange,提问作者Yous
相关产品推荐
相关产品推荐

