---
# System prepended metadata

title: 如何不使用 SDK 直接呼叫 LINE Messaging API (以 Python 為例)
tags: [Line, Python]

---

# 如何不使用 SDK 直接呼叫 LINE Messaging API (以 Python 為例)

本文件旨在說明如何不依賴任何官方 SDK，直接透過 HTTP 請求與 LINE Messaging API 進行互動。這對於理解 API 底層運作、在不支援 SDK 的環境中開發，或是進行簡單的腳本整合非常有幫助。

我們將以 Python 的 `requests` 函式庫為例，示範如何傳送一個最基本的文字訊息。

---

## 1. 前置準備

在開始之前，請確保你已經擁有：

1.  **一個 LINE Developers 帳號**：如果沒有，請至 [LINE Developers Console](https://developers.line.biz/console/) 註冊。
2.  **一個 Messaging API 的 Channel**：在 Console 中建立一個提供者 (Provider)，然後在該提供者下建立一個 Messaging API 的 Channel。
3.  **Channel Access Token (長期)**：這是呼叫 API 所需的憑證。你可以在 Channel 的 "Messaging API" 分頁中找到並發行它。
4.  **你的 User ID**：為了測試 **Push Message**，你需要一個目標對象的 User ID。最簡單的方式是將你的機器人帳號加為好友，然後傳送任何訊息給它。接著，你需要設定 Webhook 來接收這個訊息事件，從中取得你的 User ID。

---

## 2. 核心概念：Push Message

「主動傳送訊息」(Push Message) 是指由機器人主動發送訊息給用戶，不需要用戶先有互動。

*   **HTTP 方法**：`POST`
*   **API 端點 (Endpoint)**：`https://api.line.me/v2/bot/message/push`
*   **HTTP Headers**：
    *   `Content-Type`: `application/json`
    *   `Authorization`: `Bearer {你的 Channel Access Token}`
*   **Request Body (Payload)**：一個 JSON 物件，用來描述訊息的接收者 (`to`) 和內容 (`messages`)。

---

## 3. 步驟詳解：傳送 Push Message

### 3.1 準備必要資訊

*   `YOUR_CHANNEL_ACCESS_TOKEN`: 從你的 LINE Developers Console 複製。
*   `YOUR_USER_ID`: 你想要傳送訊息對象的 User ID。

### 3.2 撰寫 Python 程式碼

**Body (Payload) 的結構：**
```json
{
    "to": "YOUR_USER_ID",
    "messages": [
        {
            "type": "text",
            "text": "Hello, world!"
        }
    ]
}
```

---

## 4. 完整 Python 範例 (Push Message)

```python
import requests
import json

ACCESS_TOKEN = 'YOUR_CHANNEL_ACCESS_TOKEN'
USER_ID = 'YOUR_USER_ID'

PUSH_API_URL = 'https://api.line.me/v2/bot/message/push'

headers = {
    'Content-Type': 'application/json',
    'Authorization': f'Bearer {ACCESS_TOKEN}'
}

payload = {
    'to': USER_ID,
    'messages': [{'type': 'text','text': '這是一則來自 Python 的 Push Message！'}]
}

try:
    response = requests.post(PUSH_API_URL, headers=headers, data=json.dumps(payload))
    response.raise_for_status()
    print('Push Message 傳送成功！')
except requests.exceptions.RequestException as e:
    print('Push Message 傳送失敗：', e)
```

---

## 5. 如何執行

1.  **安裝 `requests`**：`pip install requests`
2.  **儲存檔案**：將範例程式碼儲存為 `.py` 檔案。
3.  **替換變數**：填入你的 `ACCESS_TOKEN` 和 `USER_ID`。
4.  **執行腳本**：`python <your_script_name>.py`

---

## 6. 如何回覆訊息 (Reply Message)

「回覆訊息」(Reply Message) 是針對用戶傳來的特定訊息進行回應。這與可以隨時傳送的 Push Message 不同。

**核心差異：**
*   **API 端點**：`https://api.line.me/v2/bot/message/reply`
*   **認證方式**：使用 `replyToken` 而不是 `to`。
*   `replyToken`：當用戶傳送訊息到你的聊天機器人時，LINE 會透過 Webhook 事件傳送一個 `replyToken` 給你。這個 Token 是 **一次性** 且有 **時效性** 的，只能用來回覆該則訊息一次。

**Body (Payload) 的結構：**
```json
{
    "replyToken": "從 Webhook 取得的 Reply Token",
    "messages": [
        {
            "type": "text",
            "text": "感謝您的訊息！"
        }
    ]
}
```

**範例程式碼 (概念)**

你無法直接執行此腳本，因為 `replyToken` 必須從真實的 Webhook 事件中動態取得。這段程式碼展示了在一個 Web 框架 (如 Flask 或 FastAPI) 中處理回覆的邏輯。

```python
# (這是一個概念性範例，假設在一個 Web 伺服器環境中)

# 假設你從 LINE Webhook 收到了這樣的 JSON body
webhook_event = {
    "events": [
        {
            "type": "message",
            "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", # 範例 Token
            "message": {
                "type": "text",
                "id": "14320195349999",
                "text": "你好"
            }
        }
    ]
}

# 取得 replyToken
reply_token = webhook_event['events'][0]['replyToken']

# --- 準備回覆請求 ---
REPLY_API_URL = 'https://api.line.me/v2/bot/message/reply'
ACCESS_TOKEN = 'YOUR_CHANNEL_ACCESS_TOKEN'

headers = {
    'Content-Type': 'application/json',
    'Authorization': f'Bearer {ACCESS_TOKEN}'
}

payload = {
    'replyToken': reply_token,
    'messages': [{'type': 'text', 'text': '這是一則 Reply Message！'}]
}

# --- 發送回覆 ---
try:
    response = requests.post(REPLY_API_URL, headers=headers, data=json.dumps(payload))
    response.raise_for_status()
    print('Reply Message 傳送成功！')
except requests.exceptions.RequestException as e:
    print('Reply Message 傳送失敗：', e)

```

---

## 7. 如何引用訊息 (Quote Message)

引用訊息是 Reply Message 的一項附加功能，可以讓用戶清楚地看到你的回覆是針對哪一則訊息。

要使用此功能，你需要在回覆的 `messages` 物件中，加上 `quoteToken` 欄位。

*   `quoteToken`：與 `replyToken` 一樣，`quoteToken` 也來自於 Webhook 事件中的 `message` 物件。它代表了用戶傳來的那則訊息的引用標識。

**Body (Payload) 結構 (帶有引用)：**

```json
{
    "replyToken": "從 Webhook 取得的 Reply Token",
    "messages": [
        {
            "type": "text",
            "text": "這是對你那句話的回覆。",
            "quoteToken": "從 Webhook 取得的 Quote Token"
        }
    ]
}
```

**範例程式碼 (概念)**

```python
# (接續上一個 Webhook 範例)

# 從 Webhook 事件中同時取得 replyToken 和 quoteToken
webhook_event = webhook_event['events'][0]
reply_token = webhook_event['replyToken']
quote_token = webhook_event['message']['quoteToken'] # quoteToken 在 message 物件內

# --- 準備帶有引用的回覆請求 ---
payload = {
    'replyToken': reply_token,
    'messages': [
        {
            'type': 'text',
            'text': '我正在引用你的訊息來回覆！',
            'quoteToken': quote_token
        }
    ]
}

# --- 發送回覆 ---
try:
    response = requests.post(REPLY_API_URL, headers=headers, data=json.dumps(payload))
    response.raise_for_status()
    print('帶引用的 Reply Message 傳送成功！')
except requests.exceptions.RequestException as e:
    print('Reply Message 傳送失敗：', e)
```

---

## 8. 進階：傳送不同類型的訊息

不論是 Push 還是 Reply Message，你都可以傳送文字以外的訊息類型，只需修改 `messages` 陣列的內容即可。

**範例：傳送貼圖**

```python
{
    "type": "sticker",
    "packageId": "11537",
    "stickerId": "52002734"
}
```
> **提示**：你可以在 [貼圖列表文件](https://developers.line.biz/en/docs/messaging-api/sticker-list/) 中找到可用的 `packageId` 和 `stickerId`。

---

## 9. 關於接收 Webhook 事件

本文件中的 Reply Message 和 Quote Message 都強烈依賴 Webhook 來取得必要的 `replyToken` 和 `quoteToken`。

簡單來說，你需要：
1.  準備一個公開的 HTTPS 伺服器端點 (URL)。
2.  在 LINE Developers Console 中設定你的 Webhook URL。
3.  當有事件發生時，LINE 平台會對你的 URL 發送一個 `POST` 請求。
4.  你的伺服器需要解析這個請求的 JSON 內容，並 **驗證簽名 (Signature)** 以確保請求來自 LINE。簽名驗證需要使用你的 **Channel Secret**。

手動處理 Webhook（特別是簽名驗證）比傳送訊息要複雜得多，這也是官方 SDK 主要的價值所在。

---

## 10. 重要注意事項：傳送圖片訊息中的 URL 有中文字時

當你嘗試透過 LINE Messaging API 傳送圖片訊息的 URL時，請務必對該 URL 進行 **URL 編碼 (URL Encoding)**。如果未經編碼且URL裡有中文子時，LINE 平台可能無法正確解析該 URL，導致訊息無法成功傳送或顯示異常。

這在傳送可點擊的連結或指定資源位置時尤其重要。大多數程式語言都內建了 URL 編碼的工具函式。

### 圖片訊息中的 URL 編碼

當你在傳送**圖片訊息 (Image Message)** 時，其 `originalContentUrl` 和 `previewImageUrl` 也必須是經過編碼的有效 URL。

**Body (Payload) 的結構：**
```json
{
    "type": "image",
    "originalContentUrl": "編碼後的圖片 URL",
    "previewImageUrl": "編碼後的預覽圖片 URL"
}
```

**範例程式碼 (概念)**
```python
from urllib.parse import quote

# 原始的圖片 URL
raw_image_url = "https://example.com/images/my cat photo.jpg"
raw_preview_url = "https://example.com/images/preview/my cat photo.jpg"

# 對 URL 進行編碼
encoded_image_url = quote(raw_image_url, safe='/:')
encoded_preview_url = quote(raw_preview_url, safe='/:')

# --- 準備圖片訊息的 payload ---
payload = {
    'to': USER_ID,
    'messages': [
        {
            "type": "image",
            "originalContentUrl": encoded_image_url,
            "previewImageUrl": encoded_preview_url
        }
    ]
}

# --- 發送請求 ---
# response = requests.post(PUSH_API_URL, headers=headers, data=json.dumps(payload))
```

**重點**：
*   `quote` 函式會將特殊字元 (如空格、`?`, `=`, `&`) 轉換為 `%` 開頭的格式。
*   `safe='/:,'` 參數可以避免對 URL 的協定 (`https://`) 和路徑分隔符 (`/`) 等本身合法的字元進行編碼。
*   若不進行編碼，像 URL 中的**空格**或特殊查詢參數，可能會被 LINE 的伺服器誤判，導致 URL 無法存取、圖片載入失敗，最終使您的 API 請求失敗。


---

## 11. 總結

**直接呼叫 API 的優點：**
*   **輕量**：不需要安裝整個 SDK，只依賴基本的 HTTP 客戶端。
*   **彈性**：可以在任何支援 HTTP 請求的語言或環境中使用。
*   **透明**：能清楚了解 API 的底層運作方式。

**直接呼叫 API 的缺點：**
*   **繁瑣**：需要手動組合 JSON、設定 Headers。
*   **錯誤處理**：需要自行處理 HTTP 錯誤、API 回應的錯誤碼等。
*   **Webhook 複雜**：手動實作 Webhook 的簽名驗證相對複雜且容易出錯。

對於僅需傳送簡單通知的腳本，直接呼叫 API 是一個非常好的選擇。但若要開發功能完整的聊天機器人，使用官方 SDK 通常會更有效率且穩健。