Laravel POST request to API answer - laravel

I have got a Laravel Application which should send a POST request with parameters to the WebUntis API and the response should be a session id. I can send a POST request and I get a answer but I do not get the session key. I have tested the code in Postman and there it works.
route/api.php
Route::get('auth', 'UntisController#auth');
UntisController.php
class UntisController extends Controller
{
public function auth()
{
$client = new \GuzzleHttp\Client();
$req = $client->post( 'https://asopo.webuntis.com/WebUntis/jsonrpc.do?school=htblva_villach',[
"id" => 8294829,
"method" => "authenticate",
"params" => [
"user" => "USERNAME",
"password" => "PASSWORD",
"client" => "web"
],
"jsonrpc" => "2.0"
],
['Content-Type' => 'application/json'
]);
dd($req);
}
}
the response I get with POSTMAN, the respones i want
my Postman request
The response I get from my code
I have tried it already with
dd($req->getBody());
but I do not get the sessionid i want.

You can try this method.(Send post request with api in laravel)
public function auth(Request $request)
{
$token = session('token'); //if token needed you can take from session else you can remove token
$body = [
"id" => 8294829,
"method" => "authenticate",
"params" => [
"user" => "USERNAME",
"password" => "PASSWORD",
"client" => "web"
],
"jsonrpc" => "2.0"
];
$request =
Request::create('https://asopo.webuntis.com/WebUntis/jsonrpc.do?
school=htblva_villach') , 'POST', $body);
$request->headers->set('Accept', 'application/json');
$request->headers->set('Authorization', 'Bearer ' . $token); // if not required token you can comment this line
$res = app()->handle($request);
$req = json_decode($res->getContent()); //convert to json object
dd($req);
}

Related

Codeigniter 4 Shield adding access/token route

I'm starting to work with Codeigniter 4 Shield.
I added this piece of code to my app/Config/Routes.php file.
$routes->get('/access/token', static function() {
$token = auth()->user()->generateAccessToken(service('request')->getVar('token_name'));
return json_encode(['token' => $token->raw_token]);
});
When I try to access the route in my web browser using the URL https://example.com/access/token, I obtain the error:
Call to a member function generateAccessToken() on null
produced by the line of code below:
$token = auth()->user()->generateAccessToken(service('request')->getVar('token_name'));
Background information:
I have installed Codeigniter 4 Shield using Composer, ran the respective database migrations, and everything else works fine.
My Codeigniter 4 Shield 'login' and 'register' pages work fine.
How can I load generateAccessToken() automatically in the app/Config/Routes.php file?
You need to submit the login credentials (email & password) along with your HTTP POST request to help identify the User requesting the access token. Otherwise, auth()->user() is empty, hence the error.
To generate an access token, you need to first authenticate the User.
For example: (Using email & password)
Define your 'access token' route. Notice the use of ->post(...) instead of ->get(...).
File: app/Config/Routes.php
$routes->post('auth/token', '\App\Controllers\Auth\LoginController::accessToken');
Define your Controller method that will handle the 'access token' generation. Read: Issuing the Tokens
File: app/Controllers/Auth/LoginController.php
<?php
namespace App\Controllers\Auth;
use App\Controllers\BaseController;
class LoginController extends BaseController
{
public function accessToken()
{
// Validate credentials
$rules = [
'email' => [
'label' => 'Auth.email',
'rules' => config('AuthSession')->emailValidationRules,
],
'password' => [
'label' => 'Auth.password',
'rules' => 'required',
],
];
if (!$this->validate($rules)) {
return $this->response
->setJSON(['errors' => $this->validator->getErrors()])
->setStatusCode(422);
}
if (auth()->loggedIn()) {
auth()->logout();
}
// Attempt to login
$result = auth()->attempt([
'email' => $this->request->getPost('email'),
'password' => $this->request->getPost('password')
]);
if (!$result->isOK()) {
return $this->response
->setJSON(['error' => $result->reason()])
->setStatusCode(401);
}
// Generate token and return to client
$token = auth()->user()->generateAccessToken($this->getDeviceName());
return $this->response
->setJSON(['token' => $token->raw_token]);
}
public function getDeviceName()
{
$agent = $this->request->getUserAgent();
if ($agent->isBrowser()) {
$currentAgent = $agent->getBrowser() . ' ' . $agent->getVersion();
} elseif ($agent->isRobot()) {
$currentAgent = $agent->getRobot();
} elseif ($agent->isMobile()) {
$currentAgent = $agent->getMobile();
} else {
$currentAgent = 'Unidentified User Agent';
}
return $agent->getPlatform() . " - " . $currentAgent;
}
}
Protect your /api routes using the $filters setting on app/Config/Filters.php. Read: Protecting Routes
Exclude your 'access token' ("auth/token") route together with all API routes ("api/*") from the global "session" & "toolbar" filters.
File: app/Config/Filters.php
<?php
// ...
class Filters extends BaseConfig
{
// ...
public array $globals = [
'before' => [
'session' => ['except' => [
"login*",
"register",
"auth/a/*",
"auth/token",
"api/*"
]],
],
'after' => [
'toolbar' => ['except' => ["auth/token", "api/*"]],
],
];
// ...
public array $filters = [
'tokens' => ['before' => ["api/*"]],
];
}
Make a one-time initial HTTP POST request to the auth/token route to receive the 'access token'. Upon receiving the token, store it with the client. I.e: in localStorage
$.ajax({
url: "https://your-site-domain.com/auth/token",
type: "POST",
data: {
"email": "USER-EMAIL-ADDRESS-HERE",
"password": "USER-PASSWORD-HERE",
},
success: function (response) {
window.localStorage.setItem('token', response.token);
},
error: function (jqXHR) {
console.log(jqXHR.responseText);
},
});
You may now send the received/stored access token using the Authorization header along with all your other protected API HTTP requests in your application without reauthenticating the user. i.e:
$.ajax({
url: "https://your-site-domain.com/api/rest/v1/employees",
type: "GET",
beforeSend: function (jqXHR) {
jqXHR.setRequestHeader(
"Authorization",
"Bearer " + window.localStorage.getItem('token')
);
},
data: {},
success: function (response) {
// Use the response here on success.
// I.e: listing all employees in a table.
},
error: function (jqXHR) {
console.log(jqXHR.responseText);
},
});

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

How to do concurrent guzzle http post request to rest api in laravel?

I want to make concurrent Guzzle http requests in laravel to rest api i have users in 100k i want to perform billing for users.
Currently my guzzle http is doing synchronous calls to rest api which is taking 6 hours to complete 100k post requests and the requests does not have any call backs they are just post request with users msisdn and unique id in json format.
How to do concurrent 50 requests per second so that billing is performed quickly.
Following is part of my code which i use taken from https://docs.guzzlephp.org/en/stable/quickstart.html#concurrent-requests
$requests = function ($total) {
$url = "url here";
$auth = base64_encode($username . ":" . $password);
for ($i = 0; $i < $total; $i++) {
$msgdata =[
'msisdn'=>$msisdn,
$subscription
=>$subscriptionInfo];
yield new Request('post', $url,
[
'headers' =>
[
'Content-Type' => 'application/json',
'Authorization' => $authorizaton
],
'body' => json_encode($msgdata)
]);
}
$pool = new Pool($client, $requests(50), [
'concurrency' => 5,
'fulfilled' => function (Response $response, $index) {
// this is delivered each successful response
echo $response;
},
'rejected' => function (RequestException $reason, $index) {
// this is delivered each failed request
echo $reason;
},
]);
// Initiate the transfers and create a promise
$promise = $pool->promise();
// Force the pool of requests to complete.
$promise->wait();
i am getting response as
"status":401,"error":"Unauthorized"
But request params are not incorect idk why it is giving response as incorect
finally i found the solution to my problem, the problem was in request header and body parameters.
changed this
yield new Request('post', $url,
[
'headers' =>
[
'Content-Type' => 'application/json',
'Authorization' => $authorizaton
],
'body' => json_encode($msgdata)
]);
to
yield new Request('post', $url,
[
'Content-Type' => 'application/json',
'Authorization' => $authorizaton
],
json_encode($msgdata)
);

Shopify API in PHP using GuzzleHttp array of objects

I am currently attempting to update a bunch of products via the Shopify API, however, when I am sending the request, the product is created, however, it appears to be ignoring things where it is an array or arrays (for example, images or variants).
This is my Shopify Helper class that I am using for all requests.
class Shopify {
protected $api_key;
protected $password;
protected $url;
protected $host;
protected $secret;
protected $client;
public function __construct() {
$this->api_key = env('SHOPIFY_API_KEY');
$this->password = env('SHOPIFY_API_PASSWORD');
$this->secret = env('SHOPIFY_API_SHARED_SECRET');
$this->host = env('SHOPIFY_API_HOST');
$this->url = "https://{$this->api_key}:{$this->password}#{$this->host}";
$this->client = new Client();
}
public function __call($method, $args)
{
$method = strtoupper($method);
$allowedMethods = ['POST','GET','PUT','DELETE'];
if(!in_array($method,$allowedMethods)){
throw new InvalidMethodRequestException();
}
return $this->request($method,trim($args[0]),$args[1] ?? []);
}
protected function request(string $method, string $uri, array $payload)
{
$response = $this->client->request(
$method,
"{$this->url}{$uri}",
[
'form_params' => $payload
]
);
return json_decode($response->getBody());
}
}
Here is an example of me using this client to create a product with a variant:
$shopify = new Shopify();
$result = $shopify->post('/admin/api/2020-10/products.json', [
'product' => [
'title' => $product->title,
'body_html' => $product->body_text,
"variants" => [
[ "sku" => $product->sku, "price" => 20.00 ]
]
]
]);
As I mentioned above, the product is created in Shopify, but is missing anything where the data is an array of arrays. Could this be todo with the way GuzzleHttp encodes the data? How can get this data in a format that Shopify needs?
Your code looks good. The variants output maybe need some conversion to json format.
As you can see here, the expected post request:
"variants": [
{
"option1": "First",
"price": "10.00",
"sku": "123"
},
I would try to dump the post variable before the request and see what is wrong.
I made some successfull code with laravel in the past using Facades, and worked. But it took me some time to make it as shopify needs.
PS: I'm using tokens here https://www.shopify.com/partners/blog/17056443-how-to-generate-a-shopify-api-token
See:
//my endpoint, in your case '/admin/api/2020-10/products.json
$endpoint = config('endpoint');
//registered as a token.
$token = config('token');
$postFields = 'product' => [
'title' => $product->title,
'body_html' => $product->body_text,
"variants" => [
[ "sku" => $product->sku, "price" => 20.00 ]
]
];
//in case of any problems, you can uncomment this line and inspect your request.
//json_encode will help with this
//dd(json_encode($postFields));
return Http::withHeaders([
"content-type" => "application/json",
"Authorization" => "Bearer " . $token
])->post($endpoint, $postFields)->json();

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