Skip to main content

標題:LINE Pay API 整合技術指南
描述:完整說明如何整合 LINE Pay API 建立線上支付系統,包含 LIFF 環境整合與最新實作經驗
最後更新:2025-07-09
版本:v2.0
作者:rj0217
來源:LIFF + LINE Pay 實作專案

LINE Pay API 整合技術指南

概述​

本指南說明如何整合 LINE Pay API 建立完整的線上支付系統。透過 LIFF (LINE Front-end Framework) 與 LINE Pay 的結合,可在 LINE 應用程式內提供無縫的支付體驗。

重要更新 (2025-07-09): 本指南已更新手機端 LIFF 環境跳轉解決方案及新域名整合經驗。


系統架構​

技術堆疊​

  • 前端: HTML5 + JavaScript + LIFF SDK
  • 後端: Node.js + Vercel Serverless Functions
  • 支付: LINE Pay API v3
  • 部署: Vercel
  • 域名: 支援自訂域名整合

API 流程圖​

用戶 → LIFF App → Request API → LINE Pay → 付款頁面
↓
成功頁面 ← Confirm API ← 重定向 ← 付款完成

前置準備​

1. LINE Developers 設定​

  1. 建立 LINE Login Channel
  2. 建立 LIFF App
  3. 取得 LIFF ID
  4. 設定 LIFF Endpoint URL(支援自訂域名)

2. LINE Pay 商家申請​

  1. 申請 LINE Pay 商家帳號
  2. 取得 Channel ID 與 Channel Secret
  3. 設定 IP 白名單(Vercel: 76.76.21.0/24)

3. 開發環境​

# 必要套件
npm install axios

核心 API 實作​

1. 付款請求 (Request API)​

端點​

POST /v3/payments/request

請求範例​

const requestBody = {
amount: 100,
currency: 'TWD',
orderId: 'ORDER_1234567890',
packages: [{
id: '1',
amount: 100,
name: '商品名稱',
products: [{
name: '商品名稱',
quantity: 1,
price: 100
}]
}],
redirectUrls: {
confirmUrl: 'https://yourdomain.com/api/pay/confirm',
cancelUrl: 'https://yourdomain.com/api/pay/cancel'
}
};

簽名計算​

const crypto = require('crypto');

function generateSignature(channelSecret, uri, body, nonce) {
const signatureBase = channelSecret + uri + body + nonce;
return crypto
.createHmac('sha256', channelSecret)
.update(signatureBase, 'utf8')
.digest('base64');
}

2. 付款確認 (Confirm API)​

端點​

POST /v3/payments/{transactionId}/confirm

關鍵要點​

  • 必須在用戶付款後呼叫
  • 金額必須與原始請求相同
  • 需要相同的簽名驗證機制
  • 確保從 URL 參數正確傳遞金額

請求範例​

const confirmBody = {
amount: parseInt(req.query.amount), // 從 URL 參數取得
currency: 'TWD'
};

3. 查詢 API (選用)​

端點​

GET /v3/payments/requests/{transactionId}

用於查詢交易狀態,適合實作訂單追蹤功能。


LIFF 整合要點​

1. SDK 載入​

<script src="https://static.line-scdn.net/liff/edge/2/sdk.js"></script>

2. 初始化時機(重要)​

// ✅ 正確方式
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}

// ❌ 避免使用
window.onload = init; // 可能太晚執行

3. 登入流程​

async function init() {
try {
await liff.init({ liffId: 'YOUR_LIFF_ID' });
if (liff.isLoggedIn()) {
const profile = await liff.getProfile();
// 使用 profile.userId, profile.displayName
} else {
liff.login();
}
} catch (error) {
console.error('LIFF 初始化失敗:', error);
}
}

4. 手機端付款跳轉(重要更新)​

// ✅ 2025-07-09 更新:正確的跳轉方式
async function pay() {
try {
const response = await fetch('/api/pay/request', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ amount, productName })
});

const result = await response.json();

