TenDI (Tencent) CAPTCHA
和 CapMonster Cloud

验证码解决方案、网站安装和测试。

TenDI (Tencent)解决方案的定价

验证码
价格 (USD)
$ 1.60
1000 代币
接手一个已经部署 captcha 或其他防护的站点,却无法访问源代码?此时最关心的是使用了哪种方案、配置是否正确以及如何测试。

在本文中,我们尽量回答了所有关键问题。要开始解决问题,第一步是确定当前使用的是哪种防护系统。为此,您可以查看常见验证码与反机器人防护系统列表,其中提供了可视化示例和关键特征,帮助您快速判断自己正在使用哪一种方案。

如果您发现自己的网站使用的是 TenDI (Tencent),下一步就是更深入地了解它的特性和具体工作方式。在本文中,您还可以查看 TenDI (Tencent) 的接入说明,以便彻底弄清它在您的网站上是如何运行的。这样一来,您不仅能更好地理解当前的防护机制,还可以更合理地规划后续的维护和支持。

什么是 TenDI CAPTCHA
什么是 TenDI CAPTCHA
TenDI (Tencent) CAPTCHA 是一个多层次的防机器人系统。它通过分析用户行为和特殊机制验证访问网站的是否为真实用户。用于保护注册、登录、营销活动,防止垃圾信息和数据盗取。
Background
TenDI (Tencent) 示例
Non-perception CAPTCHA
Non-perception CAPTCHA
验证自动完成,无需用户参与。适合对使用体验要求高的场景。
Slider CAPTCHA
Slider CAPTCHA
通过滑块快速简单验证。适用于大多数情况。
Graphic CAPTCHA
Graphic CAPTCHA
用户按顺序点击图像元素。用于高安全场景。
Audio CAPTCHA
Audio CAPTCHA
通过音频验证。适合有特殊需求的用户。
Smart Verification
Smart Verification
系统评估用户行为:可信用户直接放行,可疑用户进行额外验证。
Multi-dimensional Defense
Multi-dimensional Defense
使用多种防护机制:动态加密、防机器人等。

通过 CapMonster Cloud 解决 Tencent CAPTCHA

在测试带 Tencent CAPTCHA 的表单时,经常需要验证验证码工作正常且集成正确。
您可以手动测试网站上的验证码:
  • 打开表单页面并确认验证码显示正常。
  • 尝试在未完成验证码的情况下提交表单 — 服务器应返回错误。
  • 成功完成验证码后,表单应正常提交。
自动识别验证码可使用专用服务,如 CapMonster Cloud — 处理验证码参数并返回可用 token,可直接在表单中使用,无需用户操作。

通过 CapMonster Cloud API 工作的一般流程:

创建任务创建任务
arrow
发送 API 请求发送 API 请求
arrow
获取结果获取结果
arrow
将 token 应用到页面将 token 应用到页面
arrow
使用现成库识别 TenDI (Tencent) CAPTCHA
CapMonster Cloud 提供适用于 PythonJavaScript(Node.js)和 C# 的现成库。
Python
JavaScript
C#
解决、令牌插入和表单提交
Node.js 示例,完成网页上验证码全流程识别。方法:使用 HTTP 请求获取 HTML 和保护系统参数,提交答案并处理结果;或使用自动化工具(如 Playwright)— 打开页面、等待验证、通过 CapMonster Cloud 客户端提交参数、获取结果,将 token 填入表单(测试可使用正确或错误数据),查看结果。

// npx playwright install chromium

import { chromium } from 'playwright';
import { CapMonsterCloudClientFactory, ClientOptions, TenDIRequest } from '@zennolab_com/capmonstercloud-client';

// 替换为自己的值
const API_KEY = "YOUR_API_KEY";         
const WEBSITE_URL = "https://example.com";

