How to call an API using raw input using Guzzle - api

I have an API which is working well with Postman but upon trying to call it in code, I get errors. See below
In Postman
Below is how I am calling the API in code:
In Code
public function pay_bill(Request $request){
$client = new Client(); //GuzzleHttp\Client
$username = 'xxxx';
$password = 'xxx#2020*';
$credentials = base64_encode("$username:$password");
$transaction_id = intval($request->input('transaction_id'));
$amount = (int)$request->input('amount');
$bill_number = (int)$request->input('bill_number');
$return_url = $request->input('return_url');
$response = $client->post('https://gatewaytest.e.com:5000/gateway/initialize', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Basic ' . $credentials,
'X-API-KEY' => '7c4a8d09ca3762af61e59520943dc26494f8941b',
],
'form_params' => [
'transaction_id' => $transaction_id,
'total_amount' => $amount,
'bills' => ["bill_ref" => $bill_number, "amount" => $amount],
'return_url'=> $return_url
],
'verify' => true
]);
$transaction_data = $response->getBody();
return $transaction_data;
}
What am I doing wrong? How do I send body as raw like is done in postman? I imagine the problem could be due to using form_params

I finally found the solution as shown below:
'bills' => [["bill_ref" => $bill_number, "amount" => $amount]]

Related

Problem to upload file with from-param in Laravel 8 external api with guzzle or HTTP client

