Получите JSON POST с PHP

292

Я пытаюсь получить сообщение JSON POST на веб-сайте интерфейса оплаты, но не могу его расшифровать.

Когда я печатаю:

echo $_POST;

Я получил:

Array

Я ничего не получаю, когда я пытаюсь это:

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

Я ничего не получаю, когда я пытаюсь это:

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

Я получаю NULL, когда я пытаюсь это:

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

Когда я делаю:

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

Я получил:

NULL

Формат JSON (согласно платежной документации сайта):

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

Журнал сайта оплаты говорит, что все в порядке. В чем проблема?

Пабло Рамирес
источник
4
Что var_dump($_POST)говорит? Это пустой массив?
Сергей Параскив
3
$ _POST содержит словарь разделенных «&» почтовых запросов. $ _POST для JSON определенно не будет работать. Можете ли вы напечатать file_get_contents ('php: // input')? Также это var_dump ($ data-> operation); или var_dump ($ data-> operacion); ?
Акшая Шанбхог
4
JSON - это текст, почему он не доступен в POST? До тех пор, пока платежная служба отправляет этот текст в конечную точку PHP, он сможет json_decodeэто сделать. Но, возможно, служба отправляет данные в теле запроса , это другая история, и да, тогда file_get_contents('php://input')должно работать.
Сергей Параскив
1
Если так, то это было обсуждено здесь: stackoverflow.com/questions/8945879/…
Серджиу Параскив
3
$ _POST: ассоциативный массив переменных, передаваемый текущему сценарию с помощью метода HTTP POST при использовании application / x-www-form-urlencoded или multipart / form-data в качестве HTTP-типа содержимого в запросе. Не при использовании приложения / JSON.
Кристиан Сепульведа

Ответы:

476

Пытаться;

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

Судя по вашему json и вашему коду, похоже, что вы правильно написали слово операция на своем конце, но это не в json.

РЕДАКТИРОВАТЬ

Возможно также стоит попытаться повторить строку json из php: // input.

echo file_get_contents('php://input');
Дом
источник
2
Привет В обоих случаях я ничего не получаю на экране
Пабло Рамирес
6
Для чего бы это ни стоило, операция - это орфография (дать или взять акцент) на испанском языке.
Патрик
11
Суть его заключалась в том, что он неправильно произнес это в обоих местах, ни в операциях, ни в операциях в обоих местах.
msj121
2
До PHP 5.6 получение содержимого ввода php: // можно было выполнить только один раз. Мог ли ваш код или фреймворк открыть его где-то раньше?
Aljo F
90

Если у вас уже есть параметры, например, $ _POST ['eg'], и вы не хотите их изменять, просто сделайте это так:

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

Это избавит вас от необходимости менять все $ _POST на что-то еще и позволит вам по-прежнему отправлять обычные почтовые запросы, если вы хотите убрать эту строку.

Стив Чан
источник
1
Спасибо, сэр. В моем случае это сработало, так как я делаю публикацию json с Android на PHP!
vanurag
Спасибо, это сработало в моем случае. Я присваивал данные $ _POST переменной $ request, теперь я просто присвоил этой переменной содержимое php: // input.
Funder
Это сделало мой день намного проще. Спасибо.
Тайлер Маммон
47

Стоит отметить, что если вы используете json_decode(file_get_contents("php://input"))(как уже упоминали другие), это не удастся, если строка не является допустимым JSON.

Это может быть просто решено, сначала проверив, действителен ли JSON. т.е.

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

Изменить: Обратите внимание , что удаление strlen($json_params)выше , может привести к тонким ошибкам, так как json_last_error()это не изменится , когда nullили передается строка пустой, как показано здесь: http://ideone.com/va3u8U

