2012-10-19 20 views
15

Mi sono reso conto che questa domanda è stata posta in precedenza ma con un po 'di codice di esempio, quindi mi sto chiedendo di nuovo ma con almeno un po' di direzione.Come utilizzare un account di servizio per accedere all'API di Google Analytics V3 con .NET C#?

Dopo ore di ricerca, ho realizzato la seguente implementazione parziale.

namespace GoogleAnalyticsAPITest.Console 
{ 
    using System.Security.Cryptography.X509Certificates; 
    using DotNetOpenAuth.OAuth2; 
    using Google.Apis.Analytics.v3; 
    using Google.Apis.Analytics.v3.Data; 
    using Google.Apis.Authentication.OAuth2; 
    using Google.Apis.Authentication.OAuth2.DotNetOpenAuth; 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      log4net.Config.XmlConfigurator.Configure(); 
      string Scope = Google.Apis.Analytics.v3.AnalyticsService.Scopes.Analytics.ToString().ToLower(); 
      string scopeUrl = "https://www.googleapis.com/auth/" + Scope; 
      const string ServiceAccountId = "nnnnnnnnnnn.apps.googleusercontent.com"; 
      const string ServiceAccountUser = "[email protected]"; 
      AssertionFlowClient client = new AssertionFlowClient(
       GoogleAuthenticationServer.Description, new X509Certificate2(@"7039572692013fc5deada350904f55bad2588a2a-privatekey.p12", "notasecret", X509KeyStorageFlags.Exportable)) 
      { 
       Scope = scopeUrl, 
       ServiceAccountId = ServiceAccountId//,ServiceAccountUser = ServiceAccountUser 
      }; 
      IAuthorizationState state = AssertionFlowClient.GetState(client); 
      AnalyticsService service = new AnalyticsService(authenticator); 
      string profileId = "ga:xxxxxxxx"; 
      string startDate = "2010-10-01"; 
      string endDate = "2010-10-18"; 
      string metrics = "ga:visits"; 
      DataResource.GaResource.GetRequest request = service.Data.Ga.Get(profileId, startDate, endDate, metrics); 
      request.Dimensions = "ga:date"; 
      GaData data = request.Fetch(); 
     } 
    } 
} 

Ho un paio di problemi. La chiamata a AssertionFlowClient.GetState(client) risultati in una risposta "invalid_scope" come si è visto nel registro DotNetOpenAuth di

2012-10-19 13: 27: 36.272 (GMT-4) [8] INFO DotNetOpenAuth - DotNetOpenAuth, Version = 4.0 .0.11165, Culture = neutro, PublicKeyToken = 2780ccd10d57b246 (ufficiale) 2012-10-19 13: 27: 36,284 (GMT-4) [8] DEBUG DotNetOpenAuth.Messaging.Channel - Preparazione per l'invio del messaggio AssertionFlowMessage (2.0). 2012/10/19 13: 27: 36.294 (GMT-4) [8] INFO DotNetOpenAuth.Messaging.Channel - Preparato AssertionFlowMessage in uscita (2.0) Messaggio per https://accounts.google.com/o/oauth2/token: grant_type: asserzione assertion_type: http://oauth.net/grant_type/jwt/1.0/bearer asserzione: (un mazzo di caratteri codificati andare qui)

2012-10-19 13: 27: 36,296 (GMT-4) [8] DEBUG DotNetOpenAuth.Messaging.Channel - Invio di AssertionFlowMessage request. 2012-10-19 13: 27: 36,830 (GMT-4) [8] DEBUG DotNetOpenAuth.Http - HTTP POST https://accounts.google.com/o/oauth2/token 2012-10-19 13: 27: 36,954 (GMT-4) [8] ERRORE DotNetOpenAuth.Http - WebException da https://accounts.google.com/o/oauth2/token: { "errore": "invalid_scope" }

ho provato a specificare uno o entrambi ServiceAccountId e ServiceAccountUser senza fortuna.

In secondo luogo, anche se ottengo uno IAuthorizationState, non sono sicuro di come ottengo un IAuthenticator che può essere passato al costruttore di AnalyticsService.

Quello che segue è il web.config che uso per abilitare la registrazione DotNetOpenAuth.

<?xml version="1.0"?> 
<configuration> 
    <configSections> 
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net, Version=1.2.10.0, Culture=neutral, publicKeyToken=1b44e1d426115821" /> 
    <!--<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler" requirePermission="false"/>--> 
    <sectionGroup name="dotNetOpenAuth" type="DotNetOpenAuth.Configuration.DotNetOpenAuthSection, DotNetOpenAuth"> 
     <section name="openid" type="DotNetOpenAuth.Configuration.OpenIdElement, DotNetOpenAuth" requirePermission="false" allowLocation="true"/> 
     <section name="oauth" type="DotNetOpenAuth.Configuration.OAuthElement, DotNetOpenAuth" requirePermission="false" allowLocation="true"/> 
     <section name="messaging" type="DotNetOpenAuth.Configuration.MessagingElement, DotNetOpenAuth" requirePermission="false" allowLocation="true"/> 
     <section name="reporting" type="DotNetOpenAuth.Configuration.ReportingElement, DotNetOpenAuth" requirePermission="false" allowLocation="true"/> 
    </sectionGroup> 
    </configSections> 
    <log4net> 
    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender"> 
     <file value="DotNetOpenAuth.log"/> 
     <appendToFile value="true"/> 
     <rollingStyle value="Size"/> 
     <maxSizeRollBackups value="10"/> 
     <maximumFileSize value="100KB"/> 
     <staticLogFileName value="true"/> 
     <layout type="log4net.Layout.PatternLayout"> 
     <conversionPattern value="%date (GMT%date{%z}) [%thread] %-5level %logger - %message%newline"/> 
     </layout> 
    </appender> 
    <appender name="TracePageAppender" type="OpenIdProviderWebForms.Code.TracePageAppender, OpenIdProviderWebForms"> 
     <layout type="log4net.Layout.PatternLayout"> 
     <conversionPattern value="%date (GMT%date{%z}) [%thread] %-5level %logger - %message%newline"/> 
     </layout> 
    </appender> 
    <!-- Setup the root category, add the appenders and set the default level --> 
    <root> 
     <level value="ALL"/> 
     <appender-ref ref="RollingFileAppender"/> 
     <appender-ref ref="TracePageAppender"/> 
    </root> 
    <!-- Specify the level for some specific categories --> 
    <logger name="DotNetOpenAuth"> 
     <level value="ALL"/> 
    </logger> 
    </log4net> 
    <dotNetOpenAuth> 
    <!-- This is an optional configuration section where aspects of dotnetopenauth can be customized. --> 
    <!-- For a complete set of configuration options see http://www.dotnetopenauth.net/developers/code-snippets/configuration-options/ --> 
    <!--<messaging clockSkew="00:10:00" lifetime="00:03:00" strict="true">--> 
    <!--<messaging> 
     <untrustedWebRequest timeout="00:00:30" readWriteTimeout="00:00:01.500" maximumBytesToRead="1048576" maximumRedirections="10"> 
     <whitelistHosts> 
      --> 
    <!-- Uncomment to enable communication with localhost (should generally not activate in production!) --> 
    <!-- 
      <add name="localhost"/>    
     </whitelistHosts> 
     </untrustedWebRequest> 
    </messaging>--> 
    <!-- Allow DotNetOpenAuth to publish usage statistics to library authors to improve the library. --> 
    <reporting enabled="false"/> 
    </dotNetOpenAuth> 
    <appSettings> 
    <!--<add key="log4net.Internal.Debug" value="true" />--> 
    </appSettings> 
    <runtime> 
    </runtime> 
    <startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> 
    </startup> 
</configuration> 

risposta

11

Il codice seguente, corretto dalla mia domanda iniziale, si basa sull'esempio fornito da Ian Fraser a:

https://groups.google.com/forum/#!msg/google-search-api-for-shopping/4uUGirzH4Rw/__c0e4hj0ekJ

suo codice affrontato tre questioni:

  1. sembra come se AnalyticsService.Scopes.AnalyticsReadonly non funziona, almeno non per me o il modo in cui lo sto facendo.
  2. Per qualche motivo, ServiceAccountUser deve essere assegnato alla proprietà ServiceAccountId dell'istanza AssertionFlowClient.
  3. OAuth2Authenticator fornisce l'IAuthenticator che stavo cercando.

Nel progetto, comprendono i riferimenti a:

  • Lib \ DotNetOpenAuth.dll
  • Lib \ Google.Apis.dll
  • Lib \ Google.Apis.Authentication.OAuth2.dll
  • Services \ AnalyticsService \ Google.Apis.Analytics.v3.dll

-

