I'm trying to connect to the WooCommerce API using Guzzle 5 (Guzzle 6 seems not has oAuth options o.O). Woocommerce requires the oAuth authentication method to work.
This is the code I'm using:
<?php
/**
* Example of usage of Guzzle 5 to get information
* from a WooCommerce Store.
*/
require('../vendor/autoload.php');
use GuzzleHttp\Client;
use GuzzleHttp\Subscriber\Oauth\Oauth1;
use GuzzleHttp\Exception\RequestException;
$consumer_key = 'my_consumer_key'; // Add your own Consumer Key here
$consumer_secret = 'my_consumer_secret'; // Add your own Consumer Secret here
$store_url = 'http://example.com'; // Add the home URL to the store you want to connect to here
$api_path = '/wc-api/v2/';
$api_end_point = [
'root' => '',
'orders' => 'orders'
];
$base_uri = $store_url . $api_path;
$client = new Client([
'base_url' => $base_uri,
'defaults' => ['auth' => 'oauth']
]);
$oauth = new Oauth1([
'consumer_key' => $consumer_key,
'consumer_secret' => $consumer_secret,
'request_method' => 'query'
]);
$client->getEmitter()->attach($oauth);
try
{
$res = $client->get($api_end_point['orders']);
}
catch (RequestException $e)
{
$res = $e;
if ($e->hasResponse())
{
$res = $e->getResponse();
}
}
print_r($res);
echo $res->getStatusCode();
// "200"
echo $res->getHeader('content-type');
// 'application/json; charset=utf8'
echo $res->getBody();
// {"type":"User"...'
This code returns a
woocommerce_api_authentication_error: Invalid Signature - provided
signature does not match
Using pure curl functions (using this package in which I've put some functions I found here), instead, it works and I get all orders and other data I want.
SOME OTHER DETAILS
To use Guzzle 5 and oAuth I use the those composer packages:
"require": {
"guzzlehttp/guzzle": "~5.0"
},
"require-dev": {
"guzzlehttp/oauth-subscriber": "~0.2",
},
It seems there are some things that are different in creating the signature: the one created by the library I've used until now works, but the one created by the oAuth plugin (using the method getSignature()
) for Guzzle doesn't and I'm not so used to use oAuth to find the error. Is there someone who can help me identify the problem?
Updating @Aerendir answer
In his pull request, @Aerendir wrote:
In my case, I did the editing as I were trying to connect to the
WooCommerce API version 2 but that version of the API didn't implement
correctly the OAuth Core 1.0a spec. In fact, they fixed this issue in
the version 3 of the API. See Differences between V3 and older
versions.
source: https://github.com/guzzle/oauth-subscriber/pull/42#issuecomment-185631670
So, to make his answer work properly, we need to use wc-api/v3/ instead of wc-api/v2/.
The following code, works using Guzzle 6, oauth and WooCommerce api v3:
use GuzzleHttp\Client,
GuzzleHttp\HandlerStack,
GuzzleHttp\Handler\CurlHandler,
GuzzleHttp\Subscriber\Oauth\Oauth1;
$url = 'http://localhost/WooCommerce/';
$api = 'wc-api/v3/';
$endpoint = 'orders';
$consumer_key = 'ck_999ffa6b1be3f38058ed83e5786ac133e8c0bc60';
$consumer_secret = 'cs_8f6c96c56a7281203c2ff35d71e5c4f9b70e9704';
$handler = new CurlHandler();
$stack = HandlerStack::create($handler);
$middleware = new Oauth1([
'consumer_key' => $consumer_key,
'consumer_secret' => $consumer_secret,
'token_secret' => '',
'token' => '',
'request_method' => Oauth1::REQUEST_METHOD_QUERY,
'signature_method' => Oauth1::SIGNATURE_METHOD_HMAC
]);
$stack->push($middleware);
$client = new Client([
'base_uri' => $url . $api,
'handler' => $stack
]);
$response = $client->get( $endpoint, [ 'auth' => 'oauth' ] );
echo $response->getStatusCode() . '<br>';
echo $response->getHeaderLine('content-type') . '<br>';
echo $response->getBody();
Now the plugin OauthSubscriber
is available only for Guzzle 6.
Testing around again, I've found the bug: it is in the method signUsingHmacSha1()
that anyway adds an umpersand (&) to the string to sign and this causes the error from WooCommerce.
I've opened a issue on GitHub and sent a pull request to fix the bug.
The correct way to connect to the WooCommerce API V2 using Guzzle 6 (once the bug is fixed! Take care of the version of the WooCommerce API you connect: the API v3 still doesn't work!) is this:
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Handler\CurlHandler;
use GuzzleHttp\Subscriber\Oauth\Oauth1;
$options = array(
// Add the home URL to the store you want to connect to here (without the end / )
'remoteUrl' => 'http://example.com/',
// Add your own Consumer Key here
'remoteConsumerKey' => 'ck_4rdyourConsumerKey8ik',
// Add your own Secret Key here
'remoteSecretKey' => 'cs_738youconsumersecret94i',
// Add the endpoint base path
'remoteApiPath' => 'wc-api/v2/',
);
$remoteApiUrl = $options['remoteUrl'] . $options['remoteApiPath'];
$endpoint = 'orders';
$handler = new CurlHandler();
$stack = HandlerStack::create($handler);
$middleware = new Oauth1([
'consumer_key' => $options['remoteConsumerKey'],
'consumer_secret' => $options['remoteSecretKey'],
'token_secret' => '',
'token' => '',
'request_method' => Oauth1::REQUEST_METHOD_QUERY,
'signature_method' => Oauth1::SIGNATURE_METHOD_HMAC
]);
$stack->push($middleware);
$client = new Client([
'base_uri' => $remoteApiUrl,
'handler' => $stack
]);
$res = $client->get($endpoint, ['auth' => 'oauth');
As told, this connection works only with the version 2 of the WooCommerce API.
I'm investigating to understand why the V3 doesn't work.