async function solveTenDIOnPage() {
    const browser = await chromium.launch({ headless: false });
    const context = await browser.newContext();
    const page = await context.newPage();

    // 1. 打开页面
    await page.goto(WEBSITE_URL, { waitUntil: 'networkidle' });

    // 2. 等待 CAPTCHA 出现(如 input 或 iframe)
    await page.waitForSelector('#tendi_response, iframe[src*="tendi"], input[name="tendi_response"]', { timeout: 15000 });

    // 如有需要,可从页面提取 websiteKey
    const WEBSITE_KEY = await page.evaluate(() => {
        // 示例:sitekey 可能在 data 属性或全局变量中
        const el = document.querySelector('#tendi_response') || document.querySelector('div[data-sitekey]');
        return el?.getAttribute('data-sitekey') || window.TenDI_siteKey || "183268248";
    });

    console.log("Website key detected:", WEBSITE_KEY);

    const client = CapMonsterCloudClientFactory.Create(
        new ClientOptions({ clientKey: API_KEY })
    );

    // 3. 创建 TenDI 任务
    const tenDIRequest = new TenDIRequest({
        websiteURL: page.url(),
        websiteKey: WEBSITE_KEY,
    });

    const balance = await client.getBalance();
    console.log("Balance:", balance);

    // 4. 解决验证码
    const solution = await client.Solve(tenDIRequest);
    console.log("Solution:", solution);

    const { ticket, randstr } = solution.solution.data;

    // 5. 插入解决结果的方法
    await page.evaluate(({ ticket, randstr }) => {
        // 插入 input
        const inputSelectors = ['#tendi_response', 'input[name="tendi_response"]', 'input[type="hidden"]'];
        let inserted = false;
        for (const sel of inputSelectors) {
            const input = document.querySelector(sel);
            if (input) {
                input.value = ticket;
                input.dispatchEvent(new Event('input', { bubbles: true }));
                const form = input.closest('form');
                if (form) form.submit();
                inserted = true;
                break;
            }
        }

        // JS 回调函数
        if (typeof window.onCaptchaSolved === 'function') {
            window.onCaptchaSolved(ticket, randstr);
            inserted = true;
        }

        // 若无 input 和 callback
        if (!inserted) {
            window._tenDITicket = ticket;
            window._tenDIRandStr = randstr;
            console.log("Ticket and randstr saved to window._tenDITicket and window._tenDIRandStr");
        }
    }, { ticket, randstr });

    await page.waitForTimeout(5000);
    await browser.close();
}

solveTenDIOnPage().catch(console.error);
  
如何将 TenDI (Tencent) CAPTCHA 集成到网站
为了了解网站上验证码的工作方式、验证逻辑、重新连接或重新配置,请查看本节。描述了保护机制的集成流程,有助于快速掌握细节。
  • 1. 登录账户或在 Captcha Console 创建新账户。
  • 2. 打开 Verification Management 部分。
  • 3. 创建新验证码(如果尚未创建)。

将获得两个参数:CaptchaAppIdAppSecretKey,用于前端和服务器。

前端集成示例前端集成示例
arrow

集成工作原理

步骤 1: 加载 CAPTCHA JS

脚本需动态加载:

<script src="https://ca.turing.captcha.qcloud.com/TJNCaptcha-global.js"></script>

非标准加载或缓存可能导致 CAPTCHA 运行不正常。

步骤 2: 创建 TencentCaptcha 对象

加载 JS 后出现全局类:

<script src="new TencentCaptcha(domElement, CaptchaAppId, callback, options);"></script>

参数:

domElement - 嵌入 checkbox/iframe 的容器

CaptchaAppId - 您的 ID

callback - 验证完成后的操作

options - 外观设置(可选)

步骤 3: 调用方法 .show()

captcha.show();

显示 CAPTCHA,可多次调用。

步骤 4: 处理结果

Callback 接收对象:


{
  ret: 0,              // 0 -- 成功, 2 -- 用户关闭窗口
  ticket: "...",       // 服务器需要
  randstr: "...",      // 服务器也需要
  errorCode: 1001,     // 如果 CAPTCHA 未加载
  errorMessage: "..."  // 错误文本
}

服务器必须进行二次 ticket 验证。

