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

使用WhatsApp Business API无法为WABA订阅Webhooks求助

WhatsApp嵌入式注册流程中Webhook订阅失败的问题排查与解决

问题背景

已完成WhatsApp技术提供商验证,实现嵌入式注册流程,以下步骤均正常执行:

  • 交换令牌获取系统用户访问令牌
  • 通过Graph API获取WABA ID
  • 通过Graph API获取手机号ID
  • 通过Graph API注册手机号

但执行订阅Webhook通知步骤时,抛出如下异常:

Unsupported post request. Object with ID '475530585635833' does not exist, cannot be loaded due to missing permissions, or does not support this operation. Please read the Graph API documentation at https://developers.facebook.com/docs/graph-api

相关代码

请求执行顺序

// 1. Obtain exchanged token
const exchangedToken = await this.exchangeFacebookCode(code);console.log("exchangedToken:", exchangedToken);
// 2. Obtain WABA ID
const wabaId = await this.fetchWABA(exchangedToken);
console.log("wabaId:", wabaId);
// 3. Obtain Phone Number ID
const number = await this.fetchPhoneNumber(exchangedToken, wabaId);
console.log("number:", number);
// 4. Register Phone Number
await this.registerPhoneNumber(exchangedToken, number.id);
// 5. Subscribe to Webhook
await this.subscribeToWebhook(exchangedToken, wabaId);
return { id: number.id, number: number.display_phone_number};

方法实现

private async exchangeFacebookCode(code: string): Promise<string> {
const appId = "**********";
const appSecret = "**********";
try {
const response = await firstValueFrom(this.httpService.get(`https://graph.facebook.com/v12.0/oauth/access_token?client_id=${appId}&client_secret=${appSecret}&code=${code}`));
            console.log(JSON.stringify(response.data));
            const { access_token: token } = response.data;
            return token;
        } catch (e) {
            console.log("error:", e);
            return undefined;
        }
    }

    private async fetchWABA(token: string): Promise<string> {
        try {
            const observable = this.httpService.get(`https://graph.facebook.com/v21.0/debug_token?input_token=${token}`, {
                headers: {
                    "Authorization": `Bearer ${token}`
                }
            });
            const response = await lastValueFrom(observable);
            const { data } = response.data;
            console.log("WABA response:", JSON.stringify(response.data));
            const { granular_scopes: scopes } = data;
            const scope = (scopes as any[]).find(scope => scope.scope === "whatsapp_business_management");
            return scope.target_ids[0];
        } catch (e) {
            console.log("error:", e);
            return undefined;
        }
    }

    private async fetchPhoneNumber(token: string, wabaId: string): Promise<any> {
        try {
            const observable = this.httpService.get(`https://graph.facebook.com/v21.0/${wabaId}/phone_numbers?access_token=${token}`);
            const response = await lastValueFrom(observable);
            console.log("PhoneNumber ID response:", response.data);
            const { data } = response.data;
            const phoneNumber = data as any[];
            return phoneNumber && phoneNumber.length > 0 && phoneNumber[0];
        } catch (e) {
            console.log("Error during fetch phone number:", e.response.data);
        }
    }

    private async registerPhoneNumber(token: string, phoneNumberId: string): Promise<void> {
        try {
            const observable = this.httpService.post(`https://graph.facebook.com/v21.0/${phoneNumberId}/register`, {
                messaging_product: "whatsapp",
                pin: "123456"
            }, {
                headers: {
                    "Authorization": `Bearer ${token}`,
                }
            });
            const response = await lastValueFrom(observable);
            console.log("Register response:", response.data);
        } catch (e) {
            console.log("Error during phone registration:", e);
        }
    }

    private async subscribeToWebhook(token: string, wabaId: string): Promise<void> {
        try {
            const observable = this.httpService.post(`https://graph.facebook.com/v21.0/${wabaId}/subscribed_apps`, {
                headers: {
                    "Authorization": `Bearer ${token}`
                }
            });
            const response = await lastValueFrom(observable);
            console.log("Subscription response:", response.data);
        } catch (e) {
            console.log("Error during webhook subscription:", e.response.data);
        }
    }

问题分析与解决办法

核心问题:请求参数结构错误

subscribeToWebhook方法中,Axios的post参数顺序为url, data, config,但你把headers放到了第二个参数(data位置),导致请求体格式错误,同时缺少必填的messaging_product参数,这是引发错误的主要原因。

修正后的代码

private async subscribeToWebhook(token: string, wabaId: string): Promise<void> {
    try {
        const observable = this.httpService.post(
            `https://graph.facebook.com/v21.0/${wabaId}/subscribed_apps`,
            { messaging_product: "whatsapp" }, // 必须的请求体参数
            {
                headers: {
                    "Authorization": `Bearer ${token}`
                }
            }
        );
        const response = await lastValueFrom(observable);
        console.log("Subscription response:", response.data);
    } catch (e) {
        console.log("Error during webhook subscription:", e.response.data);
    }
}

额外排查点

  1. 令牌权限验证:确保交换得到的系统用户令牌拥有whatsapp_business_management权限,且该权限的目标ID与使用的WABA ID一致。
  2. WABA ID有效性:确认WABA ID存在、状态正常,未被Facebook封禁或限制。
  3. API版本一致性:exchangeFacebookCode用了v12.0,其他接口用了v21.0,建议统一使用最新稳定版本(如v21.0),避免版本兼容问题。

替代方案

如果API调用仍无法解决,可通过Facebook Business Manager手动配置Webhook:

  1. 登录Facebook Business Manager,进入对应WhatsApp账户的设置页面。
  2. 找到「Webhook」配置选项,点击「编辑」。
  3. 输入你的Webhook URL,完成验证步骤。
  4. 选择需要订阅的事件(如消息、状态更新等),并关联对应的WABA账户。

内容的提问来源于stack exchange,提问作者Aftab Baig

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 15:09:57