Sending JSON to PHP via jQuery AJAX [duplicate] - php

This question already has answers here:
Sending JSON to PHP using ajax
(8 answers)
Closed 5 years ago.
I have looked at a bunch of questions/answers on here and none of them seem to solve my problem. I am integrating a payment system that returns a JSON string via a JS library that I then need to parse on the server to compare the hash values to ensure that it is valid. So I get their response and attempt to pass it via jQuery AJAX to a PHP file on the server. The response I get from the payment system is valid JSON. If I pass it directly the result I get on the server seems to be URL encoded. If I JSON.stringify() it, it adds a bunch of extra quotes which results in invalid JSON.
function isValidJSON($str) {
json_decode($str);
return json_last_error() == JSON_ERROR_NONE;
}
$json_params = file_get_contents("php://input");
error_log($json_params);
//error_log($_POST['jsresp']);
//$respObj = json_decode(stripslashes($_POST['jsresp']));
//error_log($json_params);
if (strlen($json_params) > 0 && isValidJSON($json_params)) {
$respObj = json_decode($json_params);
} else {
error_log('bad json '.$json_params);
}
$result = 0;
$resp = json_encode($respObj->Response);
$hash = $respObj->Hash;
error_log($hash);
$calcHash = base64_encode(hash_hmac('sha512', $resp, $app->getSageClientSecret(), true));
error_log($calcHash);
if($hash === $calcHash) {
$result = 1;
}
$app->updateCartResponse($_COOKIE['qid'], $result);
And here is the jQuery AJAX call to send the data:
$(document).on('click', 'button#sps-close.sps.btn.btn-primary', function(){
var resp = $("#resp_holder").val();
$.ajax({
url: "<?=$env?>sources/processors/process_hash.php",
data: { jsresp : resp },
type: "post",
//dataType: "json",
success: function( data ) {
// nothing to do here.
}
});
var url = $("#redirect_url").val();
if(url != "") {
location.href = $("#redirect_url").val();
}
});
When I do it this way, the JSON that gets to the server looks like this:
jsresp%5Bresponse%5D=%7B%22requestId%22%3A%22443594%22%2C%22gatewayResponse%22%3A%7B%22status%22%3A%22Approved%22%2C%22reference%22%3A%22EBGHNHChw0%22%2C%22message%22%3A%22APPROVED+658658%22%2C%22code%22%3A%22658658%22%2C%22cvvResult%22%3A%22P%22%2C%22avsResult%22%3A%22+%22%2C%22riskCode%22%3A%2200%22%2C%22networkId%22%3A%2210%22%2C%22isPurchaseCard%22%3Afalse%2C%22orderNumber%22%3A%22443594%22%2C%22transactionId%22%3A%22NDViMWYzNmEwNWNiOGQxZjIwOTAwNzU4MmVjYzJhMWQ%22%2C%22timestamp%22%3A%222017-11-16T23%3A17%3A12.6584893-05%3A00%22%7D%7D&jsresp%5Bhash%5D=bgd1e0Cxhj5s1FQaUFFYk7BMnSIl4Ez1jPMopZFp%2B4MyN9chFZZoo%2F3IuZPX7bbQ%2BRyaReKN1CNJXxRmjnLMRQ%3D%3D
I don't understand what I'm doing wrong or how to get it there properly.

Based on your sample, this is what you get on the server
jsresp[response]={"requestId":"443594","gatewayResponse":{"status":"Approved","reference":"EBGHNHChw0","message":"APPROVED 658658","code":"658658","cvvResult":"P","avsResult":" ","riskCode":"00","networkId":"10","isPurchaseCard":false,"orderNumber":"443594","transactionId":"NDViMWYzNmEwNWNiOGQxZjIwOTAwNzU4MmVjYzJhMWQ","timestamp":"2017-11-16T23:17:12.6584893-05:00"}}&jsresp[hash]=bgd1e0Cxhj5s1FQaUFFYk7BMnSIl4Ez1jPMopZFp+4MyN9chFZZoo/3IuZPX7bbQ+RyaReKN1CNJXxRmjnLMRQ==
So your $_REQUEST['jsresp'] is an array
you need to json_decode the 'response' index of the array :
$respObj = json_decode($_REQUEST['jsresp']['response']);
$hash = $_REQUEST['jsresp']['hash'];
And then you can go on...

