教程

@line/bot-sdk Express 中间件:replyMessage 与 validateSignature 完整示例

@line/bot-sdk Express 中间件实战:webhook 签名验证、replyMessage 与 sentMessages、错误处理、TypeScript 类型。生产可用代码。

LineBot.pro Team11 分钟阅读
@line/bot-sdk Express 中间件:replyMessage 与 validateSignature 完整示例

#为什么需要 Express 中间件?

@line/bot-sdk 官方包含 Express 中间件,自动完成两件事:

  1. HMAC-SHA256 签名验证x-line-signature 头)
  2. JSON body 解析,签名错误返回 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)

LINE Bot webhook 架构
LINE Bot webhook 架构

#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 秒内使用,且只能用一次。

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" }] } } },
  ],
})

每次 replyMessage 最多 5 条消息

#ReplyMessageResponse.sentMessages

SDK v9(2024)起:

ts
type ReplyMessageResponse = { sentMessages: Array<{ id: string; quoteToken?: string }> }

#错误处理与 401/400

错误原因解决
401 SignatureValidationFailedexpress.json() 在前移除全局 JSON 解析
400 Invalid reply token已用或超 30 秒改用 pushMessage

#LINE Bot Webhook 架构

LINE → Webhook(middleware 验证 HMAC)→ handleEvent → replyMessage → LINE

参见 LINE bot 工具对比Rich Menu 尺寸

#常见问题

Q: Express 中间件应放在哪里? 直接挂在 webhook 路由,在任何 express.json() 之前

Q: 能否在 Express 外调用 validateSignature()? 可以:import { validateSignature } from "@line/bot-sdk",传入 raw body 与签名。

Q: sentMessages 包含什么? id(持久化 LINE 消息 ID)与可选 quoteToken 的数组。


下一步:

LineBot.pro

准备好自动化您的LINE业务了吗?

立即使用LineBot.pro开始自动化您的LINE通信。