The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

上手 LINE Notify 不求人:一行代碼都不用寫的推播通知方法

有在經營 LINE@ 的商家都知道,其實發送主動推播的成本挺高的。但各位可能不知道的是,LINE 其實也有提供一個 完全免費 的訊息推播服務叫做 LINE Notify。由於 LINE Notify 必須走 OAuth 2.0 協定來登入,又需要架設網站作為 Callback URL 用途,如果只是單純想體驗 LINE Notify 的開發者來說,就顯得有點麻煩,畢竟不是每個人都了解 OAuth 2.0 的登入流程。這篇文章我要將 OAuth 2.0 登入流程完全拆解,一步一步的給大家看,並示範如何僅透過 curlngrok 兩套工具軟體,就能走完整個流程,而且一行程式都不用寫!👍

運作方式

LINE Notify 是一個「訊息推播」服務,但跟一般開發者所理解的推播不太一樣,他的運作方式是這樣的:

  1. LINE 官方有一個特殊的 LINE Notify 帳號 (@linenotify),這是一個 LINEBot 機器人,他是一個專門用來發送訊息的帳號。

    你不需要事先加入這個帳號,只要你有訂閱任何一個 LINE Notify 通知服務,他就會主動發訊息給你。

  2. 任何 LINE 用戶都可以成為 服務提供者,可以發送推播給任何人,而且真的完全不用任何費用!

    他不像 LINE@ 有複雜的驗證程序。

  3. 任何 LINE 用戶都可以註冊 一個以上服務提供者,每個 服務提供者 通常代表著某種目的的通知服務。

    例如某網站斷線的通知,就可以註冊成一個服務提供者。或是某網站有客戶發出客服要求,也可以註冊成另一個服務提供者。通通免費!

  4. 所有的 服務提供者 都必須由 LINE 用戶 主動訂閱通知,該用戶才能收到推播通知,而且用戶隨時可以取消通知

    一律由官方的 LINE Notify 帳號發出訊息,而不是由 LINE@ 官方帳號發出訊息。

如果跟付費的 LINE@ 通知比起來,我覺得這個 LINE Notify 唯二的缺點就是:

  1. LINE Notify 不像 LINE@ 有強烈的品牌連結
  2. 所有 LINE 用戶都要主動訂閱服務才收的到訊息,而且大部分 LINE 用戶都不清楚 LINE Notify 是什麼東西!

即便如此,用來作為公司內部特定訊息的通知,或是用來整合現有服務的錯誤通知,都是非常經濟又實惠的解決方法,既不用花錢,又可以得到即時推播通知的好處!

角色定義

想要嘗試用 LINE Notify 完成通知任務,必須理解以下角色:

  1. 服務提供者 (發送訊息方)

    通常是一支程式或網站,他必須要有一個可以接受 OAuth 2.0 認證通過後的 callback 網址,你必須透過這個網址來獲取未來發送 LINE Notify 通知用的 Access Token (access_token)。

  2. 授權通知方 (任意 LINE 用戶)

    只有實際的 LINE 用戶才能授權 LINE Notify 發出通知,你必須擁有一個可以登入 LINE ID 的 E-mail 帳號才能進行授權。

  3. 訊息接收者 (接受訊息方)

    LINE Notify 服務有兩種訊息接收者:

    1. 用戶 (USER):其實就是你自己!(授權的這個用戶)
    2. 群組 (GROUP):該用戶曾經加入過的任何一個 LINE 群組。

