Description
I am trying to integrate Amadeus Self-Service API within the Laravel Environment. I am successfully able to get content by GET request, but I am not able to get content by the POST request. I have set the exceptions to display the errors thrown by the guzzle in specific.
Here is the api reference, which has the data and the endpoint which I want to post to.
https://developers.amadeus.com/self-service/category/air/api-doc/flight-offers-search/api-reference
How to reproduce
This is the method which I call from my Client.php and pass the data through by calling the POST method.
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,
],
]);
}
After calling the POST method, I pass the 'X-HTTP-Method-Override' as 'GET', and pass the data as body.
$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"],
],
],
],
],
],
]);
Additional context
Here is the error, which I caught in the log.
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)
Please spare some time to have a look, help is really appreciated.
Do the POST calls actually work using a HTTP client such as Postman or Insomnia ?
I am noticing is that you are passing an array of $options and are nesting it inside the Guzzle options. The resulting call will look something like this:
$this->client->request('POST', $uri, [
['headers' => '...', 'body' => ['...']],
'headers' => ['...']
]);
That won't work, you are going to need to unpack them this way:
public function post($uri, array $options = []) {
$this->authenticate();
return $this->client->request('POST', $uri, [
...$options,
'headers' => [
'Authorization' => 'Bearer '.$this->access_token,
],
]);
}
Notice the dots ... to unpack the options array. Also notice that you are setting the headers key twice (once in your post method definition and once in the options parameter), so only one will actually be used (by the way why exactly are you using the X-HTTP-Method-Override header ?).
Another solution if you want to pass all header and body in the POST function parameters is this:
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']
],
]);
}
Another thing you might try if this doesn't do it is using the Guzzle json option instead of body for the POST request.
when you are exploring any Amadeus Self Service API, I recommend to review the portal, because it will help you with one idea about how to make the http calls.
In your case:
https://developers.amadeus.com/self-service/category/air/api-doc/flight-offers-search/api-reference
Another help could be to review the coding examples:
https://github.com/amadeus4dev/amadeus-code-examples/blob/master/flight_offers_search/v2/post/curl/
https://github.com/amadeus4dev/amadeus-code-examples/tree/master/flight_offers_search/v2/get/curl
Maybe it's a little late but this example work for me:
$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();
...
Note: don't forget the content-type, it's not very obvious at first sight in the documentation but without it doesnt work with Guzzle for me (but with insomnia no problem)
consts of the 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';
Authentication:
/**
*
*/
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();
}';
https://github.com/paypal/Checkout-PHP-SDK
I downloaded this and i have tested it with simple php but i don't know where to put these files in which folder for CodeIgniter
https://github.com/paypal/Checkout-PHP-SDK/blob/develop/samples/CaptureIntentExamples/RunAll.php
`Creating an Order
Code:
// Construct a request object and set desired parameters
// Here, OrdersCreateRequest() creates a POST request to /v2/checkout/orders
use PayPalCheckoutSdk\Orders\OrdersCreateRequest;
$request = new OrdersCreateRequest();
$request->prefer('return=representation');
$request->body = [
"intent" => "CAPTURE",
"purchase_units" => [[
"reference_id" => "test_ref_id1",
"amount" => [
"value" => "100.00",
"currency_code" => "USD"
]
]],
"application_context" => [
"cancel_url" => "https://example.com/cancel",
"return_url" => "https://example.com/return"
]
];
try {
// Call API with your client and get a response for your call
$response = $client->execute($request);
// If call returns body in response, you can get the deserialized version from the result attribute of the response
print_r($response);
}catch (HttpException $ex) {
echo $ex->statusCode;
print_r($ex->getMessage());
}`.
I am currently using Amazon AWS SNS to send SMS to customers.
SMS works fine however I would like to simply display a success or error message when the form has been submitted depending on the outcome.
result after form submit on successful message below. I can see that statusCode with int(200) means that it was sent successfully. How can I fetch this and use it to display success or error message?
object(Aws\Result)#117(2){
[
"data": "Aws\Result": private
]=>array(2){
[
"MessageId"
]=>string(36)"f12f2261-5e13-54e8-b72e-37s26fd3c348"[
"#metadata"
]=>array(4){
[
"statusCode"
]=>int(200)[
"effectiveUri"
]=>string(35)"https://sns.eu-west-1.amazonaws.com"[
"headers"
]=>array(4){
[
"x-amzn-requestid"
]=>string(36)"716dase5-f048-5d35-8af0-sf36ce583d95"[
"content-type"
]=>string(8)"text/xml"[
"content-length"
]=>string(3)"294"[
"date"
]=>string(29)"Tue, 18 Jun 2019 19:31:28 GMT"
}[
"transferStats"
]=>array(1){
[
"http"
]=>array(1){
[
0
]=>array(0){
}
}
}
}
}[
"monitoringEvents": "Aws\Result": private
]=>array(0){
}
}
php code:
if(isset($_POST['gateeway'])){
$sender_id = $_POST['sender_id'];
$message = $_POST['message'];
$topic = 'arn:aws:sns:eu-west-1:52732446504:Testing';
try {
$result = $sns->publish([
'TargetArn' => $topic,
'Message' => $message,
'MessageAttributes' => [
'AWS.SNS.SMS.SenderID' => [
'DataType' => 'String',
'StringValue' => $sender_id,
],
'AWS.SNS.SMS.SMSType' => [
'DataType' => 'String',
'StringValue' => 'Promotional',
]
]
]);
var_dump($result);
} catch (AwsException $e) {
// output error message if fails
error_log($e->getMessage());
}
}
You can get the status code like this
$metaInfo = $result->get('#metadata');
if($metaInfo ['statusCode'] === 200){
echo "Message Sent";
}
I'm getting data from Couchdb to PHP using Guzzle library. Now I fetch data in POST format like this:
But I need response like this:
{
"status": 200,
"message": "Success",
"device_info": {
"_id": "00ab897bcb0c26a706afc959d35f6262",
"_rev": "2-4bc737bdd29bb2ee386b967fc7f5aec9",
"parent_id": "PV-409",
"child_device_id": "2525252525",
"app_name": "Power Clean - Antivirus & Phone Cleaner App",
"package_name": "com.lionmobi.powerclean",
"app_icon": "https://lh3.googleusercontent.com/uaC_9MLfMwUy6pOyqntqywd4HyniSSxmTfsiJkF2jQs9ihMyNLvsCuiOqrNxNYFq5ko=s3840",
"last_app_used_time": "12:40:04",
"last_app_used_date": "2019-03-12"
"bookmark": "g1AAAABweJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYorGBgkJllYmiclJxkkG5klmhuYJaYlW5paphibppkZmRmB9HHA9BGlIwsAq0kecQ",
"warning": "no matching index found, create an index to optimize query time"
} }
I only remove "docs": [{}] -> Anyone know I remove this ?
check My code:
$response = $client->post(
"/child_activity_stat/_find",
[GuzzleHttp\RequestOptions::JSON => ['selector' => ['parent_id' => ['$eq' => $userid], 'child_device_id' => ['$eq' => $deviceid]],]]
);
if ($response->getStatusCode() == 200) {
$result = json_decode($response->getBody());
$r = $response->getBody();
json_output(200, array(
'status' => 200,
'message' => 'Success',
"device_info" => $result
));
}
You just need to modify your data structure.
NOTE: Maybe you should add a limit of 1 if you want to only get one document. You will also need to validate that the result['docs'] is not empty.
Example:
<?php
$response = $client->post(
"/child_activity_stat/_find",
[GuzzleHttp\ RequestOptions::JSON => ['selector' => ['parent_id' => ['$eq' => $userid], 'child_device_id' => ['$eq' => $deviceid]], ]]
);
if ($response->getStatusCode() == 200) {
// Parse as array
$result = json_decode($response->getBody(),true);
// Get the first document.
$firstDoc = $result['docs'][0];
// Remove docs from the response
unset($result['docs']);
//Merge sanitized $result with $deviceInfo
$deviceInfo = array_merge_recursive($firstDoc,$result);
json_output(200, array(
'status' => 200,
'message' => 'Success',
"device_info" => $deviceInfo
));
}
In couchdb use PUT request is used to edit or to add data and DELETE remove data
$client = new GuzzleHttp\Client();
// Put request for edit
$client->put('http://your_url', [
'body' => [
'parent_id' => ['$eq' => $userid],
'child_device_id' => ['$eq' => $deviceid]
],
'allow_redirects' => false,
'timeout' => 5
]);
// To delete
$client->delete('htt://my-url', [
'body' = [
data
]
]);
I am trying to highlight my results in elastic search-php , I tried a lot with my knowledge and searching in google, but no luck , the same query is working perfectly in Sense. my query in Sense is
GET /bank/account/_search
{
"query" : {
"match_phrase" : {
"address" : "mill"
}
},
"highlight": {
"pre_tags" : ["<tag1>"],
"post_tags" : ["</tag1>"],
"fields" : {
"address" : {}
}
}
}
with above query i get exact result what i needed, this is the result i got
highlight": {
"address": [
"990 <tag1>Mill</tag1> Road"
]
}
i tried the same query using php i am not get the highlighted results my php query is
<?php
require 'vendor/autoload.php';
$client=new Elasticsearch\Client();
$indexParams = [
'index' => 'bank',
'type' => 'account',
'body' => [
'query' => [
'match' => [
"address" => "mill"
],
],
'highlight' => [
"pre_tags" => "<tag1>",
"post_tags" => "</tag1>",
'fields' => [
'address' => new \stdClass()
]
],
]
];
$results = $client->search($indexParams);
try {
$response = $client->search($indexParams);
} catch (Exception $e) {
var_dump($e->getMessage());
}
echo '<pre>',print_r($response),'</pre>';
?>
the result i aam getting is
[highlight] => Array
(
[address] => Array
(
[0] => 715 Mill Avenue
)
)
i got the answer for above question, i am sending parameters in the form of json and JSON encode the result, when i encode the result in JSON at that pre tags are came in highlight query.
my solution is
"highlight": {
"address": [
"817 Campus </span>Road</span>"
]
}