if (result.success) {
// 根據執行環境使用不同的跳轉方法
if (liff.isInClient()) {
// 在 LINE 客戶端內
liff.openWindow({
url: result.paymentUrl,
external: true
});
} else {
// 在外部瀏覽器
window.location.href = result.paymentUrl;
}
}
} catch (error) {
console.error('付款錯誤:', error);
}
}

域名整合要點(新增)​

1. 自訂域名設定​

當使用自訂域名(如 lajibro.com)時,需要注意:

  1. Vercel 域名設定

    • 在 Vercel Dashboard 添加自訂域名
    • 設定正確的 DNS 記錄
    • 注意 www 與非 www 的重定向設定
  2. LIFF Endpoint URL 更新

    • 在 LINE Developers Console 更新 LIFF Endpoint URL
    • 確保使用與 Vercel 設定一致的域名(含或不含 www)
  3. 動態 URL 處理

    const baseUrl = `https://${req.headers.host}`;
    // 自動適應不同域名

2. 域名切換注意事項​

  • 確保 SSL 憑證正確設定
  • 測試從舊域名到新域名的跳轉
  • 驗證 API 端點在新域名下正常運作

安全性考量​

1. Content Security Policy​

<meta http-equiv="Content-Security-Policy" 
content="script-src 'self' 'unsafe-inline' 'unsafe-eval'
https://static.line-scdn.net;">

注意: LIFF SDK 需要 'unsafe-eval' 權限

2. 簽名驗證​

  • 所有 API 請求都需要 HMAC-SHA256 簽名
  • 使用 Channel Secret 作為密鑰
  • Nonce 使用時間戳記確保唯一性

3. HTTPS 必要性​

  • LINE Pay 只接受 HTTPS 請求
  • LIFF 應用必須使用 HTTPS

常見整合問題​

問題 1: CORS 錯誤​

解決方案: 使用後端 API 代理請求,不要從前端直接呼叫 LINE Pay

問題 2: 簽名驗證失敗​

檢查項目:

  • Channel Secret 是否正確
  • 請求 body 的 JSON 字串化是否一致
  • Nonce 是否為字串格式

問題 3: 金額錯誤​

解決方案:

  • 確保 Request 和 Confirm 的金額相同
  • 使用 URL 參數傳遞金額到 confirm 頁面

問題 4: IP 未授權​

解決方案: 在 LINE Pay 後台加入服務器 IP 白名單

問題 5: 手機端無法跳轉(新增)​

解決方案:

  • 使用 liff.isInClient() 判斷執行環境
  • 在 LINE 內使用 liff.openWindow()
  • 在外部瀏覽器使用 window.location.href

測試指南​

1. 沙盒環境測試​

  • 使用 https://sandbox-api-pay.line.me
  • 可使用測試信用卡號
  • 交易不會實際扣款

2. 測試流程​

  1. LIFF 登入測試
  2. 建立付款請求
  3. 完成付款流程
  4. 確認後台交易紀錄
  5. 測試手機端與電腦端的跳轉行為

3. 偵錯工具​

// 加入偵錯日誌
console.log('Request Body:', JSON.stringify(requestBody));
console.log('Signature:', signature);
console.log('Response:', response.data);
console.log('Is in LINE client:', liff.isInClient());

生產環境部署​

1. LINE Login Channel 發布(重要)​

在部署到生產環境前,必須先將 LINE Login Channel 從開發狀態發布為正式版本:

  1. 登入 LINE Developers Console
  2. 選擇你的 LINE Login Channel
  3. 確認以下資訊已完整填寫:
    • Channel name
    • Channel description
    • App types
    • Email address
  4. 點擊「發布」(Publish) 按鈕
  5. 確認發布後,狀態會從「開發中」變更為「已發布」

注意: 未發布的 Channel 只有開發者和測試者可以使用,一般用戶將無法登入。

2. 環境變數設定​

const channelId = process.env.LINE_PAY_CHANNEL_ID;
const channelSecret = process.env.LINE_PAY_CHANNEL_SECRET;
const apiUrl = process.env.NODE_ENV === 'production'
? 'https://api-pay.line.me'
: 'https://sandbox-api-pay.line.me';

