Can not send POST request to Paypal Connect from inside Laravel app - php

I have an app that connects to Paypal Connect. Upon Paypal connect button click I am taken to Paypal website and I do receive a code they send after authentication. But then I can't send the POST request to paypal with authorization_code to require user info I am receiving an error. I am getting this error:
Authentication failed due to invalid authentication credentials or a missing..
And I am pretty sure that my credentials are good.
Am I missing something?
This is what Paypal gives me:
curl -X POST https://api.sandbox.paypal.com/v1/oauth2/token \
-H 'Authorization: Basic {Your Base64-encoded ClientID:Secret}=' \
-d 'grant_type=refresh_token&refresh_token={refresh token}'
I am using Guzzle to send post request. Please see code below
$client = new \GuzzleHttp\Client();
$headers = [
'Authorization' => 'Basic clientID:clientSecret'
];
$response = $client->request('POST',
'https://api.sandbox.paypal.com/v1/oauth2/token',
[
'grant_type ' => 'authorization_code',
'code' => $data['code']
],
$headers);

Looking at the paypal api documentation, it appears as though your authorization header is incorrect.
Authorization request header:
The Base64-encoded client ID and secret credentials separated by a
colon (:). Use the partner's credentials.
You can use php's base64_encode() function to do this.
$client = new \GuzzleHttp\Client();
$authorizationString = base64_encode($clientId . ':' . $clientSecret);
$client->request(
'POST',
'https://api.sandbox.paypal.com/v1/oauth2/token',
[
'headers' => [
'Authorization' => 'Basic ' . $authorizationString
],
'form_params' => [
'grant_type ' => 'authorization_code',
'code' => $data['code']
]
]
);

Related

Laravel HTTP Client - Posting XML file as application/octet-stream

I am trying to post to an external API, that accepts a XML file. The content type is application/octet-stream.
This is my code:
return Http::withToken(config('sproom.auth_token'))
->withHeaders([
'Content-Type' => 'application/octet-stream'
])
->attach('xml', file_get_contents('myfile.xml'), 'myfile')
->post('https://example.org/api/documents')->json();
When posting the above, I get an API error back: Cannot find format for document. No further documentation exists.
I am guessing that the xml file is not being sent correctly as application/octet-stream.
The external API is using Swagger as "documentation", and if I upload the XML file using the Swagger UI, I get a success response. Here in cURL:
curl -X POST "https://example.org/api/documents" -H "accept: */*" -H "Authorization: Bearer vmFrxk2+7......." -H "Content-Type: application/octet-stream" -d {}
I am not sure what I am doing wrong?
I don't think that the content type of the request is application/octet-stream, Also in the curl request you have written above has a -d
curl -X POST "https://example.org/api/documents" -H "accept: */*" -H "Authorization: Bearer vmFrxk2+7......." -H "Content-Type: application/octet-stream" -d {}
This is what is written in man curl
-d, --data
(HTTP) Sends the specified data in a POST request to the HTTP
server, in the same way that a browser does when a user has
filled in an HTML form and presses the submit button. This will
cause curl to pass the data to the server using the content-type
application/x-www-form-urlencoded. Compare to -F, --form.
If you are using ->attach, I guess the request should be multipart/form-data.
So please do see which one you need I guess you can't post files in application/x-www-form-urlencoded.
I don't think there is an option currently to attach content type to a file in attach(), so you can try using guzzle directly. It comes with laravel by default and httpclient is a wrapper over it to reduce the code.
Here is the direct guzzle code
$client = new \GuzzleHttp\Client(['headers' => ['Authorization' => 'Bearer ' . config('sproom.auth_token')]]);
$client->request('POST', 'https://example.org/api/documents', [
'headers' => [
'Accept' => '*/*'
],
'multipart' => [
[
'name' => 'myfile',
'contents' => file_get_contents('myfile.xml'),
'headers' => ['Content-Type' => 'application/octet-stream'],
'filename' => 'myfile.xml'
]
]
]);
Ultimately, I ended up using Guzzle directly:
$client = new \GuzzleHttp\Client(['headers' => ['Authorization' => 'Bearer ' . config('sproom.auth_token')]]);
try {
return $client->request('POST', config('sproom.api_url') . '/api/documents', [
'body' => file_get_contents('myfile.xml'),
'headers' => [
'Content-Type' => 'application/json',
]
])->getBody();
} catch (RequestException $exception) {
return json_decode($exception->getResponse()->getBody()->getContents());
}

How to send a file from URL through POST request using Guzzle

