414

I’m trying to receive a JSON POST on a payment interface website, but I can’t decode it.

When I print :

echo $_POST;

I get:

Array

I get nothing when I try this:

if ( $_POST ) {
    foreach ( $_POST as $key => $value ) {
        echo "llave: ".$key."- Valor:".$value."<br />";
    }
}

I get nothing when I try this:

$string = $_POST['operation'];
$var = json_decode($string);
echo $var;

I get NULL when I try this:

$data = json_decode( file_get_contents('php://input') );
var_dump( $data->operation );

When I do:

$data = json_decode(file_get_contents('php://input'), true);
var_dump($data);

I get:

NULL

The JSON format is (according to payment site documentation):

{
   "operacion": {
       "tok": "[generated token]",
       "shop_id": "12313",
       "respuesta": "S",
       "respuesta_details": "respuesta S",
       "extended_respuesta_description": "respuesta extendida",
       "moneda": "PYG",
       "monto": "10100.00",
       "authorization_number": "123456",
       "ticket_number": "123456789123456",
       "response_code": "00",
       "response_description": "Transacción aprobada.",
       "security_information": {
           "customer_ip": "123.123.123.123",
           "card_source": "I",
           "card_country": "Croacia",
           "version": "0.3",
           "risk_index": "0"
       }
    }
}

The payment site log says everything is OK. What’s the problem?

dakab
  • 5,379
  • 9
  • 43
  • 67
Pablo Ramirez
  • 4,177
  • 3
  • 12
  • 5
  • 4
    What does `var_dump($_POST)` say? Is it an empty array? – Sergiu Paraschiv Sep 18 '13 at 07:51
  • `var_dump($_POST);` what you get? – Bora Sep 18 '13 at 07:51
  • 4
    $_POST has the dictionary of "&" separated post requests. $_POST for json will DEFINITELY not work. Can you print file_get_contents('php://input')? Also is it var_dump($data->operation); or var_dump($data->operacion); ? – Akshaya Shanbhogue Sep 18 '13 at 07:53
  • Try `'; print_r($_POST); echo ''; ?>` What does that show? – ajtrichards Sep 18 '13 at 08:02
  • 5
    JSON is text, why wouldn't it be accessible in POST? As long as the payment service POSTs that text to his PHP endpoint then he should be able to `json_decode` it. But maybe the service sends data in _request body_, that's a different story and yes, `file_get_contents('php://input')` should work then. – Sergiu Paraschiv Sep 18 '13 at 08:03
  • 2
    If so then this has been discussed here: http://stackoverflow.com/questions/8945879/how-to-get-body-of-a-post-in-php – Sergiu Paraschiv Sep 18 '13 at 08:04
  • Hi. Thanks everyone. When I do `var_dump($_POST)` I get array(0) { }. When I do `echo '
    '; print_r($_POST); echo '
    ';` I get Array ( ) And yes, documentation says "we will make post request sending json in request body" When I do `$entityBody = file_get_contents('php://input'); var_dump($entityBody);` I get string(0)
    – Pablo Ramirez Sep 18 '13 at 08:52
  • Update> When I do `$data = json_decode(file_get_contents('php://input'), true); var_dump($data);` I get `NULL` – Pablo Ramirez Sep 18 '13 at 09:18
  • 5
    $_POST: _An associative array of variables passed to the current script via the HTTP POST method_ **when using application/x-www-form-urlencoded or multipart/form-data as the HTTP Content-Type in the request.** Not when using application/json. – Cristian Sepulveda May 17 '18 at 16:39
  • @PabloRamirez Hi, may i know did you have the solution? Because i also have this issue. https://stackoverflow.com/questions/18866571/receive-json-post-with-php#comment27842965_18866571 – Ying Rui Wong Aug 26 '20 at 07:52

13 Answers13

645

Try;

$data = json_decode(file_get_contents('php://input'), true);
print_r($data);
echo $data["operacion"];

From your json and your code, it looks like you have spelled the word operation correctly on your end, but it isn't in the json.

EDIT

Maybe also worth trying to echo the json string from php://input.

echo file_get_contents('php://input');
Dom
  • 7,135
  • 1
  • 11
  • 13
130

If you already have your parameters set like $_POST['eg'] for example and you don't wish to change it, simply do it like this:

$_POST = json_decode(file_get_contents('php://input'), true);

This will save you the hassle of changing all $_POST to something else and allow you to still make normal post requests if you wish to take this line out.

Steve C
  • 2,638
  • 3
  • 25
  • 27
  • 1
    Thank you sir. This worked in my case as I am doing json posting from Android to PHP! – vanurag Mar 21 '18 at 11:51
  • Thank you, it did work in my case. I was assigning the $_POST data to a $request variable, now I just assigned to that variable the content of php://input. – funder7 Aug 07 '19 at 12:55
  • Hi, I have something like this in php `$sql = "INSERT INTO userdetails (email, username) VALUES ('".$_POST['email']."', '".$_POST['username']."')"; if (mysqli_query($conn,$sql)) { $data = array("data" => "You Data added successfully"); echo json_encode($data);` . How can I change the code here so that I can pass json and push into phpmysql database fields ? – NoobCoder Jul 08 '21 at 13:02
