【问题标题】:AndroidPublisherService - Play Developer API Client - Upload aab failes due to bad credentialsAndroidPublisherService - Play Developer API 客户端 - 由于凭据错误,上传 aab 失败
【发布时间】:2021-02-02 09:52:55
【问题描述】:

尝试使用 Play Developer API 客户端中的 AndroidPublisherService。 我可以列出活动曲目和这些曲目中的版本,但是当我尝试上传新版本时,似乎无法附加之前已经进行的身份验证来读取数据。

我已使用 var googleCredentials = GoogleCredential.FromStream(keyDataStream) .CreateWithUser(serviceUsername); 进行身份验证,其中 serviceUsername 是我的服务帐户的电子邮件。

    private static void Execute(string packageName, string aabfile, string credfile, string serviceUsername)
    {
        var credentialsFilename = credfile;
        if (string.IsNullOrWhiteSpace(credentialsFilename))
        {
            // Check env. var
            credentialsFilename =
                Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS",
                    EnvironmentVariableTarget.Process);
        }

        Console.WriteLine($"Using credentials {credfile} with package {packageName} for aab file {aabfile}");
        
        var keyDataStream = File.OpenRead(credentialsFilename);
        var googleCredentials = GoogleCredential.FromStream(keyDataStream)
            .CreateWithUser(serviceUsername);
        var credentials = googleCredentials.UnderlyingCredential as ServiceAccountCredential;
        
        var service = new AndroidPublisherService();
        
        var edit = service.Edits.Insert(new AppEdit { ExpiryTimeSeconds = "3600" }, packageName);
        edit.Credential = credentials;
        var activeEditSession = edit.Execute();
        Console.WriteLine($"Edits started with id {activeEditSession.Id}");
        
        var tracksList = service.Edits.Tracks.List(packageName, activeEditSession.Id);
        tracksList.Credential = credentials;
        var tracksResponse = tracksList.Execute();
        foreach (var track in tracksResponse.Tracks)
        {
            Console.WriteLine($"Track: {track.TrackValue}");
            Console.WriteLine("Releases: ");
            foreach (var rel in track.Releases)
                Console.WriteLine($"{rel.Name} version: {rel.VersionCodes.FirstOrDefault()} - Status: {rel.Status}");
        }
        
        using var fileStream = File.OpenRead(aabfile);
        var upload = service.Edits.Bundles.Upload(packageName, activeEditSession.Id, fileStream, "application/octet-stream");
        var uploadProgress = upload.Upload();
        if (uploadProgress == null || uploadProgress.Exception != null)
        {
            Console.WriteLine($"Failed to upload. Error: {uploadProgress?.Exception}");
            return;
        }
        
        Console.WriteLine($"Upload {uploadProgress.Status}");

        var tracksUpdate = service.Edits.Tracks.Update(new Track
        {
            Releases = new List<TrackRelease>(new[]
            {
                new TrackRelease
                {
                    Name = "Roswell - Grenis Dev Test",
                    Status = "completed",
                    VersionCodes = new List<long?>(new[] {(long?) upload?.ResponseBody?.VersionCode})
                }
            })
        }, packageName, activeEditSession.Id, "internal");
        
        tracksUpdate.Credential = credentials;
        var trackResult = tracksUpdate.Execute();
        Console.WriteLine($"Track {trackResult?.TrackValue}");

        var commitResult = service.Edits.Commit(packageName, activeEditSession.Id);
        Console.WriteLine($"{commitResult.EditId} has been committed");
    }

正如代码所指出的,所有操作对象(例如 tracksList.Credential = credentials;)都可以被赋予从服务帐户生成的凭据。

