问题
I am trying to link up with Walmart.io API to get some data from their resources. But I am stuck up in the first phase.
According to Walmart.io Quick Start Doc (https://walmart.io/docs/affiliate/quick-start-guide) I am supposed to follow following steps:
- Create an account with Walmart.io
- Create an application for Web Application
- Generate a certificate ( According to their guide there should be some feature to autogenerate the certificate, but I didn't find it)
- Upload public key to the application
- We will get consumer id and key version using which along with private key, we can make a request. We need to add additional headers that includes Signature and Timestamp too.
So, I did everything, but it still isn't working.
I am using Open SSL to generate private and public key as suggested by them: https://walmart.io/key-tutorial I tried avoiding -des3 so that it doesn't ask me for passphrase too, but it didn't work either.
Here is the script I tried with
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==' \
And the response I get is
{
"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"
}
}
Hope someone gives me some insight into this problem.
Thanks in advance
回答1:
I've had this issue before, it looks like the format of the data you are trying to sign is incorrect.
In node, the content of the template string should look like this: ${consumerId}\n${timeStamp}\n${keyVersion}\n
回答2:
Turns out it was issue with generated Signature (That explains why it worked after I changed the script.
Thus here is the script that worked fine:
<?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,
);
}
}
Note: It uses guzzlehttp/guzzle library for HTTP Request
来源:https://stackoverflow.com/questions/62838147/walmart-io-authentication-issue-could-not-authenticate-in-request-auth-signat