Xero Authorization Unsuccessful error in curl request - laravel

I am having issues in accessing contact from Xero. I keep getting an error - AuthorizationUnsuccessful
Below please find the code I am using to send my request as well as the response I am getting:
'scopes' => (
'openid',
'email',
'profile',
'offline_access',
'accounting.settings',
'accounting.contacts'
)
in my xero config file
Request passing in Postman
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://api.xero.com/api.xro/2.0/Contacts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => array(
"accept: application/json",
"authorization: Bearer eyJh.......N6mbaw",
"cache-control: no-cache",
"postman-token: 51048d11-4f31-ba27-16c7-48739f14c6f0",
"xero-tenant-id: e8672ad4-ea92-4698-87aa-a69f5b049265"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
?>
Response:
{
"Type": null,
"Title": "Unauthorized",
"Status": 401,
"Detail": "AuthorizationUnsuccessful",
"Instance": "14ae9993-dc1b-4d8d-a4c0-15b2c343f337",
"Extensions": {}
}
Your assistance would be greatly appreciated.

In your headers, I don't think there is no need for postman-token, so it should look like,
CURLOPT_HTTPHEADER => array(
"Accept: application/json",
"Authorization: Bearer eyJh.......N6mbaw",
"Cache-control: no-cache",
"Xero-tenant-id: e8672ad4-ea92-4698-87aa-a69f5b049265"
)
Note the capital first letters.
The other option, easier & more organised one is to use guzzle, as you are using laravel(if > 5.1), you have guzzle already in laravel or can use HTTP Client even.
Using Guzzle
You can use Guzzle to handle curl requests,
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
public function yourFunction()
{
try {
$client = new Client();
$guzzleResponse = $client->get(
'https://api.xero.com/api.xro/2.0/Contacts', [
'headers' => [
"Accept" => "application/json",
"Authorization" => "Bearer eyJh.......N6mbaw",
"Cache-control" => "no-cache",
"Xero-tenant-id" => "e8672ad4-ea92-4698-87aa-a69f5b049265"
],
'allow_redirects' => [
'max' => 10,
],
'connect_timeout' => 30
]);
if ($guzzleResponse->getStatusCode() == 200) {
$response = json_decode($guzzleResponse->getBody(),true);
}
} catch (RequestException $e) {
// you can catch here 400 response errors and 500 response errors
// see this https://stackoverflow.com/questions/25040436/guzzle-handle-400-bad-request/25040600
} catch(Exception $e){
//other errors
}
}
You can refer more about guzzle from guzzle docs

Related

Laravel 9 | cURL request to HTTP Client

New versions of laravel have their own HTTP client. I like the syntax and want to use it. Before that I was always using cURL.
I am now trying to make a request with the new HTTP client, but I always get a weird result back. Status is 200 btw.:
{
"cookies": {},
"transferStats": {}
}
I dont know where this comes from, my endpoint does not return this.
This is the cURL version, which works:
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => env('SCAMMER_CHECK_ENDPOINT'),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => array('auth' => $data['auth'],'authUserId' => $msd_user_id,'img' => $data['base64img']),
));
$scammer_check = curl_exec($curl);
curl_close($curl);
This is the same request with the HTTP client, which does not work:
$scammer_check = Http::post(env('SCAMMER_CHECK_ENDPOINT'), [
'auth' => $data['auth'],
'authUserId' => $msd_user_id,
'img' => $data['base64img']
]);
I also tried to use raw body, but same result:
$scammer_check = Http::withBody(
json_encode(array('auth' => $data['auth'],'authUserId' => $msd_user_id,'img' => $data['base64img'])), 'application/json'
)->post(env('SCAMMER_CHECK_ENDPOINT'));
It seems like the HTTP client is returning an empty response with cookies and transferStats. This could be due to incorrect response handling.
You could try retrieving the response body by using the "body" method on the response object like this:
$response = Http::post(env('SCAMMER_CHECK_ENDPOINT'), [
'auth' => $data['auth'],
'authUserId' => $msd_user_id,
'img' => $data['base64img']
]);
$scammer_check = $response->body();
Alternatively, you could try specifying the expected response format like this:
$scammer_check = Http::post(env('SCAMMER_CHECK_ENDPOINT'), [
'auth' => $data['auth'],
'authUserId' => $msd_user_id,
'img' => $data['base64img']
])->json();

How to make post request to get data Laravel Guzzle?

