有在經營 LINE@ 的商家都知道,其實發送主動推播的成本挺高的。但各位可能不知道的是,LINE 其實也有提供一個 完全免費 的訊息推播服務叫做 LINE Notify。由於 LINE Notify 必須走 OAuth 2.0 協定來登入,又需要架設網站作為 Callback URL 用途,如果只是單純想體驗 LINE Notify 的開發者來說,就顯得有點麻煩,畢竟不是每個人都了解 OAuth 2.0 的登入流程。這篇文章我要將 OAuth 2.0 登入流程完全拆解,一步一步的給大家看,並示範如何僅透過 curl 與 ngrok 兩套工具軟體,就能走完整個流程,而且一行程式都不用寫!👍
運作方式
LINE Notify 是一個「訊息推播」服務,但跟一般開發者所理解的推播不太一樣,他的運作方式是這樣的:
-
LINE 官方有一個特殊的 LINE Notify 帳號 (@linenotify
),這是一個 LINEBot 機器人,他是一個專門用來發送訊息的帳號。
你不需要事先加入這個帳號,只要你有訂閱任何一個 LINE Notify 通知服務,他就會主動發訊息給你。
-
任何 LINE 用戶都可以成為 服務提供者,可以發送推播給任何人,而且真的完全不用任何費用!
他不像 LINE@ 有複雜的驗證程序。
-
任何 LINE 用戶都可以註冊 一個以上 的 服務提供者,每個 服務提供者 通常代表著某種目的的通知服務。
例如某網站斷線的通知,就可以註冊成一個服務提供者。或是某網站有客戶發出客服要求,也可以註冊成另一個服務提供者。通通免費!
-
所有的 服務提供者 都必須由 LINE 用戶 主動訂閱通知,該用戶才能收到推播通知,而且用戶隨時可以取消通知。
一律由官方的 LINE Notify 帳號發出訊息,而不是由 LINE@ 官方帳號發出訊息。
如果跟付費的 LINE@ 通知比起來,我覺得這個 LINE Notify 唯二的缺點就是:
- LINE Notify 不像 LINE@ 有強烈的品牌連結!
- 所有 LINE 用戶都要主動訂閱服務才收的到訊息,而且大部分 LINE 用戶都不清楚 LINE Notify 是什麼東西!
即便如此,用來作為公司內部特定訊息的通知,或是用來整合現有服務的錯誤通知,都是非常經濟又實惠的解決方法,既不用花錢,又可以得到即時推播通知的好處!
角色定義
想要嘗試用 LINE Notify 完成通知任務,必須理解以下角色:
-
服務提供者 (發送訊息方)
通常是一支程式或網站,他必須要有一個可以接受 OAuth 2.0 認證通過後的 callback
網址,你必須透過這個網址來獲取未來發送 LINE Notify 通知用的 Access Token (access_token
)。
-
授權通知方 (任意 LINE 用戶)
只有實際的 LINE 用戶才能授權 LINE Notify 發出通知,你必須擁有一個可以登入 LINE ID 的 E-mail 帳號才能進行授權。
-
訊息接收者 (接受訊息方)
LINE Notify 服務有兩種訊息接收者:
- 用戶 (
USER
):其實就是你自己!(授權的這個用戶)
- 群組 (
GROUP
):該用戶曾經加入過的任何一個 LINE 群組。
服務提供者 (發送訊息方) 要做的事
-
透過 ngrok 建立一個外部可存取的網站
安裝 ngrok 工具 (使用 Chocolatey 套件管理器)
choco install ngrok
開啟命令提示字元 (cmd.exe
) 並執行以下命令:
ngrok http 8888
請注意:你不需要撰寫任何程式碼,也不用真的有 Port 8888 的網站服務!
此時你應該會看到如下畫面,請複製 Forwarding 欄位的一個 https://xxxxxxxx.ngrok.io
的網址,這也將會成為你在 LINE Notify 訂閱通知時的 callback
參數:
開啟瀏覽器並連至 http://127.0.0.1:4040
網址,進入 ngrok 的 Web 管理介面,這裡將會紀錄所有連接到 https://xxxxxxxx.ngrok.io
網址的 HTTP 封包!
-
進入 LINE Notify 網站並登入 LINE 帳號
如果你第一次使用 LINE App,只需要手機號碼就可以開始使用。但如果要登入 LINE Notify 的話,一定要將帳號綁定「電話號碼」與「電子郵件」才可以使用此服務。
你只要到 LINE App 的設定頁面 (路徑:LINE > 主頁 > 設定 > 我的帳號),點擊「電子郵件帳號」並設定你常用的 E-mail 即可完成綁定。
-
進入 管理登錄服務 頁面
-
點擊 登錄服務 頁面
-
輸入登錄服務所需的每個欄位
除了 服務圖片 欄位外,其餘欄位皆為必填欄位。
請設定好懂好記的 服務名稱,方便未來發通知的時候,讓使用者知道是誰發送的通知。因為 LINE Notify 通知服務其實是一個 LINEBot 帳號,使用者訂閱的所有通知,全部都是透過這個帳號發送訊息,使用者要從訊息中得知「服務提供者」的唯一方法,就是透過 服務名稱 識別。
請務必輸入正確的 電子郵件帳號,因為下個步驟將會請你去收信完成電子郵件地址驗證。
而 Callback URL 欄位則請輸入你在執行 ngrok http 8888
命令時,產生的那個 https://xxxxxxxx.ngrok.io
網址 (請不要加上斜線結尾)!
-
驗證電子郵件帳號是否有效
完成電子郵件帳號驗證後,LINE Notify 服務就算設定完成!
-
取得登錄服務的 Client ID
與 Client Secret
資訊
請回到 管理登錄服務 頁面,點擊你剛剛建立的那個登錄服務,即可看見這兩個資訊。
授權通知方 (任意 LINE 用戶) 要做的事
-
登入 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 攻擊。
-
選擇您要接收通知的聊天室 (聊天室就是LINE 群組的意思)
如果使用者想要將通知發給自己,可以選擇【透過1對1聊天接收LINE Notify的通知】。
如果使用者想要將通知發給群組,可以選擇一個你以前曾經加入過的聊天室。
選取完畢後,按下 同意並連動 按鈕即可完成訂閱,此時使用者會立即收到 與「服務名稱」連動完成 的通知訊息!
-
此時瀏覽器會主動發出 HTTP POST 要求到 redirect_uri
指定的網址,並且帶入 code
與 state
表單欄位!
訊息接收者 (接受訊息方) 要做的事
如果訊息接收者是自己 (透過1對1聊天接收LINE Notify的通知
),那麼這一步什麼都不用做。
如果訊息接收者是群組 (聊天室),那麼你還必須將 @linenotify
(LINE Notify) 這個官方帳號加入到該聊天室才能收到通知!
發送推播訊息
-
取得授權碼 ( code
)
當 授權通知方 按下 同意並連動 按鈕之後,使用者的瀏覽器會直接對 redirect_uri
所設定的網址發出 HTTP POST 要求。由於我們透過 ngrok 產生的暫時網址會幫我們接收 HTTP POST 要求,所以你可以透過 http://127.0.0.1:4040/
得知 HTTP POST 傳入的內容,其中就有 code
欄位可用,請將其值複製下來!
-
取得存取權杖 ( 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"
}
任何人拿到 存取權杖 後,就可以透過該權杖發送推播通知給訂閱的目標 (USER
或 GROUP
)
如果失敗會得到以下 JSON 內容:
{
"status": 400,
"message": "invalid code",
"access_token": null
}
-
發送 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"
}
-
取得目前 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")
-
撤銷目前 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"
}
相關連結