5

I'm beginning work on a PHP script that will run as a cron job and periodically update product listings via the Google Shopping API.

I downloaded the GSC Client library for PHP and am trying to work through the Google Shopping API documentation in order to get as far as getting a token. However it feels like there's a step missing somewhere in the docs regarding how to actually request a token once you've generated the URL.

Here's my code so far:

require ("./lib/shoppingclient/GShoppingContent.php");

const G_MERCHANT_ID     = '**********';
const G_CLIENT_ID       = '**********';
const G_CLIENT_SECRET   = '**********';

$obj_client = new GSC_Client (G_MERCHANT_ID);

// Obtain an OAuth2 token to access the API with
$obj_token  = new GSC_OAuth2Token (G_CLIENT_ID, G_CLIENT_SECRET, USER_AGENT);

$str_url    = $obj_token -> generateAuthorizeUrl ('urn:ietf:wg:oauth:2.0:oob');
echo ($str_url . PHP_EOL);

/* @var $obj_response _GSC_Response */
$obj_response = $obj_token -> makeAuthenticatedRequest (curl_init ($str_url));
echo ($obj_response);

When I run the above from the commandline, I get:

https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=blah-blah-blah-etc-etc-etc...

<HTML>
<HEAD>
<TITLE>Unauthorized</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>Unauthorized</H1>
<H2>Error 401</H2>
</BODY>
</HTML>

Fatal error: Uncaught exception 'GSC_TokenError' with message 'invalid_request' in /var/samba/GoogleShoppingTest/lib/shoppingclient/GShoppingContent.php on line 624

GSC_TokenError: invalid_request in /var/samba/GoogleShoppingTest/lib/shoppingclient/GShoppingContent.php on line 624

Call Stack:
    0.0002     321888   1. {main}() /var/samba/GoogleShoppingTest/logintest.php:0
    0.0065    1446196   2. GSC_OAuth2Token->makeAuthenticatedRequest() /var/samba/GoogleShoppingTest/logintest.php:19
    0.2797    1446684   3. GSC_OAuth2Token->refresh() /var/samba/GoogleShoppingTest/lib/shoppingclient/GShoppingContent.php:722
    0.3992    1448152   4. GSC_OAuth2Token::raiseFromJson() /var/samba/GoogleShoppingTest/lib/shoppingclient/GShoppingContent.php:565

I'm fairly surely initializing a CURL object shouldn't be necessary, but I can't figure out how I get from the generated URL to an actual response to parse.

If I visit the URL generated by generateAuthorizeUrl() I get a page with a button asking me to grant permission. If I do that, I do get a page that has a token on it which as far as I can tell is valid.

However, this is for a cron script that obviously won't be able to ask the user to click a button and confirm that they want to grant permission, so obviously I'm going off track somewhere.

Has anyone managed to get the GSC_Client to work with OAuth in an entirely automatic script? If so, what am I doing wrong here?

UPDATE: For this application, I've configured the API type as "Installed application", which appears to be the correct API type for this application. This means I provide the script with the shared secret and use https://localhost or urn:ietf:wg:oauth:2.0:oob as the URL.

UPDATE 2: I don't think the GSC client's support libraries support server-to-server scenarios. Further research has indicated that I need the Google APIs client library if I want to use the private key method of authentication.

This is the code I've managed to write so far:

require ("./lib/google/oauthclient/Google_Client.php");
require ("./lib/google/shoppingclient/GShoppingContent.php");

const G_MERCHANT_ID     = '********';
const G_CLIENT_ID       = '********';
const G_CLIENT_EMAIL    = '********';
const G_CLIENT_KEY_PATH = '/path/to/the/privatekey.p12';
const G_CLIENT_KEY_PW   = 'notasecret';

$obj_client_auth  = new Google_Client ();
$obj_client_auth -> setApplicationName ('test');
$obj_client_auth -> setClientId (G_CLIENT_ID);
$obj_client_auth -> setAssertionCredentials (new Google_AssertionCredentials (
        G_CLIENT_EMAIL, 
        array (OAUTH_SCOPE), 
        file_get_contents (G_CLIENT_KEY_PATH), 
        G_CLIENT_KEY_PW));

$obj_client_auth -> getAuth () -> refreshTokenWithAssertion ();

// Get a token
$obj_token  = json_decode ($obj_client_auth -> getAccessToken ());
print_r ($obj_token);

When I run the above code I get something resembling the following in return:

stdClass Object
(
    [access_token] => ya29.AHES6ZRJohl2AfbQCKbFxNlagSqLGcjHwiylqASX1ygmwg
    [expires_in] => 3600
    [created] => 1359123809
)

I'm guessing this is a valid access token response.

However, I haven't figured out how to use the returned token with the GSC_Client library yet. While I know both these libraries originated from Google, I'm getting the distinct impression that they were developed by different teams who had little, if anything, to do with each other, and the end result is these libraries aren't cross-compatible. If anybody knows what to do here, I'd appreciate any advice you may have.

UPDATE 3

I've managed to use the oAuth library to actually pull data from Google, but it's from the Search API for shopping. I need to be doing manipulation of product listings with the Content API for shopping. There doesn't appear to be a class provided with the oAuth library for doing that, even in the contrib directory!

FYI, here's the code that does the search API request (minus the constants):

$obj_client_auth  = new Google_Client ();
$obj_client_auth -> setApplicationName ('test');
$obj_client_auth -> setClientId (G_CLIENT_ID);
$obj_client_auth -> setAssertionCredentials (new Google_AssertionCredentials (
        G_CLIENT_EMAIL, 
        array (
            //'https://www.googleapis.com/auth/structuredcontent',
            'https://www.googleapis.com/auth/shoppingapi'
            ), 
        file_get_contents (G_CLIENT_KEY_PATH), 
        G_CLIENT_KEY_PW));

$obj_client_api   = new Google_ShoppingService ($obj_client_auth);

$arr_results = $obj_client_api -> products -> listProducts ('public', array (
   'country'   => 'GB',
   'q'         => '"mp3 player" | ipod', 
   'rankBy'    => 'relevancy'
));

print_r ($arr_results);
4

2 に答える 2

1

GSC_client ライブラリが独自の OAuth2 実装と密接に結合されているため、大幅なリファクタリング作業を行わなくても Google_Client ライブラリを簡単に統合できないようです。また、GSC_Client の OAuth2 実装は、クライアント シークレットの概念と同意ページへのリダイレクトと密接に結びついているため、Google_Client 実装を代替としてラップする実装を作成する必要があります。

幸いなことに、社内で開発された Google の API とインターフェイスするためのコードベースがあり、認証システムとの結合はそれほど緊密ではありません。ちょっとした作業で、Google_Client をラップする新しい認証モジュールを追加することができました。

ただし、Google の GSC_Client を Google_Client と連携させる方法についての回答はないようです。そのため、より良い回答を探しています。

于 2013-02-01T09:20:41.300 に答える