GSC_Client и oAuth2 доступ

Я начинаю работу над сценарием PHP, который будет работать как задание cron и периодически обновлять списки продуктов через Google Shopping API.

Я загрузил клиентскую библиотеку GSC для PHP и пытаюсь работать с документацией по Google Shopping API, чтобы получить токен. Однако кажется, что где-то в документах отсутствует шаг относительно того, как на самом деле запросить токен после того, как вы сгенерировали URL.

Вот мой код до сих пор:

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

Когда я запускаю вышеизложенное из командной строки, я получаю:

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

Я вполне уверен, что инициализация объекта CURL не обязательна, но я не могу понять, каким образом я получаю от сгенерированного URL-адреса фактический ответ на анализ.

Если я захожу на URL-адрес, сгенерированный функцией generateAuthorizeUrl(), я получаю страницу с кнопкой, запрашивающей разрешение. Если я это сделаю, то получу страницу с токеном, которая, насколько я могу судить, действительна.

Однако это для сценария cron, который, очевидно, не сможет попросить пользователя нажать кнопку и подтвердить, что он хочет предоставить разрешение, поэтому, очевидно, я где-то не в курсе.

Кому-нибудь удалось заставить GSC_Client работать с OAuth полностью автоматическим скриптом? Если так, что я здесь делаю не так?

ОБНОВЛЕНИЕ: Для этого приложения я настроил тип API как "Установленное приложение", который, как представляется, является правильным типом API для этого приложения. Это означает, что я предоставляю сценарию общий секрет и использую https://localhost или же urn:ietf:wg:oauth:2.0:oob как URL.

ОБНОВЛЕНИЕ 2: Я не думаю, что библиотеки поддержки клиента GSC поддерживают межсерверные сценарии. Дальнейшие исследования показали, что мне нужна клиентская библиотека API Google, если я хочу использовать метод аутентификации с закрытым ключом.

Вот код, который мне удалось написать до сих пор:

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

Когда я запускаю приведенный выше код, я получаю что-то похожее на следующее:

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

Я предполагаю, что это действительный ответ токена доступа.

Однако я еще не понял, как использовать возвращенный токен с библиотекой GSC_Client. Хотя я знаю, что обе эти библиотеки были созданы Google, у меня сложилось четкое впечатление, что они были разработаны разными командами, которые имеют мало общего, если вообще что-то имеют, и в результате эти библиотеки не являются кросс-совместимыми., Если кто-нибудь знает, что делать здесь, я буду признателен за любые советы, которые вы можете иметь.

ОБНОВЛЕНИЕ 3

Мне удалось использовать библиотеку oAuth для получения данных из Google, но это из API поиска для покупок. Мне нужно делать манипуляции с списками продуктов с помощью Content API для покупок. Кажется, не существует класса, предоставляемого библиотекой oAuth для этого, даже в каталоге contrib!

К вашему сведению, вот код, который выполняет запрос API поиска (за вычетом констант):

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

2 ответа

Похоже, что библиотека GSC_client слишком тесно связана с собственной реализацией OAuth2 для библиотеки Google_Client, чтобы ее можно было легко интегрировать в нее без значительной работы по рефакторингу. Также реализация OAuth2 GSC_Client слишком тесно связана с концепцией секретности клиента и с перенаправлением на страницу согласия, чтобы я мог написать реализацию, которая оборачивает реализацию Google_Client в качестве замены.

К счастью, у нас есть кодовая база для взаимодействия с API Google, которая была разработана внутри компании и менее тесно связана с ее системой аутентификации. Немного поработав, можно было добавить новый модуль аутентификации, который обернул Google_Client.

Однако, похоже, нет ответа на вопрос, как заставить Google GSC_Client работать с Google_Client, поэтому я все еще ищу лучший ответ.

Я знаю, что это немного старый вопрос, но у меня были схожие требования, так как Google просто убил старый API, который мы использовали для обновления цен и доступности.

Код ниже, это то, что работает для меня. Он использует аутентификацию сервер-сервер, поэтому ввод пользователя не требуется. Вам нужно будет войти в свою консоль google api и настроить новую учетную запись службы (или использовать существующую, если она у вас есть, и файл p12), а также добавить адрес электронной почты для кода службы в свой Google Merchant Center как обычный пользователь - ну, я не уверен, если это необходимо, но я сделал это, и это работает:-)

На заметку - используя старый API, мы ищем, используя MPN, с новым 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;
}
Другие вопросы по тегам