Reciba JSON POST con PHP

292

Estoy tratando de recibir un JSON POST en un sitio web de interfaz de pago, pero no puedo decodificarlo.

Cuando imprimo:

echo $_POST;

Yo obtengo:

Array

No obtengo nada cuando intento esto:

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

No obtengo nada cuando intento esto:

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

Obtengo NULL cuando intento esto:

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

Cuando lo hago:

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

Yo obtengo:

NULL

El formato JSON es (de acuerdo con la documentación del sitio de pago):

{
   "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"
       }
    }
}

El registro del sitio de pago dice que todo está bien. ¿Cuál es el problema?

Pablo Ramirez
fuente
44
Que var_dump($_POST)dice ¿Es una matriz vacía?
Sergiu Paraschiv
3
$ _POST tiene el diccionario de "&" solicitudes de publicación separadas. $ _POST para json DEFINITIVAMENTE no funcionará. ¿Se puede imprimir file_get_contents ('php: // input')? También es var_dump ($ data-> operation); o var_dump ($ data-> operacion); ?
Akshaya Shanbhogue
44
JSON es texto, ¿por qué no sería accesible en POST? Siempre y cuando el servicio de pago envíe ese texto a su punto final PHP, entonces debería poder json_decodehacerlo. Pero tal vez el servicio envía datos en el cuerpo de la solicitud , esa es una historia diferente y sí, file_get_contents('php://input')debería funcionar entonces.
Sergiu Paraschiv
1
Si es así, esto se ha discutido aquí: stackoverflow.com/questions/8945879/…
Sergiu Paraschiv
3
$ _POST: una matriz asociativa de variables pasadas al script actual a través del método HTTP POST cuando se utiliza application / x-www-form-urlencoded o multipart / form-data como HTTP Content-Type en la solicitud. No cuando se usa application / json.
Cristian Sepúlveda

Respuestas:

476

Tratar;

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

Desde su json y su código, parece que ha deletreado la palabra operación correctamente en su extremo, pero no está en el json.

EDITAR

Quizás también valga la pena intentar hacer eco de la cadena json de php: // input.

echo file_get_contents('php://input');
Dom
fuente
2
Hola, en ambos casos no aparece nada en la pantalla
Pablo Ramirez
66
Por lo que vale, la operación es la ortografía (dar o poner acento) en español.
Patrick
11
Su punto era que no lo deletreaba correctamente en ambos lugares, ni la operación ni la operación en ambos lugares.
msj121
2
Antes de PHP 5.6, obtener el contenido de la entrada php: // solo se podía hacer una vez. ¿Podría su código o marco haberlo abierto en algún lugar antes?
aljo f
90

Si ya tiene sus parámetros configurados como $ _POST ['eg'] por ejemplo y no desea cambiarlo, simplemente hágalo así:

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

Esto le ahorrará la molestia de cambiar todos los $ _POST a otra cosa y le permitirá realizar solicitudes de publicación normales si desea eliminar esta línea.

Steve Chan
fuente
1
Gracias Señor. ¡Esto funcionó en mi caso ya que estoy publicando json desde Android a PHP!
vanurag
Gracias, funcionó en mi caso. Estaba asignando los datos $ _POST a una variable $ request, ahora solo le asigné a esa variable el contenido de php: // input.
Fundador
Esto me hizo el día mucho más fácil. Gracias.
Tyler Mammone
47

Vale la pena señalar que si usa json_decode(file_get_contents("php://input"))(como otros han mencionado), esto fallará si la cadena no es JSON válida.

Esto se puede resolver simplemente comprobando primero si el JSON es válido. es decir

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);

Editar: Tenga en cuenta que la eliminación strlen($json_params)anterior puede generar errores sutiles, ya json_last_error()que no cambia cuando nullse pasa una cadena en blanco, como se muestra aquí: http://ideone.com/va3u8U

