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

PHP中Telegram小程序数据验证失败问题排查

问题

在PHP中实现Telegram小程序数据验证函数时,验证始终返回false。使用相同的bot token,传入指定参数调用validate_telegram_data时,计算出的哈希值与接收的哈希值不一致:

  • 接收哈希:1540cf7e36ebbadfe7faea9f20ccc68431cb24e1d106f860d27a560309f1ca3b
  • 计算哈希:493b5e631f8aae6061e9079b961506c07f61a3fb4b31810ad26b01b9b1cfaadb

实现代码:

function hmac_sha256($key, $data) {
    return hash_hmac('sha256', $data, $key, true);
}

function validate_telegram_data($received_data) {
    
    global $bot_token;
    parse_str($received_data, $data);
    ksort($data);
    $received_hash = $data['hash'];
    
    unset($data['hash']);
    $data_check_string = '';
    foreach ($data as $key => $value) {
        $data_check_string .= $key . '=' . $value . "\n";
    }
    
    // print_r($data_check_string);
    $secret_key = hmac_sha256($bot_token, "WebAppData");
    $computed_hash = bin2hex(hmac_sha256($secret_key, $data_check_string));
    
    // print_r([$received_hash, $computed_hash]);
    
    if (hash_equals($computed_hash, $received_hash)) {
        if (isset($data['auth_date']) && (time() - intval($data['auth_date'])) < 86400) {
            return true;
        }
    }
    return false;
}

调用代码:

validate_telegram_data('query_id=AAGohX8eAwAAAKiFfx7ierlk&user=%7B%22id%22%3A6954124712%2C%22first_name%22%3A%22Socilizer%20Support%22%2C%22last_name%22%3A%22%22%2C%22username%22%3A%22socilizer_support%22%2C%22language_code%22%3A%22en%22%2C%22allows_write_to_pm%22%3Atrue%7D&auth_date=1725191023&hash=1540cf7e36ebbadfe7faea9f20ccc68431cb24e1d106f860d27a560309f1ca3b');  // 返回false,原因?

问题排查与修复

核心问题点

  1. HTML转义字符污染代码
    你提供的代码中存在大量HTML转义字符(如=&gt;、&quot;、&amp;&amp;、&lt;),这些字符会被PHP解析为字符串的一部分,而非正确的语法符号或字符串内容:

    • $key =&gt; $value会被解析为错误的赋值语句,而非foreach循环的键值对语法
    • &quot;WebAppData&quot;会被当成带双引号的字符串"WebAppData",而Telegram要求的是不带引号的WebAppData
  2. 换行符格式错误
    Telegram要求拼接data_check_string时,每个键值对后必须添加单个换行符(\n),而你代码中使用的是实际换行(而非转义字符\n),在不同操作系统下可能会生成\r\n(Windows),导致哈希计算不匹配。

修正后的代码

function hmac_sha256($key, $data) {
    return hash_hmac('sha256', $data, $key, true);
}

function validate_telegram_data($received_data) {
    global $bot_token;
    
    // 解析URL参数,提前判断哈希是否存在
    parse_str($received_data, $data);
    if (!isset($data['hash'])) {
        return false;
    }
    
    // 按字典序排序参数
    ksort($data);
    $received_hash = $data['hash'];
    unset($data['hash']);
    
    // 生成符合Telegram要求的校验字符串
    $data_check_string = '';
    foreach ($data as $key => $value) {
        $data_check_string .= "{$key}={$value}\n";
    }
    
    // 生成Telegram指定的密钥
    $secret_key = hmac_sha256($bot_token, "WebAppData");
    // 计算并转换为十六进制哈希
    $computed_hash = bin2hex(hmac_sha256($secret_key, $data_check_string));
    
    // 安全比较哈希,同时校验数据有效期
    if (hash_equals($computed_hash, $received_hash)) {
        if (isset($data['auth_date']) && (time() - intval($data['auth_date'])) < 86400) {
            return true;
        }
    }
    return false;
}

额外注意事项

  • 确保$bot_token变量已正确定义,且与Telegram Bot的Token完全一致(无多余空格或符号)
  • parse_str会自动解码URL编码的参数,无需额外处理user字段
  • 使用hash_equals而非普通字符串比较,避免时序攻击

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 23:58:22