Проблема оказалась в том, что заголовок Content-Type имел значение application / json. Когда PHP анализирует данные для помещения в суперглобальный объект $_POST, он ожидает, что этот заголовок будет иметь значение application / x-www-form-urlencoded или multipart / form-data, стандартные типы веб-контента. При получении данных типа содержимого application / json вы должны получить к ним доступ из входного потока php: //.
Решение:
$json_string_data = file_get_contents('php://input');
$decoded_data = json_decode($json_string_data, true);
Если ваше приложение ожидает, что данные будут доступны в суперглобальном $ _POST, то можно использовать следующее (по общему признанию хакерское) решение:
$json_string_data = file_get_contents('php://input');
$decoded_data = json_decode($json_string_data, true);
$_POST = $decoded_data;
Или для краткости:
$_POST = json_decode(file_get_contents('php://input'), true);