401 ошибка" OAuth problem=nonce used " добавление продуктов в Magento W / REST API

получение статуса 401 с сообщением" oauth_problem=nonce_used " при попытке добавить продукты в Magento с помощью REST api. Как ни странно, продукты все еще импортируются, но это действительно выбивает меня, потому что я не получаю идентификатор продукта, чтобы обновить информацию о запасах.

в Magento установить новый (установщик crucialwebhost) 1.7.0.2 и код, который я использую довольно много скопировано с сайте Magento...

$callbackUrl = '****';
$temporaryCredentialsRequestUrl = "*****/oauth/initiate?oauth_callback=".urlencode($callbackUrl);
$adminAuthorizationUrl = '*****/admin/oauth_authorize';
$accessTokenRequestUrl = '*****/oauth/token';
$apiUrl = '*****/api/rest';

$consumerKey = '*****';
$consumerSecret = '******';

try
{
$authType = ($_SESSION['state'] == 2) ? OAUTH_AUTH_TYPE_AUTHORIZATION : OAUTH_AUTH_TYPE_URI;
$oauthClient = new OAuth($consumerKey, $consumerSecret, OAUTH_SIG_METHOD_HMACSHA1, $authType);
$oauthClient->enableDebug();

if(!isset($_GET['oauth_token']) && !$_SESSION['state'])
{
  $requestToken = $oauthClient->getRequestToken($temporaryCredentialsRequestUrl);
  $_SESSION['secret'] = $requestToken['oauth_token_secret'];
  $_SESSION['state'] = 1;
  header('Location: '.$adminAuthorizationUrl.'?oauth_token='.$requestToken['oauth_token']);
  exit;
} else if($_SESSION['state'] == 1)
{
  $oauthClient->setToken($_GET['oauth_token'], $_SESSION['secret']);
  $accessToken = $oauthClient->getAccessToken($accessTokenRequestUrl);
  $_SESSION['state'] = 2;
  $_SESSION['token'] = $accessToken['oauth_token'];
  $_SESSION['secret'] = $accessToken['oauth_token_secret'];
  header('Location: '.$callbackUrl);
  exit;
} else
{
  $oauthClient->setToken($_SESSION['token'], $_SESSION['secret']);
  $resourceUrl = "$apiUrl/products";


  $productData = json_encode(array(
'type_id' => 'simple',
    'attribute_set_id' => 4,
    'sku' => $local_product['sku'],
    'weight' => 1,
    'status' => 1,
'visibility' => 4,
    'name' => $local_product['name'],
    'description' => $local_product['description'],
    'short_description' => $local_product['description'],
    'price' => $local_product['price'],
    'tax_class_id' => 0,
  ));
  $headers = array('Content-Type' => 'application/json');
  $oauthClient->fetch($resourceUrl, $productData, OAUTH_HTTP_METHOD_POST, $headers);
  $respHeader = $oauthClient->getLastResponseHeaders();


}

} catch(OAuthException $e)
{
  print_r($e);
}
}

session_destroy();

точной ошибки: {"сообщения": {"ошибка": [{"код": 401, "сообщение": "oauth_problem=nonce_used"}]}}

5 ответов


в Mage_Api2_Model_Resource, о строке 227, найдите

$this->getResponse()->setHeader('Location', $newItemLocation);

и вставьте сразу после этого:

 $this->getResponse()->setHttpResponseCode(202); 

Ref: Википедия "HTTP Location":

поле заголовка местоположения HTTP возвращается в ответах от HTTP сервер при двух обстоятельствах:

  1. чтобы попросить веб-браузер загрузить другую веб-страницу. В этом обстоятельство, заголовок местоположения должен быть отправлен со статусом HTTP кодекс устройств 3xx.
  2. чтобы предоставить информацию о местоположении нового созданный ресурс. В этом случае заголовок Location должен быть отправлено с кодом состояния HTTP 201 или 202

У меня была точно такая же проблема и неделями выслеживать проблему. Кажется, это странная комбинация Apache с PHP и переписыванием. В конце концов я создал чистую установку, и проблема исчезла. Я также попытался создать вторую установку, где проблема могла быть замечена, но не удалась - ошибка появилась только в моей производственной системе, а не в любой из тестовых установок...


