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 сервер при двух обстоятельствах:
- чтобы попросить веб-браузер загрузить другую веб-страницу. В этом обстоятельство, заголовок местоположения должен быть отправлен со статусом HTTP кодекс устройств 3xx.
- чтобы предоставить информацию о местоположении нового созданный ресурс. В этом случае заголовок 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 по той же причине, что и я, но, надеюсь, это поможет некоторым из вас. Эта ошибка, которую мы видим, когда она пытается добавить продукт дважды, кажется специфичной для конфигурации сервера и очень трудно отследить.