【问题标题】:GSC_Client and oAuth2 accessGSC_Client 和 oAuth2 访问
【发布时间】:2013-01-08 11:27:47
【问题描述】:

我开始编写一个 PHP 脚本,该脚本将作为 cron 作业运行,并通过 Google 购物 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://localhosturn: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 库一起使用。虽然我知道这两个库都来自谷歌,但我得到的明显印象是它们是由不同的团队开发的,他们之间几乎没有什么关系,最终结果是这些库不是交叉兼容的.如果有人知道在这里做什么,我将不胜感激您的任何建议。

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

【问题讨论】:

  • 你能分享一下有什么问题吗?一旦您获得了针对结构化内容范围授权的访问令牌,就可以将其与 GET/POST 请求一起传递给产品 API。你能分享一下确切的错误吗?
  • 什么是“破坏”是似乎没有任何方法可以将从 google_client 库获得的令牌注入 GSC_Content 库。它们显然彼此不兼容。

标签: php google-api oauth-2.0 google-shopping-api


【解决方案1】:

看起来 GSC_client 库与它自己的 OAuth2 实现的耦合过于紧密,以至于 Google_Client 库无需大量重构工作即可轻松集成到其中。此外,GSC_Client 的 OAuth2 实现与客户端机密概念以及重定向到同意页面的耦合过于紧密,因此我编写了一个将 Google_Client 实现包装为替代品的实现。

幸运的是,我们有一个内部开发的用于与 Google 的 API 交互的代码库,并且与其身份验证系统的耦合度较低。通过一些工作,可以向其中添加一个包装 Google_Client 的新身份验证模块。

但是,对于如何让 Google 的 GSC_Client 与 Google_Client 一起工作似乎没有答案,所以我仍在寻找更好的答案。

【讨论】:

    【解决方案2】:

    我知道这是一个有点老的问题,但我有类似的要求,因为 Google 刚刚取消了我们用来更新价格和可用性的旧 API。

    下面的代码对我有用。它使用服务器-服务器身份验证,因此不需要用户输入。您需要登录到您的 google api 控制台并设置一个新的服务帐户(如果您有一个和 p12 文件,则使用现有的)此外,您还需要将服务代码的电子邮件地址添加到您的 Google Merchant Center 中一个标准用户 - 好吧,我不确定是否需要它,但我做到了并且它有效:-)

    附带说明 - 我们使用 MPN 搜索旧 API,使用新 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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-31
      • 1970-01-01
      • 2017-08-31
      • 2018-07-17
      • 2019-03-25
      • 1970-01-01
      • 2018-12-08
      相关资源
      最近更新 更多