First i will advice you to look at the value in your #resp_holder, if the value there is correct as you want it, then you can post it using anyhow you want it, json is a string, and as long as that string conforms to json standard, and they are no special characters in the it like &, then you can decode it in your php.
You can use html or json dataType to post it.

Related

I would like to normalize my json data on server side for XSS prevention. Am i doing it the right way?

I am implementing the XSS prevention cheat rules in my app and I currently working on escaping/securing Json data and wondering if I am doing it right?
According to Rule 3.1 in the XSS prevention cheat sheet "An alternative to escaping and unescaping JSON directly in JavaScript, is to normalize JSON server-side by converting '<' to '\u003c' before delivering it to the browser."
So I have created a function in php called normalizeJson which takes in an associative array as a parameter and converts all < characters to \u003c, returning the data in json format.
I am wondering if this is the best way to do this?
I'm unsure as to whether it is ok to json_encode twice here however it didn't work when I had return $new_json (without json_encoding it again.)
function normalizeJson($data){
$json = json_encode($data);
$new_json = str_replace("<","\u003c",$data);
return json_encode($new_json);
}
Also it states in the same rule, "read the data with JSON.parse" however when I use the contentType: "application/json;charset=utf-8" in my ajax request and try parse the response with JSON.parse(data) it doesn't work.
It works perfect without JSON.parse(). I'm guessing this is because it is expecting json as a response anyway and so doesn't need to parse it with JSON.parse() but I would like clarification on this if anyone knows.
Client side Ajax request:
var token = localStorage.getItem("usertoken");
var params = {'usertoken': token, 'engage_post_text' : engage_post_text, 'post_type' : post_type};
$.ajax({
//do an ajax request passing along the user json web token for validation on server side and also the text that was submitted.
url: app_root_url + 'submit_post.php',
data: JSON.stringify(params),
type: "POST",
dataType: "json",
contentType: "application/json;charset=utf-8",
success: function(data){
var result = data;//JSON.parse(data);
var successful_insert = result.successful_insert;
if(successful_insert){
//do stuff with json data
}else{
//error
}
}
});
My php code where the ajax request is sent, and I use the normalizeJson function before returing the json back to the client side.
//need to get the data this way because we have contentType application/json set, so $_POST will no longer be populated
$rawPostData = file_get_contents('php://input');
$json = json_decode($rawPostData);
if(isset($json->usertoken)){
$token = JWT::decode($json->usertoken, 'secret_server_key'); //this will return an error if token has been tampered with
$data = array();
if($token->userID){
//token is valid and therefore user is valid so we go ahead submit the form.
$data['token_is_valid'] = true;
if(isset($json->engage_post_text)){
$postText = $json->engage_post_text;
$postType = filter_var($json->post_type, FILTER_SANITIZE_STRING);
$postTime = time();
$user_id = $token->userID;
$result = insertEngagePost($postTime, $user_id, $postText, $postType, $pdoConnection);
if($result['successful_insert'] == true){
$data['successful_insert'] = true;
$data['post_id'] = $result['post_id'];
$data['userDetails'] = getProfile($user_id, $pdoConnection);
}else{
$data['successful_insert'] = false;
}
//send back json to client side ajax request
echo normalizeJson($data);
}
}else{
//token is set but is not valid
$data['token_is_valid'] = false;
echo normalizeJson($data);
}
}else{
//token is not set.
}

json_encode(string) giving backslashes in response

