Decoding JSON after sending using PHP cUrl - php

I've researched everywhere and cannot figure this out.
I am writing a test cUrl request to test my REST service:
// initialize curl handler
$ch = curl_init();
$data = array(
"products" => array ("product1"=>"abc","product2"=>"pass"));
$data = json_encode($data);
$postArgs = 'order=new&data=' . $data;
// set curl options
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLINFO_HEADER_OUT, TRUE);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postArgs);
curl_setopt($ch, CURLOPT_URL, 'http://localhost/store/rest.php');
// execute curl
curl_exec($ch);
This works fine and the request is accepted by my service and $_Post is populated as required, with two variables, order and data. Data has the encoded JSON object. And when I print out $_Post['data'] it shows:
{"products":{"product1":"abc","product2":"pass"}}
Which is exactly what is expected and identical to what was sent in.
When I try to decode this, json_decode() returns nothing!
If I create a new string and manually type that string, json_decode() works fine!
I've tried:
strip_tags() to remove any tags that might have been added in the http post
utf8_encode() to encode the string to the required utf 8
addslashes() to add slashes before the quotes
Nothing works.
Any ideas why json_decode() is not working after a string is received from an http post message?
Below is the relevant part of my processing of the request for reference:
public static function processRequest($requestArrays) {
// get our verb
$request_method = strtolower($requestArrays->server['REQUEST_METHOD']);
$return_obj = new RestRequest();
// we'll store our data here
$data = array();
switch ($request_method) {
case 'post':
$data = $requestArrays->post;
break;
}
// store the method
$return_obj->setMethod($request_method);
// set the raw data, so we can access it if needed (there may be
// other pieces to your requests)
$return_obj->setRequestVars($data);
if (isset($data['data'])) {
// translate the JSON to an Object for use however you want
//$decoded = json_decode(addslashes(utf8_encode($data['data'])));
//print_r(addslashes($data['data']));
//print_r($decoded);
$return_obj->setData(json_decode($data['data']));
}
return $return_obj;
}

Turns out that when JSON is sent by cURL inside the post parameters & quot; replaces the "as part of the message encoding. I'm not sure why the preg_replace() function I tried didn't work, but using html_entity_decode() removed the &quot and made the JSON decode-able.

old:
$return_obj->setData(json_decode($data['data']));
new:
$data = json_decode( urldecode( $data['data'] ), true );
$return_obj->setData($data);
try it im curious if it works.

Related

why i cant json_decode my response from API?

I have tried to get data from this source, which is school detail on my country. but when i get the response, i cannot decode my response and it say Null. Idk why, but when i try to copy and paste my response result to hardcode, it can be decoded. why ?
i have tried all possible way to solve this, nothing work.
this is my code :
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'http://jendela.data.kemdikbud.go.id/api/index.php/Csekolah/detailSekolahGET?mst_kode_wilayah=026700');
$response = $res->getBody()->getContents();
$result = json_decode($response); // this return NULL
//But when i going to return the $response, it show the response.
return $response;
I expect to access the data or maybe just decode my code, and it will help me a lot.
FYI, I'am using Guzzle 6 and Laravel 5.7 to work with this.
i hope someone can try too access it to and help me.
or maybe if you want to test it you can use Curl Ways :
$param = 'index.php/Csekolah/detailSekolahGET?mst_kode_wilayah=026700';
$url='http://jendela.data.kemdikbud.go.id/api/'.$param;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec ($ch);
return $response;
The json_decode document says:
NULL is returned if the json cannot be decoded or if the encoded data
is deeper than the recursion limit.
You can use json_last_error or json_last_error_msg function to determine the problem.
I can't get the whole response, it's timeout and terminated.
Remove the line return $response;
and try the following code:
$enc = mb_detect_encoding($response);
if($enc == 'UTF-8') {
$response = preg_replace('/[^(\x20-\x7F)]*/','', $response);
}
echo "<pre>";
print_r(json_decode($response,true));
Per the documentation:
NULL is returned if the json cannot be decoded or if the encoded data is deeper than the recursion limit
Source: json_decode
Some debugging tips:
Make sure all the characters fall within utf8
Specify a depth value(higher than the default)
Make use of json_last_error see: json_last_error
If debugging tip 1 happens to be the cause of the issue, see if you can limit the return to not include the offending characters.

how to get unknown string in $_GET method through URL

