在 < UWP - 整合 Google Sign-In 與 Twitter Sign-In API> 介紹整合 Google 與 Twitter,這篇補充把 LINE login 整合進來。
整合 LINE Login 前需要先申請 LINE developer 帳號,并且建立 Channel 來取得需要的 client_id 與 client_secret。 詳細的申請可以參考 https://business.line.me/zh-hant/ 的説明,主要步驟:
- 用原本綁定在 LINE 裏面的 email 登入,它會要用戶建立一個開發者帳號
- 建立一個公司名稱,填寫必要資訊 (公司名稱可以自定義)
- 建立一個 Channel,填寫必要資訊跟圖像,要記得選擇 WEB 類型的應用,因爲 LINE App 在 Windows 上還沒有支援互相認證的功能
這樣就可以得到 client_id 與 client_secret,接下來透過下面的程式範例就可以簡單拿到 access token 做事情了。 [範例説明] 1. 沿用之前的專案 13-AppWithOAuth 加入 LINE Login。 2. 建立一個 class 來轉換 json 結果與存放 LINE access token:
public class LINEAccessToken
{
public string mid { get; set; }
public string access_token { get; set; }
public string token_type { get; set; }
public int expires_in { get; set; }
public string refresh_token { get; set; }
public object scope { get; set; }
}
3. 建立一個搭配 WebAuthenticationBroker 向 LINE 做 OAuth 的類別:
public class LINELoginAPI
{
// 先向 LINE Developer 申請帳號並建立 Channel 就可以拿到 client_id 與 client_secret
private const string ClientId = "";
private const string ClientSecret = "";
// callback 可以設定自己需要的内容,預設可以使用下列的值
private const string CallbackUri = "https://localhost";
public static async Task RequestLoginAsync()
{
// state 可以自定義,用於識別是來自該 app 所請求
string state = "Windows_LINELoginAPI";
string encodingCallback = Uri.EscapeDataString(CallbackUri);
string oauthUrl = $"https://access.line.me/dialog/oauth/weblogin?response_type=code&client_id={ClientId}&redirect_uri={encodingCallback}&state={state}";
string result = string.Empty;
try
{
WebAuthenticationResult WebAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None, new Uri(oauthUrl), new Uri(CallbackUri));
if (WebAuthenticationResult.ResponseStatus == WebAuthenticationStatus.Success)
{
var response = WebAuthenticationResult.ResponseData.ToString();
// if your callback value is not URL, don't use it. please use split string methods.
Uri redirectUri = new Uri(response);
string query = redirectUri.Query.Substring(1);
Dictionary keyValuePair = Utility.StringToDictionary(query);
// 根據結果拆解需要的内容
if (keyValuePair.ContainsKey("error"))
{
// fail: http://sample.com/{Callback URL}?error=access_denied&state=[state]&errorCode=417&errorMessage=DISALLOWED
result = keyValuePair["errorMessage"];
}
else
{
// success: http://sample.com/callback?code=b5fd32eacc791df&state=123abc
string code = keyValuePair["code"];
// 請求取得 access token
string accessToken = await RedirectGetAccessTokenAsync(code);
result = accessToken;
}
return result;
}
else if (WebAuthenticationResult.ResponseStatus == WebAuthenticationStatus.ErrorHttp)
{
return "HTTP Error returned by AuthenticateAsync() : " + WebAuthenticationResult.ResponseErrorDetail.ToString();
}
else
{
return "Error returned by AuthenticateAsync() : " + WebAuthenticationResult.ResponseStatus.ToString();
}
}
catch (Exception)
{
throw;
}
}
private static async Task RedirectGetAccessTokenAsync(string code)
{
string encodingCallback = Uri.EscapeDataString(CallbackUri);
string url = "https://api.line.me/v1/oauth/accessToken";
string postParameter = $"grant_type=authorization_code&client_id={ClientId}&client_secret={ClientSecret}&code={code}&redirect_uri={encodingCallback}";
HttpStringContent httpContent = new HttpStringContent(postParameter, Windows.Storage.Streams.UnicodeEncoding.Utf8);
httpContent.Headers.ContentType = HttpMediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");
using (HttpClient httpClient = new HttpClient())
{
var httpResponseMessage = await httpClient.PostAsync(new Uri(url), httpContent);
return await httpResponseMessage.Content.ReadAsStringAsync();
}
}
}
上面有定義 callback 是 http://localhost 這要 Channel 裏面設定 (詳細説明),參考下圖:
上面的步驟就可以讓 UWP app 與 LINE Login 的整合了。 4. 取得用戶的個人資訊:
public static async Task GetProfile(string accessToken)
{
using (HttpClient client = new HttpClient())
{
// https://api.line.me/v2/profile 設定 Authentication header
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
string jsonResult = await client.GetStringAsync(new Uri("https://api.line.me/v2/profile"));
DataContractJsonSerializer tJsonSerial = new DataContractJsonSerializer(typeof(ProfileData));
MemoryStream tMS = new MemoryStream(Encoding.UTF8.GetBytes(jsonResult));
ProfileData data = tJsonSerial.ReadObject(tMS) as ProfileData;
return data;
}
}
public class ProfileData
{
public string userId { get; set; }
public string displayName { get; set; }
public string pictureUrl { get; set; }
}
======
簡單分享了整合 LINE login 到自己的 App 或是網站裏。 希望有幫助。
References:
- WebAuthenticationBroker
- LINE Login
- Messaging API
- Social REST API
- LINE Login button
- LINE API Reference