namespace GoogleAnalyticsAPITest.Console 
{ 
    using System.Security.Cryptography.X509Certificates; 
    using Google.Apis.Analytics.v3; 
    using Google.Apis.Analytics.v3.Data; 
    using Google.Apis.Authentication.OAuth2; 
    using Google.Apis.Authentication.OAuth2.DotNetOpenAuth; 
    using Google.Apis.Util; 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      log4net.Config.XmlConfigurator.Configure();    
      const string ServiceAccountId = "nnnnnnnnnnn.apps.googleusercontent.com"; 
      const string ServiceAccountUser = "[email protected]"; 
      AssertionFlowClient client = new AssertionFlowClient(
       GoogleAuthenticationServer.Description, new X509Certificate2(@"value-privatekey.p12", "notasecret", X509KeyStorageFlags.Exportable)) 
      { 
       Scope = AnalyticsService.Scopes.AnalyticsReadonly.GetStringValue(), 
       ServiceAccountId = ServiceAccountUser //Bug, why does ServiceAccountUser have to be assigned to ServiceAccountId 
       //,ServiceAccountUser = ServiceAccountUser 
      }; 
      OAuth2Authenticator<AssertionFlowClient> authenticator = new OAuth2Authenticator<AssertionFlowClient>(client, AssertionFlowClient.GetState);    
      AnalyticsService service = new AnalyticsService(authenticator);    
      string profileId = "ga:64968920"; 
      string startDate = "2010-10-01"; 
      string endDate = "2010-10-31"; 
      string metrics = "ga:visits"; 
      DataResource.GaResource.GetRequest request = service.Data.Ga.Get(profileId, startDate, endDate, metrics); 
      request.Dimensions = "ga:date"; 
      GaData data = request.Fetch();    
     } 

    } 
} 
+0

Sembra che l'ambito di sola lettura corretto sia https://www.googleapis.com/auth/analytics.readonly. È diverso per convertire il valore di enumerazione in una stringa. Inoltre, non ho dovuto impostare ServiceAccountUser. –

+0

@BenMills puoi chiarire come sei autenticato? Suppongo che tu stia dicendo che hai impostato ServiceAccountId su un valore nnnnnnnnnnnn.apps.googleusercontent.com ma non sono sicuro che sia ciò che intendi. Ho modificato il codice per impostare l'ambito su "analytics.readonly" poiché questo è probabilmente il modo principale in cui le persone lo utilizzeranno. –

+0

Mi dispiace, avevi ragione. Ho impostato il ServiceAccountId su [email protected] Non avevo bisogno di prendere in considerazione nnnnnnnnnnnn.apps.googleusercontent.com in alcun modo. –

2

Ecco il mio esempio di lavoro postato qui [1]: Automated use of google-api-dotnet-client with OAuth 2.0 ho messo un sacco la ricerca per trovare e mettendo il codice insieme spero che questo ti consente di risparmiare un po 'di tempo.

+0

sono sicuro di aver messo un sacco di tempo in questa soluzione. Sembra che tu abbia dovuto andare a un livello inferiore rispetto all'API che sto usando. Tuttavia, l'esempio utilizza NativeApplicationClient anziché AssertionFlowClient. Apprezzo il feedback. –

1

Per quanto riguarda Richard Collette risposta, fare attenzione che usando il suo metodo se si desidera utilizzare Analytics API in sola lettura, il modo corretto di usarlo è:

string Scope = "analytics.readonly" 

e non

string Scope = AnalyticsService.Scopes.AnalyticsReadOnly.ToString().ToLower() 

come sembra dire che c'è un bug. In effetti, il bug è che il metodo .toString() restituisce analyticsreadonly e NON analytics.readonly che è il modo che piace a Google. Questo è tutto.

+1

Ottime informazioni. Direi che è un bug nell'enum allora. Qual è il punto di queste enumerazioni se non puoi usarle? –

+1

@RichardCollette Nel namespace Google.Apis.Util esiste un metodo di estensione per recuperare il valore di stringa dall'enum AnalyticsService.Scopes, AnalyticsService.Scopes.AnalyticsReadonly.GetStringValue(). –

3
string scope = Google.Apis.Util.Utilities.GetStringValue(AnalyticsService.Scopes.AnalyticsReadonly); 
+0

Questo è un metodo di estensione. Non è necessario chiamarlo in questo modo. Vedi la soluzione sopra. –

4

stavo controllando l'API di analisi di ieri e ho notato come non documentata è e non campioni, ecc

qualsiasi modo, ho creato una libreria che si potrebbe usare per analisi di accesso facilmente con paio di righe e rendere l'associazione dati diretto al DataTable per i dati restituiti è open source sul github quindi sentitevi liberi di contribuire :)

https://github.com/rmostafa/DotNetAnalyticsAPI

Uso

Esiste una mappatura diretta del codice per tutti i comandi di segnalazione dell'API di Google suddivisi in categorie allo stesso modo dell'API, quindi è possibile farlo anche senza leggere la documentazione dell'API poiché tutte le funzionalità sono documentate negli attributi, ho scritto codice che analizzato la documentazione completa api e di risorse della metriche, dimensioni, caratteristiche calcolato in un XML che ho generato dalle classi fisiche che si potrebbe usare direttamente come l'esempio di cui sopra è divertente giocare con :) godono

https://github.com/rmostafa/DotNetAnalyticsAPI

Problemi correlati