I want to pass a string from one PHP file to another using $_GET method. This string has different value each time it is being passed. As I understand, you pass GET parameters over a URL and you have to explicitly tell what the parameter is. What if you want to return whatever the string value is from providing server to server requesting it? I want to pass in json data format. Additionally how do I send it as Ajax?
Server (get.php):
<?php
$tagID = '123456'; //this is different every time
$tag = array('tagID' => $_GET['tagID']);
echo json_encode($tag);
?>
Server (rec.php):
<?php
$url = "http://192.168.12.169/RFID2/get.php?tagID=".$tagID;
$json = file_get_contents($url);
#var_dump($json);
$data = json_decode($json);
#var_dump($data);
echo $data;
?>
If I understand correctly, you want to get the tagID from the server? You can simply pass a 'request' parameter to the server that tells the server what to return.
EDIT: This really isn't the proper way to implement an API (like, at all), but for the sake of answering your question, this is how:
Server
switch($_GET['request']) {
case 'tagID';
echo json_encode($tag);
break;
}
You can now get the tagID with a URL like 192.168.12.169/get.php?request=tagId
Client (PHP with CURL)
When it comes to the client it gets a bit more complicated. You mention AJAX, but that will only work for JavaScript. Your php file can't use AJAX, you'll have to use cURL.
$request = "?request=tagID";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, '192.168.12.169/get.php' . $request);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, '3');
$content = trim(curl_exec($ch));
curl_close($ch);
echo $content;
EDIT: added the working cURL example just for completeness.
Included cURL example from: How to switch from POST to GET in PHP CURL
Client (Javascript with AJAX)
$.get("192.168.12.169/get.php?request=tagId", function(data) {
alert(data);
});

How to get access the properties in this json response?

I am executing a curl request and get a response which returns a json response. Below is the code after the response is sent back.
Response: "Zeros Replaced real token"
{"success":true,"result":{"token":"000000000","serverTime":1471365111,"expireTime":1471365411}}1
Code Used (For Testing) and accessing property:
$json = json_decode($result);
print_r($json); // Prints the Json Response
$firsttry = $json->result['token']; //Access Property results in error :Trying to get property of non-object
$secondtry = $json['token'];
echo $firsttry.'<br>';//Code can't continue because of error from $firsttry.
print_r( $secondtry.'<br>');//Nothing Prints at all
I did notice a weird anomaly where it prints a 1 at the end, where as if i do
json_encode($json);
The return response replaces the one at the end of the string with a "true"
Could the "1 or true" at the end be throwing of the json decode?
Maybe I am missing something simple?
As Requested full test code
$url = "https://website.com/restapi.php";
//username of the user who is to logged in.
$userName="adminuser"; //not real user
$fields_string; //global var
$fields = array( //array will have more in the future
'username' => urlencode($userName)
);
//url-ify the data for the POST
foreach($fields as $key=>$value) { global $fields_string;
$fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string, '&');
//open connection
$ch = curl_init();
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $url.'?'.$fields_string.'operation=getchallenge');
curl_setopt($ch,CURLOPT_POST, count($fields));
//execute post
$result = curl_exec($ch);
//close connection
curl_close($ch);
json_decode(), by default makes child objects into stdClass objects rather than arrays unless they are explicitly arrays.
Try something like:
$firsttry = $json->result->token;
The var_dump shows you the data type. Since result itself is an object, access its token with -> rather than []
$response = '{"success":true...}'
$json = json_decode($response); //var_dumping this will show you it's an object
echo $json->result->token; // 000000000
I figured out the issue. In the Curl Options I did not have
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
Once i put this in #GentelmanMax solution worked for me, but the issue was in the curl response responding directly, where as the return transfer sends back a string that php can work with, which then allowed json_decode()to function as is should. I knew it was something simple.

Can't post # to API via curl PHP

