使用Refresh Token刷新Uber Access Token时遇invalid_grant错误求助
invalid_grant错误 我之前也碰到过类似的Uber OAuth刷新令牌的坑,咱们一步步拆解可能的问题:
1. CURL请求的POST参数设置冲突
你代码里同时设置了CURLOPT_POST和CURLOPT_CUSTOMREQUEST为POST,这会干扰CURL的默认请求逻辑。CURLOPT_POST本身就会将请求方法设为POST,额外添加CURLOPT_CUSTOMREQUEST反而会导致参数解析异常。
解决办法:删掉CURLOPT_CUSTOMREQUEST这一行,同时把CURLOPT_POST的值改为布尔值true(它不需要字段数量,只需要标识是否用POST方法)。
2. 缺少必要的Content-Type请求头
Uber的OAuth令牌端点明确要求请求的Content-Type为application/x-www-form-urlencoded。虽然CURL在传递字符串形式POST参数时偶尔会自动添加这个头,但在某些场景下可能会失效,导致API无法正确解析你的参数,最终返回invalid_grant。
解决办法:添加一行代码明确设置请求头:
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
3. Refresh Token的存储/读取异常
检查你从数据库读取的MY_REFRESH_TOKEN是否和Uber首次返回的完全一致:有没有多余的空格、换行符,或者存储时被数据库字段长度截断?哪怕是一个字符的差异,都会导致令牌无效。
排查技巧:在代码里加一行var_dump(MY_REFRESH_TOKEN);,对比Uber初始响应里的refresh_token,确认两者完全匹配。
4. 初始授权时未请求offline_access权限范围
Uber的refresh_token只有在初始授权时请求了offline_access scope才会生效。如果你的授权URL里没加这个范围,哪怕拿到了refresh_token,也无法用来刷新令牌。
确认方式:检查你获取auth code的授权URL,确保包含scope=offline_access(可以和其他需要的scope用逗号分隔,比如scope=request receipt offline_access)。
修改后的完整代码示例
function refreshToken() { $url = 'https://login.uber.com/oauth/v2/token'; $fields = array( 'client_id' => MY_CLIENT_ID, 'client_secret' => MY_CLIENT_SECRET, 'grant_type' => "refresh_token", 'refresh_token' => MY_REFRESH_TOKEN ); // 用http_build_query自动处理参数编码,比手动拼接更可靠 $fields_string = http_build_query($fields); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_VERBOSE, true); // 添加Content-Type请求头 curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/x-www-form-urlencoded' )); $result = curl_exec($ch); // 新增CURL错误排查 if(curl_errno($ch)){ echo 'CURL Error: ' . curl_error($ch); } curl_close($ch); return $result; }
另外,你可以通过CURL的VERBOSE输出,查看完整的请求和响应细节,Uber有时候会在返回的JSON里给出invalid_grant更具体的错误描述,有助于进一步定位问题。
内容的提问来源于stack exchange,提问作者Andrei Fiordean