XtraSimplicity
fuente
2
Si alguien espera una cantidad bastante grande de datos en la entrada y / o un gran volumen de solicitudes, es posible que desee ampliar la función para completar opcionalmente una referencia de variable proporcionada con el resultado de json_decode, de modo que el análisis no necesite se realizará dos veces en una entrada bien formada.
faintsignal
44
Hecho de esta manera, en realidad decodifica el json dos veces. Eso es caro. Con la primera decodificación, puede guardar inmediatamente el valor decodificado, hacer esa verificación después (json_last_error () == JSON_ERROR_NONE) y luego continuar con el procesamiento si todo está bien [fallar de otro modo]
kakoma
@kakoma, definitivamente! Esto fue escrito con simplicidad en mente. Para fines educativos, la simplicidad es a menudo más importante que la eficiencia. :)
XtraSimplicity
1
Cierto. Con fines educativos. Gracias por la aclaración @XtraSimplicity Ha, incluso está a su nombre :-)
kakoma
37

Usar en $HTTP_RAW_POST_DATAlugar de $_POST.

Le dará datos POST tal como están.

Podrá decodificarlo más json_decode()tarde.

Urisavka
fuente
45
Como $ HTTP_RAW_POST_DATA se deprecia ahora, puede usarlo de esta manera para leer JSON POST$json = file_get_contents('php://input'); $obj = json_decode($json);
Bikal Basnet el
2
Para mí, esta respuesta común [use $ json = file_get_contents ('php: // input'); ] Estaba viendo que no funcionaba cuando se enviaba el JSON con la mayoría de los "caracteres de contenedor" externos como []. Esta respuesta aquí con RAW_POST_DATA hizo el truco para mí. Y está bien con mi pila PHP actual. Estuve atrapado por un tiempo ... muchas gracias por esta solución!
Gene Bo
Esto todavía es bastante actual, para los webhooks de GitLab (por ejemplo), todavía tiene que usarlo $HTTP_RAW_POST_DATA.
desarrollo
Busqué y busqué una solución y Bikel Basnet tuyo funcionó para mí. ¡Gracias!
Scooter
esto me ahorró 3 días buscando formas de detectar las variables POST de un HttpClient of Angular 2 enviando una solicitud con el tipo Content-Type: application / json
Frederick G. Sandalo
8
$data = file_get_contents('php://input');
echo $data;

Esto funcionó para mí.

hyperCoder
fuente
-5

Me gustaría publicar una respuesta que también use curl para obtener los contenidos, y mpdf para guardar los resultados en un pdf, para que obtenga todos los pasos de un caso de uso típico. Es solo código sin formato (para adaptarse a sus necesidades), pero funciona.

// 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);

En $ mysrcfile leeré datos json como este (como se indicó en las respuestas anteriores):

$data = json_decode(file_get_contents('php://input'));
// (then process it and build the page source)
Luca Reghellin
fuente
1
Demasiada información inútil. ¿Qué hace el primer código? El segundo fragmento es la respuesta aunque ...
Fipsi
@Fipsi, (y para todos los votantes negativos) mi respuesta es solo, y obviamente, un compendio de los demás. Y, como escribí, un caso de uso (mpdf). Al momento de escribir, me hubiera encantado ver una respuesta como esta, cuando estaba tratando de descubrir cómo hacerlo. Y mi segundo fragmento ciertamente NO es la respuesta, ya que para recibir datos json, los datos también deben enviarse correctamente, y no solo hay más formas de enviar, sino que a menudo la forma es exactamente el problema real. En este caso, el foco no es json_decode, sino cómo obtener algo correctamente file_get_contents('php://input').
Luca Reghellin
2
No voté en contra y entiendo tu intención. Pero la pregunta es 'Recibir JSON' y no 'Enviar JSON'. De la pregunta queda bastante claro que el OP tiene problemas para recibir y no está realmente interesado en enviar
Fipsi el