2013-01-24 30 views
5

Ich beginne mit der Arbeit an einem PHP-Skript, das als Cron-Job ausgeführt wird und regelmäßig Produkteinträge über die Google Shopping API aktualisiert.Zugriff auf GSC_Client und oAuth2

Ich habe die GSC Client library for PHP heruntergeladen und versuche durch die Google Shopping API documentation zu arbeiten, um so weit wie ein Token bekommen. Es fühlt sich jedoch so an, als ob irgendwo in den Dokumenten ein Schritt fehlte, wie man tatsächlich ein Token anfordert, sobald man die URL generiert hat.

Hier ist mein Code so weit:

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

Als ich das oben von der Kommandozeile ausführen, erhalte ich:

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 ziemlich sicher initialisieren ein CURL-Objekt sollte nicht notwendig sein, aber ich kann nicht herausfinden, woher ich komme die generierte URL zu einer tatsächlichen Antwort zum Parsen.

Wenn ich die von generateAuthorizeUrl() generierte URL besuche, bekomme ich eine Seite mit einer Schaltfläche, die mich auffordert, die Erlaubnis zu erteilen. Wenn ich das tue, bekomme ich eine Seite mit einem Token, die soweit ich weiß, gültig ist.

Dies ist jedoch für ein Cron-Skript, das nicht in der Lage ist, den Benutzer zu bitten, auf eine Schaltfläche zu klicken und zu bestätigen, dass sie die Erlaubnis erteilen möchten, also gehe ich natürlich irgendwo weg.

Hat es jemand geschafft, den GSC_Client in einem vollständig automatischen Skript mit OAuth arbeiten zu lassen? Wenn ja, was mache ich hier falsch?

AKTUALISIEREN: Für diese Anwendung habe ich den API-Typ als "Installierte Anwendung" konfiguriert, die offenbar der richtige API-Typ für diese Anwendung ist. Das bedeutet, dass ich das Skript mit dem gemeinsamen Schlüssel zur Verfügung stelle und https://localhost oder urn:ietf:wg:oauth:2.0:oob als URL verwende.

UPDATE 2: Ich glaube nicht, dass die Support-Bibliotheken des GSC-Clients Server-zu-Server-Szenarien unterstützen. Weitere Untersuchungen haben ergeben, dass ich die Google APIs client library benötige, wenn ich die private Schlüsselmethode der Authentifizierung verwenden möchte.

Dies ist der Code, den ich habe es geschafft, so weit zu schreiben:

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

Ich vermute:

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

Als ich das ich so etwas wie der im Gegenzug folgende erhalten oben Code ausführen Dies ist eine gültige Zugriffstokenantwort.

Allerdings habe ich noch nicht herausgefunden, wie Sie das zurückgegebene Token mit der GSC_Client-Bibliothek verwenden. Obwohl ich weiß, dass diese beiden Bibliotheken von Google stammen, bekomme ich den deutlichen Eindruck, dass sie von verschiedenen Teams entwickelt wurden, die wenig oder gar nichts miteinander zu tun hatten, und das Endergebnis ist, dass diese Bibliotheken nicht kompatibel sind . Wenn jemand weiß, was hier zu tun ist, würde ich mich über jeden Rat freuen, den Sie haben könnten.

UPDATE 3

Ich habe es geschafft, die oAuth Bibliothek verwenden, um tatsächlich Daten von Google zu ziehen, aber es ist von der Such-API für Shopping. Ich muss die Produktlisten mit der Content API manipulieren, um einkaufen zu können. Es scheint keine Klasse mit der oAuth-Bibliothek dafür zu geben, auch nicht im contrib-Verzeichnis!

FYI, hier ist der Code, der die Suche API-Anforderung bedeutet (minus die Konstanten):

$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); 
+0

Können Sie bitte teilen, was bricht. Sobald Sie über ein Zugriffstoken verfügen, das für den Bereich "structuredcontent" autorisiert ist, kann es mit der GET/POST-Anforderung an die Produkt-API übergeben werden. Können Sie bitte den genauen Fehler teilen? –

+0

Was "brechend" ist, ist, dass es anscheinend keine Möglichkeit gibt, das Token, wie es aus der google_client-Bibliothek stammt, in die GSC_Content-Bibliothek zu injizieren. Sie sind anscheinend nicht miteinander kompatibel. – GordonM

Antwort

1

Es sieht aus, als ob die GSC_client Bibliothek zu fest an seine eigenen OAuth2 Implementierung für die Google_Client Bibliothek gekoppelt ist, zu sein leicht integrierbar ohne wesentliche Umgestaltung. Auch die OAuth2-Implementierung des GSC_Client ist zu eng an das Client-Secret-Konzept gekoppelt und leitet zu einer Zustimmungsseite weiter, auf der ich eine Implementierung schreiben kann, die die Google_Client-Implementierung als Ersatz einfügt.

