使用GuzzleHttp刷新MS Graph Access Token返回200无响应问题
问题背景
在Microsoft Graph平台通过refresh_token刷新access token,实现逻辑参考微软官方v2.0 OAuth2授权码流文档。在Postman中构造对应请求、替换应用专属键值参数后,已成功获取新令牌。将Postman导出的PHP Guzzle格式代码复制到应用中运行,代码如下:
<?php $client = new Client(); $headers = [ 'Content-Type' => 'application/x-www-form-urlencoded', ]; $options = [ 'form_params' => [ 'client_id' => config('config.microsoft.clientId'), 'scope' => 'user.read', 'redirect_uri' => 'http://localhost:8000/callback', 'grant_type' => 'refresh_token', 'client_secret' => config('config.microsoft.ClientSecret'), 'refresh_token' => config('config.microsoft.RefToken') ]]; $request = new Request('POST', 'https://login.microsoftonline.com/common/oauth2/v2.0/token', $headers); $res = $client->sendAsync($request, $options)->wait(); echo $res;
运行代码后接口返回200状态码,但未获取到微软接口返回的实际内容,打印结果如下:
GuzzleHttp\Psr7\Response {#1514 ▼ -reasonPhrase: "OK" -statusCode: 200 -headers: array:13 [▶] -headerNames: array:13 [▶] -protocol: "1.1" -stream: GuzzleHttp\Psr7\Stream {#1524 ▼ -stream: stream resource @13 ▶} -size: null -seekable: true -readable: true -writable: true -uri: "php://temp" -customMetadata: [] } }
完全相同的请求参数在Postman、cURL中均可正常返回新令牌信息,后续测试PHP原生cURL、PHP HTTP_Request2两种请求方式,也都能在应用中正常获取响应内容,目前临时采用PHP-HTTP_Request2实现需求,需要排查GuzzleHttp出现该问题的原因。
问题原因
直接echo Guzzle返回的响应对象无法获取接口返回内容。
Guzzle的send/sendAsync方法返回的是实现PSR-7规范的Response对象实例,不是接口返回的纯字符串。接口实际返回的令牌内容存储在对象内部的Stream流属性中,直接打印对象只会输出对象的属性结构,不会自动读取流内存储的响应正文。
Postman导出的代码默认只生成基础请求构造逻辑,没有追加读取响应体的代码,才会出现状态码200、请求实际成功但看不到返回内容的情况,请求本身的参数、逻辑没有问题。
修复方案
在拿到响应对象后,主动调用响应对象的方法读取流内的正文内容即可,替换原代码最后一行的echo $res;为以下代码:
// 读取响应正文(JSON格式字符串) $responseContent = $res->getBody()->getContents(); echo $responseContent; // 如果需要直接处理令牌数据,可以直接解析为数组 // $tokenData = json_decode($responseContent, true);
补充说明:
getBody()方法会返回响应对应的Stream实例,调用getContents()即可一次性读取流中存储的全部响应内容- 该读取方式对Guzzle同步请求、异步请求返回的响应对象都生效
- 不需要修改原有请求的参数、请求头配置,原有请求逻辑已经可以正常和微软令牌端点通信
内容的提问来源于stack exchange,提问作者user1738671
相关产品推荐
相关产品推荐

