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

如何在PHP中按Facebook要求转义Unicode字符生成Webhook签名?

如何在PHP中实现符合Facebook要求的Unicode转义以生成正确的Webhook签名?

Facebook的Webhook验证规则明确:

请注意,我们使用经过Unicode转义(十六进制小写)的负载生成签名。如果直接对解码后的字节计算,会得到不同的签名。例如,字符串äöå应转义为\u00e4\u00f6\u00e5。

你在编写单元测试时遇到的问题,核心是mb_convert_encoding无法实现Facebook要求的仅对非ASCII字符做\uXXXX格式的小写十六进制转义——它是对整个字符串做编码转换,不符合需求。

解决方案

PHP中可以通过json_encode的默认行为实现符合要求的转义:json_encode会自动将非ASCII字符转义为\uXXXX格式的小写十六进制值,完全匹配Facebook的规则。你需要调整单元测试代码,确保计算签名的负载是符合该转义规则的JSON字符串,同时保证请求体与签名计算的负载一致。

修改后的单元测试代码

// 单元测试代码
$content = file_get_contents(__DIR__.'/../Responses/whatsapp_webhook.json');
$content = trim($content);

// 将原始JSON解码为数组,再重新编码为符合Facebook要求的转义格式
$payloadArray = json_decode($content, true);
// 默认参数自动转义非ASCII为\uXXXX小写,同时保持斜杠不转义
$escapedPayload = json_encode($payloadArray, JSON_UNESCAPED_SLASHES);

$secret = config('externals.meta.config.app_secret');

// 基于转义后的JSON字符串计算HMAC签名
$signature = hash_hmac(
    'sha256',
    $escapedPayload,
    $secret
);

// 发送请求时直接使用转义后的JSON字符串作为请求体,确保与签名计算的负载一致
$response = $this->post(
    route('whatsapp.webhook.message'),
    $escapedPayload,
    [
        'CONTENT_TYPE' => 'application/json',
        // Facebook签名格式为"sha256=签名值",需带上前缀
        'X-Hub-Signature-256' => "sha256={$signature}",
    ]
);
$response->assertOk();

关键注意事项

  1. 签名计算的负载必须与请求体一致:Facebook是基于发送给你的原始JSON字符串(已做Unicode转义)计算签名,测试时必须用相同转义规则的字符串计算签名,并作为请求体发送。
  2. 签名格式正确:X-Hub-Signature-256的格式是sha256=签名值,不能省略前缀。
  3. 请求头Content-Type正确:Webhook请求的Content-Type应为application/json,而非text/plain。

你的现有请求验证代码无需修改,因为$request->getContent()会直接获取Facebook发送的原始转义JSON字符串,与签名计算的负载匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 10:25:21