Я посмотрел на это и из того, что я вижу в коде, похоже, что OAuth регистрирует все ваши звонки, и если он узнает, что то же самое nonce фактически использовался с тем же самым метка как и некоторые предыдущие вызовы, он просто отбросит его с этим очень конкретным oauth_problem=nonce_used ошибка.

код app/code/core/Mage/Oauth/Model/Server.php

/**
 * Validate nonce request data
 *
 * @param string $nonce Nonce string
 * @param string|int $timestamp UNIX Timestamp
 */
protected function _validateNonce($nonce, $timestamp)
{
    $timestamp = (int) $timestamp;

    if ($timestamp <= 0 || $timestamp > (time() + self::TIME_DEVIATION)) {
        $this->_throwException('', self::ERR_TIMESTAMP_REFUSED);
    }
    /** @var $nonceObj Mage_Oauth_Model_Nonce */
    $nonceObj = Mage::getModel('oauth/nonce');

    $nonceObj->load($nonce, 'nonce');

    if ($nonceObj->getTimestamp() == $timestamp) {
        $this->_throwException('', self::ERR_NONCE_USED);
    }
    $nonceObj->setNonce($nonce)
        ->setTimestamp($timestamp)
        ->save();
}

поэтому я бы сказал, что когда вы делаете вызовы через Magento API в REST, вы должны принимать дополнительные позаботьтесь о том, чтобы каждый запрос, который вы делаете, имел свое уникальное сгенерированное значение combinaison timestamp / nonce.

см. Также

oauth_nonce. Случайное значение, однозначно генерируемое приложением.
oauth_timestamp. Положительное целое число, выраженное в количестве секунд с 1 января 1970 года 00:00: 00 GMT.

и

nonce_used: комбинация nonce-timestamp уже была используемый.

из этого источника : http://devdocs.magento.com/guides/v2.0/get-started/authentication/gs-authentication-oauth.html


у меня была точно такая же проблема, и для ее решения я посмотрел на модуль mod_rewrite apache и включил ведение журнала для этого модуля, что делается путем добавления этого в ваш Apache httpd.conf файл (это для apache 2.4 x , 2.2 x должно быть сделано по-другому

<IfModule mod_rewrite.c>
   LogLevel mod_rewrite.c:trace8
</IfModule>

ошибки затем выходят из системы в стандартный журнал ошибок apache Когда я посмотрел на переписывание здесь, я увидел, что мой запрос post переписывается дважды, в первый раз он добавляет продукты в magento и второй раз он не смог добавить продукт снова, поскольку nonce был использован, очевидно.

я мог видеть, что правило перезаписи, что вызывает это .htaccess был один

## workaround for HTTP authorization
## in CGI environment

  RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 

Я проверяю свою конфигурацию, и я действительно работал быстро CGI php, и я проверил это, проверив значение API сервера из скрипта PHP info. Я потратил так много времени, пытаясь решить эту проблему, что я знаю корень, потому что я просто изменил PHP с CGI php на модуль apache, и Эй, preto мой запрос post теперь переписывается только один раз и возвращает весь неуловимый код ответа 200.


Обойти:

используйте SOAP API.

причина не использовать его раньше:

SOAP API не предоставлял возможности для настраиваемых атрибутов продукта или полей приращения количества продукта.

исправления:

добавьте любое поле, которое вы хотите к продукту, используя SOAP api, сначала создав массив объектов для них, как это (последние 4 строки кода ниже повторяются для каждого добавленного поля):

$additionalAttrs = array();

$per_item = new stdClass();
$per_item->key = 'price_per_item';
$per_item->value = $local_product['price'];
$additionalAttrs['single_data'][] = $per_item;

и добавить его к вашему продукту массив с ключом "additional_attributes" типа:

'additional_attributes' => $additionalAttrs,

Я знаю, что эта работа помогает только людям, которые избегали SOAP API по той же причине, что и я, но, надеюсь, это поможет некоторым из вас. Эта ошибка, которую мы видим, когда она пытается добавить продукт дважды, кажется специфичной для конфигурации сервера и очень трудно отследить.