.NET 6 - Build Line Notify Web API
文章目錄
此篇文章將會透過 .NET 6 來實作Line Notify,傳送文字、貼圖與相片至Line。
詳細的Line API規格請至Line官方文件查詢。
Implementation
1. Line Notify服務申請
自Line Notify申請服務以取得Client ID、Client Secret,並設定Callback URL。

2. 基本設定
- 在appsettings.json中,設定
client_id
、client_secret
、redirect_uri
。
"LineNotifySetting": {
"client_id": "...", // Client ID
"client_secret": "...", // Client Secret
"redirect_uri": "http://localhost:4200" // Callback URL
},
- 建立資料模型(data model)。
public class LineNotifySetting
{
public string Client_ID { get; set; } = null!;
public string Client_Secret { get; set; } = null!;
public string Redirect_URI { get; set; } = null!;
}
- 建立服務(service)。
- 宣告欲使用的LINE Notify API。
- 注入IConfiguration,以取得appsettings.json中的
LineNotifySetting
。 - 注入IHttpClientFactory,並在program.cs中呼叫AddHttpClient方法進行註冊,以建立HttpClient執行個體來發送Http請求。
// Add HttpClient service builder.Services.AddHttpClient();
public class LineNotifyService
{
private const string LineAuthorizeAPI = "https://notify-bot.line.me/oauth/authorize";
private const string LineTokenAPI = "https://notify-bot.line.me/oauth/token";
private const string LineNotifyAPI = "https://notify-api.line.me/api/notify";
private const string LineRevokeAPI = "https://notify-api.line.me/api/revoke";
private readonly IConfiguration _configuration;
private readonly LineNotifySetting _lineNotifySetting = new LineNotifySetting();
private readonly IHttpClientFactory _httpClientFactory;
public LineNotifyService(IConfiguration configuration, IHttpClientFactory httpClientFactory)
{
_configuration = configuration;
_lineNotifySetting.Client_ID = _configuration["LineNotifySetting:client_id"];
_lineNotifySetting.Client_Secret = _configuration["LineNotifySetting:client_secret"];
_lineNotifySetting.Redirect_URI = _configuration["LineNotifySetting:redirect_uri"];
_httpClientFactory = httpClientFactory;
}
}
2. 導向Line Notify授權網頁
將使用者導向Line Notify服務授權之頁面。
![]() | ![]() |
LineNotifyService.cs
public string GetAuthorizationUrl(string name) { var URL = LineAuthorizeAPI; URL += "?response_type=code"; URL += $"&client_id={_lineNotifySetting.Client_ID}"; URL += $"&redirect_uri={_lineNotifySetting.Redirect_URI}"; URL += "&scope=notify"; URL += $"&state={name}"; URL += "&response_mode=form_post"; return URL; }
LineNotifyController.cs
[HttpGet("{name}")] public IActionResult GetAuthorizationUrl(string name) { var URL = _lineNotifyService.GetAuthorizationUrl(name); return Ok(Content(URL)); }
3. 取得AccessToken
授權成功後,將自動導向至服務路徑(redirect_uri),並帶有兩參數code
與state
。該服務路徑應自動發送Post請求,透過code來取得AccessToken。此範例將取得的AccessToken傳回前台,實務上應將取得的AccessToken存入資料庫。
LineNotifyService.cs
public async Task<HttpResponseMessage> PostTokenAsync(string code) { HttpClient client = _httpClientFactory.CreateClient(); client.Timeout = new TimeSpan(0, 0, 60); var content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("grant_type", "authorization_code"), new KeyValuePair<string, string>("code", code), new KeyValuePair<string, string>("redirect_uri", _lineNotifySetting.Redirect_URI), new KeyValuePair<string, string>("client_id", _lineNotifySetting.Client_ID), new KeyValuePair<string, string>("client_secret", _lineNotifySetting.Client_Secret) }); return await client.PostAsync(LineTokenAPI, content); }
LineNotifyController.cs
[HttpPost] public async Task<IActionResult> PostTokenAsync([FromBody] LineAuthRes authRes) { try { var res = await _lineNotifyService.PostTokenAsync(authRes.Code); var msg = await res.Content.ReadAsStringAsync(); return StatusCode((int)res.StatusCode, msg); } catch (Exception ex) { return StatusCode((int)HttpStatusCode.InternalServerError, ex.Message); } }
LineAuthRes.cs
public class LineAuthRes { public string Code { get; set; } = null!; public string State { get; set; } = null!; }
4. 發送訊息
在Header加上Authorization Bearer <access_token>
,以發送Line訊息;認證方式為Bearer,憑證則為使用者的Access Token。
訊息可為一般文字、貼圖或相片,但須注意message
參數不可為空。
LineNotifyService.cs
public async Task<HttpResponseMessage> SendAsync(string token, LineSendInfo info) { HttpClient client = _httpClientFactory.CreateClient(); client.Timeout = new TimeSpan(0, 0, 60); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); var uri = $"{LineNotifyAPI}?message={info.Message}"; if (info.StickerPackageId != null) uri = $"{uri}&stickerPackageId={info.StickerPackageId}"; if (info.StickerId != null) uri = $"{uri}&stickerId={info.StickerId}"; var content = new MultipartFormDataContent(); if (info.ImageFile != null) { if(info.ImageFile.Length > 0) { using (var ms = new MemoryStream()) { await info.ImageFile.CopyToAsync(ms); var baContent = new ByteArrayContent(ms.ToArray()); content.Add(baContent, "imageFile", info.ImageFile.FileName); } } } else { content = null; } return await client.PostAsync(uri, content); }
LineNotifyController.cs
[HttpPost("Notify")] public async Task<IActionResult> PostMessageAsync(string token, [FromForm] LineSendInfo info) { try { var res = await _lineNotifyService.SendAsync(token, info); var msg = await res.Content.ReadAsStringAsync(); return StatusCode((int)res.StatusCode, msg); } catch (Exception ex) { return StatusCode((int)HttpStatusCode.InternalServerError, ex.Message); } }
LineSendInfo.cs
public class LineSendInfo { public string Message { get; set; } = null!; public IFormFile? ImageFile { get; set; } public string? StickerPackageId { get; set; } public string? StickerId { get; set; } }
5. 撤消AccessToken
LineNotifyService.cs
public async Task<HttpResponseMessage> RevokeToken(string token) { HttpClient client = _httpClientFactory.CreateClient(); client.Timeout = new TimeSpan(0, 0, 60); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); return await client.PostAsync(LineRevokeAPI, null); }
LineNotifyController.cs
[HttpPost("Revoke")] public async Task<IActionResult> RevokeAsync(string token) { try { var res = await _lineNotifyService.RevokeToken(token); var msg = await res.Content.ReadAsStringAsync(); return StatusCode((int)res.StatusCode, msg); } catch (Exception ex) { return StatusCode((int)HttpStatusCode.InternalServerError, ex.Message); } }