PHP cURL重复请求致MercadoLibre OAuth令牌获取失败
Mercado Libre OAuth Token 获取报错修复方案
问题场景
向https://api.mercadolibre.com/oauth/token发送POST请求,传入新生成的授权code获取access token时,返回错误:
{"cause":[],"error":"invalid_grant","error_description":"Error validating grant. Your authorization code or refresh token may be expired or it was already used","status":400}
问题根源
自定义Request类的httpRequest方法里有两次curl_exec($curl)调用,导致请求被重复发送:第一次请求成功拿到token,但授权code已被消耗;第二次请求因为code已使用,返回上述错误。
修复代码
修改Request类的httpRequest方法,移除重复的curl_exec调用,保留一次执行并正确处理错误:
class Request { private function httpRequest( string $method, string $url, array $headers, array $data=array() ) { $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => $method, CURLOPT_HTTPHEADER => $headers )); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($curl, CURLOPT_HEADER, 0); if ($method != "GET" && $data) { curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data)); } // 仅执行一次curl请求,统一处理错误 $response = curl_exec($curl); if (curl_errno($curl)) { $error = curl_errno($curl)." - ".curl_error($curl); } elseif ($response === false) { trigger_error(curl_error($curl)); } curl_close($curl); if (isset($error)) { return $error; } return $response; } // 以下get/post/put方法保持不变 public function get( string $url, array $headers, array $data=array() ) { if ($data) { $url = Utils::urlParams($url, $data); } return $this->httpRequest($method = "GET", $url, $headers); } public function post( string $url, array $headers, array $data=array() ) { return $this->httpRequest($method = "POST", $url, $headers, $data); } public function put( string $url, array $headers, array $data ) { return $this->httpRequest($method = "PUT", $url, $headers, $data); } }
修复说明
- 删除原代码中第二次
$response = curl_exec($curl);调用,避免重复发送请求 - 调整错误处理逻辑:先执行请求,再判断curl错误,同时保留原有的
trigger_error处理请求失败场景 - 保持
CURLOPT_RETURNTRANSFER => true,确保响应内容存入$response变量而非直接输出
验证结果
修复后,调用accessToken方法仅发送一次请求,成功返回有效access token:
{"access_token":"APP_USR-731450979634979-062614-76a6db201965f6c18c1108cebc48fb1d-1405568857","token_type":"Bearer","expires_in":21600,"scope":"offline_access read write","user_id":1405568857,"refresh_token":"TG-6499d6c7eea12900019aba4d-1405568857"}
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