The endpoint what I'm using works fine when I tested it in this way:
curl -X POST ".../api/save" -H "accept: application/json" -H "Content-Type: multipart/form-data" -F "file=#test.xlsx;type=application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
Now I need to send the file using Guzzle in Laravel, but I got 400 Bad Request from the API endpoint. The file is stored in the public disk, so I'm sending the URL.
This is what I have so far:
$headers = [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
'Content-Type' => 'multipart/form-data',
];
$response = $this->client->request('POST', '.../api/save', [
'headers' => $headers,
'multipart' => [
[
'name' => 'image_file',
'contents' => $file->url,
]
]
]);
what you are trying to do is breaking some http protocols.
you can't, in a request, send a ressource link and expect the server to download it before resuming request treatment.
Either you download the file from the url and include its content in your request,
OR
send the url and have the code logic on the server to download it.

MailChimp API call with OAuth 2 token

I am unable to call Mailchimps API 3.0 endpoints such as /lists using OAuth 2 tokens.
I already have the token and have the endpoint from the /metadata call however, when I attempt to access /lists using the below
//Get lists
$client = new \GuzzleHttp\Client(['base_uri' => $datacenter]);
$headers = [
'Authorization' => 'OAuth ' . $token,
'Accept' => 'application/json',
'Host' => $client_endpoint,
'User-Agent' => 'oauth2-draft-v10'
];
$response = $client->request('GET', 'lists', [
'headers' => $headers
]);
$lists = json_decode($response->getBody());
Surely there is a simple solution, I am new to OAuth 2 and MailChimp, and struggling to find any information about MailChimp calls using OAuth2 tokens.
I have also tried the below...
//Get list data
$client = new \GuzzleHttp\Client(['base_uri' => $client_endpoint]);
$headers = [
'Authorization' => 'OAuth ' . $token
];
$response = $client->request('GET', 'lists',[
'user' => 'anystring:' . $token,
'headers' => $headers
]);
Log::debug($response);
Any help from here would be extremely useful
It seems that providing the token in the headers in the format Authorization: OAuth [token] doesn't work as expected.
I completed the following request using PostMan, code provided for ease of use:
// GET https://us1.api.mailchimp.com/3.0/lists
// authorization:"Bearer 0319[redacted]f966"
$response = $client->get( $datacenter.'/3.0/lists', [
'headers' => ['Authorization' => 'Bearer ' . $token]
]);
$lists = json_decode($response->getBody());
Note: the code is untested, the request is tested

Convert a cURL [GET] request to Guzzle

I have this curl request:
curl -k -H"Authorization: Bearer 905290532905902390523905krai20" https://example.com/something?limit=1
Bearer is a token_type ($token_type).
The long string is an access token ($access_token)
How can I convert this to a Guzzle request? I already converted another curl POST request to Guzzle, but this isn't the same deal.
Well, I've never used this library in my life, but after a quick look at the documentation, it seems this should work:
$client = new GuzzleHttp\Client([
'base_uri' => 'https://example.com/something?limit=1'
]);
$client->request('GET', '/get', [
'headers' => [
'Authorization' => 'Bearer 905290532905902390523905krai20',
]
]);

Curl to GuzzleHttp request

I have been given the following curl request:
curl -H "Content-Type:application/json" -H "Api-Key:someapikey" -X -d {"address":"30598 West Street","city":"Oakdale"}' PUT "https://somedomain/api/members/1234567"
I am trying to replicate this with GuzzleHttp like so:
$headers = [
'Api-Key' => $this->apiKey,
'Content-Type' => 'application/json',
];
$client = new Client([
'headers' => $headers,
]);
$res = $client->put("{$this->baseUrl}/members/{$fields['vip_id']}", [
'form_params' => $fields,
]);
I keep on getting a 415 Unsupported Media Type response. From the curl I was given I think I have all my bases covered. However, when I debug it shows that my Content Type is set to application/x-www-form-urlencoded. According to the documentation, the header is set to this only if the Content-Type header isn't already set and form_params is included. As I am already setting this header, it shouldn't be switching right? Please help!
The reason your headers are being overridden is because the form_params option to the request is specifically for sending x-www-form-urlencoded data.
You can omit the Content-Type header from your options completely and instead use the json key in the request to send JSON data.
$headers = [
'Api-Key' => $this->apiKey,
];
$client = new Client([
'headers' => $headers,
]);
$res = $client->put("{$this->baseUrl}/members/{$fields['vip_id']}", [
'json' => $fields, // causes Guzzle to set content type to application/json
// and json_encode your $fields
]);

Categories