Receba JSON POST com PHP

292

Estou tentando receber um JSON POST em um site de interface de pagamento, mas não consigo decodificá-lo.

Quando imprimo:

echo $_POST;

Eu recebo:

Array

Não recebo nada quando tento isso:

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

Não recebo nada quando tento isso:

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

Eu recebo NULL quando tento isso:

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

Quando eu faço:

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

Eu recebo:

NULL

O formato JSON é (de acordo com a documentação do site de pagamento):

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

O log do site de pagamento diz que está tudo bem. Qual é o problema?

Pablo Ramirez
fonte
4
O que var_dump($_POST)diz? É uma matriz vazia?
Sergiu Paraschiv
3
$ _POST possui o dicionário de "&" solicitações de postagem separadas. $ _POST para json DEFINITIVAMENTE não funcionará. Você pode imprimir file_get_contents ('php: // input')? Também é var_dump ($ data-> operação); ou var_dump ($ data-> operacion); ?
Akshaya Shanbhogue
4
JSON é texto, por que não seria acessível no POST? Desde que o serviço de pagamento POSTE esse texto para o terminal PHP, ele poderá json_decodefazê - lo. Mas talvez o serviço envie dados no corpo da solicitação , isso é uma história diferente e sim, file_get_contents('php://input')deve funcionar então.
Sergiu Paraschiv
1
Em caso afirmativo, isso foi discutido aqui: stackoverflow.com/questions/8945879/…
Sergiu Paraschiv
3
$ _POST: Uma matriz associativa de variáveis ​​transmitidas ao script atual por meio do método HTTP POST ao usar application / x-www-form-urlencoded ou multipart / form-data como o HTTP Content-Type na solicitação. Não ao usar application / json.
Cristian Sepulveda

Respostas:

476

Experimentar;

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

No seu json e no seu código, parece que você digitou a palavra operação corretamente do seu lado, mas não está no json.

EDITAR

Talvez também valha a pena tentar ecoar a string json de php: // input.

echo file_get_contents('php://input');
Dom
fonte
2
Oi Nos dois casos, não recebo nada na tela #
Pablo Ramirez
6
Pelo que vale, operacion é a ortografia (dar ou receber um sotaque) em espanhol.
Patrick
11
Seu argumento era que ele não o soletrou corretamente nos dois lugares, nem em operações nem em operações nos dois lugares.
msj121
2
Antes do PHP 5.6, obter o conteúdo da entrada php: // só podia ser feito uma vez. Seu código ou estrutura poderia abri-lo em algum lugar antes?
21715
90

Se você já possui seus parâmetros definidos como $ _POST ['eg'], por exemplo, e não deseja alterá-lo, faça o seguinte:

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

Isso poupará o trabalho de alterar todos os $ _POST para outra e permitirá que você faça solicitações de postagem normais, se desejar eliminar esta linha.

Steve Chan
fonte
1
Obrigado senhor. Isso funcionou no meu caso, pois estou postando json do Android para o PHP!
vanurag
Obrigado, funcionou no meu caso. Eu estava atribuindo os dados $ _POST a uma variável $ request, agora acabei de atribuir a essa variável o conteúdo do php: // input.
Funder
Isso apenas tornou meu dia muito mais fácil. Obrigado.
Tyler Mammone 25/04
47

Vale ressaltar que se você usar json_decode(file_get_contents("php://input"))(como outros já mencionaram), isso falhará se a sequência não for JSON válida.

Isso pode ser resolvido simplesmente verificando se o JSON é válido. ie

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 que a remoção strlen($json_params)acima pode resultar em erros sutis, como json_last_error()se não mudar quando nullou uma cadeia em branco é passado, como mostrado aqui: http://ideone.com/va3u8U

XtraSimplicity
fonte
2
Se alguém espera uma quantidade bastante grande de dados na entrada e / ou um grande volume de solicitações, pode desejar estender a função para preencher opcionalmente uma referência de variável fornecida com o resultado de json_decode, para que a análise não precise ser executado duas vezes em entrada bem formada.
faintsignal 02/02/19
4
Feito dessa maneira, você realmente decodifica o json duas vezes. Isso é caro. Com o primeiro decodificar, você pode imediatamente salvar o valor decodificado, faça o cheque depois (json_last_error () == JSON_ERROR_NONE) e depois prosseguir com o processamento se está tudo bem [falham em contrário]
Kakoma
@kakoma, definitivamente! Isso foi escrito com a simplicidade em mente. Para fins educacionais, a simplicidade costuma ser mais importante que a eficiência. :)
XtraSimplicity 27/03/19
1
Verdade. Para fins de educação. Obrigado pelo esclarecimento @XtraSimplicity Ha, é mesmo em seu nome :-)
Kakoma
37

Use em $HTTP_RAW_POST_DATAvez de $_POST.

Ele fornecerá os dados do POST como estão.

Você será capaz de decodificá-lo usando json_decode()mais tarde.

Urisavka
fonte
45
Desde $ HTTP_RAW_POST_DATA é depreciado agora você pode usar desta forma para ler JSON POST$json = file_get_contents('php://input'); $obj = json_decode($json);
Bikal Basnet
2
Para mim, essa resposta comum [use $ json = file_get_contents ('php: // input'); ] Eu estava vendo que não funcionou quando o JSON estava sendo enviado com a maioria dos "caracteres de contêiner" externos como []. Esta resposta aqui com RAW_POST_DATA fez o truque para mim. E está bem com minha pilha PHP atual. Fiquei preso por um tempo .. muito obrigado por esta solução!
Gene Bo
Este ainda é bastante atual, por gitlab webhooks (por exemplo), você ainda tem que usar $HTTP_RAW_POST_DATA.
developius
Eu procurei e procurei uma solução e o seu Bikel Basnet funcionou para mim. Obrigado!
Scooter
isso salvou minha 3 dias procurando maneiras de pegar as variáveis POST de um HttpClient de Angular 2 enviar um pedido com o tipo Content-Type: application / json
Frederick G. Sandalo
8
$data = file_get_contents('php://input');
echo $data;

Isso funcionou para mim.

hyperCoder
fonte
-5

Gostaria de postar uma resposta que também use curl para obter o conteúdo e mpdf para salvar os resultados em um pdf, para que você obtenha todas as etapas de um caso de uso típico. É apenas um código bruto (para ser adaptado às suas necessidades), mas 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);

No $ mysrcfile, lerei dados json como este (como indicado nas respostas anteriores):

$data = json_decode(file_get_contents('php://input'));
// (then process it and build the page source)
Luca Reghellin
fonte
1
Muita informação inútil. O que o primeiro código faz? O segundo trecho é a resposta tho ..
Fipsi
@Fipsi (e para todos os que rejeitam) minha resposta é apenas e, obviamente, um compêndio dos outros. E, como escrevi, um caso de uso (mpdf). No momento em que escrevi, eu adoraria ver uma resposta como essa, quando estava tentando descobrir como. E meu segundo trecho certamente NÃO é a resposta, pois para receber dados json, os dados também precisam ser enviados corretamente, e não apenas existem mais maneiras de enviar, mas geralmente o caminho, é exatamente o verdadeiro problema. Nesse caso, o foco não é json_decode; é como obter algo corretamente file_get_contents('php://input').
Luca Reghellin
2
Não diminuí o voto e entendo sua intenção. Mas a pergunta é 'Receive JSON' e não 'Send JSON'. É muito claro a partir da pergunta que o OP tem problemas recebendo e não está realmente interessado em enviar
Fipsi