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