tencent cloud

接入相关
最后更新时间:2025-10-24 14:12:47
接入相关
最后更新时间: 2025-10-24 14:12:47

不规范接入问题

未动态加载验证码 JS 会产生哪些问题?

1. 接入方式:Web/App 客户端接入验证码时,没有采用动态加载 JS 的方式,而是通过其他手段规避加载。
2. 安全风险:以上接入方式会导致验证码无法正常更新,对抗能力无法保证,甚至引起误拦截及前端报错。
3. 解决方案:动态引入验证码 JS,详情请参见 Web客户端接入

未接入票据校验会产生哪些问题?

1. 接入方式:仅客户端接入了验证码,服务端未接入票据校验。
2. 安全风险:未接入票据校验,会导致黑产轻易伪造验证结果,失去验证码人机对抗效果。
3. 解决方案:服务端完成票据校验接入,详情请参见 接入票据校验(Web 及 App)

跨端框架(React-Native,Flutter等)WebView 接入问题

为何在开发测试中频繁触发风控拦截?

当 WebView 组件使用内嵌 HTML 内容时,由于没有明确的域名来源,浏览器会将其视为 null 或 file:// 协议。这会导致风控系统将此类设备上报为异常设备。在使用内嵌 HTML 时,建议通过设置 baseUrl 来指定一个合法的域名来源。 配置示例如下:
<WebView
source={{
html: captchaHtml,// html 字符串模板
baseUrl: 'https://ca.turing.captcha.qcloud.com' // 使用腾讯验证码的域名作为 baseUrl
}}
....// 其他必要配置
/>

Web/App 客户端接入问题

测试过程中,提示“您的操作过于频繁,请稍后再试”,该如何解决?

这是验证码服务拦截疑似恶意用户的表现。可能是用户在同一网络环境下高频集中地访问同一场景的验证码服务,导致的小规模风控拦截。解决方法如下:
等待10 - 20分钟后重新进行测试。
尝试更换 IP 或 设备再体验。
登录 验证码控制台,进入验证“安全配置”,将恶意拦截等级调至“体验优先”。

Android 使用 Web 前端 H5 方式进行接入,调试过程中先弹出空白背景,后弹出验证码页面如何调整?

调试过程中,正常情况下会首先调起 WebView 加载网页,然后弹出验证码页面。
如果出现先弹出空白背景,后弹出图形验证页面的现象。形成原因如下:
加载验证码 js 的时间导致白屏。
空白层形成原因是页面没有内容时,加载的 WebView 就显示出来,需要等待 ready 事件触发后再进行 webview 展示。
因此,Android 需要先加载页面但不进行展示,等待 ready 回调后,再通知 Android 进行展示。ready 配置说明,请参见 Web 客户端接入-创建验证码对象 文档。
options={ready: function(size){
// 与Android通信
}}
new TencentCaptcha(appId, callback, options);

App客户端接入验证码显示不完整如何调整?

验证码根据容器宽高进行居中显示,验证码显示不完整可能由于容器本身设置较宽,导致展示的验证码被截断,该情况需要对客户端的弹框进行调整。此外随意加载其他 WebView 都可能会出现截断的情况。

验证码域名被某运营商屏蔽怎么办?

说明:
当验证码主域名被某运营商屏蔽后,您可以采用动态请求 JS-SDK 方法判断从而请求我们的备份域名。
<!doctype html>
<html lang="en">

<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Web Domain Name Switching Demo</title>
</head>

