如何使用oAuth与Guzzle 5(或者更好,与Guzzle 6)


How to use oAuth with Guzzle 5 (or, better, with Guzzle 6)

我正在尝试使用Guzzle 5连接到WooCommerce API (Guzzle 6似乎没有oAuth选项o.O)。Woocommerce需要oAuth认证方法才能工作。

这是我使用的代码:

<?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"...'

代码返回

woocommerce_api_authentication_error: Invalid Signature -提供签名不匹配

使用纯curl函数(使用这个包,我在这里找到了一些函数),相反,它工作,我得到了所有的订单和其他我想要的数据。

其他细节

要使用Guzzle 5和oAuth,我使用那些编写器包:

"require": {
    "guzzlehttp/guzzle": "~5.0"
},
"require-dev": {
    "guzzlehttp/oauth-subscriber": "~0.2",
},

似乎有一些东西在创建签名是不同的:一个由我使用的库创建到现在为止的工作,但是由oAuth插件(使用方法getSignature())创建的Guzzle没有,我不太习惯使用oAuth来找到错误。有人能帮我找出问题所在吗?

更新@Aerendir答案

在他的pull request中,@Aerendir写道:

在我的情况下,我做编辑,因为我试图连接到WooCommerce API版本2,但那个版本的API没有实现事实上,OAuth Core 1.0a规范已经修复了这个问题API的版本3。请参阅V3和更早版本之间的区别版本。

来源:https://github.com/guzzle/oauth-subscriber/pull/42 issuecomment - 185631670

因此,为了使他的答案正常工作,我们需要使用wc-api/v3/而不是wc-api/v2/

下面的代码,使用Guzzle 6, oauth和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();

现在插件OauthSubscriber只适用于Guzzle 6。再次测试,我发现了这个bug:它是在signUsingHmacSha1()方法中,无论如何添加一个字符(&)到字符串签名,这会导致WooCommerce的错误。

我已经在GitHub上打开了一个问题,并发送了一个拉请求来修复这个错误。

使用Guzzle 6连接到WooCommerce API V2的正确方法(一旦错误被修复!)注意你连接的WooCommerce API的版本:API v3仍然不工作!)是这样的:

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');

如上所述,此连接仅适用于版本2的WooCommerce API。

我正在调查为什么V3不能工作。