[英]Unable to POST request using guzzle with the Amadeus API
描述
我正在尝试将 Amadeus 自助服务 API 集成到 Laravel 环境中。 我可以通过GET
请求成功获取内容,但无法通过POST
请求获取内容。 我已经设置了异常来具体显示 guzzle 抛出的错误。
这是 api 参考,其中包含我要发布到的数据和端点。 https://developers.amadeus.com/self-service/category/air/api-doc/flight-offers-search/api-reference
如何重现
这是我从我的 Client.php 调用并通过调用 POST 方法传递数据的方法。
public function __construct() {
throw_if(static::$instance, 'There should be only one instance of this class');
static::$instance = $this;
$this->client = new Client([
'base_uri' => 'https://test.api.amadeus.com/',
]);
}
public function get($uri, array $options = []) {
$this->authenticate();
return $this->client->request('GET', $uri, [
$options,
'headers' => [
'Authorization' => 'Bearer '.$this->access_token,
],
]);
}
public function post($uri, array $options = []) {
$this->authenticate();
return $this->client->request('POST', $uri, [
$options,
'headers' => [
'Authorization' => 'Bearer '.$this->access_token,
],
]);
}
调用 POST 方法后,我将“X-HTTP-Method-Override”作为“GET”传递,并将数据作为正文传递。
$requests_response = $client->post('v2/shopping/flight-offers', [
'headers' => [
'X-HTTP-Method-Override' => 'GET',
],
'body' => [
[
"currencyCode" => "USD",
"originDestinations" => [
[
"id" => "1",
"originLocationCode" => "RIO",
"destinationLocationCode" => "MAD",
"departureDateTimeRange" => [
"date" => "2022-11-01",
"time" => "10:00:00",
],
],
[
"id" => "2",
"originLocationCode" => "MAD",
"destinationLocationCode" => "RIO",
"departureDateTimeRange" => [
"date" => "2022-11-05",
"time" => "17:00:00",
],
],
],
"travelers" => [
["id" => "1", "travelerType" => "ADULT"],
["id" => "2", "travelerType" => "CHILD"],
],
"sources" => ["GDS"],
"searchCriteria" => [
"maxFlightOffers" => 2,
"flightFilters" => [
"cabinRestrictions" => [
[
"cabin" => "BUSINESS",
"coverage" => "MOST_SEGMENTS",
"originDestinationIds" => ["1"],
],
],
"carrierRestrictions" => [
"excludedCarrierCodes" => ["AA", "TP", "AZ"],
],
],
],
],
],
]);
附加上下文
这是我在日志中发现的错误。
local.ERROR: Guzzle error {"response":{"GuzzleHttp\\Psr7\\Stream":"
{
\"errors\": [
{
\"code\": 38189,
\"title\": \"Internal error\",
\"detail\": \"An internal error occurred, please contact your administrator\",
\"status\": 500
}
]
}
"}}
local.ERROR: Server error: POST https://test.api.amadeus.com/v2/shopping/flight-offers resulted in a 500 Internal Server Error response:
{
"errors": [
"code": 38189,
(truncated...)
"exception":"[object] (GuzzleHttp\\Exception\\ServerException(code: 500): Server error: POST https://test.api.amadeus.com/v2/shopping/flight-offers resulted in a 500 Internal Server Error response:
"errors": [
"code": 38189,
(truncated...)
at C:\\xampp\\htdocs\\Application\\vendor\\guzzlehttp\\guzzle\\src\\Exception\\RequestException.php:113)
请花点时间看看,非常感谢帮助。
POST 调用是否真的使用 HTTP 客户端(如 Postman 或 Insomnia)工作?
我注意到您正在传递一组$options
并将其嵌套在 Guzzle 选项中。 生成的调用将如下所示:
$this->client->request('POST', $uri, [
['headers' => '...', 'body' => ['...']],
'headers' => ['...']
]);
那行不通,您将需要以这种方式解压缩它们:
public function post($uri, array $options = []) {
$this->authenticate();
return $this->client->request('POST', $uri, [
...$options,
'headers' => [
'Authorization' => 'Bearer '.$this->access_token,
],
]);
}
注意点...
以解压缩选项数组。 另请注意,您将headers
键设置了两次(一次在您的 post 方法定义中,一次在 options 参数中),因此实际上只会使用一个(顺便说一下,您为什么要使用X-HTTP-Method-Override
标头?)。
如果要在 POST 函数参数中传递所有标头和正文,另一种解决方案是:
public function post($uri, array $options = []) {
$this->authenticate();
return $this->client->request('POST', $uri, [
'json' => $options['json'], // I would suggest 'json' because it looks like the API is looking for a JSON body, if that doesn't work go with 'body'
'headers' => [
'Authorization' => 'Bearer '.$this->access_token,
...$options['headers']
],
]);
}
如果不这样做,您可能会尝试的另一件事是使用 Guzzle json
选项而不是 POST 请求的body
。
当您探索任何 Amadeus Self Service API 时,我建议您查看门户,因为它会帮助您了解如何进行 http 调用。
在您的情况下: https ://developers.amadeus.com/self-service/category/air/api-doc/flight-offers-search/api-reference
另一个帮助可能是查看编码示例:
也许有点晚了,但这个例子对我有用:
$options = [
'headers' => [
'Authorization' => sprintf('Bearer %s', $this->getApiToken()),
'content-type' => 'application/vnd.amadeus+json',
'X-HTTP-Method-Override' => 'GET',
],
'body' => '{
"currencyCode": "XPF",
"originDestinations": [
{
"id": 1,
"originLocationCode": "PPT",
"originRadius": null,
"alternativeOriginsCodes": [],
"destinationLocationCode": "CDG",
"alternativeDestinationsCodes": [],
"departureDateTimeRange": {
"date": "2022-12-22",
"dateWindow": "I2D"
},
"includedConnectionPoints": [],
"excludedConnectionPoints": []
}
],
"travelers": [
{
"id": "1",
"travelerType": "ADULT",
"associatedAdultId": null
}
],
"sources": [
"GDS"
]
}'
];
try {
...
$response = $this->httpClient->post(self::AMADEUS_API_URL_FLIGHT_OFFER, $options);
$body = $response->getBody();
...
注意:不要忘记内容类型,乍一看在文档中不是很明显,但没有它对我来说不适用于 Guzzle(但失眠没问题)
class 的常量:
private const AMADEUS_API_CLIENT_GRANT_TYPE = 'client_credentials';
private const AMADEUS_API_URL_AUTH = '/v1/security/oauth2/token';
private const AMADEUS_API_URL_FLIGHT_OFFER = '/v2/shopping/flight-offers';
验证:
/**
*
*/
public function authenticate()
{
if (!is_null($this->getApiToken())) {
return $this->getApiToken();
}
$options = [
'form_params' => [
'client_id' => $this->apiId, //setted in the parent construct
'client_secret' => $this->apiKey, //setted in the parent construct
'grant_type' => self::AMADEUS_API_CLIENT_GRANT_TYPE,
]
];
try {
$response = $this->httpClient->post(self::AMADEUS_API_URL_AUTH, $options);
} catch (ClientExceptionInterface $exception) {
...
}
if ($response->getStatusCode() != Response::HTTP_OK) {
throw new ApiException($errorMessage, [$response->getReasonPhrase()], $response->getStatusCode());
}
$body = $response->getBody();
//custom serializer, AmadeusAuthenticationResponse is a mapping based on Amadeus authentication response
$authenticationResponse = $this->serializer->convertSerializationToData($body->getContents(), AmadeusAuthenticationResponse::class);
$this->setApiToken($authenticationResponse->getAccessToken());
return $this->getApiToken();
}';
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.