尝试使用其余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”}]}}
答案 0 :(得分:7)
在Mage_Api2_Model_Resource中,关于第227行,找到
$this->getResponse()->setHeader('Location', $newItemLocation);
并在此之后插入:
$this->getResponse()->setHttpResponseCode(202);
参考:维基百科“HTTP位置”:
HTTP位置标头字段在HTTP的响应中返回 服务器在两种情况下:
- 要求网络浏览器加载其他网页。在这 情况下,Location头应该以HTTP状态发送 代码为3xx。
- 提供有关新位置的信息 创造了资源。在这种情况下,Location标头应该 使用HTTP状态代码201或202
发送 醇>
答案 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的人,但希望它可以帮助你们中的一些人。我们看到它试图两次添加产品的错误似乎是服务器配置特定的,很难追踪。