Google APIには各種言語用クライアントライブラリが用意されていて、もちろんC#用のクライアントライブラリも存在します。ただ、情報が少なく、詰まるところもあったので、使い方をまとめておきます。環境は.NET Core 2.1およびVisual Studio Codeです。作成するアプリの形式は、コンソールアプリです。
リンク
- C#クライアントライブラリのサイト
- C#クライアントライブラリのリポジトリ
- サンプル集
- APIリファレンス ※バージョンが古いので注意
リポジトリを見ると、メンテンナンスモードと書かれているので不安になってしまいますが、FAQのページを見ると、「メンテナンスモード=成熟し、完成しているので機能追加はしない」とのことです。バグは修正されますし、新しいAPIが追加されれば対応すると明言されているので大丈夫そうです。
事前準備
- Google Cloud Consoleにアクセスして、プロジェクトを作成します。
- サイドバーから「APIとサービス」を選択し、利用したいAPIを有効化します。
- 同じく「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.");
}
}
}
}