"灾难恢复模式"

若 CAPTCHA 未加载(如 CDN 不可用),可自动发放“紧急票”,不影响业务流程。

场景:

  • 尝试创建 CAPTCHA → 错误。
  • 调用 loadErrorCallback().
  • 生成 ticket,如:
    trerror_<errorcode>_<appid>_<timestamp>
  • 正常继续处理,服务器识别为紧急票并决定处理方式。

AppId 加密(可选)

如需最高安全,可发送加密版本 AppId,而非明文:

aidEncrypted = Base64(IV + AES256(AppId & timestamp & ttl))

需要:

  • 32 字节密钥 (AppSecretKey → 补齐至 32 字节)
  • AES-256 CBC + PKCS7Padding
  • 16 字节 IV
  • 时间戳和有效期(秒)

服务器端加密示例 (Python)


from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import base64

def encrypt(plaintext, key, iv):
    cipher = AES.new(key, AES.MODE_CBC, iv)
    ciphertext = cipher.encrypt(pad(plaintext.encode(), AES.block_size))
    return base64.b64encode(iv + ciphertext).decode("utf-8")

服务器验证

步骤 1. 配置 API 访问

在密钥管理面板 (CAM / API Key Management) 获取 API 的 SecretIdSecretKey,用于签名请求。

步骤 2. 调用 API DescribeCaptchaResult

客户端返回 ticketrandstr 后,服务器发送请求:

  • Action: DescribeCaptchaResult
  • Version: 2019-07-22 (或当前有效)

参数:

CaptchaType - 9 (固定值)

Ticket - 字符串 — 客户端返回的 ticket

Randstr - 字符串 — 客户端返回的 randstr

CaptchaAppId - 您的 AppId

AppSecretKey - 您的密钥

UserIp - 用户 IP(建议提供)

步骤 3. 处理响应

API 返回:

  • CaptchaCode: integer验证结果
  • 0 (或 OK) — CAPTCHA 通过,ticket 有效

如果 CaptchaCode === OK,用户视为通过验证,否则拒绝。

示例 — Node.js 验证 ticket


import { v20190722 as captcha } from "@tencentcloud/tencentcloud-sdk-nodejs";
const client = new captcha.Client({
  credential: {
    secretId: "YOUR_SECRET_ID",
    secretKey: "YOUR_SECRET_KEY"
  },
  region: "ap-project", // 如果需要,指定地区
});

async function verifyCaptcha(ticket, randstr, userIp) {
  const params = {
    CaptchaType: 9,
    Ticket: ticket,
    Randstr: randstr,
    CaptchaAppId: YOUR_APP_ID,
    AppSecretKey: "YOUR_APP_SECRET_KEY",
    UserIp: userIp
  };

  const resp = await client.DescribeCaptchaResult(params);
  const code = resp.Response.CaptchaCode;
  return code === 0;
}
HelpIcon

关于将 Tencent CAPTCHA 集成到网站的更多信息,请参考 官方文档

Background
可能的错误与调试
Bug Icon
验证码未加载
(错误 1001、1002 或无效签名提示) — 原因可能是请求参数不正确。请确保 CaptchaAppIdAppSecretKey 以及所有请求参数均填写正确。
Bug Icon
ticket/randstr 无效或为空
确保客户端正确传递了两个参数。
Bug Icon
解决超时
增加服务器端等待时间。
验证防护的可靠性
连接后,确保防护正常工作非常重要。
安全与优化建议
仅在服务器存储 <span class="font-bold">AppSecretKey</span>,不要发送到浏览器或嵌入 JS 代码中。
记录完整 Tencent CAPTCHA 响应,包括错误码、请求时间及验证参数 — 有助于快速诊断问题。
所有参数传输使用 HTTPS <span class="font-bold">(ticket, randstr)</span>,防止篡改。
在页面上放置正确的 <span class="font-bold">隐私政策</span> 和 <span class="font-bold">Tencent 使用条款</span> 链接,符合授权要求。
结论