服務提供者 (發送訊息方) 要做的事

  1. 透過 ngrok 建立一個外部可存取的網站

    安裝 ngrok 工具 (使用 Chocolatey 套件管理器)

    choco install ngrok
    

    開啟命令提示字元 (cmd.exe) 並執行以下命令:

    ngrok http 8888
    

    請注意:你不需要撰寫任何程式碼,也不用真的有 Port 8888 的網站服務!

    此時你應該會看到如下畫面,請複製 Forwarding 欄位的一個 https://xxxxxxxx.ngrok.io 的網址,這也將會成為你在 LINE Notify 訂閱通知時的 callback 參數:

    2020-02-18_02-13-30

    開啟瀏覽器並連至 http://127.0.0.1:4040 網址,進入 ngrok 的 Web 管理介面,這裡將會紀錄所有連接到 https://xxxxxxxx.ngrok.io 網址的 HTTP 封包!

  2. 進入 LINE Notify 網站並登入 LINE 帳號

    如果你第一次使用 LINE App,只需要手機號碼就可以開始使用。但如果要登入 LINE Notify 的話,一定要將帳號綁定「電話號碼」與「電子郵件」才可以使用此服務。

    你只要到 LINE App 的設定頁面 (路徑:LINE > 主頁 > 設定 > 我的帳號),點擊「電子郵件帳號」並設定你常用的 E-mail 即可完成綁定。

  3. 進入 管理登錄服務 頁面

  4. 點擊 登錄服務 頁面

  5. 輸入登錄服務所需的每個欄位

    除了 服務圖片 欄位外,其餘欄位皆為必填欄位。

    請設定好懂好記的 服務名稱,方便未來發通知的時候,讓使用者知道是誰發送的通知。因為 LINE Notify 通知服務其實是一個 LINEBot 帳號,使用者訂閱的所有通知,全部都是透過這個帳號發送訊息,使用者要從訊息中得知「服務提供者」的唯一方法,就是透過 服務名稱 識別。

    請務必輸入正確的 電子郵件帳號,因為下個步驟將會請你去收信完成電子郵件地址驗證。

    Callback URL 欄位則請輸入你在執行 ngrok http 8888 命令時,產生的那個 https://xxxxxxxx.ngrok.io 網址 (請不要加上斜線結尾)!

  6. 驗證電子郵件帳號是否有效

    完成電子郵件帳號驗證後,LINE Notify 服務就算設定完成!

  7. 取得登錄服務的 Client IDClient Secret 資訊

    請回到 管理登錄服務 頁面,點擊你剛剛建立的那個登錄服務,即可看見這兩個資訊。

    2020-02-18_04-00-14

授權通知方 (任意 LINE 用戶) 要做的事

  1. 登入 LINE Notify 訂閱通知介面

    使用者必須進入以下網址,才能訂閱你的 LINE Notify 通知 (特定服務提供者提供的通知):

    https://notify-bot.line.me/oauth/authorize?response_type=code&scope=notify&response_mode=form_post&client_id=xxxxxxxxxxxxxxxxxxxx&redirect_uri=http://xxxxxxxx.ngrok.io/&state=f094a459-1d16-42d6-a709-c2b61ec53d60
    

    這其實是一個 OAuth 2.0 的登入流程,使用者不太需要真的懂這些,只要能連到這個網址即可訂閱通知。

    開發者只要能產生正確的 URL 給使用者用即可,但這個網址又臭又長,每個查詢字串的用途說明如下:

    • scope: 固定寫 notify 就對了。

    • response_type: 固定寫 code 就對了。

    • response_mode: 這個參數可以忽略,但你也可以寫 form_post 當成 HTTP 回應的模式。

    • redirect_uri: 請設定你 ngrok 產生的暫時網址,當訂閱完成後,使用者會被導向到這個網址。

      請特別要注意的一件事,這裡設定的 URL 必須跟你之前註冊時所設定的 Callback URL 完全一樣,連網址最後是否有斜線結尾,都要完全一樣才行。

    • client_id: 請設定登錄服務的 Client ID

    • state: 設定一組亂碼,其實輸入什麼都可以,此參數主要用來防止 CSRF 攻擊。

  2. 選擇您要接收通知的聊天室 (聊天室就是LINE 群組的意思)

    如果使用者想要將通知發給自己,可以選擇【透過1對1聊天接收LINE Notify的通知】。

    如果使用者想要將通知發給群組,可以選擇一個你以前曾經加入過的聊天室。

    選取完畢後,按下 同意並連動 按鈕即可完成訂閱,此時使用者會立即收到 與「服務名稱」連動完成 的通知訊息!

  3. 此時瀏覽器會主動發出 HTTP POST 要求到 redirect_uri 指定的網址,並且帶入 codestate 表單欄位!

訊息接收者 (接受訊息方) 要做的事

如果訊息接收者是自己 (透過1對1聊天接收LINE Notify的通知),那麼這一步什麼都不用做。

如果訊息接收者是群組 (聊天室),那麼你還必須將 @linenotify (LINE Notify) 這個官方帳號加入到該聊天室才能收到通知!