Glücklicherweise verfügen wir über eine Codebasis für die Schnittstelle zu den Google APIs, die intern entwickelt wurde und weniger eng mit dem Authentifizierungssystem verbunden ist. Mit ein wenig Arbeit war es möglich, ein neues Authentifizierungsmodul hinzuzufügen, das Google_Client umschloss.

Es scheint jedoch keine Antwort darauf zu geben, wie Google GSC_Client mit Google_Client arbeiten kann, so dass ich immer noch nach einer besseren Antwort suche.

0

Ich weiß, dass dies eine etwas alte Frage ist, aber ich hatte ähnliche Anforderungen, da Google gerade die alte API, die wir verwendeten, um Preise und Verfügbarkeit zu aktualisieren, getötet hatte.

Der folgende Code ist was für mich funktioniert. Es verwendet die Server-Server-Authentifizierung, sodass keine Benutzereingabe erforderlich ist. Sie müssen sich bei Ihrer Google API-Konsole anmelden und ein neues Dienstkonto einrichten (oder ein vorhandenes verwenden, wenn Sie eines und die p12-Datei haben). Außerdem müssen Sie die E-Mail-Adresse für den Dienstcode in Ihrem Google Merchant Center hinzufügen ein Standardbenutzer - na ja, ich bin nicht sicher, ob es erforderlich ist, aber ich tat es und es funktioniert :-)

Auf einer seitlichen Anmerkung - die alte API verwenden wir die MPN Suche verwenden, mit dem neuen AP

require_once realpath(dirname(__FILE__) . '/src/Google/autoload.php'); 
require_once realpath(dirname(__FILE__) . '/src/Google/Service/ShoppingContent.php'); 


$merchantId = '<<MY_MERCHANT_ID>>'; 
$client_id = '<<MY_GOOGLE_API_SERVICE_ACCOUNT_ID>>'; 
$client_email = <<MY_GOOGLE_API_SERVICE_ACCOUNT_EMAIL>>'; 
$scopes = array('https://www.googleapis.com/auth/content'); 
$private_key = file_get_contents('<<MY_GOOGLE_API_SERVICE_ACCOUNT_P12_FILE>>'); 
$credentials = new Google_Auth_AssertionCredentials(
    $client_email, 
    $scopes, 
    $private_key 
); 

$client = new Google_Client(); 
$client->setAssertionCredentials($credentials); 
$client->setScopes($scopes); 
$client->setAccessType("offline"); 

if ($client->getAuth()->isAccessTokenExpired()) $client->getAuth()->refreshTokenWithAssertion(); 
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) { 
    $client->setAccessToken($_SESSION['access_token']); 
} else { 
    $authUrl = $client->createAuthUrl(); 
} 

$service = new Google_Service_ShoppingContent($client); 

//Example to get sku information 
$ret = getsku($client, $service, $merchantId, 'DC35DS'); 
echo "<pre>"; print_r($ret); echo "</pre>"; 

//Example to set price and availability 
$ret = update_Price_Availability($client, $service, $merchantId, $itemid, $price, $availability); 
echo "<pre>"; print_r($ret); echo "</pre>"; 


function update_Price_Availability($client, $service, $merchantId, $itemid, $newprice = null, $availability = null) { 
    $inventory = new Google_Service_ShoppingContent_InventorySetRequest(); 
    $price = new Google_Service_ShoppingContent_Price(); 
    $ctrl = 0; 
    if ($newprice !== null) { 
     $price->setValue($newprice); 
     $price->setCurrency('GBP'); 
     $inventory->setPrice($price); 
     $ctrl = 1; 
    } 
    if ($availability !== null) { 
     $inventory->setAvailability($availability); 
     $ctrl = 1; 
    } 
    if ($ctrl == 0) { 
     return array('Errors'=>array('Nothing to do')); 
    } 
    try { 
     $return = $service->inventory->set($merchantId, 'online', 'online:en:GB:'.$itemid, $inventory); 
    } catch (Google_Service_Exception $e) { 
     return array('Errors'=>$e->geterrors(),'Message'=>$e->getmessage()); 
    } 
    return getsku($client, $service, $merchantId, $itemid); 
} 

function getsku($client, $service, $merchantId, $itemid) { 
    try { 
     $product = $service->products->get($merchantId, 'online:en:GB:'.$itemid); 
    } catch (Google_Service_Exception $e) { 
     $product = array('Errors'=>$e->geterrors(),'Message'=>$e->getmessage()); 
    } 
    return $product; 
}