66

It is worth pointing out that if you use json_decode(file_get_contents("php://input")) (as others have mentioned), this will fail if the string is not valid JSON.

This can be simply resolved by first checking if the JSON is valid. i.e.

function isValidJSON($str) {
   json_decode($str);
   return json_last_error() == JSON_ERROR_NONE;
}

$json_params = file_get_contents("php://input");

if (strlen($json_params) > 0 && isValidJSON($json_params))
  $decoded_params = json_decode($json_params);

Edit: Note that removing strlen($json_params) above may result in subtle errors, as json_last_error() does not change when null or a blank string is passed, as shown here: http://ideone.com/va3u8U

XtraSimplicity
  • 5,704
  • 1
  • 28
  • 28
  • 4
    If someone is expecting a rather large amount of data in the input and/or a high volume of requests, they may want to extend the function to optionally populate a provided variable reference with the result of json_decode, so that the parsing does not need to be performed twice on well-formed input. – faintsignal Feb 02 '19 at 01:23
  • 7
    Done this way, you actually decode the json twice. That's expensive. With the first decode, you can immediately save the decoded value, do that check afterwards (json_last_error() == JSON_ERROR_NONE) and then proceed with the processing if all is well [fail otherwise] – kakoma Mar 26 '19 at 17:12
  • @kakoma, most definitely! This was written with simplicity in mind. For education purposes, simplicity is often more important than efficiency. :) – XtraSimplicity Mar 27 '19 at 08:35
  • 1
    True. For education purposes. Thanks for the clarification @XtraSimplicity Ha, it is even in your name :-) – kakoma Mar 27 '19 at 08:51
  • PHP8.3 Now has `json_validate()`. https://stackoverflow.com/a/19498903/2943403 and https://php.watch/versions/8.3/json_validate – mickmackusa Sep 02 '23 at 10:16
37

Use $HTTP_RAW_POST_DATA instead of $_POST.

It will give you POST data as is.

