Recevez JSON POST avec PHP

292

J'essaie de recevoir un JSON POST sur un site Web d'interface de paiement, mais je ne peux pas le décoder.

Quand j'imprime:

echo $_POST;

Je reçois:

Array

Je ne reçois rien quand j'essaye ceci:

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

Je ne reçois rien quand j'essaye ceci:

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

J'obtiens NULL lorsque j'essaye ceci:

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

Quand je fais:

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

Je reçois:

NULL

Le format JSON est (selon la documentation du site de paiement):

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

Le journal du site de paiement indique que tout est OK. Quel est le problème?

Pablo Ramirez
la source
4
Que var_dump($_POST)dit-on? Est-ce un tableau vide?
Sergiu Paraschiv
3
$ _POST a le dictionnaire des demandes de publication séparées "&". $ _POST pour json ne fonctionnera DEFINITIVEMENT. Pouvez-vous imprimer file_get_contents ('php: // input')? C'est aussi var_dump ($ data-> operation); ou var_dump ($ data-> operacion); ?
Akshaya Shanbhogue
4
JSON est du texte, pourquoi ne serait-il pas accessible dans POST? Tant que le service de paiement POSTE ce texte sur son point de terminaison PHP, il devrait pouvoir le faire json_decode. Mais peut-être que le service envoie des données dans le corps de la demande , c'est une autre histoire et oui, cela file_get_contents('php://input')devrait fonctionner alors.
Sergiu Paraschiv
1
Si oui, cela a été discuté ici: stackoverflow.com/questions/8945879/…
Sergiu Paraschiv
3
$ _POST: tableau associatif de variables transmises au script actuel via la méthode HTTP POST lors de l'utilisation de application / x-www-form-urlencoded ou multipart / form-data comme HTTP Content-Type dans la demande. Pas lors de l'utilisation de l'application / json.
Cristian Sepulveda

Réponses:

476

Essayer;

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

D'après votre json et votre code, il semble que vous ayez orthographié correctement le mot opération de votre côté, mais ce n'est pas dans le json.

ÉDITER

Peut-être vaut-il aussi la peine d'essayer de faire écho à la chaîne json de l'entrée php: //.

echo file_get_contents('php://input');
Dom
la source
2
Salut Dans les deux cas, je ne reçois rien à l'écran
Pablo Ramirez
6
Pour ce que ça vaut, operacion est l'orthographe (donner ou prendre un accent) en espagnol.
Patrick
11
Son argument était qu'il ne l'avait pas orthographié correctement aux deux endroits, que ce soit l'opéracion ou l'opération aux deux endroits.
msj121
2
Avant PHP 5.6, obtenir le contenu de l'entrée php: // ne pouvait se faire qu'une seule fois. Votre code ou votre framework aurait-il pu l'ouvrir quelque part auparavant?
aljo f
90

Si vous avez déjà vos paramètres définis comme $ _POST ['eg'] par exemple et que vous ne souhaitez pas le changer, faites-le simplement comme ceci:

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

Cela vous évitera les tracas de changer tous les $ _POST en quelque chose d'autre et vous permettra de toujours faire des demandes de publication normales si vous souhaitez supprimer cette ligne.

Steve Chan
la source
1
Merci Monsieur. Cela a fonctionné dans mon cas, car je fais de la publication json d'Android vers PHP!
vanurag
Merci, cela a fonctionné dans mon cas. J'assignais les données $ _POST à ​​une variable $ request, maintenant je viens d'assigner à cette variable le contenu de l'entrée php: //.
Funder
Cela a rendu ma journée tellement plus facile. Merci.
Tyler Mammone
47

Il convient de noter que si vous utilisez json_decode(file_get_contents("php://input"))(comme d'autres l'ont mentionné), cela échouera si la chaîne n'est pas JSON valide.

Cela peut être simplement résolu en vérifiant d'abord si le JSON est valide. c'est à dire

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: Notez que la suppression strlen($json_params)ci-dessus peut entraîner des erreurs subtiles, comme json_last_error()cela ne change pas quand nullou une chaîne vide est passée, comme indiqué ici: http://ideone.com/va3u8U

