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

如何通过WhatsApp API创建动态列表?Node.js+WATI开发问题排查

问题背景
  • 开发场景:基于Node.js开发WhatsApp聊天机器人,选用WATI作为WhatsApp API服务提供商
  • 实现目标:封装列表类交互消息发送方法,无需每次硬编码列表行标题,仅传入标题数组即可自动生成符合格式要求的rows字段,单条row的目标格式为{"title":"对应行标题"}
  • 故障表现:封装完成的方法调用后,列表消息未成功发送,且未返回明确报错信息
  • 运行截图:程序运行输出截图
现有问题代码

server.js

// packages
const express = require('express');
require('dotenv').config("./env");
const WA = require('./whatsapp.js');
const cors = require('cors');

const webApp = express();

webApp.use(express.json());
webApp.use(cors());

// Route for WhatsApp
webApp.post('/whatsapp', async (req, res) => {
    var data = ['row 1', 'row 2']
    WA.sendListInteractive(data, whatsapp_number)
    res.end();
});

webApp.listen(process.env.PORT, () => {
    console.log(`Server is up and running at ${process.env.PORT}`);
});

whatsapp.js

const sendListInteractive = async (data, senderID) => {
    data = []
    var options = {
        'method': 'POST',
        'url': 'https://' + process.env.URL + '/api/v1/sendInteractiveListMessage?whatsappNumber=' + senderID,
        'headers': {
            'Authorization': process.env.API,
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            "header": "", //optional
            "body": "Body",
            "footer": "", //optional
            "buttonText": "Button Text",
            "sections": [
                {
                    "title": "string",
                    "rows": [
                        data.forEach(
                            e => {
                                {
                                    "title :" + e
                                }
                            }
                        )
                    ]
                }
            ]
        })

    };
    request(options, function (error, response) {
        if (error) console.log(error);
        console.log(response.body);
    });
}
问题排查与修复方案

按代码执行顺序,共有5处核心问题,逐一修复即可正常发送消息:

  • 入参被意外清空
    问题:sendListInteractive方法第一行写了data = [],直接把外部传入的标题数组重置为空数组,后续遍历拿不到任何传入的行数据
    修复:直接删除这行覆盖入参的代码
  • rows字段生成逻辑完全错误
    问题:forEach方法本身没有返回值,且代码中写的"title :" + e既不是合法对象,键名还多打了空格,最终生成的rows是全空的无效数组,完全不符合接口要求
    修复:改用map方法遍历数组,返回结构合法的对象,正确写法为data.map(e => ({ title: e }))
  • 请求回调无法捕获接口参数错误
    问题:现有回调仅判断了网络请求层的error,没有校验HTTP状态码,也没有把返回的字符串格式body解析为JSON,WATI接口的参数校验错误不会触发request层的error,只会在响应体里返回错误码,现有逻辑拿不到真实报错
    修复:回调中增加HTTP状态码判断,对响应体做JSON解析,方便定位参数问题
  • 请求参数不符合WATI接口规范
    问题:header、footer字段传空字符串会被接口判定为无效参数,不需要时直接删除字段即可;sections下的title不能传无意义的"string",需填写实际的分组名称;另外要确认Authorization头格式为Bearer <你的API密钥>,漏写Bearer 前缀会导致鉴权失败但无明确提示
  • 接收方号码变量未定义、方法未正确导出
    问题:server.js路由中直接使用了未声明的whatsapp_number变量,实际接收方号码需要从WhatsApp webhook的请求体中解析获取,传空值会导致请求地址无效;同时whatsapp.js未导出写好的方法,外部引用时会拿到undefined
    修复:从req.body中解析出发送消息的用户手机号再传入发送方法,补全模块导出逻辑

修复后参考代码

whatsapp.js 修复版

const request = require('request'); // 确认已安装并引入request依赖

const sendListInteractive = async (data, senderID) => {
    const options = {
        method: 'POST',
        url: `https://${process.env.URL}/api/v1/sendInteractiveListMessage?whatsappNumber=${senderID}`,
        headers: {
            Authorization: `Bearer ${process.env.API}`, // 补全Bearer鉴权前缀
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            // 移除无内容的空header、footer字段
            body: "请选择选项",
            buttonText: "点击选择",
            sections: [
                {
                    title: "选项列表", // 替换为实际业务分组名称
                    rows: data.map(e => ({ title: e })) // 用map生成符合格式的rows数组
                }
            ]
        })
    };

    request(options, function (error, response) {
        if (error) {
            console.log('网络请求错误:', error);
            return;
        }
        // 打印完整响应信息方便排查
        console.log('HTTP状态码:', response.statusCode);
        console.log('接口返回内容:', JSON.parse(response.body));
    });
}

module.exports = { sendListInteractive }; // 补全方法导出

server.js 路由修复版

webApp.post('/whatsapp', async (req, res) => {
    const data = ['row 1', 'row 2'];
    // 从WATI webhook回调体中取用户手机号,字段名可根据实际回调结构调整
    const whatsappNumber = req.body.waId || req.body.sender;
    if (whatsappNumber) {
        WA.sendListInteractive(data, whatsappNumber);
    }
    res.end();
});

内容的提问来源于stack exchange,提问作者Dummy Cron

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 11:24:15