我开始研究一个PHP脚本,该脚本将作为cron作业运行,并通过Google Shopping API定期更新产品列表。
我下载了GSC Client library for PHP,并尝试通过Google Shopping API documentation来获取令牌。然而,感觉就像在文档中某处有关于如何在生成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到解析的实际响应。
如果我访问generateAuthorizeUrl()生成的URL,我会看到一个带有按钮的页面,要求我授予权限。如果我这样做,我会得到一个页面,上面有一个令牌,据我所知是有效的。
然而,这是一个cron脚本,显然无法要求用户点击按钮并确认他们想要授予权限,所以很明显我会偏离某个地方。
有没有人设法让GSC_Client在完全自动的脚本中使用OAuth?如果是这样,我在这里做错了什么?
更新:对于此应用程序,我已将API类型配置为“已安装的应用程序”,这似乎是此应用程序的正确API类型。这意味着我为脚本提供了共享密钥,并使用https://localhost
或urn:ietf:wg:oauth:2.0:oob
作为URL。
更新2 :我认为GSC客户端的支持库不支持服务器到服务器方案。进一步的研究表明,如果我想使用私钥认证方法,我需要Google APIs client library。
这是我到目前为止编写的代码:
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提取数据,但它来自Search 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);
答案 0 :(得分:1)
看起来GSC_client库与其自己的OAuth2实现过于紧密耦合,以便Google_Client库可以轻松集成到其中,而无需进行重大的重构工作。此外,GSC_Client的OAuth2实现与客户端机密概念过于紧密耦合,并重定向到同意页面,以便我编写一个实现,将Google_Client实现包装为替代品。
幸运的是,我们有一个代码库,用于与内部开发的Google API进行交互,并且与其身份验证系统的联系较少。通过一些工作,可以为其添加一个包含Google_Client的新身份验证模块。
然而,似乎没有答案如何让谷歌的GSC_Client与Google_Client合作,所以我仍然在寻找更好的答案。
答案 1 :(得分:0)
我知道这是一个稍微陈旧的问题,但我有类似的要求,因为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;
}