douludi8413 2019-07-17 08:40
浏览 128
已采纳

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

I am trying to connect to the Google Shopping Products API to create some new product items. Before I do that more complex task, I am just trying to connect to get a list of the existing products.

I have setup a Service Account within Google API console and downloaded the json key file. I have saved the file to the server. I have then taken all of the examples from Google's documents and tried to piece them together.

VARIABLE NOTES:
$KEY_FILE_LOCATION - this is the location of the json service account key file.
$merchantid - this is the merchantid of my Google Merchant Centre

CODE:

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

What I am having trouble with, is how to connect the authentication to the actual google shopping call. The connection to the content/v2/merchantid/products call returns this response: { "error": { "errors": [ { "domain": "global", "reason": "required", "message": "Login Required", "locationType": "header", "location": "Authorization" } ], "code": 401, "message": "Login Required" } }

So how do I connect the oauth 2.0 authentication service account json to the actual call. I can't find anything in the documentation or online, about how you actually connect the two things together. I have integrations with other Google API's but none of the code I have provides a clear example of implementing this.

EDIT: Following the documentation through further I have managed to work out a flow that may work. I need to use JWT to obtain a token for the call to the API - the code below is being used to access the token, but it is still failing on the last section. The response from this call is { "error": "invalid_grant", "error_description": "Invalid JWT Signature." }. The signature section of the JWT is the only section that looks different to the example Google has given - my code outputs a signature of 43 characters whereas googles is significantly longer.

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

I am trying to follow the 'computing the signature' section of this https://developers.google.com/identity/protocols/OAuth2ServiceAccount

  • 写回答

2条回答 默认 最新

  • dos8244 2019-07-18 14:57
    关注

    Okay, I have managed to work through this over 2 days, and have the solution. I am posting it here to help out others in the future who may struggle with this. This is for using php with a google service account to obtain a token using JWT and then make a call to get all products from your Google Merchant Shopping account.

    $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-----
    XXXXXapprox 6 lines long key from json fileXXXXXX
    -----END PRIVATE KEY-----
    "; //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;
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改