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

Vercel部署的NextJS端点调用WhatsApp API出现504超时错误

问题分析与解决方案

核心原因

你遇到的504超时问题,本质是WhatsApp Webhook的响应超时要求与当前代码同步处理逻辑的冲突:

  • WhatsApp要求Webhook端点必须在10秒内返回响应,否则会重复发送请求;
  • 你的代码在处理POST请求时,会先执行generateResponse和调用Facebook API这两个异步操作,再返回200响应。如果这两个操作的总耗时接近或超过10秒,Vercel的Serverless Function会触发超时,同时WhatsApp会不断重试,导致大量504日志。

代码层面修复(优先解决)

1. 立即返回响应,异步处理消息逻辑

修改POST请求的处理流程,先给WhatsApp返回200确认,再后台异步处理回复操作:

import type { NextApiRequest, NextApiResponse } from 'next'
import axios from 'axios'

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  if (req.method === 'GET') {
    const mode = req.query['hub.mode']
    const challenge = req.query['hub.challenge']
    const token = req.query['hub.verify_token']

    if (mode && token) {
      if (mode === 'subscribe' && token === myToken) {
        res.status(200).send(challenge)
      } else {
        // 修复:添加end()避免请求挂起
        res.status(403).end()
      }
    } else {
      // 补充分支:无mode或token时返回403
      res.status(403).end()
    }
  } else if (req.method === 'POST') {
    const body = req.body
    if (!secretKey) {
      return res.status(404).json({ message: 'No Secret Key Provided' })
    }

    if (body.object && 
        body.entry?.[0].changes?.[0].value.messages?.[0]) {
      // 先立即返回200,确认收到请求
      res.status(200).end()

      // 异步处理消息回复,不阻塞响应
      (async () => {
        try {
          const phoneId = body.entry[0].changes[0].value.metadata.phone_number_id
          const from = body.entry[0].changes[0].value.messages[0].from
          const msg_body = body.entry[0].changes[0].value.messages[0].text.body

          const response = await generateResponse(msg_body)
          await axios({
            method: 'post',
            url: `https://graph.facebook.com/v17.0/${phoneId}/messages`,
            headers: {
              'Content-Type': 'application/json',
              Authorization: `Bearer ${accessToken}`,
            },
            data: {
              messaging_product: 'whatsapp',
              to: from,
              text: { body: response },
            },
          })
        } catch (err) {
          console.error('消息处理失败:', err)
        }
      })()
    } else {
      res.status(404).end()
    }
  } else {
    res.status(404).end()
  }
}

2. 修复GET请求的遗漏分支

原GET请求中,当mode或token不存在时,没有返回响应,会导致请求挂起,引发超时。需要补充else分支返回403并结束请求。

3. 添加消息去重

WhatsApp会因超时重复发送相同消息,建议用Vercel KV或Redis存储已处理的消息ID,避免重复回复:

// 处理消息前检查是否已处理过
const msgId = body.entry[0].changes[0].value.messages[0].id
const isProcessed = await kv.get(`processed:${msgId}`)
if (isProcessed) return

// 处理完成后标记已处理
await kv.set(`processed:${msgId}`, 'true', { ex: 86400 }) // 24小时过期

Vercel配置层面调整

1. 调整函数超时时间

Vercel Serverless Functions默认超时10秒,可在vercel.json中调整到最大60秒(但核心还是异步处理,因为WhatsApp只等10秒):

{
  "functions": {
    "pages/api/your-endpoint.ts": {
      "maxDuration": 60
    }
  }
}

2. 使用Edge Functions

Edge Functions启动更快,超时时间30秒,适合处理Webhook。只需在函数顶部添加:

export const config = {
  runtime: 'edge',
}

3. 检查环境变量

确保myToken、secretKey、accessToken等环境变量在Vercel控制台正确配置,没有未定义的情况导致代码异常。


内容的提问来源于stack exchange,提问作者Ben Shekhtman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 21:14:54