I am using Mirakl api. I faced an issue with the file upload with form-peram in Laravel 8 external api with guzzle or HTTP client.I got 400 Bad Request.The api expects file with from-param like this
{
"order_documents": [{
"file_name": String,
"type_code": String
}]
}
The documentation of my endpoint can be found from this link (http://185.29.149.41/eci/mir/doc/api/OR74.html) and here is my codes --
public function upload_order(Request $request)
{
$order_id = $request->order_id;
if ($files = $request->file('files')) {
$name = $files->getClientOriginalName();
Storage::disk('invoice')->put($name, file_get_contents($files->getRealPath()));
$path = Storage::disk('invoice')->path($name);
}
$file['order_documents'][] = [
'file_name' => $name,
'type_code' => $request->type_code,
];
$json = json_encode($file);
$data = [
['name' => 'order_documents','contents' => $json],
];
$data[] = [
'name' => 'files',
'contents' => mb_convert_encoding($path, 'UTF-8', 'UTF-8'),
'filename' => $name,
];
$body['multipart'] = $data;
$configApi = $this->configApi($this->getMarketplaceID($request->marketplace), auth()->user()->id);
$url = $configApi['url'].'/api/orders/'.$order_id.'/documents';
$client = new Client(['verify' => false]);
$response = $client->request(
'POST',
$url,
[
'multipart' => $data,
'headers' => $configApi['headers']
]);
return json_decode($response->getBody(), true);
}

Laravel 5.1 Guzzle - Undefined offset: 0

I need to access an API so I use guzzle6 and I write a function:
public function test()
{
$client = new GuzzleHttp\Client(['defaults' => ['verify' => false]]);
try {
$res = $client->post('https://example.com/api/v2/oauth/token?grant_type=client_credentials', [
'headers' => [
'Content-Type' => 'application/x-www-form-urlencoded',
],
'auth' => [
'Username' => 'user_5639',
'Password' => 'pass_asdhbas67yausihd7qaw8'
]
]);
$res = json_decode($res->getBody()->getContents(), true);
}
catch (GuzzleHttp\Exception\ClientException $e) {
$response = $e->getResponse();
$result = json_decode($response->getBody()->getContents());
return response()->json(['data' => $result]);
}
}
but I got error:
ErrorException in Client.php line 346: Undefined offset: 0
When I try at POSTMAN the same request everything is fine:
How to solve my problem?
If you have a look at the Guzzle Manual for the auth-option, you'll see it expects a numerically indexed array, with the username on index 0 and the password on index 1.
So this should work:
$res = $client->post('https://example.com/api/v2/oauth/token?grant_type=client_credentials', [
'headers' => [
'Content-Type' => 'application/x-www-form-urlencoded',
],
'auth' => [
'user_xxxx', 'pass_xxxxx'
]
]);

How to add a list using (api sendgrid) cakephp

I'm trying to make requests in external Web Services with Cake HttpSocket, I'm trying to create a new list I'm getting an error from api sendgrid
[body] => {"errors":[{"message":"request body is invalid"}]}
public function addemail() {
$HttpSocket = new HttpSocket();
$lista = array('name' => 'Teste');
$retorno = $HttpSocket->post('https://api.sendgrid.com/v3/contactdb/lists', $lista,
array(
'header' => array(
'Content-Type' => 'application/json',
'Authorization' => 'Bearer SG.XXXXXXXXX'
)
));
if ($retorno->isOk()) {
debug($retorno->body());
}
}
what is wrong? in the sendgrid documentation says that the body should be this way
{
"name": "listname"
}
You need to json encode the array like so:
$lista = json_encode(array('name' => 'Teste'));

API returning 400 Bad Request response

I have built an API and an application that uses that API. Everything was working but now, for some reason, I get a 400 Bad Request response. I am not sure if I changed something in the code so I wanted to double check it was correct.
So my API call is this
$client = new GuzzleHttp\Client();
$jsonData = json_encode($data);
$req = $client->request('POST', 'https://someurl.com/api/v1/createProject', [
'body' => $jsonData,
'headers' => [
'Content-Type' => 'application/json',
'Content-Length' => strlen($jsonData),
]
]);
$output = $req->getBody()->getContents();
The API has a route set up correctly which uses post. The function it calls is correct, and I have changed it for testing to simply return
return response()->json(["Success", 200]);
When I test the API out within Postman, I can see that Success is returned. When I test the API within the other application I have built, I dont even see a POST request within the console, I am just displayed a Laravel error 400 Bad Request.
What could be the cause of this issue?
Thanks
Update
I have changed the request to this
$data= json_encode($data);
$req = $client->post('https://someurl.com/api/v1/createProject', [
'body' => $data
]);
If I output $data after it has been encoded, I get something like this
{
"projectName":"New Project",
"clientName":"Test Client",
}
Within the controller function of the API that is being called, I simply do
return response()->json(['name' => $request->input('clientName')]);
The 400 error has now gone, but I now get null returned to me
{#326 ▼
+"name": null
}
Request is being injected into the function as it should be. Should I be returning the data in a different way?
Thanks
Probably you did $ composer update and Guzzle updated.
So if you are using newest Guzzle (guzzlehttp/guzzle (6.2.2)) you do POST request:
$client = new GuzzleHttp\Client();
$data = ['name' => 'Agent Smith'];
$response = $client->post('http://example.dev/neo', [
'json' => $data
]);
You do not need to specify headers.
To read response you do following:
$json_response = json_decode($response->getBody());
My full example (in routes file web.php routes.php)
Route::get('smith', function () {
$client = new GuzzleHttp\Client();
$data = ['name' => 'Agent Smith'];
$response = $client->post('http://example.dev/neo', [
'json' => $data,
]);
$code = $response->getStatusCode();
$result = json_decode($response->getBody());
dd($code, $result);
});
Route::post('neo', function (\Illuminate\Http\Request $request) {
return response()->json(['name' => $request->input('name')]);
});
or you could use following (shortened), but code above is "shorter"
$json_data = json_encode(['name' => 'Agent Smith']);
$response = $client->post('http://example.dev/neo', [
'body' => $json_data,
'headers' => [
'Content-Type' => 'application/json',
'Content-Length' => strlen($json_data),
]
]);
note: If you are running PHP5.6, change always_populate_raw_post_data to -1 (or uncomment the line) in php.ini and restart your server. Read more here.
In my case I was using public IP address in BASE_URL while I should have been using the private IP. From mac you can get your IP by going into system preferences -> network.
This is with Android + Laravel (API)

How can i use post request in pecl_http library

hotelbeds api
The api required to use post request with some fields, but i don't know where are the fields will be added!! ( in GET request i add the fields in the url like any request )
the api code
`
$apiKey = "8z8a7tupn5hubhjxqh8ubuz7";
$sharedSecret = "jsSJq2msbU";
$signature = hash("sha256", $apiKey.$sharedSecret.time());
$endpoint = "https://api.test.hotelbeds.com/activity-api/3.0/activities";
$request = new \http\Client\Request("POST",
$endpoint,
[ "Api-Key" => $apiKey,
"X-Signature" => $signature,
"Accept" => "application/json" ,
]);
$client = new \http\Client;
$client->enqueue($request)->send();
$response = $client->getResponse();
echo "<pre>";
print_r($response->getBody());
echo "</pre>";
the api said
The available filters for the search is listed below.
It contains an array of filter with the following structure:
[{"searchFilterItems": [{"type": "destination", "value": "BCN"}]}]
The Object “searchFilterItems” contains the following attributes: type > and value.
The following examples illustrate the different types and values for > each filter:
Country
{"type": "country", "value": "PT"}
I had the same issue, took me a little while to figure it out. Turns out you need to use the Body class to represent the post data.
$msg = new http\Message\Body();
$msg->addForm([
'field1' => 'value',
'field2' => 'value2'
]);
$headers = null;
$request = new http\Client\Request('POST', 'https://example.com', $headers, $msg);
$client = new http\Client();
$client->enqueue($request);
$client->send();
$response = $client->getResponse();
There are some more methods available in the Message and Body class for including files, etc.
Try this way
$request = new http\Client\Request;
$body = new http\Message\Body;
$body->append('{Your JSON}');
$request->setRequestUrl('https://api.hotelbeds.com/hotel-api/1.0 hotels');
$request->setRequestMethod('POST');
$request->setBody($body);
$request->setHeaders(array(
'Accept' => 'application/json',
'Content-Type' => 'application/json',
'Api-Key' => $owapiKey,
'X-Signature' => $signature,
//'Accept-Encoding' => 'Gzip', //Deflate
'cache-control' => 'no-cache'
));
try {
$client = new http\Client;
$client->enqueue($request)->send();
$response = $client->getResponse();
if ($response->getResponseCode() != 200) {
echo("HTTP CONNECT FAILURE: -> ".
$response->getTransferInfo("effective_url").
$response->getInfo().$response->getResponseCode() );
} else {
$res=$response->getBody()->toString();
}
} catch (Exception $ex) { echo("Error while sending request, reason: %s\n".$ex->getMessage()); }