You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

PHP中使用Access Token访问Microsoft Graph API的SDK问题咨询

问题1:InMemoryAccessTokenCache初始化错误解决

错误原因

你传入的AccessToken参数中,expires使用了相对过期时间(3600秒),但AccessToken类要求该值为绝对时间戳(从Unix纪元开始的秒数)。另外,用包含一次性授权码的AuthorizationCodeContext初始化缓存,也会导致缓存键生成失败。

修正步骤

  1. 正确构造AccessToken实例,将expires改为绝对时间戳:
    $accessToken = new AccessToken([
        'access_token' => $token->access_token,
        'refresh_token' => $token->refresh_token,
        'expires' => time() + 3600 // 当前时间加上有效期,生成绝对时间戳
    ]);
    
  2. 使用RefreshTokenContext替代AuthorizationCodeContext初始化缓存,避免授权码干扰:
    $tokenRequestContext = new RefreshTokenContext(
        "tenantId",
        "clientId",
        "clientSecret",
        $token->refresh_token // 直接传入已获取的refresh_token
    );
    
  3. 重新初始化缓存与客户端:
    $cache = new InMemoryAccessTokenCache($tokenRequestContext, $accessToken);
    $client = GraphServiceClient::createWithAuthenticationProvider(
        GraphPhpLeagueAuthenticationProvider::createWithAccessTokenProvider(
            GraphPhpLeagueAccessTokenProvider::createWithCache(
                $cache,
                $tokenRequestContext,
                ["offline_access", "user.read", "mail.read", "mail.send", "mail.readbasic", "mail.readwrite", "imap.accessasuser.all", "smtp.send"]
            )
        )
    );
    
问题2:解决仅能发起一次请求、后续"Invalid grant"错误

错误原因

授权码(authCode)是一次性使用凭证,用它获取令牌后授权码立即失效,重复使用会触发"Invalid grant"错误。

实现多次请求的方案

  1. 持久化存储refresh_token:首次用授权码获取到access_tokenrefresh_token后,将refresh_token保存到数据库、文件等持久化介质,不要每次请求都用授权码初始化客户端。
  2. 用RefreshTokenContext初始化客户端:后续请求直接读取保存的refresh_token创建RefreshTokenContext,SDK会自动在access_token过期时,用refresh_token刷新获取新令牌,无需手动处理。
  3. 使用持久化缓存(可选):如果需要跨会话保持令牌,不要用InMemoryAccessTokenCache,改用基于数据库或文件的自定义缓存类,确保令牌在多次请求间保留并自动刷新。

完整示例代码

首次获取并保存refresh_token(仅执行一次)

// 首次用授权码获取令牌
$tokenRequestContext = new AuthorizationCodeContext(
    "tenantId",
    "clientId",
    "clientSecret",
    "authCode",
    "redirectUrl"
);
$tokenProvider = new GraphPhpLeagueAccessTokenProvider($tokenRequestContext, ["offline_access", "user.read", "mail.read"]);
$accessToken = $tokenProvider->getAccessToken();

// 自定义函数:将refresh_token保存到持久化存储
saveRefreshToken($accessToken->getRefreshToken());

后续多次请求使用refresh_token

// 自定义函数:从持久化存储读取refresh_token
$savedRefreshToken = getSavedRefreshToken();

// 用refresh_token创建上下文
$tokenRequestContext = new RefreshTokenContext(
    "tenantId",
    "clientId",
    "clientSecret",
    $savedRefreshToken
);

// 初始化缓存与令牌提供者
$cache = new InMemoryAccessTokenCache($tokenRequestContext);
$tokenProvider = GraphPhpLeagueAccessTokenProvider::createWithCache(
    $cache,
    $tokenRequestContext,
    ["offline_access", "user.read", "mail.read", "mail.send", "mail.readbasic", "mail.readwrite", "imap.accessasuser.all", "smtp.send"]
);

// 创建客户端并发起多次请求
$client = GraphServiceClient::createWithAuthenticationProvider(
    GraphPhpLeagueAuthenticationProvider::createWithAccessTokenProvider($tokenProvider)
);

// 第一次请求
$me = $client->me()->get()->wait();
// 第二次请求(自动处理令牌刷新)
$messages = $client->me()->messages()->get()->wait();

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

火山引擎 最新活动