Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OAuth and v3 only #77

Open
solasus opened this issue Apr 16, 2019 · 6 comments
Open

OAuth and v3 only #77

solasus opened this issue Apr 16, 2019 · 6 comments

Comments

@solasus
Copy link

solasus commented Apr 16, 2019

Coming August 28, 2019 - Walmart will be depreciating Digital Signatures and going with oAuth authentication only.

https://developer.walmart.com/#/apicenter/marketPlace/latest#apiAuthentication

Additionally versions 1 & 2 will also be depreciated.

Questions

  • Can this package be easily updated to use the oAuth methods?
  • What would it take to make this fully use v3 of the api?
@mjmmagic
Copy link

mjmmagic commented Jun 5, 2019

I hope someone can provide a solution here as well.

I'm NOT a programmer, but I wrote a test PHP file which successfully authenticates with the new Authentication protocol (using the new token method). But I am having trouble integrating that into the existing code.

From what I can see, the authentication (old way) is done in AuthSubscriber.php. However, when I try to change the headers in order to use the new ones, I am getting all kinds of errors.

In other words, this is how the original headers code is written:

$headers = [
            'WM_SVC.NAME' => 'Walmart Marketplace',
            'WM_QOS.CORRELATION_ID' => base64_encode(Random::string(16)),
            'WM_SEC.TIMESTAMP' => $timestamp,
            'WM_SEC.AUTH_SIGNATURE' => $signature,
            'WM_CONSUMER.ID' => $consumerId,
        ];

Notice that doesn't contain the new OAuth parameters for tokens.

So I changed it to the following which contain the new parameters:

$headers = [
		'Authorization: Basic ' => $authorization,
		'WM_SVC.NAME: Walmart Marketplace',
		'WM_SEC.ACCESS_TOKEN: ' => $token,
		'WM_QOS.CORRELATION_ID: ' => base64_encode(Random::string(16)),
		'Host: marketplace.walmartapis.com',
		];

But that is giving me the following error:

"PHP Fatal error: Uncaught exception 'GuzzleHttp\Exception\ClientException' with message 'Client error response [url] https://marketplace.walmartapis.com/v3/feeds?feedType=inventory [status code] 401 [reason phrase] Unauthorized' in php\vendor\guzzlehttp\guzzle\src\Exception\RequestException.php:89"

Since my new headers work in my test program, I assume there is something else I am missing in order to authenticate with Fillup's code.

@solasus
Copy link
Author

solasus commented Jun 5, 2019

I'm assuming that you already have a function that goes out and gets a $token (which would be a separate call to the api. These tokens are only valid for 900 seconds (15min).

Also, you may run into problems here because I believe many functions are using v2 of the api. And I'm not sure if it will remain supported or forced to use v3 (current).

That said, I created a some standalone code that just used curl to post to but are using headers like yours. I think the problem you have is that either Host is not correct and/or the array is tripping things up. My array looks like this:
$headers = [ 'Authorization: Basic '.$Client_Auth, 'WM_SVC.NAME: Walmart Marketplace', 'WM_SEC.ACCESS_TOKEN: '.getToken(), 'WM_QOS.CORRELATION_ID: '.generateRandomString(12), 'Host: marketplace.walmartapis.com', 'Content-Type: application/json', 'Accept: application/json', ];
getToken() is my function to generate a new token on each run and generateRandomString(12) is as the name says.

Here's the full code to upload bulk inventory (minus the bits that add to the product info array = $feedData).

`// Walmart defaults
$Host = 'https://marketplace.walmartapis.com';
$Client_ID = 'YOUR CLIENT ID';
$Client_Secret = 'YOUR CLIENT SECRET';
$Client_Auth = base64_encode($Client_ID.':'.$Client_Secret);

// random string
function generateRandomString($length = 10) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}

// Get token for Oauth
function getToken(){
global $Host, $Client_Auth;
$url = $Host.'/v3/token';
$headers = [
'Authorization: Basic '.$Client_Auth,
'Content-Type: application/x-www-form-urlencoded',
'Accept: application/json',
'WM_SVC.NAME: Walmart Marketplace',
'WM_QOS.CORRELATION_ID: '.generateRandomString(12),
'WM_SVC.VERSION: 1.0.0',
'Host: marketplace.walmartapis.com',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'grant_type=client_credentials');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_ENCODING , '');
$response = curl_exec($ch);
if (curl_errno($ch)) {
print "Error: " . curl_error($ch);
exit();
}
curl_close($ch);
$json = json_decode($response, true);
$access_token = $json['access_token'];
return $access_token;
}

$feedData = [
'InventoryHeader' => [
'version' => '1.4',
],
'Inventory' => $feedData
];

// walmart api
if($api == 1) {
$data_string = json_encode($feedData); // , JSON_FORCE_OBJECT
// echo $data_string;
// exit;
$url = $Host.'/v3/feeds?feedType=inventory';
$headers = [
'Authorization: Basic '.$Client_Auth,
'WM_SVC.NAME: Walmart Marketplace',
'WM_SEC.ACCESS_TOKEN: '.getToken(),
'WM_QOS.CORRELATION_ID: '.generateRandomString(12),
'Host: marketplace.walmartapis.com',
'Content-Type: application/json',
'Accept: application/json',
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_ENCODING , '');

$response = curl_exec($ch);
if (curl_errno($ch)) {
    print "Error: " . curl_error($ch);
    exit();
}
curl_close($ch);

print_r($response);
echo '<br><br>';

}
`

hope this helps...

@solasus
Copy link
Author

solasus commented Jun 5, 2019

... not sure why code didn't format properly, sorry.

@mjmmagic
Copy link

mjmmagic commented Jun 5, 2019

That's okay, I appreciate your code and I will give it a shot. It's very similar to what I wrote in my own test PHP file.

Question: is your $feedData in JSON or XML format? I assume JSON based on the header but I'm not a great coder and wanted to double check.

Also, am I correct in saying that you aren't really using the Fillup's method of calling initiating his Client class like this anymore:

$client = new Inventory(
			[
				'consumerId' => CONSUMERID,
				'privateKey' => PRIVATEKEY,
				],
				Item::ENV_PROD
			);
$feed = $client->bulk([
				'InventoryFeed' => [
					'InventoryHeader' => [
						'version' => '1.4',
					],
					'inventory' => 
						$arrItem,
				]
			]);

My original goal (and possibly the original poster on this thread) was to try and just update the few instances in Fillup's code so that it would just authenticate the new way, but still use the old frame work. Oh, and possibly change any instances of v2 to v3 for the new versions.

But it's seeming more like it's not being supported by him anymore, and it might be easier to just rewrite everything in my own functions like you did above for Bulk Inventory uploading. The only functions I really use is Bulk Inventory Update, Import Orders, and Update Prices.

@solasus
Copy link
Author

solasus commented Jun 5, 2019

$feedData is a php array that is then json'd by json_encode($feedData)

Yeah - I stared trying to work on this as well - but between battling with guzzle and walmart, I couldn't tell where the problems were originating. So, I opted to just do straight up php code. We only have 4 functions that we need to perform: inventory, get new orders, update shipping info on orders, and refund orders.

@mjmmagic
Copy link

mjmmagic commented Jun 5, 2019

You and I sound like we are brothers from another mother! I came to all the same conclusions: that it's too time consuming to decipher all the Guzzle errors, so just start from scratch and code everything on our own. That way, when future changes happen, it's easier to manage without trying to figure out someone else's coding!

I really appreciate your responding to this thread (even though I didn't start it). Hopefully I can reach out to you if I have any other issues, but if not, I wish you the best Solasus!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants