PHP调用Facebook Graph API时access token过期问题如何解决?
问题原因
你遇到的报错是因为当前使用的是Facebook默认的短期用户访问令牌,这类令牌的默认有效期仅为1~2小时,所以运行一段时间后就会过期失效,不需要每次请求都刷新或重新生成token,只需要在令牌过期/即将过期时更新即可。
具体操作步骤
1. 先将短期令牌兑换为60天有效期的长期用户令牌
你可以直接在服务端发起请求兑换长期令牌,请求参数如下:
- 端点地址:
https://graph.facebook.com/v11.0/oauth/access_token - 请求方式:GET
- 所需参数:
grant_type:固定值为fb_exchange_tokenclient_id:你的Facebook应用IDclient_secret:你的Facebook应用密钥fb_exchange_token:你当前持有的短期访问令牌
PHP兑换示例代码:
function exchangeLongLivedToken($shortToken, $clientId, $clientSecret) { $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch, CURLOPT_URL, 'https://graph.facebook.com/v11.0/oauth/access_token?'.http_build_query([ 'grant_type' => 'fb_exchange_token', 'client_id' => $clientId, 'client_secret' => $clientSecret, 'fb_exchange_token' => $shortToken ])); $res = json_decode(curl_exec($ch), true); curl_close($ch); // 长期令牌存在返回的access_token字段中,同时会返回expires_in有效期秒数 return $res['access_token'] ?? false; }
拿到长期令牌后存在服务端本地即可,不需要每次请求都兑换。
2. 新增令牌失效的自动处理逻辑
在你原有拉取动态的代码中新增错误判断,当捕获到code=190且error_subcode=463的过期错误时,再触发令牌刷新逻辑即可:
$accessToken = "你存储的长期令牌"; $clientId = "你的应用ID"; $clientSecret = "你的应用密钥"; $ch = curl_init(); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_TIMEOUT, 30); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch, CURLOPT_URL, 'https://graph.facebook.com/v11.0/me/feed?'.http_build_query( array( "limit" => "3", "fields" => "attachments,created_time", "access_token" => $accessToken ))); $response = json_decode(curl_exec($ch),true); curl_close($ch); // 新增错误判断 if (isset($response['error'])) { $err = $response['error']; // 令牌过期时重新兑换 if ($err['code'] == 190 && $err['error_subcode'] == 463) { $newToken = exchangeLongLivedToken($accessToken, $clientId, $clientSecret); if ($newToken) { // 将新的长期令牌更新到本地存储,再重新发起拉取请求即可 $accessToken = $newToken; // 这里重新执行拉取动态的逻辑即可 } else { // 兑换失败说明用户撤销了授权/应用权限变更,需要引导用户重新授权获取新的短期令牌再兑换 } } }
注意事项
client_secret属于应用敏感信息,只能存储在服务端,绝对不能暴露在前端代码中- 长期令牌的有效期为60天,有效期内如果用户修改Facebook密码、撤销应用授权、你的应用权限发生变更,令牌也会提前失效,这种情况下需要引导用户重新授权获取新的短期令牌,再兑换为长期令牌使用
- 不需要每次接口请求都刷新令牌,仅在捕获到过期错误时触发刷新即可,避免不必要的请求消耗
内容的提问来源于stack exchange,提问作者Trombone0904
相关产品推荐
相关产品推荐

