Walmart.io 身份验证问题 - 无法验证 in-request,身份验证签名
Walmart.io authentication issue - Could not authenticate in-request, auth signature
我正在尝试 link 与 Walmart.io API 一起从他们的资源中获取一些数据。但是我卡在了第一阶段。
根据 Walmart.io 快速入门文档 (https://walmart.io/docs/affiliate/quick-start-guide),我应该遵循以下步骤:
- 使用 Walmart.io
创建一个帐户
- 为Web应用程序创建一个应用程序
- 生成证书(根据他们的指南,应该有一些自动生成证书的功能,但我没有找到)
- 将 public 密钥上传到应用程序
- 我们将获得消费者 ID 和密钥版本,使用它们和私钥,我们可以发出请求。我们需要添加额外的 headers,其中也包括签名和时间戳。
所以,我做了一切,但仍然没有用。
我正在按照他们的建议使用 Open SSL 生成私钥和 public 密钥:https://walmart.io/key-tutorial
我尝试避免使用 -des3,这样它也不会要求我输入密码,但它也没有用。
这是我试过的脚本
curl --location --request GET 'https://developer.api.walmart.com/api-proxy/service/affil/product/v2/taxonomy' \
--header 'WM_SEC.KEY_VERSION: 2' \
--header 'WM_CONSUMER.ID: <Consumer_ID>' \
--header 'WM_CONSUMER.INTIMESTAMP: 1594389945813' \
--header 'WM_SEC.AUTH_SIGNATURE: W5PEHIew3LsnATk0zxJddeo416YEpMIjvk1b7lW9VMIZFx55erc/5df/FK9UtS5i48q057oASo0AX3SDd2hx+QSeyiX3FtLAgAgiZnGqQ6nJndySWgL5ih/GaUTXIC6dd048GFEZlC6axXdGoTWNzX9P0n/2DwLF9EtvMjdvjB1kum0z2xKz/lQGlvnjVkGK9sZdSUa5rfgxKSPi7ix+LRIJWYwt6mTKUlGz2vP1YjGcZ7gVwAs9o8iFC//0rHUWFwaEGrT0aZJtS7fvSFtKj5NRfemX4fwRO4cgBRxPWy9MRooQwXPmKxRP75PxHKTerv8X6HvRo0GdGut+2Krqxg==' \
我得到的回复是
{
"details": {
"Description": "Could not authenticate in-request, auth signature : Signature verification failed: affil-product, version: 2.0.0, env: prod",
"wm_svc.version": "2.0.0",
"wm_svc.name": "affil-product",
"wm_svc.env": "prod"
}
}
希望有人能给我一些关于这个问题的见解。
提前致谢
我以前遇到过这个问题,看来您要签名的数据格式不正确。
在节点中,模板字符串的内容应该是这样的:${consumerId}\n${timeStamp}\n${keyVersion}\n
原来是生成的签名有问题(这解释了为什么它在我更改脚本后起作用。
因此这是运行良好的脚本:
<?php
use GuzzleHttp\Psr7;
use GuzzleHttp\Exception\RequestException;
class Walmart{
private $host;
private $consumer_id;
private $private_key_file;
private $headers;
private $sec_key_version;
private $client;
private $options;
public function __construct($config){
$this->host = $config['host'];
$this->consumer_id = $config['consumer_id'];
$this->private_key_file = $config['private_key_file'];
$this->sec_key_version = $config['sec_key_version'];
$this->options = array();
$this->client = new GuzzleHttp\Client();
}
public function lookup_product($publisher_id='', $ids='', $upc='', $format='json'){
$this->load_options();
$url_params = array(
'format' => $format,
);
if($publisher_id){
$url_params['publisher_id'] = $publisher_id;
}
if($ids){
$url_params['ids'] = $ids;
}
if($upc){
$url_params['upc'] = $upc;
}
$query = http_build_query($url_params);
$url = $this->host . '/product/v2/items?'.$query;
try {
$res = $this->client->request('GET', $url, $this->options);
$body = $res->getBody();
if($res->getStatusCode() == 200){
return $this->response(false, json_decode($body, true));
}else{
return $this->response(array(
'title' => 'Unable to get products',
'stack' => $body,
));
}
} catch (RequestException $e) {
$err = Psr7\str($e->getRequest());
if ($e->hasResponse()) {
$err .= Psr7\str($e->getResponse());
}
return $this->response(array(
'title' => 'Unable to get products',
'stack' => $err,
));
}
}
private function load_options(){
$timestamp = time()*1000;
$this->options = array(
'debug' => (defined("DEBUG") && DEBUG) ? true: false,
'headers' => array(
'WM_SEC.KEY_VERSION' => $this->sec_key_version,
'WM_CONSUMER.ID' => $this->consumer_id,
'WM_CONSUMER.INTIMESTAMP' => $timestamp,
'WM_SEC.AUTH_SIGNATURE' => $this->get_signature($timestamp),
)
);
}
private function get_signature($timestamp){
$message = $this->consumer_id."\n".$timestamp."\n".$this->sec_key_version."\n";
$pkeyid = openssl_pkey_get_private("file://".$this->private_key_file);
openssl_sign($message, $signature, $pkeyid, OPENSSL_ALGO_SHA256);
$signature = base64_encode($signature);
openssl_free_key($pkeyid);
return $signature;
}
private function response($err, $data=false){
return array(
'error' => $err,
'data' => $data,
);
}
}
注意:它使用 guzzlehttp/guzzle HTTP 请求库
这是一个基于上面 Abiral post 的完整示例:
<?php
/**
* Sample script to sign and send a request to the Walmart Affiliate Marketing API.
*
* https://walmart.io/docs/affiliate/introduction
*
* Usage:
* 1. Fill out the required variables at the top of this script.
* 2. Install dependencies via composer install.
* 3. Run via php index.php or by opening this script in a browser.
*
* Acknowledgements:
* Abiral Neupane at
* @gorenstein at https://gitter.im/IO-support/community?at=5f2e5d2051bb7d3380d9b58b
*/
include './vendor/autoload.php';
use \GuzzleHttp\Client;
/**
* Create an account at Walmart.io. Then create an application. Then follow the
* steps at https://walmart.io/key-tutorial to create a set of keys. Upload
* the public key (its contents start with BEGIN PUBLIC KEY) into the
* production environment of the application that you created.
*/
$consumer_id = 'Paste here the consumer id that you will see in your application details after pasting the public key';
$key = 'Paste here the private key. Full, including BEGIN and END PRIVATE KEY lines.';
$version = '1';
$timestamp = round(microtime(true) * 1000);
$message = $consumer_id . "\n" . $timestamp . "\n" . $version . "\n";
$pkeyid = openssl_pkey_get_private($key);
openssl_sign($message, $signature, $pkeyid, OPENSSL_ALGO_SHA256);
$signature = base64_encode($signature);
openssl_free_key($pkeyid);
$api = 'https://developer.api.walmart.com';
$product_resource = 'api-proxy/service/affil/product/v2/items/316226539';
$client = new Client(['base_uri' => $api]);
$response = $client->get($product_resource, [
'headers' => [
'WM_SEC.KEY_VERSION' => $version,
'WM_CONSUMER.ID' => $consumer_id,
'WM_CONSUMER.INTIMESTAMP' => $timestamp,
'WM_SEC.AUTH_SIGNATURE' => $signature,
]
]);
print_r(json_decode($response->getBody()->__toString()));
发表了以上内容
我正在尝试 link 与 Walmart.io API 一起从他们的资源中获取一些数据。但是我卡在了第一阶段。
根据 Walmart.io 快速入门文档 (https://walmart.io/docs/affiliate/quick-start-guide),我应该遵循以下步骤:
- 使用 Walmart.io 创建一个帐户
- 为Web应用程序创建一个应用程序
- 生成证书(根据他们的指南,应该有一些自动生成证书的功能,但我没有找到)
- 将 public 密钥上传到应用程序
- 我们将获得消费者 ID 和密钥版本,使用它们和私钥,我们可以发出请求。我们需要添加额外的 headers,其中也包括签名和时间戳。
所以,我做了一切,但仍然没有用。
我正在按照他们的建议使用 Open SSL 生成私钥和 public 密钥:https://walmart.io/key-tutorial 我尝试避免使用 -des3,这样它也不会要求我输入密码,但它也没有用。
这是我试过的脚本
curl --location --request GET 'https://developer.api.walmart.com/api-proxy/service/affil/product/v2/taxonomy' \
--header 'WM_SEC.KEY_VERSION: 2' \
--header 'WM_CONSUMER.ID: <Consumer_ID>' \
--header 'WM_CONSUMER.INTIMESTAMP: 1594389945813' \
--header 'WM_SEC.AUTH_SIGNATURE: W5PEHIew3LsnATk0zxJddeo416YEpMIjvk1b7lW9VMIZFx55erc/5df/FK9UtS5i48q057oASo0AX3SDd2hx+QSeyiX3FtLAgAgiZnGqQ6nJndySWgL5ih/GaUTXIC6dd048GFEZlC6axXdGoTWNzX9P0n/2DwLF9EtvMjdvjB1kum0z2xKz/lQGlvnjVkGK9sZdSUa5rfgxKSPi7ix+LRIJWYwt6mTKUlGz2vP1YjGcZ7gVwAs9o8iFC//0rHUWFwaEGrT0aZJtS7fvSFtKj5NRfemX4fwRO4cgBRxPWy9MRooQwXPmKxRP75PxHKTerv8X6HvRo0GdGut+2Krqxg==' \
我得到的回复是
{
"details": {
"Description": "Could not authenticate in-request, auth signature : Signature verification failed: affil-product, version: 2.0.0, env: prod",
"wm_svc.version": "2.0.0",
"wm_svc.name": "affil-product",
"wm_svc.env": "prod"
}
}
希望有人能给我一些关于这个问题的见解。
提前致谢
我以前遇到过这个问题,看来您要签名的数据格式不正确。
在节点中,模板字符串的内容应该是这样的:${consumerId}\n${timeStamp}\n${keyVersion}\n
原来是生成的签名有问题(这解释了为什么它在我更改脚本后起作用。
因此这是运行良好的脚本:
<?php
use GuzzleHttp\Psr7;
use GuzzleHttp\Exception\RequestException;
class Walmart{
private $host;
private $consumer_id;
private $private_key_file;
private $headers;
private $sec_key_version;
private $client;
private $options;
public function __construct($config){
$this->host = $config['host'];
$this->consumer_id = $config['consumer_id'];
$this->private_key_file = $config['private_key_file'];
$this->sec_key_version = $config['sec_key_version'];
$this->options = array();
$this->client = new GuzzleHttp\Client();
}
public function lookup_product($publisher_id='', $ids='', $upc='', $format='json'){
$this->load_options();
$url_params = array(
'format' => $format,
);
if($publisher_id){
$url_params['publisher_id'] = $publisher_id;
}
if($ids){
$url_params['ids'] = $ids;
}
if($upc){
$url_params['upc'] = $upc;
}
$query = http_build_query($url_params);
$url = $this->host . '/product/v2/items?'.$query;
try {
$res = $this->client->request('GET', $url, $this->options);
$body = $res->getBody();
if($res->getStatusCode() == 200){
return $this->response(false, json_decode($body, true));
}else{
return $this->response(array(
'title' => 'Unable to get products',
'stack' => $body,
));
}
} catch (RequestException $e) {
$err = Psr7\str($e->getRequest());
if ($e->hasResponse()) {
$err .= Psr7\str($e->getResponse());
}
return $this->response(array(
'title' => 'Unable to get products',
'stack' => $err,
));
}
}
private function load_options(){
$timestamp = time()*1000;
$this->options = array(
'debug' => (defined("DEBUG") && DEBUG) ? true: false,
'headers' => array(
'WM_SEC.KEY_VERSION' => $this->sec_key_version,
'WM_CONSUMER.ID' => $this->consumer_id,
'WM_CONSUMER.INTIMESTAMP' => $timestamp,
'WM_SEC.AUTH_SIGNATURE' => $this->get_signature($timestamp),
)
);
}
private function get_signature($timestamp){
$message = $this->consumer_id."\n".$timestamp."\n".$this->sec_key_version."\n";
$pkeyid = openssl_pkey_get_private("file://".$this->private_key_file);
openssl_sign($message, $signature, $pkeyid, OPENSSL_ALGO_SHA256);
$signature = base64_encode($signature);
openssl_free_key($pkeyid);
return $signature;
}
private function response($err, $data=false){
return array(
'error' => $err,
'data' => $data,
);
}
}
注意:它使用 guzzlehttp/guzzle HTTP 请求库
这是一个基于上面 Abiral post 的完整示例:
<?php
/**
* Sample script to sign and send a request to the Walmart Affiliate Marketing API.
*
* https://walmart.io/docs/affiliate/introduction
*
* Usage:
* 1. Fill out the required variables at the top of this script.
* 2. Install dependencies via composer install.
* 3. Run via php index.php or by opening this script in a browser.
*
* Acknowledgements:
* Abiral Neupane at
* @gorenstein at https://gitter.im/IO-support/community?at=5f2e5d2051bb7d3380d9b58b
*/
include './vendor/autoload.php';
use \GuzzleHttp\Client;
/**
* Create an account at Walmart.io. Then create an application. Then follow the
* steps at https://walmart.io/key-tutorial to create a set of keys. Upload
* the public key (its contents start with BEGIN PUBLIC KEY) into the
* production environment of the application that you created.
*/
$consumer_id = 'Paste here the consumer id that you will see in your application details after pasting the public key';
$key = 'Paste here the private key. Full, including BEGIN and END PRIVATE KEY lines.';
$version = '1';
$timestamp = round(microtime(true) * 1000);
$message = $consumer_id . "\n" . $timestamp . "\n" . $version . "\n";
$pkeyid = openssl_pkey_get_private($key);
openssl_sign($message, $signature, $pkeyid, OPENSSL_ALGO_SHA256);
$signature = base64_encode($signature);
openssl_free_key($pkeyid);
$api = 'https://developer.api.walmart.com';
$product_resource = 'api-proxy/service/affil/product/v2/items/316226539';
$client = new Client(['base_uri' => $api]);
$response = $client->get($product_resource, [
'headers' => [
'WM_SEC.KEY_VERSION' => $version,
'WM_CONSUMER.ID' => $consumer_id,
'WM_CONSUMER.INTIMESTAMP' => $timestamp,
'WM_SEC.AUTH_SIGNATURE' => $signature,
]
]);
print_r(json_decode($response->getBody()->__toString()));
发表了以上内容