如果你接手了一个已经集成了验证码或其他防护系统的网站,但又无法访问其代码,也不用担心!要判断实际使用了哪种技术其实并不难。为了核实其是否正常工作,你可以在隔离的测试环境中使用CapMonster Cloud识别服务,确保令牌处理机制和校验逻辑都运行正常。

对于TenDI (Tencent),只需识别出所用的系统,观察其行为,并确认防护是否正常工作即可。本文演示了如何识别 TenDI (Tencent),以及到哪里查找其接入或重新配置的说明文档,从而帮助你自信地维护防护方案并掌控其运行情况。

Conclusion

关于 TenDI (Tencent) CAPTCHA 的常见问题

TenDI 提供多种挑战类型,以适应不同的风险级别和用户体验需求。

  • Non-Perception — 在后台静默运行,实现低摩擦验证。
  • Slider — 使用拖拽拼图进行标准可见验证。
  • Graphic — 要求用户点击特定图形,适用于较高风险流量。
  • Audio — 为视觉挑战提供无障碍替代方案。
  • Smart Verification — 让可信用户静默通过,仅对可疑会话显示挑战。

TenDI 还包含 Multi-dimensional Defense,即 10 种后台保护机制,可提高抗机器人能力。对于 CapMonster Cloud,无论页面上显示何种挑战,请始终使用 type: CustomTaskclass: "TenDI"。更多 API 详情请参阅 此处

客户端返回 ticketrandstr 后,服务器必须通过调用腾讯 DescribeCaptchaResult API 进行验证。要验证 ticket,请发送包含以下参数的已签名 API 请求:

  • CaptchaType: 9
  • Ticket: 客户端返回的 ticket
  • Randstr: 客户端返回的 randstr
  • CaptchaAppId: 您的 AppId
  • AppSecretKey: 您的 captcha 密钥
  • UserIp: 用户 IP 地址(推荐)

服务器还需要腾讯云 API 凭证(SecretIdSecretKey)来签署请求。

检查响应中的 CaptchaCode 值:

  • 0OK: captcha 通过,ticket 有效
  • 任何其他值: 验证失败,应拒绝请求
  • 切勿在前端代码中暴露 AppSecretKey
  • 在服务器端使用腾讯加密的 CaptchaAppId 流程。在后端生成加密值并发送给客户端。
  • CAPTCHA 解决后,将客户端的 ticketrandstr 发送到后端,通过 DescribeCaptchaResult API 验证。
  • 将所有密钥和验证逻辑保留在后端。

分步设置请参阅本页上方的 如何将 TenDI (Tencent) CAPTCHA 集成到网站

在腾讯客户端集成流程中,TenDI 支持可选参数 aidEncrypted,用于在 widget 初始化时替换明文 CaptchaAppId

aidEncrypted 的生成方式如下:aidEncrypted = Base64(IV + ciphertext)

ciphertext 是对包含 AppId、当前 Unix 时间戳和 ttl(过期时间,秒)的字符串进行加密的结果。加密使用 AES-256-CBCPKCS7 填充。

每个请求生成随机 16 字节 IV,并置于加密输出之前。

最终二进制值经 Base64 编码后作为 aidEncrypted 传递给 widget。

如果腾讯 CAPTCHA 脚本无法加载或初始化,TenDI Disaster Recovery 模式允许用户流程继续,而不是阻塞请求。

  • 当 CAPTCHA JavaScript 无法加载或启动时(例如因网络或 CDN 问题),调用 loadErrorCallback()
  • 这将创建格式为 trerror_<errorcode>_<CaptchaAppId>_<timestamp> 的灾难恢复 ticket。
  • ticket 通过正常回调流程返回,ret: 0(成功)。
  • 在服务器端,不要仅凭 ret: 0 视为正常成功。还需检查 ticket 前缀(trerror_)和 errorCode = 1001 以检测灾难恢复模式。

为确保可靠运行,请在加载 CAPTCHA 脚本之前定义错误处理程序,并在 JS 加载错误时调用它。