Let say, the Secret Key is XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX and md5key is YYYYYYYY.
I made a Query String QS
Qs = “method=RegUserInfo&Key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&Time=20140101123456&Username=DemoUser001”;
After urlencode I got q='j4tjorjwarfj3trwise0safrwg2wt4awari0fwjfeoh'
I made MD5 String for building the signature (QS + md5key + Time + Key):
s = BuildMD5(QS + “YYYYYYYY” + “20140101123456” + “XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX”);
I got s='1234567890abcdef'
So will get q=j4tjorjwarfj3trwise0safrwg2wt4awari0fwjfeoh&s=1234567890abcdef
How to resulting POST method query (using “Content-Type: application/x-www-form-urlencoded”)
by POST to http://xxxxx.com/api/api.aspx
My code is
$param = "q=".$q."&s=".$s;
$client = new Client(['headers' => [
'Content-Type' => 'application/x-www-form-urlencoded',
]]);
try{
$response = $client->request('POST','http://xxxxxx.com/api/api.aspx', [
'query' => [$param],
]);
}catch(ClientException $e){
$response = $e->getResponse();
$responseBodyAsString = $response->getBody()->getContents();
dd($responseBodyAsString);
}
}
but I get 403 Forbidden
If you want Content-Type: application/x-www-form-urlencoded you need to use form_params request option.
try{
$client = new \GuzzleHttp\Client(['headers' => ['Authorization' => 'Bearer ' . $your_token]]);
$guzzleResponse = $client->post(
$api_url, [
'form_params' => [
'grant_type' => 'xxxxx',
'key' => 'xxx',
'time' => 'xxxx',
'username' => 'xxxxxx'
]
]);
if ($guzzleResponse->getStatusCode() == 200) {
$response = json_decode($guzzleResponse->getBody(),true);
//perform your action with $response
}
}
catch(\GuzzleHttp\Exception\RequestException $e){
// you can catch here 40X response errors and 500 response errors
}catch(Exception $e){
//other errors
}
know more about form_params

Send data from Laravel application using Sendinblue

Please I need to send daily a group of data from my LARAVEL application using Sendinblue API [this how the external server API looks like ( api.sendinblue.com/v3/contacts/identifier ) ], I've managed to used Sendinblue PHP code to send one contact on the time.
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sendinblue.com/v3/contacts/identifier",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => "{\"attributes\":{\"newKey\":\"New Value\"}}",
CURLOPT_HTTPHEADER => [
"Accept: application/json",
"Content-Type: application/json",
"api-key: My API"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
?>
My question there is a way to send all data at once and daily in an automatic way?
Should I use a For each in the controller or there is another ways?
Thank you in advance.
Yes, you can do it with Laravel scheduler.
Read More about scheduler

Restful API with Laravel

I'm developing a restful API with laravel. Authorization is done using a SECRET_KEY & PUBLIC_KEY as shown in the sample request code below.
How do i retrieve the Authorization header key value from the Request?
I would also appreciate links to any resources that would guide me through better implementation & best practice in creating a Restful API with Laravel.
$curl = curl_init();
$url = "http://api.example.com/v1/users";
$secretKey = env('SECRET_KEY');
$publicKey = env('PUBLIC_KEY');
$firstName = "John";
$lastName = "Doe";
$email = "example#gmail.com";
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "{\r\n \"firstName\": \"$firstName\",\r\n \"lastName\": \"$lastName\",\r\n \"email\": \"$email\",\r\n \"secretKey\": \"$secretKey\",\r\n}",
CURLOPT_HTTPHEADER => array(
"Content-Type: application/json",
'Authorization: Bearer ' . $publicKey,
),
));
$response = curl_exec($curl);
curl_close($curl);
The request() helper contains everything from the request.
Just dd(request()->header()) to see the full list of the request headers.
You can check the official documentaion : https://laravel.com/docs/7.x/eloquent-resources#introduction
Also you might want to use a tool like Postman to test your API easily.

form_params method get guzzle php

I have an API get list user. postmen
and Headers Content-Type = application/json
- In laravel, I use guzzle to call api
code demo:
$client = new Client();
$headers = ['Content-Type' => 'application/json'];
$body = [
'json' => [
"filter" => "{}",
"skip" => 0,
"limit" => 20,
"sort" => "{\"createAt\": 1}",
"select" => "fullname username",
"populate" => "'right', 'group'",
]
];
\Debugbar::info($body);
$response = $client->get('http://sa-vn.com:2020/api/users/user', [
'form_params' => $body
]);
echo $response->getBody();
But it does not working! please help me
form_params and body both are different params in guzzle. check json
$json = [
"filter" => json_encode((object)[]),
"skip" => 0,
"limit" => 20,
"sort" => json_encode((object)['createAt'=>1]),
"select" => "fullname username",
"populate" => "'right', 'group'"
];
$response = $client->request('get', 'http://sa-vn.com:2020/api/users/user', [
'json' => $json,
]);
If any error occur try without json_encode as well.
$json = [
"filter" => (object)[],
"skip" => 0,
"limit" => 20,
"sort" => (object)['createAt'=>1],
"select" => "fullname username",
"populate" => "'right', 'group'"
];
As per Guzzle doucmentation
form_params
Used to send an application/x-www-form-urlencoded POST request.
json
The json option is used to easily upload JSON encoded data as the body of a request. A Content-Type header of application/json will be added if no Content-Type header is already present on the message.
You are passing json data in postman. So you can use json instead of form_params
Change
$response = $client->get('http://sa-vn.com:2020/api/users/user', [
'form_params' => $body
]);
to
$response = $client->get('http://sa-vn.com:2020/api/users/user', [
'json' => $body
]);

Resources