You will be able to decode it using json_decode() later.

Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
Urisavka
  • 551
  • 4
  • 3
  • 53
    Since $HTTP_RAW_POST_DATA is depreciated now you can use in this way to read JSON POST `$json = file_get_contents('php://input'); $obj = json_decode($json);` – Bikal Basnet Sep 14 '14 at 07:31
  • 2
    For me this common answer [ use $json = file_get_contents('php://input'); ] I was seeing did not work when the JSON was being sent with outer most "container chars" as []. This answer here with RAW_POST_DATA did the trick for me. And is fine with my current PHP stack. I was stuck for a while .. thanks very much for this solution! – Gene Bo Mar 18 '15 at 21:21
  • This is still pretty current, for [GitLab](https://gitlab.com) webhooks (for example), you still have to use ```$HTTP_RAW_POST_DATA```. – developius Oct 02 '16 at 10:11
  • I searched and searched for a solution and Bikel Basnet yours worked for me. Thanks! – Scooter Mar 01 '17 at 00:41
  • this saved my 3 days looking at ways to catch the POST variables from an HttpClient of Angular 2 sending a request with type Content-Type: application/json – Frederick G. Sandalo Dec 18 '17 at 03:58
  • 1
    Warning This feature was DEPRECATED in PHP 5.6.0, and REMOVED as of PHP 7.0.0. – victorelec14 Jun 16 '20 at 09:42
15

Read the doc:

In general, php://input should be used instead of $HTTP_RAW_POST_DATA.

as in the php Manual

gdm
  • 7,647
  • 3
  • 41
  • 71
  • 8
    Warning This feature was DEPRECATED in PHP 5.6.0, and REMOVED as of PHP 7.0.0. => http://php.net/manual/en/reserved.variables.httprawpostdata.php – Promo Dec 28 '16 at 09:13
  • 2
    And the link is now broken – RiggsFolly Jan 04 '21 at 13:06
  • In the case of POST requests, it is preferable to use php://input instead of $HTTP_RAW_POST_DATA as it does not depend on special php.ini directives. Moreover, for those cases where $HTTP_RAW_POST_DATA is not populated by default, it is a potentially less memory intensive alternative to activating always_populate_raw_post_data. php://input is not available with enctype="multipart/form-data". – GabrieleMartini Apr 03 '21 at 15:10
12
$data = file_get_contents('php://input');
echo $data;

This worked for me.

hyperCoder
  • 271
  • 2
  • 13
11

You can use bellow like.. Post JSON like bellow

enter image description here

Get data from php project user bellow like

// takes raw data from the request 
$json = file_get_contents('php://input');
// Converts it into a PHP object 
$data = json_decode($json, true);

 echo $data['requestCode'];
 echo $data['mobileNo'];
 echo $data['password'];
Enamul Haque
  • 4,789
  • 1
  • 37
  • 50
  • This is the answer. PHP only interprets body in formData form, not JSON. The code from @enamul-haque fixes that. – theking2 Apr 21 '22 at 09:16
5

Quite late.
It seems, (OP) had already tried all the answers given to him.
Still if you (OP) were not receiving what had been passed to the ".PHP" file, error could be, incorrect URL.
Check whether you are calling the correct ".PHP" file.
(spelling mistake or capital letter in URL)
and most important
Check whether your URL has "s" (secure) after "http".
Example:

"http://yourdomain.com/read_result.php"

should be

"https://yourdomain.com/read_result.php"

or either way.
add or remove the "s" to match your URL.

sifr_dot_in
  • 3,153
  • 2
  • 33
  • 42
4

If all of the above answers still leads you to NULL input for POST, note that POST/JSON in a localhost setting, it could be because you are not using SSL. (provided you are HTTP with tcp/tls and not udp/quic)

PHP://input will be null on non-https and if you have a redirect in the flow, trying configuring https on your local as standard practice to avoid various issues with security/xss etc

JonathanC
  • 180
  • 7
1

The decoding might be failing (and returning null) because of php magic quotes.

If magic quotes is turned on anything read from _POST/_REQUEST/etc. will have special characters such as "\ that are also part of JSON escaped. Trying to json_decode( this escaped string will fail. It is a deprecated feature still turned on with some hosters.

Workaround that checks if magic quotes are turned on and if so removes them:

function strip_magic_slashes($str) {
    return get_magic_quotes_gpc() ? stripslashes($str) : $str;
}

$operation = json_decode(strip_magic_slashes($_POST['operation']));
Daan Bakker
  • 6,122
  • 3
  • 24
  • 23
1

I too ran into this issue with the same results.

  1. $_POST was empty.
  2. file_get_contents('php://input') was empty
  3. Even the $_REQUEST array was empty.

Background:

I was posting to an index.php file within an ajax/post directory, i.e. ajax/post/index.php

The url I was using was https://example.com/ajax/post.

The Problem:

The $_POST array was empty because the server used a 301 redirect to move my request from https://example.com/ajax/post to https://example.com/ajax/post/. Note the trailing slash. The redirect occurred, but the posted body did not come along with it.

The Solution

Try adding a trailing slash to the url you are posting to.

Instead of https://example.com/ajax/post try using https://example.com/ajax/post/

jeremysawesome
  • 7,033
  • 5
  • 33
  • 37
0

I got "null" when I tried to retrieve a posted data in PHP

{
    "product_id": "48",
    "customer_id": "2",  
    "location": "shelf",  // shelf, store <-- comments create php problems
    "damage_types":{"Pests":1, "Poke":0, "Tear":0}
     // "picture":"jhgkuignk"  <-- comments create php problems
}

You should avoid commenting JSON code even if it shows no errors

-3

I'd like to post an answer that also uses curl to get the contents, and mpdf to save the results to a pdf, so you get all the steps of a tipical use case. It's only raw code (so to be adapted to your needs), but it works.

// import mpdf somewhere
require_once dirname(__FILE__) . '/mpdf/vendor/autoload.php';

// get mpdf instance
$mpdf = new \Mpdf\Mpdf();

// src php file
$mysrcfile = 'http://www.somesite.com/somedir/mysrcfile.php';
// where we want to save the pdf
$mydestination = 'http://www.somesite.com/somedir/mypdffile.pdf';

// encode $_POST data to json
$json = json_encode($_POST);

// init curl > pass the url of the php file we want to pass 
// data to and then print out to pdf
$ch = curl_init($mysrcfile);

// tell not to echo the results
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1 );

// set the proper headers
curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json', 'Content-Length: ' . strlen($json) ]);

// pass the json data to $mysrcfile
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);

// exec curl and save results
$html = curl_exec($ch);

curl_close($ch);

// parse html and then save to a pdf file
$mpdf->WriteHTML($html);
$this->mpdf->Output($mydestination, \Mpdf\Output\Destination::FILE);

In $mysrcfile I'll read json data like this (as stated on previous answers):

$data = json_decode(file_get_contents('php://input'));
// (then process it and build the page source)
Luca Reghellin
  • 7,426
  • 12
  • 73
  • 118
  • 2
    Too much useless information.. What does the first code do? The second snippet is the answer tho.. – Fipsi Jul 20 '19 at 10:11
  • @Fipsi, (and to all the downvoters) my answer is only, and quite obviously, a compendium of the others. And,as I wrote, a use case (mpdf). At the time of writing, I would have LOVED to see an answer like this, when I was trying to figure out how to. And my second snippet is certainly NOT the answer, since to receive json data, the data has to be also properly sent, and not only there are more ways to send, but often the way, is exactly the real problem. In this case, the focus is not json_decode, it's instead how to properly get something from `file_get_contents('php://input')`. – Luca Reghellin Jul 22 '19 at 05:50
  • 5
    I didn't downvote and I understand your intention.. But the question is 'Receive JSON' and not 'Send JSON'. It's pretty clear from the question that the OP has issues receiving and isn't really interested in sending – Fipsi Jul 22 '19 at 06:02