但是实际的上传操作 var upload = service.Edits.Bundles.Upload(packageName, activeEditSession.Id, fileStream, "application/octet-stream"); 没有公开 .Credential 对象,并且总是失败:

    The service androidpublisher has thrown an exception: Google.GoogleApiException: Google.Apis.Requests.RequestError
Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project. [401]
Errors [
        Message[Login Required.] Location[Authorization - header] Reason[required] Domain[global]
]

   at Google.Apis.Upload.ResumableUpload`1.InitiateSessionAsync(CancellationToken cancellationToken)
   at Google.Apis.Upload.ResumableUpload.UploadAsync(CancellationToken cancellationToken)

那么,我将如何在此处使用给定凭据提供实际的上传操作?

【问题讨论】:

    标签: c# .net google-play-services service-accounts


    【解决方案1】:

    白天设法解决了这个问题,我在创建 GoogleCredential 对象时错过了一次对 CreateScoped() 的调用,以及对上传对象的 InitiateSession() 的调用。

                var googleCredentials = GoogleCredential.FromStream(keyDataStream)
                    .CreateWithUser(serviceUsername)
                    .CreateScoped(AndroidPublisherService.Scope.Androidpublisher);
    
    

    完成后,我可以通过调用获得有效的 oauth 令牌

                var googleCredentials = GoogleCredential.FromStream(keyDataStream)
                    .CreateWithUser(serviceUsername)
                    .CreateScoped(AndroidPublisherService.Scope.Androidpublisher);
                
                var credentials = googleCredentials.UnderlyingCredential as ServiceAccountCredential;
                var oauthToken = credentials?.GetAccessTokenForRequestAsync(AndroidPublisherService.Scope.Androidpublisher).Result;
    

    我现在可以在上传请求中使用该 oauth 令牌:

                upload.OauthToken = oauthToken;
                _ = await upload.InitiateSessionAsync();
                
                var uploadProgress = await upload.UploadAsync();
                if (uploadProgress == null || uploadProgress.Exception != null)
                {
                    Console.WriteLine($"Failed to upload. Error: {uploadProgress?.Exception}");
                    return;
                }
    
    

    成功将新的 aab 文件上传到 google play store 内部测试轨道的完整代码示例如下所示:

            private async Task UploadGooglePlayRelease(string fileToUpload, string changeLogFile, string serviceUsername, string packageName)
            {
                var serviceAccountFile = ResolveServiceAccountCertificateInfoFile();
                if (!serviceAccountFile.Exists)
                    throw new ApplicationException($"Failed to find the service account certificate file. {serviceAccountFile.FullName}");
                
                var keyDataStream = File.OpenRead(serviceAccountFile.FullName);
                var googleCredentials = GoogleCredential.FromStream(keyDataStream)
                    .CreateWithUser(serviceUsername)
                    .CreateScoped(AndroidPublisherService.Scope.Androidpublisher);
                
                var credentials = googleCredentials.UnderlyingCredential as ServiceAccountCredential;
                var oauthToken = credentials?.GetAccessTokenForRequestAsync(AndroidPublisherService.Scope.Androidpublisher).Result;
                
                var service = new AndroidPublisherService();
                
                var edit = service.Edits.Insert(new AppEdit { ExpiryTimeSeconds = "3600" }, packageName);
                edit.Credential = credentials;
                var activeEditSession = await edit.ExecuteAsync();
                _logger.LogInformation($"Edits started with id {activeEditSession.Id}");
                
                var tracksList = service.Edits.Tracks.List(packageName, activeEditSession.Id);
                tracksList.Credential = credentials;
                var tracksResponse = await tracksList.ExecuteAsync();
                foreach (var track in tracksResponse.Tracks)
                {
                    _logger.LogInformation($"Track: {track.TrackValue}");
                    _logger.LogInformation("Releases: ");
                    foreach (var rel in track.Releases)
                        _logger.LogInformation($"{rel.Name} version: {rel.VersionCodes.FirstOrDefault()} - Status: {rel.Status}");
                }
    
                var fileStream = File.OpenRead(fileToUpload);
                var upload = service.Edits.Bundles.Upload(packageName, activeEditSession.Id, fileStream, "application/octet-stream");
                
                upload.OauthToken = oauthToken;
                _ = await upload.InitiateSessionAsync();
                
                var uploadProgress = await upload.UploadAsync();
                if (uploadProgress == null || uploadProgress.Exception != null)
                {
                    Console.WriteLine($"Failed to upload. Error: {uploadProgress?.Exception}");
                    return;
                }
                
                _logger.LogInformation($"Upload {uploadProgress.Status}");
    
                var releaseNotes = await File.ReadAllTextAsync(changeLogFile);
    
                var tracksUpdate = service.Edits.Tracks.Update(new Track
                {
                    Releases = new List<TrackRelease>(new[]
                    {
                        new TrackRelease
                        {
                            Name = $"{upload?.ResponseBody?.VersionCode}",
                            Status = "completed",
                            InAppUpdatePriority = 5,
                            CountryTargeting = new CountryTargeting { IncludeRestOfWorld = true },
                            ReleaseNotes = new List<LocalizedText>(new []{ new LocalizedText {  Language = "en-US", Text = releaseNotes } }),
                            VersionCodes = new List<long?>(new[] {(long?) upload?.ResponseBody?.VersionCode})
                        }
                    })
                }, packageName, activeEditSession.Id, "internal");
                
                tracksUpdate.Credential = credentials;
                var trackResult = await tracksUpdate.ExecuteAsync();
                _logger.LogInformation($"Track {trackResult?.TrackValue}");
    
                var commitResult = service.Edits.Commit(packageName, activeEditSession.Id);
                commitResult.Credential = credentials;
                await commitResult.ExecuteAsync();
                
                _logger.LogInformation($"{commitResult.EditId} has been committed");
            }
    
    

    【讨论】:

      猜你喜欢
      • 2022-06-25
      • 1970-01-01
      • 2020-01-03
      • 2014-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-22
      相关资源
      最近更新 更多