FLASK WEBHOOK

      在〈FLASK WEBHOOK〉中尚無留言

本篇使用 Flask 架設伺服器,不建議使用,在此僅作記錄用。

上一篇的 Line BOT 簡介中,BOT 可以自動回覆訊息,但功能極為陽春。雖然也可以設定 AI 自動回覆訊息,但這功能將於 2024/05/15 停用。

所以我們必需架設一台伺服器,分析客戶端傳入的內容才決定要如何回應,最終將回應訊息透過 BOT 傳送給客戶端手機,示意圖如下。

Line Channel access token 

在底下的伺服器代碼中,有二個很重要的變數要設定,分別是 Line Channel acccess token 及 Line secret。因為 Line 網站上查詢這二個變數的位置有變,所以先說明一下取得的方式。

請先由 https://developers.line.biz/zh-hant/ 選擇 Console,再按下 Messaging API。

接下來再選擇 Messageing API 分頁

往下拉後,會看到 Channel access token,第一次需按下 issue 按鈕產生新的 access token,日後若要變更,可以按下 Reissue。請把 access token 複製記下,等會要填入 python 代碼中的 access_token 變數。

再切換到 Basic settings 分頁

往下拉即可看到 Channel secret,此數字也需記要,要填入後面 python 代碼的 secret 變數中。

Line BOT 設定

請進入 Line BOT 網站的設定/Messaging API,將聊天關掉,Webhook 打開。

Django 伺服器

Webhook Url 最後要加 “/”,比如 https://xxx.ddns.net/line/

本例以 Linux 作為

Flask 伺服器

本例以 Linux 作為說明,請在 Linux 下設定好虛擬環境後,先安裝如下套件

mkdir bot
cd bot
python3 -m venv .venv
source .venv/bin/activate
pip install flask line-bot-sdk

然後使用 flask 架設網站,請新增 linebotServer.py 檔案,代碼如下

#!/server/linebot/.venv/bin/python3

from flask import Flask, request
import json
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, TextMessage, TextSendMessage

app = Flask(__name__)

@app.route("/thomas", methods=['POST'])
def thomas():
    body = request.get_data(as_text=True)                    #取得收到的訊息
    try:
        json_data = json.loads(body)                         # json 格式化訊息內容
        access_token = '你的 Line channel access token'
        secret = '你的 Line secret'
        line_bot_api = LineBotApi(access_token)              # 確認 token 是否正確
        handler = WebhookHandler(secret)                     # 確認 secret 是否正確
        signature = request.headers['X-Line-Signature']      # 加入回傳的 headers
        handler.handle(body, signature)                      # 綁定訊息回傳的相關資訊
        tk = json_data['events'][0]['replyToken']            # 取得回傳訊息的 Token
        type = json_data['events'][0]['message']['type']     # 取得 LINe 收到的訊息類型
        if type=='text':
            msg = json_data['events'][0]['message']['text']  # 取得 LINE 收到的文字訊息
            print(msg)                                       # 印出內容
            reply = msg
        else:
            reply = '你傳的不是文字呦~'
        print(reply)
        line_bot_api.reply_message(tk,TextSendMessage(reply))# 回傳訊息
    except:
        print("error",body)                                          # 如果發生錯誤,印出收到的內容
    return 'OK'                                              # 驗證 Webhook 使用,不能省略

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=7001)

假設你的網域為 https://xxx.ddns.net,則上述的 @app.route(“/thomas“, methods=[“post”]) 表示要連接你的伺服器網域為 https://xxx.ddns.net/thomas,然後函數名稱可以隨便訂。

這樣有個好處,就是你可以一直接其它人的案子,比如客戶的帳號是 jerry,可以依樣寫個 @app.route(‘jerry’, methods=[‘post’]) 及 def jerry(),然後把網域 https://xxx.ddns.net/jerry 發送給客戶,共同使相同的 xxx.ddns.net 網域。

另外 flask 預設使用的 port 為 5000,且不允許外部連線,所以如果要改變 port 及允許外部連線,需改成

app.run(host='0.0.0.0', port=7001)

最後記得要執行此程式,啟動伺服器

Nginx 設定

接下來需設定 Nginx,本例以 Linux  作為說明,請執行如下指令

sudo vim /etc/nginx/sites-available/default

然後在裏面新增如下藍色的設定。請注意,黑色的部份是本人原本就設定好的 php 轉址,而且必需要有 ssl 認証,因為 Line BOT 的 webhook 只接受 https 的協定。

server {
        server_name mahalphp.ddns.net;
        root /data/server/wordpress;
        add_header X-Frame-Options SAMEORIGIN;#禁止網頁被內崁
        index index.php index.html;
        location ~* \.(ico|css|js|gif|jpe?g|png|ogg|ogv|svg|svgz|eot|otf|woff)(\?.+)?$ {
                expires max;
                log_not_found off;
        }
        location / {
                try_files $uri $uri/ /index.php?$args;
        }
        location ~* \.php$ {
                fastcgi_pass 127.0.0.1:9000;
                fastcgi_index index.php;
                fastcgi_split_path_info ^(.+\.php)(.*)$;
                include fastcgi_params;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        }

        location /thomas {
                proxy_pass http://localhost:7001;
                proxy_set_header Host $http_host;#將客戶端的 HOST 傳入 Django
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/mahalphp.ddns.net/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/mahalphp.ddns.net/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

最後請重啟 nginx

sudo systemctl restart nginx

設定 ip 分享器

請將 ip 分享器打開,選擇 port forwarding 將 443 port 指向到伺服器 ip。至於 7001 port 則是由 Nginx 在內部進行跳轉,所以不需要 forwarding。

設定 Line BOT Webhook

再次進入 Line BOT 網頁中的 Messaging API,Webhook URL 選 Edit,將網址 https://xxx.ddns.net/thomas 填入,然後按下 Verify 驗証,如果成功就會顯示 success

測試

執行上面的代碼後使用 Line 與 BOT 聊天,此時客戶輸入什麼,BOT 就會以同樣的訊息回應。

開機自動啟動 Python Server

先將 linebotServer.py 改成 755 權限

sudo chmod 755 /server/linebot/linebotServer.py

然後於 /etc/init.d 底下新增 linebot 檔案,內容如下

#!/bin/sh
/server/linebot/linebotServer.py

接下來於 rc3.d 目錄下設定軟連結

cd /etc/rc3.d
sudo ln -s ../init.d/linebot S99linebot

重新開機後,就會自動啟動 linebotServer.py 伺服器了

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *