401错误“;oauth_problem=nonce_used";向带有Rest API的Magento添加产品

401错误“;oauth_problem=nonce_used";向带有Rest API的Magento添加产品,api,magento,rest,oauth,Api,Magento,Rest,Oauth,尝试使用rest api向Magento添加产品时,获取401状态,返回“oauth_problem=nonce_used”消息。奇怪的是,这些产品仍然是进口的,但这真的让我很反感,因为我没有得到更新库存信息的产品id Magento安装是全新的(CrucalWebHost安装程序)1.7.0.2,我使用的代码几乎是从Magento站点复制和粘贴的 $callbackUrl = '****'; $temporaryCredentialsRequestUrl = "*****/oauth/init

尝试使用rest api向Magento添加产品时,获取401状态,返回“oauth_problem=nonce_used”消息。奇怪的是,这些产品仍然是进口的,但这真的让我很反感,因为我没有得到更新库存信息的产品id

Magento安装是全新的(CrucalWebHost安装程序)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”}]}

解决方法:

使用soapapi

之前未使用的原因:

SOAPAPI不提供在自定义产品属性或产品数量增量字段中进行修改的能力

修正:

使用SOAP api向产品中添加您想要的任何字段,方法是首先为这些字段创建一个对象数组,如下所示(为添加的每个字段重复下面的最后4行代码):

然后使用“附加属性”键将其添加到产品阵列中,如:


我知道这项工作只会帮助那些出于与我相同的原因而避免使用SOAP API的人,但希望它能帮助你们中的一些人。我们看到的两次尝试添加产品的错误似乎是特定于服务器配置的,很难追踪。

我也遇到了同样的问题,花了数周时间追踪问题。这似乎是Apache与PHP和重写的奇怪结合。最后,我创建了一个干净的安装,问题就解决了。我还尝试创建第二个安装,在那里可以观察到问题,但失败了-错误只出现在我的生产系统中,而没有出现在任何测试安装中…

在Mage_Api2_Model_资源中,关于第227行,找到

$this->getResponse()->setHeader('Location', $newItemLocation);
并在此之后插入:

 $this->getResponse()->setHttpResponseCode(202); 
参考:维基百科“HTTP位置”:

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

  • 要求web浏览器加载不同的网页。在这个 在这种情况下,应该使用HTTP状态发送位置标头 代码为3xx
  • 提供有关新项目位置的信息 创建资源。在这种情况下,应该使用位置标头 发送时,HTTP状态代码为201或202

  • 我看了一下这个,从代码中看到,它看起来像是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();
    }
    
    /**
    *验证nonce请求数据
    *
    *@param字符串$nonce nonce字符串
    *@param string | int$timestamp UNIX timestamp
    */
    受保护函数_validateNonce($nonce,$timestamp)
    {
    $timestamp=(int)$timestamp;
    if($timestamp(time()+self::time_偏差)){
    $this->\u throwException(“”,self::ERR\u TIMESTAMP\u拒绝);
    }
    /**@var$nonceObj Mage\u Oauth\u Model\u Nonce*/
    $nonceObj=Mage::getModel('oauth/nonce');
    $nonceObj->load($nonce,'nonce');
    if($nonceObj->getTimestamp()==$timestamp){
    $this->\u throwException(“”,self::ERR\u NONCE\u USED);
    }
    $nonceObj->setNonce($nonce)
    ->setTimestamp($timestamp)
    ->save();
    }
    
    所以我想说,当您在REST中通过MagentoAPI进行调用时,您应该特别注意,您发出的每个请求都有自己独特的生成组合timestamp/nonce值

    也看到

    现在。由应用程序唯一生成的随机值。
    oauth_时间戳。一个正整数,表示自1970年1月1日00:00:00 GMT以来的秒数

    已使用nonce_:已使用nonce时间戳组合


    从这个来源:

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

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

    我检查了我的配置,我确实运行了快速cgi php,我通过检查php信息脚本中服务器API的值来检查这一点。我花了很长时间试图解决这个问题,我知道根本原因,我只是将php从cgi php改为apache模块,嘿,preto,我的post请求现在只被重写一次,并返回所有的elusive 200响应代码。

    在Magento中添加产品的实际调用似乎每调用一次就运行两次。我在../Mage/Oauth/Model/Server.php中编辑了_validateNonce函数以跳过验证过程,现在我收到一个错误,指出我插入的产品中的SKU必须是唯一的(它正在插入产品)。因此,它似乎插入了产品,然后再次尝试插入它,从而导致错误…这应该是一个有趣的追踪…有人想击败我;-)你找到解决方案了吗?遇到同样的问题,破解核心代码是绝对不可能的。这肯定有效,但我们需要另一个解决方案,它不会因为这个评论而修改Magento core files@user1392439。你也可以使用
    $this->getResponse()来做到这一点;
    …不需要设置HttpResponseCode。
    /**
     * 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();
    }
    
    <IfModule mod_rewrite.c>
       LogLevel mod_rewrite.c:trace8
    </IfModule>
    
    ## workaround for HTTP authorization
    ## in CGI environment
    
      RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]