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

如何用PHP实现Telegram WebApp Bot文档中的验证逻辑?

Telegram 数据验证的PHP正确实现方法

你的代码验证失败,核心问题是没遵循Telegram官方的字符串拼接规则和密钥生成逻辑,以下分两种常见场景给出正确实现:


场景1:Telegram Web App 用户数据验证

这是前端调用Telegram Web App后,后端验证用户数据合法性的场景:

<?php
// 替换为你的机器人令牌
$bot_token = '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11';

// 从请求中获取Telegram传递的参数(比如从GET的init_data解析)
$init_data = $_GET;
$telegram_hash = $init_data['hash'];
unset($init_data['hash']);

// 1. 按键名字典序升序排序参数
ksort($init_data);

// 2. 拼接成「key=value」格式,用换行符连接
$data_check_string = '';
foreach ($init_data as $key => $value) {
    $data_check_string .= "$key=$value\n";
}
// 移除最后一个多余的换行符
$data_check_string = rtrim($data_check_string, "\n");

// 3. 生成验证专用密钥
$secret_key = hash_hmac('sha256', 'WebAppData', $bot_token, true);

// 4. 计算待验证的哈希值(二进制结果)
$computed_hash = hash_hmac('sha256', $data_check_string, $secret_key, true);

// 5. 解码Telegram返回的hash(base64url转标准base64)
$telegram_hash_bin = base64_decode(strtr($telegram_hash, '-_', '+/'));

// 6. 安全对比哈希(避免时序攻击)
if (hash_equals($computed_hash, $telegram_hash_bin)) {
    echo "验证通过";
} else {
    echo "验证失败";
}
?>

关键注意点:

  • 必须用hash_equals()做对比,不能直接用==,防止时序攻击
  • Telegram返回的hash是base64url编码,需要替换-为+、_为/后再解码
  • 参数必须严格按字典序升序排序,拼接时每个key=value后加换行,最后一个无换行
  • 验证密钥是基于WebAppData字符串和bot token生成的HMAC结果,不是直接用bot token

场景2:Telegram Webhook 请求验证

这是后端接收Telegram推送消息时,验证请求合法性的场景:

<?php
$bot_token = '你的机器人令牌';
// 如果你设置了Webhook的Secret Token,直接对比请求头即可(推荐)
$secret_token = '你设置的Webhook Secret Token';

// 方式1:使用Secret Token验证(最简单)
$received_secret = $_SERVER['HTTP_X_TELEGRAM_BOT_API_SECRET_TOKEN'] ?? '';
if ($received_secret === $secret_token) {
    echo "验证通过";
} else {
    echo "验证失败";
}

// 方式2:无Secret Token时,用签名验证
$received_signature = $_SERVER['HTTP_X_TELEGRAM_BOT_API_SIGNATURE'] ?? '';
if (str_starts_with($received_signature, 'sha256=')) {
    $received_hash = substr($received_signature, 7);
    $request_body = file_get_contents('php://input');
    $computed_hash = hash_hmac('sha256', $request_body, $bot_token);
    
    if (hash_equals($computed_hash, $received_hash)) {
        echo "验证通过";
    } else {
        echo "验证失败";
    }
} else {
    echo "验证失败";
}
?>

你之前代码的问题总结:

  1. 没有按Telegram要求的规则拼接待签名字符串(缺排序、缺key=value格式、缺换行连接)
  2. 密钥生成不符合规则(Web App场景下不是直接用bot token)
  3. 未正确处理Telegram返回的hash编码格式

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 00:05:21