XtraSimplicity
источник
2
Если кто-то ожидает довольно большой объем данных на входе и / или большой объем запросов, он может захотеть расширить функцию, чтобы опционально заполнить предоставленную ссылку на переменную результатом json_decode, чтобы анализ не требовал быть выполненным дважды на правильно сформированном входе.
faintsignal
4
Сделано таким образом, вы на самом деле декодировать JSON дважды. Это дорого. При первом декодировании вы можете сразу сохранить декодированное значение, затем выполнить эту проверку (json_last_error () == JSON_ERROR_NONE), а затем продолжить обработку, если все хорошо [иначе не
получится
@kakoma, определенно! Это было написано с простотой в виду. В образовательных целях простота часто важнее эффективности. :)
XtraSimplicity
1
Правда. Для образовательных целей. Спасибо за разъяснения @XtraSimplicity Ха, это даже на ваше имя :-)
kakoma
37

Используйте $HTTP_RAW_POST_DATAвместо $_POST.

Это даст вам данные POST как есть.

Вы сможете расшифровать его, используя json_decode()позже.

Urisavka
источник
45
Поскольку $ HTTP_RAW_POST_DATA устарела, теперь вы можете использовать этот способ для чтения JSON POST$json = file_get_contents('php://input'); $obj = json_decode($json);
Bikal Basnet
2
Для меня это общий ответ [use $ json = file_get_contents ('php: // input'); ] Я видел, что не работало, когда JSON отправлялся с большинством внешних «контейнерных символов» как []. Этот ответ здесь с RAW_POST_DATA помог мне. И хорошо с моим текущим стеком PHP. Я застрял на некоторое время .. большое спасибо за это решение!
Джин Бо
Это все еще довольно актуально, для веб- хитов GitLab (например), вы все еще должны использовать $HTTP_RAW_POST_DATA.
developius
Я искал и искал решение, и Bikel Basnet ваш работал на меня. Спасибо!
Скутер
это сэкономило мне 3 дня на поиски способов перехвата переменных POST от HttpClient из Angular 2, отправив запрос с типом Content-Type: application / json
Фредерик Г. Сандало
12

Прочитайте документацию:

В общем, вместо $ HTTP_RAW_POST_DATA следует использовать ввод php: //.

как в руководстве по PHP

Giuseppe
источник
4
Предупреждение Эта функция была УСТАРЕЛА в PHP 5.6.0 и УДАЛЕНА с PHP 7.0.0. => php.net/manual/en/reserved.variables.httprawpostdata.php
Промо-
8
$data = file_get_contents('php://input');
echo $data;

Это сработало для меня.

hyperCoder
источник
-5

Я хотел бы опубликовать ответ, который также использует curl для получения содержимого и mpdf для сохранения результатов в pdf, так что вы получите все шаги типичного варианта использования. Это всего лишь необработанный код (чтобы его можно было адаптировать к вашим потребностям), но он работает.

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

В $ mysrcfile я буду читать данные json следующим образом (как указано в предыдущих ответах):

$data = json_decode(file_get_contents('php://input'));
// (then process it and build the page source)
Лука Регеллин
источник
1
Слишком много бесполезной информации. Что делает первый код? Второй фрагмент - это ответ, который ...
Fipsi
@Fipsi, (и для всех downvoters) мой ответ - только, и совершенно очевидно, сборник других. И, как я уже писал, пример использования (mpdf). На момент написания статьи мне бы хотелось увидеть такой ответ, когда я пытался понять, как это сделать. И мой второй фрагмент, безусловно, НЕ является ответом, поскольку для получения данных JSON эти данные также должны быть отправлены надлежащим образом, и не только существует больше способов отправки, но часто это именно реальная проблема. В этом случае фокус не json_decode, а как правильно получить что-то file_get_contents('php://input').
Лука Регеллин
2
Я не понизил голос и понимаю ваше намерение. Но вопрос заключается в том, чтобы «получить JSON», а не «отправить JSON». Из вопроса довольно ясно, что у ОП есть проблемы с получением и он не очень заинтересован в отправке
Fipsi