Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
26
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

Organization

C#を使ってGoogle APIにアクセスする

Google APIには各種言語用クライアントライブラリが用意されていて、もちろんC#用のクライアントライブラリも存在します。ただ、情報が少なく、詰まるところもあったので、使い方をまとめておきます。環境は.NET Core 2.1およびVisual Studio Codeです。作成するアプリの形式は、コンソールアプリです。

リンク

リポジトリを見ると、メンテンナンスモードと書かれているので不安になってしまいますが、FAQのページを見ると、「メンテナンスモード=成熟し、完成しているので機能追加はしない」とのことです。バグは修正されますし、新しいAPIが追加されれば対応すると明言されているので大丈夫そうです。

事前準備

  1. Google Cloud Consoleにアクセスして、プロジェクトを作成します。
  2. サイドバーから「APIとサービス」を選択し、利用したいAPIを有効化します。
  3. 同じく「APIとサービス」から、認証情報を作成します。認証情報の種類については、記事(Google APIの認証の種類)を書きましたので、参考にしてください。作成したら、鍵ファイルをダウンロードしましょう。

セットアップ

まずはプロジェクトを作成し、依存関係を追加します。ここでは例として、Calendar APIのクライアントライブラリを追加します。

dotnet new console
dotnet add package Google.Apis.Calendar.v3

以下のページで、サポートされているAPI一覧があります。バージョンナンバーをクリックすると、詳細が見られます。

なお、クライアントライブラリ共通のAPIはGoogle.Apisパッケージ、認証のAPIはGoogle.Apis.Authパッケージに独立しており、依存関係としてインストールされます。複数APIのクライアントライブラリを追加する場合は、これらを明示的に追加しておいたほうが、バージョン管理が楽かもしれません。

鍵ファイルの追加

ダウンロードした鍵ファイルを、プロジェクトのルートに置きます。間違って公開しないよう、注意しましょう。本番では、環境変数で渡すなど、セキュアな方法を使ってください。

認可の取得

C#のクライアントライブラリでは、ICredentialを実装したクラスが、取得した認可情報を保持することになっています。このICredentialのインスタンスを使って各APIにアクセスすることになります。

サービスアカウントの場合

using (var stream = new FileStream("service_account_key.json", FileMode.Open, FileAccess.Read))
{
    ICredential credential = GoogleCredential.FromStream(stream)
         .CreateScoped(new[] { CalendarService.Scope.CalendarReadonly }).UnderlyingCredential;
}

service_account_key.jsonが、サービスアカウントの鍵ファイルです。

scopeは、認可を得たい権限です。APIごとに設定されています。Calendar APIの場合は、calendar、calendar.readonlyの二つのscopeがあります。C#のクライアントライブラリでは、各API用クライアントライブラリに定数として登録されています。

OAuth2認証の場合

using (var stream = new FileStream("client_secret.json", FileMode.Open, FileAccess.Read))
{
    string credPath = "token"; // tokenを保存するディレクトリ
    Task<UserCredential> credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
        GoogleClientSecrets.Load(stream).Secrets,
        new[] { CalendarService.Scope.CalendarReadonly },
        "user", CancellationToken.None, new FileDataStore(credPath, true));  // 第二引数をtrueにすると、カレントディレクトリからの相対パスに保存される
}

client_secret.jsonが、OAuth2認証の鍵ファイルです。

実行すると、おなじみのGoogleのOAuth認可ページがブラウザで開きます。ユーザーアクションを待つ必要があるので、Taskが返ります。UserCredentialは、もちろんICredentialを実装したクラスです。

サンプル

あとは、取得したICredentialのインスタンスを使って、各APIにアクセスするだけです。
以下は、Calendar APIにアクセスするサンプルです。リポジトリはこちらです。

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Calendar.v3;
using Google.Apis.Calendar.v3.Data;
using Google.Apis.Services;
using Google.Apis.Util.Store;

namespace csharp_googleapi
{
    class Program
    {
        static void Main(string[] args)
        {
            new Program().Run().Wait();
        }

        private ICredential GetServiceAccountCredential(string[] scopes)
        {
            using (var stream = new FileStream("service_account_key.json", FileMode.Open, FileAccess.Read))
            {
                return GoogleCredential.FromStream(stream)
                     .CreateScoped(scopes).UnderlyingCredential;
            }
        }

        private Task<UserCredential> GetUserCredential(string[] scopes)
        {
            using (var stream = new FileStream("client_secret.json", FileMode.Open, FileAccess.Read))
            {
                string credPath = "token.json";
                return GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GoogleClientSecrets.Load(stream).Secrets,
                    scopes,
                    "user", CancellationToken.None, new FileDataStore(credPath, true));
            }
        }

        private async Task Run()
        {
            var scopes = new[] { CalendarService.Scope.CalendarReadonly };
            // ICredential credential = GetServiceAccountCredential(scopes);
            ICredential credential = await GetUserCredential(scopes);
            GetCalendar(credential, "(カレンダーID)"); // アクセスしたいカレンダーのID
        }

        private void GetCalendar(ICredential credential, string calendarId)
        {
            var service = new CalendarService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = "Get Calendar Sample",
            });

            EventsResource.ListRequest request = service.Events.List(calendarId);
            request.TimeMin = DateTime.Now;
            request.ShowDeleted = false;
            request.SingleEvents = true;
            request.MaxResults = 10;
            request.OrderBy = EventsResource.ListRequest.OrderByEnum.StartTime;

            // List events.
            Events events = request.Execute();
            Console.WriteLine("Upcoming events:");
            if (events.Items != null && events.Items.Count > 0)
            {
                foreach (var eventItem in events.Items)
                {
                    string when = eventItem.Start.DateTime.ToString();
                    if (String.IsNullOrEmpty(when))
                    {
                        when = eventItem.Start.Date;
                    }
                    Console.WriteLine("{0} ({1})", eventItem.Summary, when);
                }
            }
            else
            {
                Console.WriteLine("No upcoming events found.");
            }
        }
    }
}
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
26
Help us understand the problem. What are the problem?