XtraSimplicity
la source
2
Si quelqu'un attend une quantité assez importante de données en entrée et / ou un volume élevé de demandes, il peut souhaiter étendre la fonction pour remplir éventuellement une référence de variable fournie avec le résultat de json_decode, afin que l'analyse ne soit pas nécessaire être effectué deux fois sur une entrée bien formée.
faintsignal
4
De cette façon, vous décodez le json deux fois. C'est cher. Avec le premier décodage, vous pouvez immédiatement enregistrer la valeur décodée, faire cette vérification après (json_last_error () == JSON_ERROR_NONE) puis poursuivre le traitement si tout va bien [échec sinon]
kakoma
@kakoma, certainement! Cela a été écrit avec simplicité à l'esprit. À des fins éducatives, la simplicité est souvent plus importante que l'efficacité. :)
XtraSimplicity
1
Vrai. À des fins éducatives. Merci pour la clarification @XtraSimplicity Ha, c'est même en votre nom :-)
kakoma
37

Utilisez $HTTP_RAW_POST_DATAau lieu de $_POST.

Il vous donnera les données POST telles quelles.

Vous pourrez le décoder json_decode()ultérieurement.

Urisavka
la source
45
Puisque $ HTTP_RAW_POST_DATA est déprécié maintenant, vous pouvez utiliser de cette manière pour lire JSON POST$json = file_get_contents('php://input'); $obj = json_decode($json);
Bikal Basnet
2
Pour moi, cette réponse courante [use $ json = file_get_contents ('php: // input'); ] Je voyais que cela ne fonctionnait pas lorsque le JSON était envoyé avec la plupart des "caractères de conteneur" externes comme []. Cette réponse ici avec RAW_POST_DATA a fait l'affaire pour moi. Et ça va avec ma pile PHP actuelle. J'étais coincé pendant un moment .. merci beaucoup pour cette solution!
Gene Bo
C'est encore assez courant, pour les webhooks GitLab (par exemple), vous devez toujours utiliser $HTTP_RAW_POST_DATA.
developius
J'ai cherché et cherché une solution et Bikel Basnet a travaillé pour moi. Merci!
Scooter
cela a sauvé mes 3 jours à chercher des moyens d'attraper les variables POST à ​​partir d'un HttpClient d'Angular 2 en envoyant une demande avec le type Content-Type: application / json
Frederick G. Sandalo
8
$data = file_get_contents('php://input');
echo $data;

Cela a fonctionné pour moi.

hyperCoder
la source
-5

Je voudrais publier une réponse qui utilise également curl pour obtenir le contenu, et mpdf pour enregistrer les résultats dans un pdf, afin que vous obteniez toutes les étapes d'un cas d'utilisation typique. Ce n'est que du code brut (donc à adapter à vos besoins), mais ça marche.

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

Dans $ mysrcfile, je vais lire des données json comme celle-ci (comme indiqué dans les réponses précédentes):

$data = json_decode(file_get_contents('php://input'));
// (then process it and build the page source)
Luca Reghellin
la source
1
Trop d'informations inutiles. Que fait le premier code? Le deuxième extrait est la réponse.
Fipsi
@Fipsi, (et à tous les downvoters) ma réponse est seulement, et bien évidemment, un recueil des autres. Et, comme je l'ai écrit, un cas d'utilisation (mpdf). Au moment d'écrire ces lignes, j'aurais ADORÉ voir une réponse comme celle-ci, lorsque j'essayais de comprendre comment. Et mon deuxième extrait n'est certainement PAS la réponse, car pour recevoir des données json, les données doivent également être correctement envoyées, et non seulement il y a plus de façons d'envoyer, mais souvent la manière, c'est exactement le vrai problème. Dans ce cas, le focus n'est pas json_decode, c'est plutôt comment obtenir correctement quelque chose file_get_contents('php://input').
Luca Reghellin du
2
Je n'ai pas downvote et je comprends votre intention .. Mais la question est "Recevoir JSON" et non "Envoyer JSON". Il est assez clair d'après la question que l'OP a des problèmes de réception et n'est pas vraiment intéressé à envoyer
Fipsi