發送推播訊息

  1. 取得授權碼 ( code )

    授權通知方 按下 同意並連動 按鈕之後,使用者的瀏覽器會直接對 redirect_uri 所設定的網址發出 HTTP POST 要求。由於我們透過 ngrok 產生的暫時網址會幫我們接收 HTTP POST 要求,所以你可以透過 http://127.0.0.1:4040/ 得知 HTTP POST 傳入的內容,其中就有 code 欄位可用,請將其值複製下來!

    2020-02-18_03-03-09

  2. 取得存取權杖 ( access_token ) (Access Token)

    安裝 curl 工具 (使用 Chocolatey 套件管理器)

    choco install curl -y
    

    你必須發送一個 HTTP POST 到 https://notify-bot.line.me/oauth/token 才能取得存取權杖,命令如下:

    curl -d "grant_type=authorization_code&redirect_uri=https://xxxxxxxx.ngrok.io&client_id=xxxxxxxxxxxxxxxxxxxxxxx&client_secret=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&code=xxxxxxxxxxxxxxxxxxxxxx" https://notify-bot.line.me/oauth/token
    

    參數說明如下:

    • grant_type: 固定寫 authorization_code 就對了。
    • redirect_uri: 請設定你 ngrok 產生的暫時網址。
    • client_id: 登錄服務的 Client ID 資訊
    • client_secret: 登錄服務的 Client Secret 資訊
    • code: 上個步驟取得的授權碼 ( code )

    如果有成功發出 Access Token 你將會得到以下 JSON 內容:

    {
      "status": 200,
      "message": "access_token is issued",
      "access_token":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    }
    

    任何人拿到 存取權杖 後,就可以透過該權杖發送推播通知給訂閱的目標 (USERGROUP)

    如果失敗會得到以下 JSON 內容:

    {
      "status": 400,
      "message": "invalid code",
      "access_token": null
    }
    
  3. 發送 LINE Notify 通知訊息

    任何通知訊息都需要有 Access Token 才能發出!

    你可以透過以下 curl 命令發出 LINE Notify 通知訊息:

    curl -H "Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -d "message=Hello World" https://notify-api.line.me/api/notify
    

    這裡的 -H 參數代表著 HTTP POST 的一個自訂標頭 (Custom Header),而 Authorization 則是用來通過身分驗證用的標頭,而 Bearer 則代表我們將傳入一個 Bearer Token,後面的 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 就是我們在上一步取得的 Access Token 存取權杖。

    如果成功發出訊息,你會得到以下 JSON 回應,並且在 LINE App 上也會即時收到通知訊息:

    {
      "status": 200,
      "message": "ok"
    }
    

    如果 Access Token 已經被撤銷,則會得到以下回應:

    {
      "status": 401,
      "message": "Invalid access token"
    }
    
  4. 取得目前 Access Token 狀態

    只要對 https://notify-api.line.me/api/status 發出 GET 要求即可獲得 Access Token 狀態:

    curl -H "Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" https://notify-api.line.me/api/status
    

    以下是 Access Token 有效的回應內容:

    {
      "status": 200,
      "message": "ok",
      "targetType": "USER",
      "target": "Will"
    }
    

    備註:上述 targetType 可能的值有 USER (用戶) 或 GROUP (聊天室)。

    如果 Access Token 已經被撤銷,則會得到以下回應:

    {
      "status": 401,
      "message": "Invalid access token"
    }
    

    如果想得知目前 Access Token 的 API Rate Limit 相關資訊,可以改用以下命令查詢:

    curl -D - -H "Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" https://notify-api.line.me/api/status
    

    這裡的 -D - 代表將 Response Headers 全部輸出到 STDOUT 螢幕上,這時你會得到以下資訊:

    HTTP/1.1 200
    Server: nginx
    Date: Mon, 17 Feb 2020 15:33:26 GMT
    Content-Type: application/json;charset=UTF-8
    Transfer-Encoding: chunked
    Connection: keep-alive
    Keep-Alive: timeout=3
    X-RateLimit-Limit: 1000
    X-RateLimit-ImageLimit: 50
    X-RateLimit-Remaining: 998
    X-RateLimit-ImageRemaining: 50
    X-RateLimit-Reset: 1581953606
    

    其中的 X-RateLimit-Remaining 就是你這個 Token 在這一個小時內還能用幾次。

    還有 X-RateLimit-Reset 代表著下次 Reset 用量限制的時間點,這是 UTC epoch seconds 單位。

    若要在 Linux 下查詢這個數字所代表的時間點,可以輸入以下命令查詢:

    date -d @1581953606
    

    若要在 PowerShell 下查詢這個數字所代表的時間點,可以輸入以下命令查詢:

    (([System.DateTimeOffset]::FromUnixTimeSeconds(1581953606)).DateTime.ToLocalTime()).ToString("s")
    
  5. 撤銷目前 Access Token

    只要對 https://notify-api.line.me/api/revoke 發出 POST 要求即可撤銷 Access Token:

    curl -X POST -H "Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" https://notify-api.line.me/api/revoke
    

    以下是成功撤銷 Access Token 的回應內容:

    {
      "status": 200,
      "message": "ok"
    }
    

    如果 Access Token 本來就無效,則會得到以下回應:

    {
      "status": 401,
      "message": "Invalid access token"
    }
    

相關連結

留言評論