<body>
<div id="cap_frame"></div>
</body>
<script>
// Maximum time to load script
const MAX_SCRIPT_LOAD_TIME = 10000;
/**
* load script promise
* @param {object} config
*/
function loadScriptPromise(config) {
return new Promise((resolve, reject) => {
loadScript(config, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
});
}
/**
* error callback
* @param {string} captchaAppid
*/
function errorCallback(captchaAppid) {
// error ticket
const ticket = `trerror_1001_${captchaAppid}_${Math.floor(new Date().getTime() / 1000)}`;
const result = {
ret: -1,
randstr: `@${Math.random().toString(36).substr(2)}`,
ticket,
errorCode: 1001,
errorMessage: 'jsload_error',
};
console.log(result);
}
/**
* success callback
* @param {object} result
*/
function globalCallback(result) {
console.log(result);
}

/**
* dynamic load script
* @param {object} src timeout
* @param {function} cb
*/
function loadScript({ src, timeout = MAX_SCRIPT_LOAD_TIME }, cb) {
const startTime = Date.now();
const script = document.createElement('script');
script.async = true;
script.src = src;
let finished = false;
const cleanup = () => {
if (script.parentNode) {
script.parentNode.removeChild(script);
}
script.onload = null;
script.onerror = null;
};
const executeCallback = (err, result) => {
if (finished) return;
finished = true;
clearTimeout(timer);
cleanup();
cb(err, result);
};
var timer = setTimeout(() => {
executeCallback(new Error('Script load timeout'));
}, timeout);

script.onload = () => {
const cost = Date.now() - startTime;
executeCallback(null, cost);
};
script.onerror = () => {
executeCallback(new Error('Script load error'));
};
document.head.appendChild(script);
}
/**
* use captcha sdk
* @param {string} appid
*/
function useCaptcha(appid) {
const captcha = new TencentCaptcha(
document.getElementById('cap_frame'),
appid,
globalCallback,
{},
);
captcha.show();
}
/**
* load captcha sdk
* @param {string} appid
*/
async function loadCaptchaSDK(appid) {
const MAX_SCRIPT_LOAD_TIME = 10000;
const cdnUrls = [
'https://ca.turing.captcha.qcloud.com/TJNCaptcha-global.js',
'https://www.tycaptcha.com/TJNCaptcha-global.js',
];
for (const [index, src] of cdnUrls.entries()) {
try {
console.log(`Trying Domain ${index + 1}: ${src}`);
await loadScriptPromise({ src, timeout: MAX_SCRIPT_LOAD_TIME });
console.log(`Domain ${index + 1} Load Success`);
return useCaptcha(appid);
} catch (error) {
console.warn(`Domain ${index + 1} Load Failed:`, error.message);
if (index === cdnUrls.length - 1) {
console.error('All Domains Load Failed');
return errorCallback(appid);
}
}
}
}
loadCaptchaSDK('Yours CaptchaAppid').catch(console.error);
</script>
</html>

服务端接入问题

核查验证码票据接口返回值都包含哪些风险类型?

EvilBitmap 字段说明

EvilBitmap 为十进制 int 类型数值,使用时需转为二进制数值,每个二进制位代表了一种风控拦截策略大类。
二进制位
风控拦截策略大类
示例
0
秒拨代理 IP 异常

EvilBitmap 返回34,转为二进制值为100010,其二进制位1/5为1,说明对应的风控拦截策略为:IP 短时聚集异常 + 数据参数异常。
1
IP 短时聚集异常(短时间内多次发起验证)
2
CaptchaAppId + IP 短时聚集异常(短时间内多次发起验证)
3
CaptchaAppId + IP + 设备短时聚集异常(短时间内多次发起验证)
4
流量特征异常(例如 TCP 协议栈信息异常)
5
数据参数异常(例如 浏览器参数异常)
6
蜜罐异常(执行了不该执行的逻辑)
7
行为聚类异常

DeviceRiskCategory 字段说明

编码
风险类型
风险类型描述
101
综合评分风险
-
102
模拟鼠标轨迹风险
疑似机器模拟鼠标轨迹(仅适用于浏览器)
201
恶意请求风险
疑似使用工具发起恶意请求
301
模拟器风险
疑似使用模拟器
401
设备篡改风险
疑似篡改设备硬件信息
501
疑似黑产风险
疑似使用黑灰产设备
601
行为风险
疑似使用自动化操作
701
浏览器风险
疑似浏览器被篡改

本页内容是否解决了您的问题?
您也可以 联系销售 提交工单 以寻求帮助。

文档反馈