I am creating an array of objects in js and sending it to one of my controllers after stringify'ing the array.
var arr = new Array();
for(i=0;i<noOfDeals;i++){
var deals = {'percentageMin':document.getElementById("pmin"+i).value,
'percentageMax':document.getElementById("pmax"+i).value,
'modelApplicable': document.getElementById("model"+i).value,
'maxCashback' : document.getElementById("maxcash"+i).value,
'dealId' : document.getElementById("deal"+i).value
};
arr.push(deals);
}
alert(JSON.stringify(arr));
$.ajax({method:'get',url:'abc?data='+JSON.stringify(arr),success:function(response) {
//response = JSON.parse(response);
response = JSON.parse(response);
alert(response.body);
response = JSON.parse(response.body);
if(response.status != undefined && response.status == 'SUCCESS') {
alert('Merchant details updated successfully. Refresh the page to see the changes.');
}
else {
alert('Could not update merchant details, Some Error Occurred');
}
}});
In my controller i am encoding the data and then sending to hit the API :
public function updateselectedmerchants(){
if (isset($_GET['data'])) {
$str_data = $_GET['data'];
print_r(json_encode(array('deals' => $str_data)));
die;
}
}
The Output :
{"deals":"[{\"percentageMin\":\"1.00\",\"perentageMax\":\"0.00\",\"modelApplicable\":\"3\",\"maxCashback\":\"30.00\",\"dealId\":\"7\"}"}
The desired output :
{"deals":[{\"percentageMin\":\"1.00\",\"perentageMax\":\"0.00\",\"modelApplicable\":\"3\",\"maxCashback\":\"30.00\",\"dealId\":\"7\"}]}
There are three things which are unwanted in the output which is coming :
1) The double quotes before the first square brackets should not be there.
2) The ending square bracket is not present
3) "/" appearing
Please help me with this.
You should do
$str_data = json_decode($_GET['data'], true);
print_r(json_encode(array('deals' => $str_data)));
Otherwise $str_data remains a string, and will be JSON encoded as such, while it looks like you want it to be a PHP array structure, and then encode all of that into valid JSON again.
See this PHP 'fiddle'
You probably generate " or ' somewhere you dont want to.
Not sure if it work 100%, but try:
public function updateselectedmerchants(){
if (isset($_GET['data'])) {
$str_data = json_decode($_GET['data']);
print_r(json_encode(array('deals' => $str_data)));
die;
}
}
You should try PHP approach:
http://php.net/manual/en/function.urlencode.php
http://php.net/manual/en/function.urldecode.php
Just decode array and encode it on the other side.

Transfer JavaScript Array to PHP array using ajax?

