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