I have something very strange going on here. I am building a API using CodeIgniter that uses data posted to it via CURL.
A WordPress site is posting information to the CodeIgniter API, and all is working, apart from when a password input field posts a string containing an #.
I straight away put this down to XSS protection, but this is disabled. I get no CURL errors, and the data isn't received by the CodeIgniter method (but is when there's no #).
I've tried everything, googled it to no avail, tried using htmlentities(), no luck whatsoever.
I've tried printing $_POST['fieldname'] before the data gets passed to CURL and it prints the string back (even when containing '#'), and on the codeIgniter side to debug, I've tried getting a method to return the sent data which it does, unless the sent data contains #. At my whits end, tried using my REST client to test codeIgniter API and that strangely works fine when sending strings with #, so I'm guessing its something wrong with the CURL command?
Thanks in advance.
Ste
-- EDIT: Code --
/* WORDPRESS SITE */
// ....
// When $_POST['pass'] doesn't contain '#' it passes data fine,
// print $_POST['pass'] works too even with an '#'...
// ...also tried htmlentities($_POST['pass']) with no luck
$data_to_post = array('pass' => $_POST['pass'], 'user' => $_POST['user']);
$result = do_api_call('return_posted_values', $data_to_post);
// ....
function do_api_call($method, $request = array()) {
$ch = curl_init(API_URL.$method);
// Add the api key to the request
$request['api_key'] = API_KEY;
foreach ($request as $key => $value) {
// Serialize any arrays
if (is_array($value)) $request[$key] = serialize($value);
}
// Set the curl
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
$status = curl_getinfo($ch);
curl_close($ch);
//print $result;
$result = json_decode($result);
return $result;
}
/* CODEIGNITER SIDE */
/* THIS METHOD IS IN API CLASS */
public function return_posted_values() {
// Return the posted data as string works fine when the data has no #
$return $this->input->post('user').' - '.$this->input->post('pass');
$this->response($return);
}
Replace # with %40 inside your password. or use urlencode() function over the password to escape these characters.

Callback from API not happening after posting parameters to API URL from server side

API integration description
The API needs a form to be posted to the API URL with some input fields and a customer token. The API processes and then posts response to a callback.php file on my server. I can access the posted vals using $_POST in that file. That's all about the existing method and it works fine.
Requirement
To hide the customer token value from being seen from client side. So I started with sending server side post request.
Problem
I tried with many options but the callback is not happening -
1) CURL method
$ch = curl_init(API_URL);
$encoded = '';
$_postArray['customer_token'] = API_CUSTOMER_TOKEN;
foreach($_postArray as $name => $value)
{
$encoded .= urlencode($name).'='.urlencode($value).'&';
}
// chop off last ampersand
$encoded = substr($encoded, 0, strlen($encoded)-1);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $encoded);
$resp = curl_exec($ch);
curl_close($ch);
echo $resp;
$resp echoes 1 if the line curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); is removed but the callback does not happen. I am setting a session variable in the callback script to verify.Is it needed that the API be synchronous in order to use curl method, so that curl_exec returns the response?
2) without CURL as given in Posting parameters to a url using the POST method without using a form
But the callback is not happening.
I tried with the following code too, but looks like my pecl is not installed properly because the HttpRequest() is not defined.
$req = new HttpRequest($apiUrl, HttpRequest::METH_POST);
$req->addQueryData($params);
try
{
$r->send();
if ($r->getResponseCode() == 200)
{
echo "success";
// success!
}
else
{
echo "failure";
// got to the API, the API returned perhaps a RESTful response code like 404
}
}
catch (HttpException $ex)
{
// couldn't get to the API (probably)
}
Please help me out! I just need to easily send a server side post request and get the response in the callback file.
Try to debug your request using the curl_get_info() function:
$header = curl_getinfo($ch);
print_r($header);
Your request might be OK but it my result in an error 404.
EDIT: If you want to perform a post request, add this to your code:
curl_setopt($ch, CURLOPT_POST, true);
EDIT: Something else I mentioned at your code: You used a '1' at the 'CURLOPT_RETURNTRANSFER' but is should be 'true':
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
At least this is how I usually do it, and you never know if the function will also understand a '1' as 'true';
EDIT: The real problem: I copy-pasted your source and used it on one of my pages getting this error:
Warning: urlencode() expects parameter 1 to be string, array given in C:\xampp\htdocs\phptests\test.php on line 8
The error is in this line:
foreach($_postArray as $name => $value)
$_postArray is an array with one value holding the other values and you need either another foreach or you simple use this:
foreach($_postArray['customer_token'] as $name => $value)
As discussed in the previous question, the callback is an entirely separate thing from your request. The callback also will not have your session variables, because the remote API is acting as the client to the callback script and has its own session.
You should really show some API documentation here. Maybe we're misunderstanding each other but as far as I can see, what you are trying to do (get the callback value in the initial CURL request) is futile, and doesn't become any less futile by asking twice.

Categories