I am trying to call a shiplogic API (based in AWS), but I get 400 Bad Request
error.
I have tried various ways to request response from the AWS API such as S3, I have tried creating my own signature for a cURL request, and now I am trying this code.
$host = "api.shiplogic.com";
$accessKey = 'AKIA55D****';
$secretKey = 'cx0WDJLNj1Bmn2**';
$requestUrl = 'https://api.shiplogic.com';
$uri = '/tracking/shipments';
$httpRequestMethod = 'GET';
$data = '{"tracking_reference": "M3RPH"}';
require 'AWS/aws-autoloader.php';;
use AwsSignatureSignatureV4;
use AwsCredentialsCredentials;
use GuzzleHttpClient;
use GuzzleHttpPsr7Request;
use PsrHttpClientClientInterface;
$signature = new SignatureV4('execute-api', 'af-south-1');
$credentials = new Credentials($accessKey, $secretKey);
$psr7Request = new Request($httpRequestMethod, $requestUrl.$uri, ["content-type"=>"application/json"], $data);
$client = new Client([$requestUrl, 'timeout' => 30]);
$sr = $signature->signRequest($psr7Request, $credentials);
$response = $client->send($sr);
var_dump($response);
The short error is: PHP Fatal error: Uncaught GuzzleHttpExceptionClientException: Client error: GET https://api.shiplogic.com/tracking/shipments resulted in a 400 Bad Request response: Invalid or incomplete input
The full error is:
PHP Fatal error: Uncaught GuzzleHttpExceptionClientException: Client error: `GET https://api.shiplogic.com/tracking/shipments` resulted in a `400 Bad Request` response:
Invalid or incomplete input
in /home/path/myurl.com/path/AWS/GuzzleHttp/Exception/RequestException.php:113
Stack trace:
#0 /home/path/myurl.com/path/AWS/GuzzleHttp/Middleware.php(65): GuzzleHttpExceptionRequestException::create()
#1 /home/path/myurl.com/path/AWS/GuzzleHttp/Promise/Promise.php(204): GuzzleHttpMiddleware::GuzzleHttp{closure}()
#2 /home/path/myurl.com/path/AWS/GuzzleHttp/Promise/Promise.php(153): GuzzleHttpPromisePromise::callHandler()
#3 /home/path/myurl.com/path/AWS/GuzzleHttp/Promise/TaskQueue.php(48): GuzzleHttpPromisePromise::GuzzleHttpPromise{closure}()
#4 /home/path/myurl.com/path/AWS/GuzzleHttp/Promise/Promise.php(248): GuzzleHttpPromiseTaskQueue->run()
#5 /home/path/myurl.com/path/AWS/GuzzleHttp/Promise/Promise.php(224): GuzzleHttpPromisePromise->invokeWaitFn()
#6 /home/path/myurl.com/path/AWS/GuzzleHttp/Promise/Promise.php(269): GuzzleHttpPromisePromise->waitIfPending()
#7 /home/path/myurl.com/path/AWS/GuzzleHttp/Promise/Promise.php(226): GuzzleHttpPromisePromise->invokeWaitList()
#8 /home/path/myurl.com/path/AWS/GuzzleHttp/Promise/Promise.php(62): GuzzleHttpPromisePromise->waitIfPending()
#9 /home/path/myurl.com/path/AWS/GuzzleHttp/Client.php(129): GuzzleHttpPromisePromise->wait()
#10 /home/path/myurl.com/path/apiSign.php(22): GuzzleHttpClient->send()
#11 {main}
thrown in /home/path/myurl.com/path/AWS/GuzzleHttp/Exception/RequestException.php on line 113
EDIT:
Screenshot of cURL created by Postman
EDIT 2
Response from using $psr7Request = new Request($httpRequestMethod, $requestUrl.$uri.'?tracking_reference=M3RPH');
GuzzleHttpPsr7Response Object
(
[reasonPhrase:GuzzleHttpPsr7Response:private] => OK
[statusCode:GuzzleHttpPsr7Response:private] => 200
[headers:GuzzleHttpPsr7Response:private] => Array
(
[Date] => Array
(
[0] => Sat, 30 Jul 2022 09:08:57 GMT
)
[Content-Type] => Array
(
[0] => application/json
)
[Content-Length] => Array
(
[0] => 743
)
[Connection] => Array
(
[0] => keep-alive
)
[Ship-Logic-Request-Id] => Array
(
[0] => e78565f7-3a63-4831-8cdd-f4c720c13f06
)
[Apigw-Requestid] => Array
(
[0] => WEs-jjI6ifMEPcQ=
)
)
[headerNames:GuzzleHttpPsr7Response:private] => Array
(
July 28, 2022 => Date
[content-type] => Content-Type
[content-length] => Content-Length
[connection] => Connection
[ship-logic-request-id] => Ship-Logic-Request-Id
[apigw-requestid] => Apigw-Requestid
)
[protocol:GuzzleHttpPsr7Response:private] => 1.1
[stream:GuzzleHttpPsr7Response:private] => GuzzleHttpPsr7Stream Object
(
[stream:GuzzleHttpPsr7Stream:private] => Resource id #45
[size:GuzzleHttpPsr7Stream:private] =>
[seekable:GuzzleHttpPsr7Stream:private] => 1
[readable:GuzzleHttpPsr7Stream:private] => 1
[writable:GuzzleHttpPsr7Stream:private] => 1
[uri:GuzzleHttpPsr7Stream:private] => php://temp
[customMetadata:GuzzleHttpPsr7Stream:private] => Array
(
)
)
)
POSTMAN response from the same call:
{
"shipments": [
{
"provider_id": 10,
"shipment_id": 14135,
"short_tracking_reference": "G9G",
"status": "cancelled",
"shipment_time_created": "2021-05-21T12:12:03.365338Z",
"shipment_time_modified": "2022-05-31T14:00:34.375688Z",
"shipment_collected_date": null,
"shipment_delivered_date": null,
"collection_from": "uAfrica.com",
"delivery_to": "",
"collection_hub": "Gauteng",
"delivery_hub": "Gauteng",
"service_level_code": "ECO",
"tracking_events": [
{
"id": 1940829,
"parcel_id": 0,
"date": "2021-11-22T14:21:00.000529Z",
"status": "delivered",
"source": "corneladmin",
"message": ""
},
{
"id": 1940828,
"parcel_id": 0,
"date": "2021-11-22T14:20:59.925068Z",
"status": "collected",
"source": "corneladmin",
"message": ""
},
{
"id": 1940812,
"parcel_id": 0,
"date": "2021-11-22T14:20:45.323472Z",
"status": "delivered",
"source": "corneladmin",
"message": ""
},
{
"id": 1940811,
"parcel_id": 0,
"date": "2021-11-22T14:20:45.317556Z",
"status": "collected",
"source": "corneladmin",
"message": ""
},
{
"id": 1940755,
"parcel_id": 0,
"date": "2021-11-22T14:19:12.481537Z",
"status": "delivered",
"source": "corneladmin",
"message": ""
},
{
"id": 1940754,
"parcel_id": 0,
"date": "2021-11-22T14:19:12.462331Z",
"status": "collected",
"source": "corneladmin",
"message": ""
},
{
"id": 1940726,
"parcel_id": 0,
"date": "2021-11-22T14:18:37.02554Z",
"status": "delivered",
"source": "sandbox-admin",
"lat": -25.806655,
"lng": 28.334732,
"message": "POD files captured"
},
{
"id": 1940725,
"parcel_id": 0,
"date": "2021-11-22T14:18:37.011858Z",
"status": "collected",
"source": "sandbox-admin",
"message": ""
},
{
"id": 1940713,
"parcel_id": 0,
"date": "2021-11-22T14:18:20.002241Z",
"status": "delivered",
"source": "sandbox-admin",
"lat": -25.806655,
"lng": 28.334732,
"message": "POD files captured"
},
{
"id": 1940712,
"parcel_id": 0,
"date": "2021-11-22T14:18:19.995663Z",
"status": "collected",
"source": "sandbox-admin",
"message": ""
},
{
"id": 332828,
"parcel_id": 0,
"date": "2021-06-04T09:30:36.170053Z",
"status": "cancelled",
"source": "sandbox-admin",
"message": ""
},
{
"id": 254076,
"parcel_id": 0,
"date": "2021-05-21T12:12:03.846219Z",
"status": "submitted",
"source": "sandbox-admin",
"message": ""
}
]
}
]
}
2
Answers
I was facing the same issue while using Creatio API. Just like your case the API was working in Postman but not when using Curl in PHP.
Sometimes postman sends some extra headers in the HTTP request. In my case postman was sending a
cookie
header anonymously. So to check this: Navigate to the code section of Postman which appears on the right side of the application. Choose PHP as a programming language, it will show you the completeCurl
request for your case.Hope this helps!
The documentation says that
you need to pass the
tracking_reference
parameter on the query string (just as you did with Postman):But that’s not what your code does:
The exception message clearly shows that the parameter is missing from the URL:
You should do something like this instead: