Issue converting from cURL to Guzzle 6 with JSON and XML file - php

I am having a hard time converting cURL to Guzzle6. I'm want to send a name and reference UUID via JSON AND the contents of an XML file to process to a REST endpoint.
cURL
curl -H 'Expect:' -F
'request={"name":"test", "reference":"870e0320-021e-4c67-9169-d4b2c7e5b9c9"}'
-F 'file=#sample.xml' http://ec2-48-88-173-9.us-east-1.compute.amazonaws.com:8180/rs/process
Guzzle
$client = new Client(['debug' => true]);
$request = $client->request('POST',
'http://ec2-48-88-173-9.us-east-1.compute.amazonaws.com:8180/rs/process', [
'multipart' => [
[
'name' => 'data',
'contents' => "{'name':'test','reference':870e0320-021e-4c67-9169-d4b2c7e5b9c9}",
'headers' => ['Content-Type' => 'application/json']
],
[
'name' => 'file',
'contents' => fopen('sample.xml', 'r'),
'headers' => ['Content-Type' => 'text/xml']
],
]
]
);
$response = $request->getBody()->getContents();
Also, I'm not sure what the 'name' fields should be ('name' => 'data'), etc.

This is the Guzzle equivalent of your curl command:
$client = new Client(['debug' => true]);
$request = $client->request('POST',
'http://ec2-48-88-173-9.us-east-1.compute.amazonaws.com:8180/rs/process', [
'multipart' => [
[
'name' => 'request',
'contents' => "{'name':'test','reference':870e0320-021e-4c67-9169-d4b2c7e5b9c9}",
],
[
'name' => 'file',
'contents' => fopen('sample.xml', 'r'),
],
]
]
);
$response = $request->getBody()->getContents();
For the file Guzzle will specify the appropriate content type, as curl does. Name for the first part is request — from -F
'request={"name":"test", "reference":"870e0320-021e-4c67-9169-d4b2c7e5b9c9"}'

Related

Paypal Customer Dispute API - Provide Evidence always returns MISSING_OR_INVALID_REQUEST_BODY

I've been trying to upload a pdf file when providing an evidence to Paypal Disputes in the Claim Stage after verifying that the dispute case has the /provide-evidence on its HATEOAS links, the curl code below works in the CLI:
$ curl -v -X POST https://api.sandbox.paypal.com/v1/customer/disputes/PP-D-12345/provide-evidence \
-H "Content-Type: multipart/related" \
-H "Authorization: Bearer {AccessToken}" \
-F 'input={"evidences":[{"evidence_type": "PROOF_OF_FULFILLMENT", "evidence_info": {"tracking_info": [{"carrier_name": "FEDEX", "tracking_number": "123456789"}]}, "notes": "Test"}]};type=application/json' \
-F 'file1=#D:\Sample\storage\app\paypal\sample.pdf'
However when converted to PHP, either using curl or guzzle the API returns VALIDATION_ERROR - MISSING_OR_INVALID_REQUEST_BODY, I've tried almost every possible approach, but the error is consistent.
Using Guzzle: (trying to copy the working curl above as much as possible, since Guzzle can't send multipart/related request, I had to modify the content-type manually).
$pdf = 'D:\Sample\storage\app\paypal\sample.pdf';
$input = [
'evidences' => [
[
'evidence_type' => 'PROOF_OF_FULFILLMENT',
'evidence_info' => [
'tracking_info' => [
'carrier_name' => "FEDEX",
'tracking_number' => '122533485'
]
],
'notes' => 'Test',
],
]
];
$client = new \GuzzleHttp\Client([
'base_uri' => 'https://api.sandbox.paypal.com',
'timeout' => 2.0,
'version' => 1.1
]);
$options = [
'headers' => [
'Authorization' => "Bearer $token",
],
'multipart' => [
[
'name' => 'input',
'contents' => json_encode($input),
'headers' => ['Content-Type' => 'application/json']
],
[
'name' => 'file1',
'contents' => fopen($pdf, 'r'),
'filename' => 'sample.pdf',
'headers' => ['Content-Type' => 'application/pdf']
],
]
];
$url = '/v1/customer/disputes/'.$disputeId.'/provide-evidence';
$headers = isset($options['headers']) ? $options['headers'] : [];
$body = new \GuzzleHttp\Psr7\MultipartStream($options['multipart']);
$request = new \GuzzleHttp\Psr7\Request('POST', $url, $headers, $body, '1.1');
$modify['set_headers']['Content-Type'] = 'multipart/related; boundary=' . $request->getBody()->getBoundary();
$request = \GuzzleHttp\Psr7\modify_request($request, $modify);
$response = $client->send($request);
The guzzle code above still return {VALIDATION_ERROR - MISSING_OR_INVALID_REQUEST_BODY} and same result when I just do a normal multipart/form-data request.
What could be the issue? Any ideas or suggestion would very much help, thanks.
$input = [
'evidences' => [
[
'evidence_type' => 'PROOF_OF_FULFILLMENT',
'evidence_info' => [
'tracking_info' => [
'carrier_name' => "FEDEX",
'tracking_number' => '122533485'
]
],
'notes' => 'Test',
],
]
];
This is your $input, if you json_encode() it, you get
{
"evidences":
[
{
"evidence_type":"PROOF_OF_FULFILLMENT",
"evidence_info":{
"tracking_info":{
"carrier_name":"FEDEX",
"tracking_number":"122533485"
}
},
"notes":"Test"
}
]
}
which does not matches with your request body,
I have changed your $input by inserting another square bracket,
$input = [
'evidences' => [
[
'evidence_type' => 'PROOF_OF_FULFILLMENT',
'evidence_info' => [
'tracking_info' => [[
'carrier_name' => "FEDEX",
'tracking_number' => '122533485'
]]
],
'notes' => 'Test',
],
]
];
Now it matches your curl request,
{
"evidences":
[
{
"evidence_type":"PROOF_OF_FULFILLMENT",
"evidence_info":
{
"tracking_info":
[
{
"carrier_name":"FEDEX",
"tracking_number":"122533485"
}
]
},
"notes":"Test"
}
]
}
I hope it helps. If it doesn't work, then problem might lie somewhere else but the request body will match, you can try the guzzle call first.

How to send Fast Excel to Guzzle post request

i use Fast Excel library from https://github.com/rap2hpoutre/fast-excel, can i put return from ->download('file.xlsx') to Guzzle post request? with this code i'm not get anything
$httpClient = new \GuzzleHttp\Client([
'headers' => [
'Authorization' => mdmTokenGenerate($token),
'Accept' => 'application/json'
],
'verify' => false
]);
$response = $httpClient->post(
"{$client->domain}/api/push", [
'multipart' => [
[
'name' => 'file',
'contents' => (new FastExcel(MasterNumbers::limit(1000)->get()))->download('file.xlsx')
]
]
]
);

How to pass Laravel $request->file(...) directly to Guzzle POST request

How can I pass the $request->file(...) to Guzzle thru POST request?
Or is it even possible? Should I upload it first?
This is my attempt:
$client = new Client([ 'base_uri' => 'http://api.domain.com']);
$response = $client->post(
'/api/dosomething',
[
'multipart' => [
[
'Content-type' => 'multipart/form-data',
'name' => 'photo_1',
'contents' => $request->file('photo_1')
]
]
]
);
This is not working. The response body is just blank.
I found the solution below (We need to specify the path of the temporary file in the temp folder with the code $file->getPathName()):
$client = new Client([ 'base_uri' => 'http://api.domain.com']);
$file = $request->file('photo_1')
$response = $client->post(
'/api/dosomething',
[
'multipart' => [
[
'Content-type' => 'multipart/form-data',
'name' => 'photo_1',
'contents' => fopen($file->getPathName(), 'r')
]
]
]
);

Post data and file using Guzzle - PHP & Laravel

I am using guzzle 6.3 to post a file along with some data to my api built on laravel 5.5. When i post the data, i am not able to get the data sent to the api except the file posted.
Client Side
$client = new Client([
'headers' => [ 'Content-Type' => 'application/json' ]
]);
$response = $client->request('POST',$url, [
'multipart' => [
[
'name' => 'body',
'contents' => json_encode(['documentation' => 'First Doc', 'recipient' => ['78011951231']]),
'headers' => ['Content-Type' => 'application/json']
],
[
'name' => 'file',
'contents' => fopen('/path/public/media/aaaah.wav', 'r'),
'headers' => ['Content-Type' => 'audio/wav']
],
],
]);
echo($response->getBody()->getContents());
API Controller
if (($Key)) {
return response()->json([
'status' => 'success',
'documenation' => $request->get('documentation'),
'recipient' => $request->get('recipient'),
'file' =>$request->get('file'),
'media'=>$request->hasFile('file')
]);
}
Response
{"status":"error","documentation":null,,"recipient":null,"file":null,"media":true}
Why am i getting NULL returned for the data that i am posting? Could it be because of the file that i am posting ?

Guzzle 6 send multipart data

I'd like to add some data to a Guzzle Http Request. There are file name, file content and header with authorization key.
$this->request = $this->client->request('POST', 'url', [
'multipart' => [
'name' => 'image_file',
'contents' => fopen('http://localhost:8000/vendor/l5-swagger/images/logo_small.png', 'r'),
'headers' =>
['Authorization' => 'Bearer uCMvsgyuYm0idmedWFVUx8DXsN8QzYQj82XDkUTw']
]]);
but I get error
Catchable Fatal Error: Argument 2 passed to GuzzleHttp\Psr7\MultipartStream::addElement() must be of the type array, string
given, called in vendor\guzzlehttp\psr7\src\MultipartStream.php on line 70 and defined in vendor\guzzlehttp\psr7\src\MultipartStream.php line 79
In Guzzle 6 documentation is something like this: http://docs.guzzlephp.org/en/latest/request-options.html#multipart
Who knows where I made a mistake?
Here is the solution. Header with access token should be outside multipart section.
$this->request = $this->client->request('POST', 'request_url', [
'headers' => [
'Authorization' => 'Bearer access_token'
],
'multipart' => [
[
'Content-type' => 'multipart/form-data',
'name' => 'image_file',
'contents' => fopen('image_file_url', 'r')
]
]
]);
As per the docs, "The value of multipart is an array of associative arrays", so you need to nest one level deeper:
$this->request = $this->client->request('POST', 'url', [
'multipart' => [
[
'name' => 'image_file',
'contents' => fopen('http://localhost:8000/vendor/l5-swagger/images/logo_small.png', 'r'),
'headers' => ['Authorization' => 'Bearer uCMvsgyuYm0idmedWFVUx8DXsN8QzYQj82XDkUTw']
]
]
]);
try this
works for me
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Utils;
$this->client = new Client([
'base_uri' => 'https://baseurl'
]);
$body = Utils::tryFopen($tempPath . $fileName, 'r');
$res = $this->client->request(
'POST',
'url',
[
'headers' => [
...
],
'body' => $body
]
);

Categories