You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

生产环境Viber Webhook设置失败:data参数类型错误求助

解决Viber Bot生产环境设置Webhook时报错:The "data" argument must be one of type string, TypedArray, or DataView

我刚碰到过几乎一模一样的问题,折腾半天终于找到根源——Viber Bot的中间件需要读取原始请求体(raw body)来计算HMAC签名验证,但你的Express全局配置的body-parser把请求体解析成了JSON对象,导致验证时传入Hmac.update的是对象而非原始的字符串/Buffer。本地用ngrok正常是因为本地环境的请求处理逻辑和生产环境有差异,没影响到原始请求体的获取。

错误原因分析

看错误栈里的MessageValidator._calculateHmacFromMessage调用,这里需要传入原始请求体内容生成HMAC,但全局的body-parser.json()已经把请求体解析成了JS对象,Viber中间件拿到的不是它需要的原始数据类型,所以抛出了类型错误。

解决方案(推荐第一种,路由隔离更清晰)

把body-parser的JSON解析只应用到需要的路由(比如你的/api/admin),不给Viber的webhook路由应用任何body-parser解析,让Viber中间件自己处理原始请求体:

修改你的主服务器代码:

const path = require("path");
const publicPath = path.join(__dirname, "../public");
const express = require("express");
const http = require("http");
const env = require("dotenv");
const bodyParser = require("body-parser");
env.config({ path: path.resolve(__dirname + "/.env") });
const app = express();
const server = http.createServer(app);
const adminActionRoute = require('./routes/admin');

app.use(express.static(publicPath));

// 只给/admin路由应用body-parser解析,不要全局配置
app.use('/api/admin', bodyParser.json({ verify: verifyRequestSignature }));
app.use('/api/admin', bodyParser.urlencoded({ limit: '200mb', extended: true }));
app.use('/api/admin', adminActionRoute);

const viberBot = require('../viber_chat/utils/bot')
// Viber webhook路由直接使用中间件,不经过body-parser的JSON解析
app.use('/viber/webhook', viberBot.middleware())

server.listen(5000, () => {
  viberBot.setWebhook(process.env.VB_WEBHOOK_URL);
  console.log("server starts at port 5000");
});
module.exports = server; //for testing

备选方案(如果必须全局解析JSON)

如果你的其他路由需要全局JSON解析,可以在body-parser的verify函数里把原始请求体存到req.rawBody,让Viber中间件能读取到:

function verifyRequestSignature(req, res, buf) {
  // 保存原始请求体到req.rawBody
  req.rawBody = buf;
  // 你的原有签名验证逻辑...
}

// 全局配置,但保留原始请求体
app.use(bodyParser.json({ verify: verifyRequestSignature }));
app.use(bodyParser.urlencoded({ limit: '200mb', extended: true }));

// Viber中间件会自动读取req.rawBody(部分viber-bot版本支持,不确定的话优先用第一种方案)
app.use('/viber/webhook', viberBot.middleware())

额外检查点

  1. 确认生产环境的VB_WEBHOOK_URL是公网可访问的,且Viber服务器能正常请求到
  2. 检查生产环境的VB_API_KEY是否正确加载(可以在启动时打印出来验证)
  3. 如果用了反向代理(比如Nginx),确保配置里没有修改请求体,并且传递了正确的Content-Type头

内容的提问来源于stack exchange,提问作者Thet Htun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:15:53