3. 錯誤處理​

try {
// API 呼叫
} catch (error) {
if (error.response) {
// LINE Pay 回傳的錯誤
console.error('API Error:', error.response.data);
} else {
// 網路或其他錯誤
console.error('System Error:', error.message);
}
}

4. 監控建議​

  • API 回應時間
  • 付款成功率
  • 錯誤類型分析
  • 用戶行為追蹤
  • 手機端與電腦端的使用比例

程式碼範例​

完整的 Request Handler(更新版)​

const axios = require('axios');
const crypto = require('crypto');

module.exports = async function handler(req, res) {
// CORS 設定
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');

if (req.method === 'OPTIONS') return res.status(200).end();
if (req.method !== 'POST') return res.status(405).json({ error: 'Method not allowed' });

try {
const { amount, productName } = req.body;

// 參數驗證
if (!amount || !productName) {
return res.status(400).json({
success: false,
error: '缺少必要參數'
});
}

// 設定值
const channelSecret = process.env.LINE_PAY_CHANNEL_SECRET;
const channelId = process.env.LINE_PAY_CHANNEL_ID;
const orderId = `ORDER_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
const baseUrl = `https://${req.headers.host}`; // 動態取得域名

// 建立請求 body
const requestBody = {
amount: parseInt(amount),
currency: 'TWD',
orderId: orderId,
packages: [{
id: '1',
amount: parseInt(amount),
name: productName,
products: [{
name: productName,
quantity: 1,
price: parseInt(amount)
}]
}],
redirectUrls: {
confirmUrl: `${baseUrl}/api/pay/confirm?orderId=${orderId}&amount=${amount}`,
cancelUrl: `${baseUrl}/api/pay/cancel?orderId=${orderId}`
}
};

// 簽名計算
const uri = '/v3/payments/request';
const nonce = Date.now().toString();
const bodyString = JSON.stringify(requestBody);
const signatureBase = channelSecret + uri + bodyString + nonce;

const signature = crypto
.createHmac('sha256', channelSecret)
.update(signatureBase, 'utf8')
.digest('base64');

// API 請求
const response = await axios.post(
`https://api-pay.line.me${uri}`, // 正式環境
requestBody,
{
headers: {
'Content-Type': 'application/json',
'X-LINE-ChannelId': channelId,
'X-LINE-Authorization-Nonce': nonce,
'X-LINE-Authorization': signature
},
timeout: 30000
}
);

// 回傳結果
if (response.data.returnCode === '0000') {
return res.json({
success: true,
orderId: orderId,
paymentUrl: response.data.info.paymentUrl.web,
transactionId: response.data.info.transactionId
});
} else {
throw new Error(response.data.returnMessage);
}

} catch (error) {
console.error('Payment error:', error.response?.data || error.message);
return res.status(500).json({
success: false,
error: error.response?.data?.returnMessage || error.message
});
}
};

地區差異注意事項​

LINE Pay 服務可用性​

根據 2025 年 7 月的資訊:

  • 日本地區: LINE Pay 服務將於 2025 年 4 月 30 日終止
  • 台灣地區: LINE Pay 服務正常運作中
  • 其他地區: 請查詢當地 LINE Pay 服務狀態

建議定期關注 LINE Pay 官方公告以了解最新服務狀態。


參考資源​


結論​

LINE Pay API 整合需要注意許多細節,從簽名計算到錯誤處理都需要謹慎實作。透過本指南的說明與範例,開發者應能順利完成整合並建立穩定的支付系統。

記住關鍵要點:

  1. 正確的 LIFF 初始化時機
  2. 完整的 Confirm API 實作
  3. 妥善的錯誤處理
  4. 安全的簽名驗證
  5. 根據執行環境使用適當的跳轉方法

文檔迭代紀錄​

協作夥伴戳記

  1. 2025/06/29 初版建立
  2. 2025/07/09 Claude 4 Opus - 更新手機端跳轉解決方案、新域名整合經驗、地區服務差異說明