401错误“oauth_problem = nonce_used”将产品添加到Magento w / Rest API

时间:2013-04-02 18:54:20

标签: api magento rest oauth

尝试使用其余api向Magento添加产品时,返回获取401状态并显示“oauth_problem = nonce_used”消息。奇怪的是,这些产品仍然是进口的,但它确实让我失望,因为我没有得到更新股票信息的产品ID。

Magento安装是全新的(criticalwebhost安装程序)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();

确切错误:{“messages”:{“error”:[{“code”:401,“message”:“oauth_problem = nonce_used”}]}}

5 个答案:

答案 0 :(得分:7)

在Mage_Api2_Model_Resource中,关于第227行,找到

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

并在此之后插入:

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

参考:维基百科“HTTP位置”:

  

HTTP位置标头字段在HTTP的响应中返回   服务器在两种情况下:

     
      
  1. 要求网络浏览器加载其他网页。在这   情况下,Location头应该以HTTP状态发送   代码为3xx。
  2.   
  3. 提供有关新位置的信息   创造了资源。在这种情况下,Location标头应该   使用HTTP状态代码201或202
  4. 发送   

答案 1 :(得分:1)

我遇到了完全相同的问题,并花了数周的时间来追查问题。它似乎是Apache与PHP和重写的奇怪组合。最后我创建了一个干净的安装,问题就消失了。我还尝试创建第二个安装,可以观察到问题但失败了 - 错误只出现在我的生产系统中,而不是出现在任何测试装置中......

答案 2 :(得分:1)

我看了这个,从我在代码中看到的内容看起来,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();
}

所以我想说,当您通过REST中的Magento API进行调用时,您应该特别注意每个请求都有自己唯一生成的组合时间戳/现时值。

另见

  

oauth_nonce。由应用程序唯一生成的随机值   oauth_timestamp。一个正整数,以1970年1月1日00:00:00 GMT之后的秒数表示。

  

nonce_used:已使用nonce-timestamp组合。

从此来源:http://devdocs.magento.com/guides/v2.0/get-started/authentication/gs-authentication-oauth.html

答案 3 :(得分:0)

我遇到了完全相同的问题,为了解决这个问题,我查看了mod_rewrite apache模块并打开了此模块的日志记录,这是通过将其添加到您的apache httpd.conf文件来完成的(这是针对apache 2.4x,2.2x需要以不同的方式完成

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

然后将错误记录到apache标准error_log中 当我在这里查看重写时,我可以看到我的帖子请求被重写了两次,第一次将产品添加到magento,第二次无法在使用nonce时再次添加产品,显然。

我可以看到在.htaccess中导致这种情况的重写规则就是那个

## workaround for HTTP authorization
## in CGI environment

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

我检查了我的配置,我确实在快速运行cgi php,我通过从php信息脚本检查Server API的值来检查这一点。我花了很长时间试图解决这个问题,因为我知道根本原因我只是简单地将PHP从CGI php更改为apache模块,而现在我的帖子请求只被重写一次并返回所有难以捉摸的200响应代码。

答案 4 :(得分:-4)

解决方法:

使用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的人,但希望它可以帮助你们中的一些人。我们看到它试图两次添加产品的错误似乎是服务器配置特定的,很难追踪。