チュートリアル
@line/bot-sdk Express Middleware:replyMessage と validateSignature の完全な実例
@line/bot-sdk Express middleware の実用例:webhook 署名検証、replyMessage と sentMessages、エラー処理、TypeScript 型定義。本番対応コード。
LineBot.pro Team11 分で読めます

#なぜ Express Middleware が必要?
公式 @line/bot-sdk には Express 互換 middleware が同梱されており、手作業だと再実装が面倒な 2 つの処理を担います:
- webhook 署名検証(
x-line-signatureヘッダー)を HMAC-SHA256 で検証 - JSON body の parse と署名不一致時の HTTP 401 拒否
既に開発中なら LINE チャットボット開発 と LINE API 統合 も併読してください。
#インストールとプロジェクト設定
bash
npm init -y
npm i express @line/bot-sdk
npm i -D typescript @types/express ts-node-dev
bash
LINE_CHANNEL_ACCESS_TOKEN=...
LINE_CHANNEL_SECRET=...
#最小動作例
ts
import express from "express"
import { middleware, messagingApi, WebhookEvent } from "@line/bot-sdk"
const config = {
channelAccessToken: process.env.LINE_CHANNEL_ACCESS_TOKEN!,
channelSecret: process.env.LINE_CHANNEL_SECRET!,
}
const client = new messagingApi.MessagingApiClient({ channelAccessToken: config.channelAccessToken })
const app = express()
app.post("/webhook", middleware(config), async (req, res) => {
const events: WebhookEvent[] = req.body.events
await Promise.all(events.map(handleEvent))
res.status(200).end()
})
async function handleEvent(event: WebhookEvent) {
if (event.type !== "message" || event.message.type !== "text") return
const r = await client.replyMessage({
replyToken: event.replyToken,
messages: [{ type: "text", text: `Echo: ${event.message.text}` }],
})
console.log(r.sentMessages.map(m => m.id))
}
app.listen(3000)

#validateSignature() の動作
ts
import crypto from "node:crypto"
function validateSignature(body, secret, signature) {
const computed = crypto.createHmac("sha256", secret).update(body).digest("base64")
return crypto.timingSafeEqual(Buffer.from(computed), Buffer.from(signature))
}
失敗ケース:
express.json()を middleware より先に設定- リバースプロキシが
Content-Lengthを書き換え channelSecretの末尾に改行
#replyMessage(replyToken, ...) — 完全例
replyToken は 30 秒以内 に使用、1 回のみ。
ts
await client.replyMessage({
replyToken: event.replyToken,
messages: [
{ type: "text", text: "こんにちは!" },
{ type: "flex", altText: "予約確認", contents: { type: "bubble", body: { type: "box", layout: "vertical", contents: [{ type: "text", text: "予約確認", weight: "bold" }] } } },
],
})
1 回の replyMessage で 最大 5 メッセージまで。
#ReplyMessageResponse.sentMessages
SDK v9(2024)以降:
ts
type ReplyMessageResponse = {
sentMessages: Array<{ id: string; quoteToken?: string }>
}
#エラー処理と 401/400
| エラー | 原因 | 解決 |
|---|---|---|
| 401 SignatureValidationFailed | express.json() が先 | webhook より前で削除 |
| 400 Invalid reply token | トークン使用済 or 30秒超 | pushMessage 使用 |
#LINE Bot Webhook アーキテクチャ
LINE → Webhook(middleware が HMAC 検証) → handleEvent → replyMessage → LINE
LINE bot builder 比較 と Rich Menu サイズ も参照。
#よくある質問
Q: Express middleware はどこに置く?
webhook ルートに直接、express.json() より前に。
Q: validateSignature() を Express 外で呼ぶには?
import { validateSignature } from "@line/bot-sdk" で raw body と署名を渡す。
Q: sentMessages には何が入っている?
id(永続的な LINE メッセージ ID)と任意の quoteToken の配列。
次のステップ: