如何使用Guzzle PHP获取SENT数据的主体


How do I get the body of SENT data with Guzzle PHP?

我在PHP中使用Guzzle(v6.1.1)向服务器发出POST请求。它工作正常。我正在添加一些日志记录函数来记录发送和接收的内容,但我无法弄清楚如何获取 Guzzle 发送到服务器的数据。我可以很好地获得响应,但是如何获取发送的数据?(这将是 JSON 字符串。

这是我代码的相关部分:

$client = new GuzzleHttp'Client(['base_uri' => $serviceUrlPayments ]);
    try {
       $response = $client->request('POST', 'Charge', [
            'auth' => [$securenetId, $secureKey],
            'json' => [     "amount" => $amount,
                            "paymentVaultToken" => array(
                                    "customerId" => $customerId,
                                    "paymentMethodId" => $token,
                                    "publicKey" => $publicKey
                                    ),
                            "extendedInformation" => array(
                                    "typeOfGoods" => $typeOfGoods,
                                    "userDefinedFields" => $udfs,
                                    "notes" => $Notes
                                    ),
                            'developerApplication'=> $developerApplication 
            ]
    ]);
    } catch (ServerErrorResponseException $e) {
        echo (string) $e->getResponse()->getBody();
    }

    echo $response->getBody(); // THIS CORRECTLY SHOWS THE SERVER RESPONSE
    echo $client->getBody();           // This doesn't work
    echo $client->request->getBody();  // nor does this

任何帮助将不胜感激。我确实尝试在 Guzzle 源代码中查找类似于 getBody() 的函数,该函数可以处理该请求,但我不是 PHP 专家,所以我没有想出任何有用的东西。我也搜索了很多谷歌,但发现只有人们在谈论从服务器获取响应,我没有问题。

您可以通过创建中间件来完成这项工作。

use GuzzleHttp'Client;
use GuzzleHttp'HandlerStack;
use GuzzleHttp'Middleware;
use Psr'Http'Message'RequestInterface;
$stack = HandlerStack::create();
// my middleware
$stack->push(Middleware::mapRequest(function (RequestInterface $request) {
    $contentsRequest = (string) $request->getBody();
    //var_dump($contentsRequest);
    return $request;
}));
$client = new Client([
    'base_uri' => 'http://www.example.com/api/',
    'handler' => $stack
]);
$response = $client->request('POST', 'itemupdate', [
    'auth' => [$username, $password],
    'json' => [
        "key" => "value",
        "key2" => "value",
    ]
]);

但是,这会在接收响应之前触发。您可能想要执行以下操作:

$stack->push(function (callable $handler) {
    return function (RequestInterface $request, array $options) use ($handler) {
        return $handler($request, $options)->then(
            function ($response) use ($request) {
                // work here
                $contentsRequest = (string) $request->getBody();
                //var_dump($contentsRequest);
                return $response;
            }
        );
    };
});

使用 Guzzle 6.2。

在过去的几天里,我也一直在为此苦苦挣扎,同时尝试构建一种用于审核与不同 API 的 HTTP 交互的方法。 在我的情况下,解决方案是简单地倒带请求正文。

请求的正文实际上是作为流实现的。 因此,当发送请求时,Guzzle 会从流中读取。 读取完整的流会将流的内部指针移动到末尾。 因此,当您在发出请求后调用getContents()时,内部指针已经位于流的末尾并且不返回任何内容。

解决方案是什么? 将指针倒回开头,然后再次读取流。

<?php
// ...
$body = $request->getBody();
echo $body->getContents(); // -->nothing
// Rewind the stream
$body->rewind();
echo $body->getContents(); // -->The request body :)

从 5.7 开始对 Laravel的解决方案:

MessageFormatter 使用变量替换,请参阅以下内容:https://github.com/guzzle/guzzle/blob/master/src/MessageFormatter.php

     $stack = HandlerStack::create();
        $stack->push(
            Middleware::log(
                Log::channel('single'),
                new MessageFormatter('Req Body: {request}')
            )
     );
    $client = new Client();
    $response = $client->request(
        'POST',
        'https://url.com/go',
        [
            'headers' => [
                "Content-Type" => "application/json",
                'Authorization' => 'Bearer 123'
            ],
            'json' => $menu,
            'handler' => $stack
        ]
    );

您可以通过执行以下命令重现请求创建的数据字符串

$data = array(
    "key" => "value",
    "key2" => "value",
); 
$response = $client->request('POST', 'itemupdate', [
    'auth' => [$username, $password],
    'json' => $data,
]);
// ...
echo json_encode($data);

这会将数据输出为 JSON 字符串。

http://php.net/manual/fr/function.json-encode.php 的文档

编辑

Guzzle有一个Request和一个Response类(以及许多其他课程)。
Request实际上有一个getQuery()方法,该方法将包含data的对象作为私有对象返回,与所有其他成员相同。
您也无法访问它。

这就是为什么我认为手动编码它是更简单的解决方案。如果你想知道 Guzzle 做了什么,它还有一个 Collection 类来转换数据并在请求中发送数据。