I am trying to transfer a list of data from a javascript array to a php array and I can't seem to get ajax to do the trick. Can someone show me the code on how to do this? So far here is what I have, which is just the array:
JAVASCRIPT
var dates;
// the dates array is then filled up here
// it contains information in the form {'2012-01-01', '2012-03-12', ...}
$.ajax({
type: "REQUEST",
url: "NAMEOFPHPFILE.php",
data: { sendData1 : dates },
success: function() {
alert("Attempting to transfer array -> AJAX");
}
});
var submissions;
// the submissions array is then filled up here
// it contains information in the form {int, int, ...}
// ect ......... with 3 more arrays using { sendData2 : submissions },
PHP
<?php
$bDates = $_REQUEST['sendData1'];
// need to set this array = to the JavaScript dates array
$bSubmissions = $_REQUEST['sendData2'];
// need to set this array = to the JavaScript submissions array
?>
I would prefer to use the REQUEST method to prevent information logging into the URL. This code also doesn't work when trying POST instead of REQUEST
At the very end of the .php page, I am outputting a bunch of arrays onto a CSV page where I iterate through the arrays and place their elements in the file. This already works, but I need to transfer some of these arrays from javascript to PHP so that I can spit out the data. That looks like this:
<?php
$stringData = "Dates, Number of Lines Changed, , Bug Dates, Arrivals, Fixed, Closed, Hold_";
for($i = 0; $i < sizeof($dataXAxis); $i++){
$date = substr($_REQUEST['Dates'][$i+1], 0, 24);
$stringData .= "$date, $dataYAxis[$i], , $bDates[$i], $bSubmissions[$i], $bCompletions[$i], $bDones[$i], $bRejections[$i]_";
}
echo '<BR><BR>Download Your CSV File';
?>
Why doesn't the AJAX work? The arrays appear empty...
One method would be to try sending the data in the form of JSON. Then using json_decode, you can convert it to an array. Example:
var Json = {"User1":"John", "User2":"Joe", "User3","Jerry"};
var data = "data="+Json;
hr = new XMLHttpRequest();
hr.onreadystatechange = function(){
if(hr.readyState == 4 && hr.status == 200){
console.log(hr.responseText);
}
}
hr.open("POST", "parsefile.php", true);
hr.send(data);
Then when you get the data in your PHP file it's something like:
$data = $_POST['data'];
$array = json_decode($data, true);
This all will tell php to turn our data into an assosciative array. It can then be manipulated as an assosciative array.
I was literally just working on this.
jQuery
var group_ids = $('.form-elements li').map(function(){
return $(this).data('group-id')
}).get()
$.get('{{ url('group/update_order_by') }}', {group_ids: group_ids});
PHP from the restful Laravel framework
public function get_update_order_by()
{
$group_ids = Input::get("group_ids");
$group_count = count($group_ids);
for ($i = 0; $i < $group_count; ++$i) {
$group = Group::find($group_ids[$i] );
$group->order_by = $i;
$group->save();
}
return true;
}
Raw PHP (ugh...)
$group_ids = $_GET("group_ids");
$group_count = count($group_ids);
for ($i = 0; $i < $group_count; ++$i) {
echo $group_ids[$i];
}
return true;
The simply convert an array to string
var data = [1,2,"hello"];
var data_str = data.join(",");
and afterwards convert the string to array in php:
$array = explode(",", $_REQUEST["data"]);
In PHP, the REQUEST expects arrays to be passed in the following format:
sendData1[]=first&sendData1[]=second&sendData1[]=third
This is automatically converted into an array:
$sendData = $_REQUEST['sendData`];
echo $sendData[0];
echo $sendData[1];
First, for the sake of simplicity, create an array holding both arrays you want to send and parse:
var request = Array(dates, submissions);
Second, make sure you're sending your request as properly formatted JSON. In addition, when testing I recommend returning the output from the remote file in your callback to see how your data was parsed. I recommend the following implementation, as well as sending via POST:
$.ajax({
type: "POST",
url: "NAMEOFPHPFILE.php",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(request),
success: function(data) {
alert(data);
}
});
In your PHP file, get you can parse the contents of the aforementioned request into an array using the following:
<?php
// convert json data read from the input stream to an array
// *note* you MUST set the true flag in the json_decode() function, otherwise it will convert the data into an object
$request = json_decode(file_get_contents('php://input'), true);
var_dump($request);
You should now get an alert containing the var_dump of the array(looks messy, I know!).
This should be enough to get you started, hope it helps!

How to pass HTML via JSON from PHP to AJAX - properly

I'm still in AJAX stuff since morning so maybe thats the reason why some things does't work as they schould - let's forget about it. To sum up, my problem is coincident with passing HTML via JSON. An example of the PHP code:
$list = "<strong>This is test</strong>";
$response = array('success'=>true, 'src' => $list);
echo json_encode($response);
Basicly that's the main part of the code which is responsible for passing the HTML to AJAX. Now, let's have a look on part of AJAX code:
success: function(output)
{
alert(output);
json = $(output).find(".content").text();
var data = $.parseJSON(json);
if(data.success == true)
{
obj_a.parents(".row").append(data.src);
obj_a.attr("id", "rollBack");
obj_a.text("Roll back");
}
},
Some of you will ask what am I doing in this part:
json = $(output).find(".content").text();
The answer is: I retrieve the json string from the ".content" box, so when I alert variable "json: i get:
{"success":true,"src":"1. dsfasdfasdffbcvbcvb<\/span>Edytuj<\/span> <\/a>Usu \u0144<\/span><\/div>2. vbnvbnm454t<\/span>Edytuj<\/span><\/a>Usu\u0144<\/span><\/div>3. ndfhgndgfhndfhgndfhd<\/span>Edytuj<\/span><\/a>Usu\u0144<\/span><\/div><\/div>"}
The problem is that I do not get this HTML... I get only text witout any HTML tags, styles etc...
String which I get, rather than HTML:
"1. dsfasdfasdffbcvbcvbEdytujUsuń2. vbnvbnm454tEdytujUsuń3. ndfhgndgfhndfhgndfhdEdytujUsuń"
Please don't try to look for anything smart or gunius in the above string because u won't - it's only a test string.
Acording to the part of PHP code - in my case I get "This is test" rather than "This is test".
To sum up my question is, how to pass these HTML tags or whole HTML code via json from PHP to AJAX.
I think you're misunderstanding how jQuery.ajax() works. You just need to tell it that dataType: 'json' (meaning that you're expecting JSON output from the server), and it takes care of the rest. You don't need to use jQuery.parseJSON(). The success() method will be given a JavaScript object representing the server response.
success: function(output)
{
// output is a JS object here:
alert(output.success); // true
// ...
},
To get your HTML from that point, you would just access output.src.
You can specify dataType: 'json' in your ajax request and receive an object(i.e. json already parsed) in your success call. eg
$.ajax(url, {
dataType: 'json',
success: function(output)
{
if(output.success == true)
{
obj_a.parents(".row").append(output.src);
obj_a.attr("id", "rollBack");
obj_a.text("Roll back");
}
},
if you can't change dataType you would call $.parseJSON on output
function(output)
{
alert(output);
var data = $.parseJSON(output);
if(data.success == true)
{
obj_a.parents(".row").append(data.src);
obj_a.attr("id", "rollBack");
obj_a.text("Roll back");
}
},

Getting json on Ajax response callback

I am trying to create a little ajax chat system (just for the heck of it) and I am using prototype.js to handle the ajax part.
One thing I have read in the help is that if you return json data, the callback function will fill that json data in the second parameter.
So in my php file that gets called I have:
header('Content-type: application/json');
if (($response = $acs_ajch_sql->postmsg($acs_ajch_msg,$acs_ajch_username,$acs_ajch_channel,$acs_ajch_ts_client)) === true)
echo json_encode(array('lastid' => $acs_ajch_sql->msgid));
else
echo json_encode(array('error' => $response));
On the ajax request I have:
onSuccess: function (response,json) {
alert(response.responseText);
alert(json);
}
The alert of the response.responseText gives me {"lastid": 8 } but the json gives me null.
Anyone know how I can make this work?
This is the correct syntax for retrieving JSON with Prototype
onSuccess: function(response){
var json = response.responseText.evalJSON();
}
There is a property of Response: Response.responseJSON which is filled with a JSON objects only if the backend returns Content-Type: application/json, i.e. if you do something like this in your backend code:
$this->output->set_content_type('application/json');
$this->output->set_output(json_encode($answer));
//this is within a Codeigniter controller
in this case Response.responseJSON != undefined which you can check on the receiving end, in your onSuccess(t) handler:
onSuccess:function(t) {
if (t.responseJSON != undefined)
{
// backend sent some JSON content (maybe with error messages?)
}
else
{
// backend sent some text/html, let's say content for my target DIV
}
}
I am not really answering the question about the second parameter of the handler, but if it does exist, for sure Prototype will only provide it in case of proper content type of the response.
This comes from Prototype official :
Evaluating a JavaScript response
Sometimes the application is designed
to send JavaScript code as a response.
If the content type of the response
matches the MIME type of JavaScript
then this is true and Prototype will
automatically eval() returned code.
You don't need to handle the response
explicitly if you don't need to.
Alternatively, if the response holds a
X-JSON header, its content will be
parsed, saved as an object and sent to
the callbacks as the second argument:
new Ajax.Request('/some_url', {
method:'get', onSuccess:
function(transport, json){
alert(json ? Object.inspect(json) : "no JSON object");
}
});
Use this functionality when you want to fetch non-trivial
data with Ajax but want to avoid the
overhead of parsing XML responses.
JSON is much faster (and lighter) than
XML.
You could also just skip the framework. Here's a cross-browser compatible way to do ajax, used in a comments widget:
//fetches comments from the server
CommentWidget.prototype.getComments = function() {
var commentURL = this.getCommentsURL + this.obj.type + '/' + this.obj.id;
this.asyncRequest('GET', commentURL, null);
}
//initiates an XHR request
CommentWidget.prototype.asyncRequest = function(method, uri, form) {
var o = createXhrObject()
if(!o) { return null; }
o.open(method, uri, true);
o.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
var self = this;
o.onreadystatechange = function () {self.callback(o)};
if (form) {
o.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
o.send(makePostData(form));
} else {
o.send('');
}
}
//after a comment is posted, this rewrites the comments on the page
CommentWidget.prototype.callback = function(o) {
if (o.readyState != 4) { return }
//turns the JSON string into a JavaScript object.
var response_obj = eval('(' + o.responseText + ')');
this.comments = response_obj.comments;
this.refresh()
}
I open-sourced this code here http://www.trailbehind.com/comment_widget

Categories