I am using Laravel to call an external API.
This is my Client:
<?php
use GuzzleHttp\Client;
$client = new Client();
$response = $client->request('POST',
'https://example.org/oauth/token', [
'headers' => [
'cache-control' => 'no-cache',
'Content-Type' => 'application/x-www-form-urlencoded',
],
'form_params' => [
'client_id' => '2',
'client_secret' => 'client-secret',
'grant_type' => 'password',
'username' => 'username',
'password' => 'password',
],
]);
$accessToken = json_decode((string)$response->getBody(),
true)['access_token'];
Now I can use this to fetch something:
<?php
$response = $client->request('GET',
'https://example.org/api/items/index', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer '.$accessToken,
],
]);
So now I don't want to initiate the client on every method again. So maybe there's a cool/Laravel-like way to provide the $client to the controller on specific routes?
I thought about an app service provider or an middleware, but I'd love to see an example :-)
Perhaps you can use singleton? Wrap your implementation in a class lets say YourHttpClient then in your AppServiceProviders register method add:
$this->app->singleton('YourHttpClient', function ($app) {
return new YourHttpClient();
});
Then you should be able to typehint it in your controller constructors like this
class SomeController {
private $client;
public function __construct(YourHttpClient $client) {
$this->client = $client;
}
}
Related
I am working on an API and MySQL project that will save some of the data in MySQL and some in the API
Controller (index function):
{
$response = Http::post('http://example.com/authenticate', [
'Username' => 'ADMIN',
'Password' => 'ADMIN',
'Token' => 'FK98D...',
]);
$token = json_decode($response, true);
$apiURL = 'http://example.com/api/SalesOrder/';
$headers = [
'Content-Type' => 'application/json',
'Authorization' => $token,
];
$response2 = Http::withHeaders($headers)->get($apiURL);
$data = $response2->json();
$jobdetail = JobDetail::all();
return view('api.auth.orders.index', compact('data','jobdetail'));
}
the above function is working correctly
Controller (store function):
public function store(Request $request)
{
$response = Http::post('http://example.com/authenticate', [
'Username' => 'ADMIN',
'Password' => 'ADMIN',
'Token' => 'FK98D...',
]);
$token = json_decode($response, true);
$request->validate([
'job_order_no' => 'required',
'sap_no' => 'required',
'pic_name' => 'required',
]);
JobDetail::create($request->all());
$store = Http::withHeaders([
'Content-Type' => 'application/json',
'Authorization' => $token,
])->post('http://example.com/api/SalesOrder/', [
'DocNo' => $request->job_order_no,
'TotalQty' => $request->TotalQty,
'TotalTransferredAOQty' => $request->TotalTransferredAOQty,
'SODTL' => array([
'DtlKey' => "",
'ItemCode' => $request->ItemCode,
])
]);
return $store;
}
and the above function is storing data to API and MySQL
note: that 'DocNo' is using the 'job_order_no' request so both will be the same value to be able to call it for show function (i am not sure if this is the best approach)
Controller (show function):
public function show($DocNo,JobDetail $company)
{
$client = new Client();
$headers = [
'Content-Type' => 'application/x-www-form-urlencoded'
];
$options = [
'form_params' => [
'Username' => 'ADMIN',
'Password' => 'ADMIN',
'Token' => 'FK98DL...'
]
];
$request = new Psr7Request('POST', 'http://example.com/authenticate', $headers);
$res = $client->sendAsync($request, $options)->wait();
$token = json_decode($res->getbody(),true);
$client = new Client();
$headers = [
'Authorization' => $token,
'Content-Type' => 'application/x-www-form-urlencoded'
];
$options = [
'form_params' => [
'DocNo' => $DocNo
]
];
$request = new Psr7Request('GET', 'http://example/api/SalesOrder/GetSalesOrder/', $headers);
$res = $client->sendAsync($request, $options)->wait();
$data = json_decode($res->getBody(),true);
return view('api.auth.orders.show', compact('data','company'));
}
view (to redirect to show page):
<td class="text-center"></td>
how to redirect the above "a" tag to get the data from API and MySQL from 'DocNo' ('DocNo' is 'job_order_no' in MySQL as i mentioned above in store function)
is there a query that i need to add to show function to get data from database where the DocNo from the API equals DocNo from MySQL?
SOLUTION:
i used query to get the same value from MySQL as showing below:
$jobs = DB::table('jobdetails')->where('job_order_no', $DocNo)->first();
i want to store response data like private property to variable when called method
use Illuminate\Support\Facades\Http;
public function myMethod(){
$result = [];
$response = Http::asForm()->withHeaders([
'origin' => 'https://example.com',
'content-type' => 'application/x-www-form-urlencoded',
'referer' => 'https://example.com',
])->post('https://example.com', [
'email' => 'example#gmail.com',
'pass' => 'mypassword',
'login' => 'Log+In',
'withCredentials' => true,
]);
$result = $response;
}
Result :
but i can't use keys in this result
I successfully create server and client app both using laravel, I can access data from server app to client app also. But now I want to create another client app using codeigniter. Authorization works except for the callback method. So how can I convert the this code
Route::get('/callback', function (Request $request) {
$http = new GuzzleHttp\Client;
$response = $http->post('http://your-app.com/oauth/token', [
'form_params' => [
'grant_type' => 'authorization_code',
'client_id' => 'client-id',
'client_secret' => 'client-secret',
'redirect_uri' => 'http://example.com/callback',
'code' => $request->code,
],
]);
return json_decode((string) $response->getBody(), true);
});
into CodeIgniter 2?
Thanks
Anyways, I already fixed it.
adding "guzzlehttp/guzzle": "~6.0" in composer.json
running composer update
callback method code
$http = new \GuzzleHttp\Client;
$response = $http->post('http://localhost:8000/oauth/token', [
'form_params' => [
'grant_type' => 'authorization_code',
'client_id' => '3',
'client_secret' => 'client-secret-from-db',
'redirect_uri' => 'ci-client-app/callback',
'code' => $this->input->get('code', TRUE)
],
]);
echo '<pre>', print_r(json_decode((string) $response->getBody(), true));
I have a problem with my Bearer-Authorization in Guzzle-HTTP.
I use it to test my PHP-REST-API with PHPUnit.
here is my test method:
public function testGetMe()
{
$client = new Client([
'base_uri' => $this->apiBaseURL
]);
$data = ['email' => $email, 'password' => '12345'];
$client->post('register', [
'form_params' => $data]
);
$responseJson = json_decode($response->getBody());
$myToken = $responseJson->data->token;
$response = $client->request('GET', 'users', [
'headers' => [
'Authorization' => 'Bearer '.$myToken
],
'debug' => true
]);
}
But if I set the token hard coded like this:
public function testGetMe()
{
$client = new Client([
'base_uri' => $this->apiBaseURL
]);
$data = ['email' => $email, 'password' => '12345'];
$client->post('register', [
'form_params' => $data]
);
$responseJson = json_decode($response->getBody());
$myToken = eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE0NjQ5NzExMzQsImp0aSI6IjByR3FpOW15Rm1rRGo2TU9sMVhkK3dRU3p1V0pWejM1UEhiU2dTMmg5SEU9IiwiaXNzIjoiQXBwTmFtZSIsIm5iZiI6MTQ2NDk3MTE0NCwiZXhwIjoxNDY0OTczMTQ0LCJzdWIiOiJ0ZXN0QG1haWwuZGUifQ.yA4a_S6ILCeqENm00H712g9uF5g9eSz_BmnaMDdZ2r4p5e1q88g0T09IG2WKCi1oExoBfQ8VTmKeX6ZQv0RydQ;
$response = $client->request('GET', 'users', [
'headers' => [
'Authorization' => 'Bearer '.$myToken
],
'debug' => true
]);
}
and also with Postman, it is working.
It's the same token which I receive from my REST-API.
Do you have any ideas what's wrong?
I'm trying to request this way:
$body = [];
$body['holder_name'] = $full_name;
$body['bank_code'] = $bank_number;
$body['routing_number'] = $branch_number;
$body['account_number'] = $account_number;
$body['type'] = 'checking';
$client = new GuzzleHttp\Client([
'base_url' => [$url, []],
'headers' => ['content-type' => 'application/json', 'Accept' => 'application/json'],
'defaults' => [
'auth' => [$publishable_key, ''],
],
'body' => json_encode($body),
]);
The problem is that this request is being set without Content-Type.
What am I doing wrong?
Ok .. the problem was that I was setting body and headers outside of defautls. the solution is:
$client = new GuzzleHttp\Client([
'base_url' => [$url, []],
'defaults' => [
'auth' => [$publishable_key, ''],
'headers' => ['content-type' => 'application/json', 'Accept' => 'application/json'],
'body' => json_encode($body),
],
]);
Guzzle 6
Guzzle will set the Content-Type header to
application/x-www-form-urlencoded when no Content-Type header is
already present.
You have 2 options.
Option 1: On the Client directly
$client = new GuzzleHttp\Client(
['headers' => [
'Content-Type' => 'application/json'
]
]
);
Option 2: On a Per Request basis
// Set various headers on a request
$client = new GuzzleHttp\Client();
$client->request('GET', '/whatever', [
'headers' => [
'Content-Type' => 'application/json'
]
]);
You can refer to Guzzle 6: Request Options
I was encountering the same issue with the Hubspot API that requires to set application/json as Content-Type for POST requests.
I fixed it this way
$client = new Client([
'base_uri' => 'https://api.hubapi.com/',
'timeout' => 5,
'headers' => ['Content-Type' => 'application/json']
]);
And then performing my requests the regular way
try
{
$response = $client->request('POST', '/contacts/v1/contact/email/test#test.com/profile',
['query' => MY_HUBSPOT_API_KEY, 'body' => $body]);
}
catch (RequestException $e) { print_r($e); }
I hope this helps.