从 API 获取产品数据的初始调用不起作用 - 无法确定如何将 OAuth 2.0 连接到调用

Initial call to get product data from API is not working - cannot work out how to connect OAuth 2.0 to the call

我正在尝试连接到 Google 购物产品 API 以创建一些新的产品项目。在执行更复杂的任务之前,我只是尝试连接以获取现有产品的列表。

我在 Google API 控制台中设置了一个服务帐户并下载了 json 密钥文件。我已将文件保存到服务器。然后,我从 Google 的文档中获取了所有示例,并试图将它们拼凑在一起。

变量注释:
$KEY_FILE_LOCATION - 这是 json 服务帐户密钥文件的位置。
$merchantid - 这是我的 Google Merchant Center

的 merchantid

代码:

    $client->setAuthConfig($KEY_FILE_LOCATION);
    $client->setApplicationName('Merchant Centre');
    $client->setScopes('https://www.googleapis.com/auth/content');
    echo "<br/><br/>client: ".json_encode($client);

    $url = "https://www.googleapis.com/content/v2/".$merchantid."/products";
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, TRUE);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $data = curl_exec($ch);
    echo "<br/><br/>data: ".$data;

我遇到的问题是如何将身份验证连接到实际的 google 购物电话。 content/v2/merchantid/products 的连接调用 returns 此响应: { "error": { "errors": [ { "domain": "global", "reason": "required", "message": "Login Required", "locationType": "header", "location": "Authorization" } ], "code": 401, "message": "Login Required" } }

那么如何将oauth 2.0认证服务账号json连接到实际调用中呢。我在文档或网上找不到任何关于如何将这两件事实际连接在一起的内容。我与其他 Google API 进行了集成,但是我的代码 none 提供了一个清晰的实现示例。

编辑: 通过进一步阅读文档,我设法制定了一个可能有效的流程。我需要使用 JWT 获取令牌以调用 API - 下面的代码用于访问令牌,但它在最后一部分仍然失败。此调用的响应是 { "error": "invalid_grant", "error_description": "Invalid JWT Signature." }。 JWT 的签名部分是唯一看起来与 Google 给出的示例不同的部分 - 我的代码输出 43 个字符的签名,而 googles 明显更长。

$header = json_encode(['alg' => 'RS256', 'typ' => 'JWT']);
$base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));

$iat = strtotime("now");
$exp = strtotime("+1 hour");
$currenttime = date("H:i:s");

$claimset = json_encode(['iss' => 'REDACTED', 
'scope' => 'https://www.googleapis.com/auth/content', 
'aud' => 'https://www.googleapis.com/oauth2/v4/token', 
'exp' => $exp, 
'iat' => $iat]);
$base64UrlClaimSet = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($claimset));
$signature = hash_hmac('sha256', $base64UrlHeader . "." . $base64UrlClaimSet, $privatekey, true);
$base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));
$jwt = $base64UrlHeader . "." . $base64UrlClaimSet . "." . $base64UrlSignature;

$url = "https://www.googleapis.com/oauth2/v4/token";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=".$jwt);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$data = curl_exec($ch);
echo "<br/><br/>data: ".$data;

我正在尝试关注此 https://developers.google.com/identity/protocols/OAuth2ServiceAccount

的 'computing the signature' 部分

401 表示请求未经授权。您需要在请求中发送 Authorization header,这取决于授权需要哪种身份验证令牌(应该在 api 文档中)。要使用 cURL(例如不记名令牌)在 PHP 中设置 header:

$header = array(
    'Authorization: Bearer <insert-token-here>'
);

curl_setopt($ch, CURLOPT_HTTPHEADER, $header);

好的,我已经设法在 2 天内解决了这个问题,并找到了解决方案。我将其张贴在这里是为了帮助将来可能会为此苦苦挣扎的其他人。这是为了使用 php 和 google 服务帐户来使用 JWT 获取令牌,然后调用以从您的 Google 商家购物帐户获取所有产品。

$merchantid = xxxxxxxxx; //this is a 9 digit code found in top left of Merchant Center
$email = 'xxxxxxxxxxx@merchant-center-xxxxxxxxxxxx.iam.gserviceaccount.com'; //this is the email address assigned to the service account
$privatekey = "-----BEGIN PRIVATE KEY-----\nXXXXXapprox 6 lines long key from json fileXXXXXX\n-----END PRIVATE KEY-----\n"; //this is the long key that you download within the json file at the end of the service account setup
$header = json_encode(['alg' => 'RS256', 'typ' => 'JWT']);
$base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));
$iat = strtotime("now");
$exp = strtotime("+1 hour");
$currenttime = date("H:i:s");
$claimset = json_encode(['iss' => $email, 
'scope' => 'https://www.googleapis.com/auth/content', 
'aud' => 'https://www.googleapis.com/oauth2/v4/token', 
'exp' => $exp, 
'iat' => $iat]);
$base64UrlClaimSet = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($claimset));
$binary_signature = "";
$algo = "SHA256";
openssl_sign($base64UrlHeader.".".$base64UrlClaimSet, $binary_signature, $privatekey, $algo);
$jwtSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($binary_signature));
$jwt = $base64UrlHeader . "." . $base64UrlClaimSet . "." . $jwtSignature;
$url = "https://www.googleapis.com/oauth2/v4/token";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=".$jwt);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
$accesstoken = substr($data, strpos($data, 'access_token') + 16);
$arr = explode('"',trim($accesstoken));
$accesstoken = $arr[0]; 
$url = "https://www.googleapis.com/content/v2/".$merchantid."/products";
$header = array(
    'Authorization: Bearer '.$accesstoken
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
echo "<br/><br/>data: ".$data;