Call JSON API with params in PHP (with example) - php

Formerly i used XML way to get data from external API. Now, internal company policy orders to use JSON to communicate with API. I know what data i should send in request and how data i'll get back but i have no idea how to call with API by JSON.
My PHP server is localhost.
Let JSON API be located https://api.example.com/service-api and i'm sure it works fine.
Request
{"action":"authorization", "args":{"username":"firstname#dev.com","password":"qpujy676"}}
Callback
{"status":"OK", "token":"8hsa77hh687y3sbdha7ah3dajknfa93"}
I found example but i dont know what is Http_client(), what is it role and what it will do.
$http = new Http_Client();
$http->setUri('https://api.example.com/service-api');
$postdata = array(
'action' => 'authorization',
'args' => array(
'username' => 'firstname#dev.com',
'password' => 'qpujy676',
)
);
if (CRYPT_KEY_API) { //if encrypted data
$postdata ['rand'] = md5(time() . rand(2303, 85500));
$postdata = json_encode($postdata);
$postdata = Crypt::encrypt($postdata);
} else {
$postdata = json_encode($postdata);
}
$http->setRawData($postdata, 'application/json');
$response = $http->request(POST);
if ($response->isSuccessful()) {
$responseData = $response->getBody();
if (CRYPT_KEY_API) { //if encrypted data
$responseData = Crypt::decrypt($responseData);
}
$results = json_decode($responseData, true);
} else {
$error_message = "<p>Error</p>\n";
$error_message .= "HTTP Status: " . $response->getStatus() . "\n";
$error_message .= "HTTP Headers:\n";
$responseHeaders = $response->getHeaders();
foreach ($responseHeaders as $responseHeaderName => $responseHeaderValue) {
$error_message .= "$responseHeaderName: $responseHeaderValue\n";
}
throw new Exception($error_message);
}
Practically i need only exemplary http_client class to solve my problem :-) Especially
setRawData($postdata, 'application/json')
request(POST)
getBody()
I creared method autorization_test(), that supposedly should response with external API. Supposedly, because it output is:
Warning:
file_get_contents(https://api.example.com/service-api):
failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in
C:\xampp\htdocs\prestashop1611\modules\miniwa\miniwa.php on line 180
Error
public function authorization_test()
{
$domain = MINIWA_DOMAIN;
$username = 'tester#user.com';
$password = '12345';
$postData = array(
'action' => 'authorization',
'args' => array(
'domain' => $domain,
'username' => $username,
'password' => $password,
),
);
$postData = json_encode($postData);
//$postData = Crypt::encrypt($postData);
$context = stream_context_create(array(
'http' => array(
// http://www.php.net/manual/en/context.http.php
'method' => 'POST',
'header' => 'Content-Type: application/json',
'content' => $postData,
)
));
// Send the request
$response = file_get_contents('https://api.example.com/service-api', FALSE, $context);
// Check for errors
if($response === FALSE){
die('Error');
}
//$response= Crypt::decrypt($response);
// Decode the response
$responseData = json_decode($response, TRUE);
// send the output data to view
$smarty->assign(array(
'json_decoded_output' => $responseData,
));
return $smarty;
Why there's no positive output?

Here you have whole documentation:
https://pear.php.net/manual/en/package.http.http-client.http-client-summary.php

API was disabled, now is OK, code is right.

Related

Recaptcha missing-input-response

I have a problem with google reCaptcha.
Here is my php code:
$secret = 'SECRET_KEY';
$response = $_POST['g-recaptcha-respone'];
$remoteip = $_SERVER['REMOTE_ADDR'];
$url = "https://www.google.com/recaptcha/api/siteverify?secret=$secret&response=$response&remoteip=$remoteip";
$result_json = file_get_contents($url);
$resulting = json_decode($result_json, true);
print_r($resulting);
if($resulting['success']) {
//Success
}
input of print_r is: Array ( [success] => [error-codes] => Array ( [0] => missing-input-response ) )
How to solve this problem?
Thanks for answers
Please note : g-recaptcha-respone != g-recaptcha-response
Google reCatcha API you might need to specify additional parameters to the file_get_contents function call, setting the context options specifically for SSL (If site has SSL).
// If submitted check response
if ($_POST["g-recaptcha-response"]) {
// Input data
$secret = 'SECRET_KEY';
$response = $_POST['g-recaptcha-response'];
$remoteip = $_SERVER['REMOTE_ADDR'];
$url = "https://www.google.com/recaptcha/api/siteverify";
$post_data = http_build_query(
array(
'secret' => $secret,
'response' => $response,
'remoteip' => $remoteip
)
);
$options=array(
// If site has SSL then
'ssl'=>array(
// In my case its /etc/ssl/certs/cacert.pem
'cafile' => '/path/to/cacert.pem',
'verify_peer' => true,
'verify_peer_name' => true,
),
'http' =>
array(
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => $post_data
)
);
$context = stream_context_create( $options );
$result_json = file_get_contents( $url, false, $context );
$resulting = json_decode($result_json, true);
if($resulting['success']) {
//Success
} else {
// action for no response
}
At least on ubuntu - If site has SSL
cd /usr/local/share/ca-certificates
sudo curl http://curl.haxx.se/ca/cacert.pem -o cacert.crt
sudo update-ca-certificates
sudo update-ca-certificates –fresh
and your cafile and path will be
capath=/etc/ssl/certs/
cafile=/etc/ssl/certs/cacert.pem
In my case I needed to add two extra parameters ('', '&') in this call:
http_build_query(array(
'secret' => $secret,
'response' => $response,
'remoteip' => $remoteip
), '', '&');
This error happened to me because I had two instances of the ReCaptcha element on my page (one for mobile views, one for desktop). As soon as I removed one of them this error stopped.
I'm not able to comment so I'm going to answer here. I copied my code which works perfectly and btw $_POST['g-recaptcha-respone'], are you sure your inputs name is g-recaptcha-respone?
$secret = 'SECRET-KEY';
$response = $_POST['g-recaptcha-response'];
$ip = $_SERVER['REMOTE_ADDR'];
$dav = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".$secret."&response=".$response."&remoteip=".$ip);
$res = json_decode($dav,true);
if ($res['success']) {
die(json_encode(0));
} else {
die(json_encode(1));
}
Just a note on this, you should be sending all your params via POST not GET (see https://developers.google.com/recaptcha/docs/verify#api_request). Use something like cURL to help make the request.

Post request with file_get_content not working

I am trying to use file_get_contents to "post" to a url and get auth token. The problem I am having is that it returns a error.
Message: file_get_contents(something): failed to open stream: HTTP request failed! HTTP/1.1 411 Length Required.
I am not sure what is causing this but need help. Here is the function.
public function ForToken(){
$username = 'gettoken';
$password = 'something';
$url = 'https://something.com';
$context = stream_context_create(array (
'http' => array (
'header' => 'Authorization: Basic ' . base64_encode("$username:$password"),
'method' => 'POST'
)
));
$token = file_get_contents($url, false, $context);
if(token){
var_dump($token);
}else{
return $resultArray['result'] = 'getting token failed';
}
}
I tried it with POSTMAN, and it works, so only problem I am having is that why isnt it working with file_get_contents.
Cannot command so i will do it this way. If you use Postman why don't you let Postman generate the code for you. In postman you can click code at a request and you can even select in what coding language you wanne have it. Like PHP with cURL:
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "http://somthing.com/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => array(
"password: somthing",
"username: gettoken"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
Hope this will help!
I can not comment because of my reputation;
In some servers file_get_content is not available...
You may try with CURL like this
Your request havent any data and content length is missing.
You can try this:
public function ForToken(){
$username = 'gettoken';
$password = 'something';
$url = 'https://something.com';
$data = array('foo' => 'some data');
$data = http_build_query($data);
$context_options = array (
'http' => array (
'method' => 'POST',
'header'=> "Content-type: application/x-www-form-urlencoded\r\n"
. "Authorization: Basic " . base64_encode("$username:$password") . "\r\n"
. "Content-Length: " . strlen($data) . "\r\n",
'content' => $data
)
);
$context = context_create_stream($context_options);
$token = file_get_contents($url, false, $context);
if(token){
var_dump($token);
}else{
return $resultArray['result'] = 'getting token failed';
}
}
Here is similar problem:
How to fix 411 Length Required error with file_get_contents and the expedia XML API?
RFC2616 10.4.12
https://www.rfc-editor.org/rfc/rfc2616#section-10.4.12
Code: (Doesn't work, see below)
public function ForToken(){
$username = 'gettoken';
$password = 'something';
$url = 'https://something.com';
$context = stream_context_create(array (
'http' => array (
'header' => 'Authorization: Basic ' . base64_encode("$username:$password") . 'Content-Length: ' . strlen($url) . '\r\n',
'method' => 'POST'
)
));
$token = file_get_contents($url, false, $context);
if(token){
var_dump($token);
}else{
return $resultArray['result'] = 'getting token failed';
}
}
2nd Try:
public function ForToken(){
$username = 'gettoken';
$password = 'something';
$url = 'https://something.com';
$context_options = array (
'http' => array (
'method' => 'POST',
'header'=> "Content-type: application/x-www-form-urlencoded\r\n" . "Authorization: Basic " . base64_encode("$username:$password") . "Content-Length: " . strlen($url) . "\r\n",
'content' => $url
)
);
$context = stream_context_create($context_options);
$token = file_get_contents($url, false, $context);
if(token){
var_dump($token);
}else{
return $resultArray['result'] = 'getting token failed';
}
}
This is from patryk-uszynski's answer formatted with the OP's code.

Google Short URL API: Forbidden

I have what I think is correctly written code yet whenever I try and call it I'm getting permission denied from Google.
file_get_contents(https://www.googleapis.com/urlshortener/v1/url): failed to open stream: HTTP request failed! HTTP/1.0 403 Forbidden
This isn't a rate limit or anything as I currently have zero ever used...
I would have thought this is due to an incorrect API key but I've tried resetting it a number of times. There isn't some downtime while the API is first applied is there?
Or am I missing a header setting or something else just as small?
public function getShortUrl()
{
$longUrl = "http://example.com/";
$apiKey = "MY REAL KEY IS HERE";
$opts = array(
'http' =>
array(
'method' => 'POST',
'header' => "Content-type: application/json",
'content' => json_encode(array(
'longUrl' => $longUrl,
'key' => $apiKey
))
)
);
$context = stream_context_create($opts);
$result = file_get_contents("https://www.googleapis.com/urlshortener/v1/url", false, $context);
//decode the returned JSON object
return json_decode($result, true);
}
It seems I need to manually specify the key in the URL
$result = file_get_contents("https://www.googleapis.com/urlshortener/v1/url?key=" . $apiKey, false, $context);
This now works. There must be something funny with how the API inspects POST for the key (or lack of doing so).
Edit: For anyone in the future this is my complete function
public static function getShortUrl($link = "http://example.com")
{
define("API_BASE_URL", "https://www.googleapis.com/urlshortener/v1/url?");
define("API_KEY", "PUT YOUR KEY HERE");
// Used for file_get_contents
$fileOpts = array(
'key' => API_KEY,
'fields' => 'id' // We want ONLY the short URL
);
// Used for stream_context_create
$streamOpts = array(
'http' =>
array(
'method' => 'POST',
'header' => [
"Content-type: application/json",
],
'content' => json_encode(array(
'longUrl' => $link,
))
)
);
$context = stream_context_create($streamOpts);
$result = file_get_contents(API_BASE_URL . http_build_query($fileOpts), false, $context);
return json_decode($result, false)->id;
}

Can file_get_contents() return HTML on 4xx?

I need to send a POST request from PHP to a remote HTTPS address, which returns a JSON.
I've used the following code:
//$url = ...
$data = array('username' => $username, 'password' => $passwort);
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data),
),
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
However at the last line the function fails with a failed to open stream: HTTP request failed! HTTP/1.1 403 FORBIDDEN error.
The server also sends an explanation in HTML format, but I have no idea how to access it through file_get_contents. Help?
EDIT: I will use cURL instead.
As far as I know it is not possible. But if you use an HTTP client like Guzzle you will be able to perform this request very easy and handle errors gracefully. Also Guzzle uses cURL under the hood so you don't have to deal with it directly!
Send your POST request like this:
$client = new GuzzleHttp\Client();
$response = $client->post($url, [
'body' => [
'username' => $username,
'password' => $password
]
]);
echo $response->getStatusCode(); // 200
echo $response->getHeader('content-type'); // 'application/json; charset=utf8'
echo $response->getBody(); // {"type":"User"...'
var_export($response->json()); // Outputs the JSON decoded data
Because you are placing the username and password in the body array it will automatically be url encoded!
You will be able to deal with errors in an OO way and get the body of the 4xx response if the response exists:
try {
$client->get('https://github.com/_abc_123_404');
} catch (RequestException $e) {
echo $e->getRequest();
if ($e->hasResponse()) {
echo $e->getResponse();
}
}
See the documentation for more information.

Make a HTTPS request through PHP and get response

I want to make HTTPS request through PHP to a server and get the response.
something similar to this ruby code
http = Net::HTTP.new("www.example.com", 443)
http.use_ssl = true
path = "uri"
resp, data = http.get(path, nil)
Thanks
this might work, give it a shot.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
// Set so curl_exec returns the result instead of outputting it.
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Get the response and close the channel.
$response = curl_exec($ch);
curl_close($ch);
for more info, check
http://unitstep.net/blog/2009/05/05/using-curl-in-php-to-access-https-ssltls-protected-sites/
To open HTTPS stream I could only work it out using both HTTP and SSL context options…
Thus something like:
<?php
$postdata = http_build_query(
array(
'var1' => 'some content',
'var2' => 'doh'
)
);
$opts = array(
'ssl' => array(
'verify_peer' => false,
'verify_peername' => false
// Instead ideally use
// 'cafile' => 'path Certificate Authority file on local filesystem'
),
'http' => array(
'method' => 'POST',
'header' =>
'Content-type: application/x-www-form-urlencoded'."\r\n".
''
'content' => $postdata
)
);
$context = stream_context_create($opts);
$result = file_get_contents('https://example.com/submit.php', false, $context);
// A Good friend
var_dump($http_response_header);
?>
The Zend Framework has a nice component called Zend_Http_Client which is perfect for this kind of transaction.
Under the hood it uses curl to make requests, but you'll find Zend_Http_Client has a much nicer interface to work with and is easier to configure when you want to add custom headers or work with responses.
If all you want to do is retrieve the page contents with minimal work, you may be able to do the following, depending on your server's configuration:
$data = file_get_contents('https://www.example.com/');
Example how to use HttpRequest to post data and receive the response:
<?php
//set up variables
$theData = '<?xml version="1.0"?>
<note>
<to>my brother</to>
<from>me</from>
<heading>hello</heading>
<body>this is my body</body>
</note>';
$url = 'http://www.example.com';
$credentials = 'user#example.com:password';
$header_array = array('Expect' => '',
'From' => 'User A');
$ssl_array = array('version' => SSL_VERSION_SSLv3);
$options = array(headers => $header_array,
httpauth => $credentials,
httpauthtype => HTTP_AUTH_BASIC,
protocol => HTTP_VERSION_1_1,
ssl => $ssl_array);
//create the httprequest object
$httpRequest_OBJ = new httpRequest($url, HTTP_METH_POST, $options);
//add the content type
$httpRequest_OBJ->setContentType = 'Content-Type: text/xml';
//add the raw post data
$httpRequest_OBJ->setRawPostData ($theData);
//send the http request
$result = $httpRequest_OBJ->send();
//print out the result
echo "<pre>"; print_r($result); echo "</pre>";
?>
There are 2 examples, GET and POST methods, but they both require the HttpRequest library to be included.
If you don't have the HttpRequest library included, kindly check this answer on how to include it: HttpRequest not found in php
GET example:
<?php
$r = new HttpRequest('http://example.com/feed.rss', HttpRequest::METH_GET);
$r->setOptions(array('lastmodified' => filemtime('local.rss')));
$r->addQueryData(array('category' => 3));
try {
$r->send();
if ($r->getResponseCode() == 200) {
file_put_contents('local.rss', $r->getResponseBody());
}
} catch (HttpException $ex) {
echo $ex;
}
?>
Post Example
<?php
$r = new HttpRequest('http://example.com/form.php', HttpRequest::METH_POST);
$r->setOptions(array('cookies' => array('lang' => 'de')));
$r->addPostFields(array('user' => 'mike', 'pass' => 's3c|r3t'));
$r->addPostFile('image', 'profile.jpg', 'image/jpeg');
try {
echo $r->send()->getBody();
} catch (HttpException $ex) {
echo $ex;
}
?>

Categories