UP by Jawbone のライフログを Windows アプリで取得する(4)
UP by Jawbone のライフログを Windows アプリで取得する(3)の続きです
WebView に無理やり?リダイレクトを通して code が取得できたので、ここからアクセストークンを取得します
前回の JawboneService をカスタマイズ!
/// <summary> /// Jawbone アクセスサービス /// </summary> public class JawboneService { /// <summary> /// トークン要求 Uri /// </summary> private static readonly string RequestTokenBaseUri = @"https://jawbone.com/auth/oauth2/auth?response_type=code&client_id={0}&scope={1}&redirect_uri={2}"; /// <summary> /// Client ID /// </summary> private static readonly string ClientId = @"登録アプリの Client ID"; /// <summary> /// App Secret /// </summary> private static readonly string AppSecret = @"登録アプリの App Secret"; /// <summary> /// アクセス範囲 /// </summary> private static readonly string Scopes = @"extended_read sleep_read mood_read"; /// <summary> /// リダイレクト Uri(ダミー) /// </summary> private static readonly string RedirectUri = @"https://localhost:5555"; /// <summary> /// トークン問い合わせ Uri /// </summary> private static readonly string TokenBaseUri = @"https://jawbone.com/auth/oauth2/token?client_id={0}&client_secret={1}&grant_type={2}&code={3}"; /// <summary> /// API エンドポイント Uri /// </summary> private static readonly string ApiBaseUri = @"https://jawbone.com/nudge/api/v.1.1/{0}"; /// <summary> /// トークン要求用 Uri を構成する /// </summary> /// <returns>トークン要求用 Uri</returns> public string GetRequestTokenUri() { return string.Format(RequestTokenBaseUri, Uri.EscapeDataString(ClientId), Uri.EscapeDataString(Scopes), Uri.EscapeDataString(RedirectUri)); } /// <summary> /// アクセストークンを取得 /// </summary> /// <param name="redirectUri">リダイレクトされた Uri</param> /// <returns>Task</returns> public async Task GetToken(string redirectUri) { try { var decoder = new WwwFormUrlDecoder(new Uri(redirectUri).GetComponents(UriComponents.Query, UriFormat.Unescaped)); var request = WebRequest.CreateHttp(string.Format(TokenBaseUri, ClientId, AppSecret, @"authorization_code", decoder.GetFirstValueByName("code"))); var response = await request.GetResponseAsync() as HttpWebResponse; string content = string.Empty; if (response.StatusCode != HttpStatusCode.OK) { throw new InvalidOperationException(); } using (var stream = new StreamReader(response.GetResponseStream())) { content = await stream.ReadToEndAsync(); App.AppSettings.Settings.AccessToken = JsonConvert.DeserializeObject<JawboneAccessToken>(content, new JsonSerializerSettings() { Culture = new CultureInfo("ja-jp") }); await App.AppSettings.SaveAsync(); } } catch (Exception ex) { Debug.WriteLine(ex.ToString()); } } /// <summary> /// API でデータを取得する /// </summary> /// <param name="path">エンドポイントパス</param> /// <returns>取得データ</returns> public async Task<string> GetDataAsync(string path) { try { var request = WebRequest.CreateHttp(string.Format(ApiBaseUri, path.Trim('/'))); var accessToken = App.AppSettings.Settings.AccessToken; request.Headers["Authorization"] = string.Format("{0} {1}", accessToken.TokenType, accessToken.Token); var response = await request.GetResponseAsync() as HttpWebResponse; string content = string.Empty; if (response.StatusCode != HttpStatusCode.OK) { throw new InvalidOperationException(); } using (var stream = new StreamReader(response.GetResponseStream())) { content = await stream.ReadToEndAsync(); } return content; } catch (Exception ex) { Debug.WriteLine(ex.ToString()); } return string.Empty; } }
下記の GetToken メソッドでアクセストークンの情報が JSON で取得できます
/// <summary> /// アクセストークンを取得 /// </summary> /// <param name="redirectUri">リダイレクトされた Uri</param> /// <returns>Task</returns> public async Task GetToken(string redirectUri) { try { var decoder = new WwwFormUrlDecoder(new Uri(redirectUri).GetComponents(UriComponents.Query, UriFormat.Unescaped)); var request = WebRequest.CreateHttp(string.Format(TokenBaseUri, ClientId, AppSecret, @"authorization_code", decoder.GetFirstValueByName("code"))); var response = await request.GetResponseAsync() as HttpWebResponse; string content = string.Empty; if (response.StatusCode != HttpStatusCode.OK) { throw new InvalidOperationException(); } using (var stream = new StreamReader(response.GetResponseStream())) { content = await stream.ReadToEndAsync(); App.AppSettings.Settings.AccessToken = JsonConvert.DeserializeObject<JawboneAccessToken>(content, new JsonSerializerSettings() { Culture = new CultureInfo("ja-jp") }); await App.AppSettings.SaveAsync(); } } catch (Exception ex) { Debug.WriteLine(ex.ToString()); } }
JSON は access_token、token_type、expires_in、refresh_token のプロパティが含まれるので、このプロパティに合わせた JsonProperty 属を付与した Model クラスに JSON.NET でデシリアライズしています
/// <summary> /// API でデータを取得する /// </summary> /// <param name="path">エンドポイントパス</param> /// <returns>取得データ</returns> public async Task<string> GetDataAsync(string path) { try { var request = WebRequest.CreateHttp(string.Format(ApiBaseUri, path.Trim('/'))); var accessToken = App.AppSettings.Settings.AccessToken; request.Headers["Authorization"] = string.Format("{0} {1}", accessToken.TokenType, accessToken.Token); var response = await request.GetResponseAsync() as HttpWebResponse; string content = string.Empty; if (response.StatusCode != HttpStatusCode.OK) { throw new InvalidOperationException(); } using (var stream = new StreamReader(response.GetResponseStream())) { content = await stream.ReadToEndAsync(); } return content; } catch (Exception ex) { Debug.WriteLine(ex.ToString()); } return string.Empty; }
あとはこんな感じで各 API のエンドポイントに向けて、「Authorization」HTTP ヘッダを付与したリクエストを送るだけ!
試しに https://jawbone.com/nudge/api/v.1.1/users/settings にアクセスしてみるとこんな JSON が返ってきました
{ "meta": { "user_xid": "zXsLRB653S6dHUwObgQ9QA", "message": "OK", "code": 200, "time": 1402576212}, "data": { "metric": 1, "xid": "zXsLRB653S6dHUwObgQ9QA", "share_sleep": true, "share_mood": true } }
リダイレクトさえ解決すればライフログ取得も簡単ですね!