做過上一篇實作 Line Notify 通知服務 (1)後,雖然作法有些複雜,但對 Line Notify 的連動的操作以及發訊息的方法有了認識,這篇打算將複雜封裝,做成一隻隻的 API 服務,讓使用上變得簡單。

我使用的開發工具是 Visual Studio 2017,使用 ASP.NET Core 專案範本。

首先在 Visual Studio 新增專案,選擇 ASP.NET Core Web 應用程式(.NET Core)

選擇 Web API 範本。

連動 Line Notify

參考 Commit:加入設定與 Line Notify 連動的控制器

第一步就是要進行 Line Notify 的帳號連動,建立一個 AuthorizeController 控制器,來處理和連動授權相關的方法。

這裡主要是轉址到特定 Line Notify 的連動頁面,並將我們建立的服務識別碼(Client ID)及相關設定送過去,這樣使用者就可以連動到我們指定的服務。

這段有兩個地方須修改成對應服務的設定值:

  • _clientId = "[YOUR_CLIENT_ID]";
  • _redirectUri = "[YOUR_CALLBACK_URL]";

設定 Callback 並取得發送訊息的 Token

參考 Commit:新增對應的 Callback 和取得使用者 Access Token 的功能

使用者設定玩連動後,會產生一組 Authorize Code 並回傳給指定的 Callback 位置,這裡就是建立 Callback 的位置,並透過 FetchToken 這個方法,來取得發送訊息的 Token。

/// <summary>取得使用者 Token</summary>
/// <param name="code">用來取得 Access Tokens 的 Authorize Code</param>
/// <returns></returns>
private async Task<string> FetchToken(string code)
{
    using (var client = new HttpClient())
    {
        client.Timeout = new TimeSpan(0, 0, 60);
        client.BaseAddress = new Uri(_tokenUrl);

        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", _redirectUri),
            new KeyValuePair<string, string>("client_id", _clientId),
            new KeyValuePair<string, string>("client_secret", _clientSecret)
        });
        var response = await client.PostAsync("", content);
        var data = await response.Content.ReadAsStringAsync();

        return JsonConvert.DeserializeObject<JObject>(data)["access_token"].ToString();
    }
}

在取到 Token 後,隨即透過 URL 參數的方式,傳回指定的前端頁面 _successUri(這個位置會是下一篇的前端網頁)。

這段有兩個地方須修改成對應服務的設定值:

  • _clientSecret = "[YOUR_CLIENT_SECERT]";
  • _successUri = "[http://XXX.XXX.XXX/LineNotifyPage]";

發送文字訊息

參考 Commit:加入傳訊訊息的控制器,增加傳送文字訊息的方法

取到 Token 後,我們就可以借此來發送訊息,這裡在建立一支 LineNotifyController 控制器來處理發送訊息的大小事了。

發送文字訊息有兩個主要參數:

  1. token 令牌
  2. message 文字訊息

接到這兩個參數後,我們就可以透過 https://notify-api.line.me/api/notify Line Notify 的 API 服務來發訊訊息。

// GET: api/LineNotify/SendMessage?target=PoyChang&message=HelloWorld
/// <summary>傳送文字訊息</summary>
/// <param name="token">令牌</param>
/// <param name="message">訊息</param>
[HttpGet]
[Route("SendMessage")]
public async Task<IActionResult> SendMessage(string token, string message)
{
    using (var client = new HttpClient())
    {
        client.BaseAddress = new Uri(_notifyUrl);
        client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);

        var form = new FormUrlEncodedContent(new[]
        {
            new KeyValuePair<string, string>("message", message)
        });

        await client.PostAsync("", form);
    }

    return new EmptyResult();
}

這裡要注意的是,Token 必須設定在 HTTP Header 中的 Authorization 中才能通過授權驗證。

發送進階訊息

參考 Commit:

Line Notify 還提供發送貼圖以及圖片的服務,而在實作這兩個服務的時候,所需要的參數比較多,所以我這裡先建了一個傳送訊息用的模型,用來接收所有相關資訊,這部分可參考官方文件中 Notification 段落的說明。

有了訊息模型,順手增加了一個訊息模型搭配 POST 方法來傳送訊息的方法,這樣在前端就可以使用 JSON Object 來傳資料,然後交由 Web API 做 Data Binding,操作上會方便很多。

改完傳送文字訊息的方法,我們還可以做下面兩個:傳送官方貼圖、傳送圖片檔案。

傳送官方貼圖

參考 Commit:增加傳送官方貼圖的方法

發送官方貼圖有四個主要參數:

  1. Token 令牌
  2. Message 文字訊息
  3. stickerPackageId 貼圖包識別碼
  4. stickerId 貼圖識別碼

貼圖包和貼圖的識別碼可以參考這個 sticker_list.pdf

傳送圖片檔案

參考 Commit:增加傳送圖片檔案的方法

發送圖片檔案有四個主要參數:

  1. Token 令牌
  2. Message 文字訊息
  3. FileUri 圖片檔案路徑
  4. Filename 圖片檔案名稱

你會發現傳送訊息的三種方法都長得很像,不外乎就是透過 HttpClient 去傳送參數給 Line Notify API 服務,只要 Token 是合法的,參數符合特定條件,就 OK 了。

而且每一個傳送訊息的方法,都一定要有文字訊息,沒有這個了話,就會回傳下列訊息,告訴你 400 錯誤,還會貼心地和你說文字訊息不能是空的唷~

{
  "status": 400,
  "message": "message: may not be empty"
}

取得貼圖資訊

貼圖人人愛用,但如果每次要發送貼圖都要找一次 sticker_list.pdf 這個檔案了話,那就累了,如果有更簡單的方式那就好了

因此我整理了一份 JSON 檔,裡面包含各貼圖包的識別碼及相關資訊,這裡我也實作一隻取得貼圖及清單的控制器 StickersController

取得貼圖清單

參考 Commit:

因為清單已經整理好了,這裡只需要建立一個讀取 JSON 檔案的方法,然後將資料回傳給前端,就搞定了。

取得貼圖圖示

參考 Commit:

如果只是傳回 JSON 清單,看著識別碼是沒有感覺的,能再提供貼圖圖片了話,就更清楚知道這個貼圖識別碼是啥了。

首先,要先取得所有貼圖圖示,這其實很簡單,只要安裝 Line 桌面版的應用程式,然後在聊天視窗中有執行過下載貼圖的動作,你就會在這個資料夾中 C:\Users\[UserAccount]\AppData\Local\LINE\Data\Sticker 看到所有的貼圖圖示了,而且這裡會依照貼圖包識別碼來做分類,把我們需要的貼圖複製一份下來即可。

接著在實作回傳貼圖的方法時,要注意的是檔案存取的路徑,但因為整個貼圖的資料夾結構,其實是依照識別碼做分類的,資料夾是貼圖包識別碼 stickerPackageId,然後檔案名稱也就是貼圖識別碼 stickerId,所以可以很輕鬆的取到正確路徑。

接者回傳時使用 FileContentResult 型別,然後給他讀出來的檔案及對應的 Content-Type 即可。

程式碼

關於本篇文章完整的程式碼以上傳至 GitHub:https://github.com/poychang/TestLineNotifyAPI,或點此下載

如果有介紹不清楚的地方,歡迎留言討論:)


參考資料:


Poy Chang

Trial and Error