# 星辉数盾人机验证 BitCaptcha 接入文档(完整)

人机验证 BitCaptcha 是星辉数盾(星辉数智旗下)的人机验证服务:前端拿一次性凭证,后端核销放行。四端一份 SDK。本文件为纯文本 Markdown,便于 AI 读取;对应 SDK 0.6.2,更新于 2026-09-22。

---

## 快速接入

三步接上一个登录 / 注册 / 下单的人机验证:

1. 在控制台(/console/)注册,拿到站点的 captcha_id(客户端用)与 secret_key(只放后端)。
2. 前端引入 SDK,用户通过后在 onVerify 拿到 validate,随业务请求提交。
3. 后端带 secret_key 调核销接口,result:true 才放行。

```html
<div id="captcha"></div>
<script src="https://shudun.bitbeam.cn/sdk/bitcaptcha.min.js"></script>
<script>
  BitCaptcha.init({
    element: '#captcha',
    captchaId: 'YOUR_CAPTCHA_ID',
    onVerify(err, data) {
      if (!err) submitLogin({ captcha: data.validate }) // data.validate 交给后端核销
    }
  })
</script>
```

前端"通过"不代表安全——必须在后端用 secret_key 核销 validate,通过才放行。

---

## 工作原理与凭证模型

三个角色:客户端(网页 / 小程序 / App)展示拼图并拿到一次性凭证 validate;你的业务后端带 secret_key 核销凭证;星辉数盾服务出题、判定、签发凭证。

- captcha_id:客户端。站点标识,24 位十六进制。泄露无害,配合 Origin 白名单可防盗用。
- secret_key:仅业务后端。核销凭证用,48 位十六进制。可在控制台轮换,轮换后旧 key 立即失效。
- validate:客户端 → 业务后端。一次性通过凭证(带签名与过期时间),约 120 字符。
- token:SDK 内部。一道题的标识,2 分钟过期,只能校验一次,业务侧无需关心。

---

## 服务端二次校验

这一步必须做,而且只能在你的服务器上做。只有核销成功才放行业务。

请求:POST https://shudun.bitbeam.cn/api/v1/captcha/verify,Content-Type: application/json
body:{"validate": "<前端提交的 validate>", "secret_key": "<你的 secret_key>"}

返回:
- result (boolean):true 放行;false 拒绝
- captcha_id (string):核销的站点 id,建议与你配置的比对
- token (string):本题标识,用于日志关联
- reason (string):used 已核销 / expired 超 180s / bad_signature 被篡改或 secret 已轮换 / bad_secret secret 不对 / malformed 格式错误

Python:
```python
r = requests.post(f"{HOST}/api/v1/captcha/verify",
                  json={"validate": validate, "secret_key": SECRET}, timeout=5)
if not r.json().get("result"):
    abort(400, "captcha failed")
```

Node:
```js
const r = await fetch(`${HOST}/api/v1/captcha/verify`, {
  method: "POST", headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ validate, secret_key: process.env.CAPTCHA_SECRET })
}).then(r => r.json());
if (!r.result) throw new Error("captcha failed");
```

每个 validate 只能核销一次,重放会得到 used;接口超时(建议 5s)按拒绝处理并提示重试。

---

## 安全与数据

- 答案只在服务端;客户端拿到的是题图和运动方式。位置与角度必须同时对上,每题曲线不同。
- 一道题只能校验一次,2 分钟过期;凭证只能核销一次,180 秒过期。
- 服务端综合拖动轨迹、时序、运行环境等信号打分,并对同一来源的连续失败做冷却。
- 校验请求的载荷在客户端加密传输,配合 SDK 版本轮换抬高脚本伪造成本。
- Origin 白名单可防止其他网站盗用你的 captcha_id 消耗额度。
- 只加载图片不验证的刷图流量会被自动识别并临时限制,不消耗你的额度;控制台会提示,误判可联系我们解除。
- 必须 https。Web 端加密依赖浏览器安全上下文,http 下(localhost 除外)会退化为明文并被服务端拒绝。

采集了什么:SDK 在拖动时上报滑块位移与轨迹(相对坐标与时间)、屏幕尺寸与像素比、语言与时区、是否触屏、是否处于自动化环境。服务端记录请求 IP 与 UA 摘要用于绑定与限流,保留不超过 10 分钟。不采集 Cookie、账号、页面内容或输入框内容。

---

## 私有化部署

```shell
git clone ... shudun && cd shudun
# 改 docker-compose.yml 里的 SESSION_SECRET / PUBLIC_URL
docker compose up -d --build
curl -s http://127.0.0.1:8790/api/v1/health   # {"status":"ok"}
```

关键环境变量:
- BITCAPTCHA_PUBLIC_URL:对外地址,控制台生成接入代码用。
- BITCAPTCHA_SESSION_SECRET:控制台登录态签名,生产必填。
- BITCAPTCHA_SDK_KEY:与三端 SDK 内置值一致,改动需同时发新版 SDK。
- BITCAPTCHA_REDIS_URL:多实例 / 多 worker 必填。
- BITCAPTCHA_TRUST_PROXY:nginx 之后置 1。
- BITCAPTCHA_TOLERANCE / RISK_THRESHOLD:拼图容差(px)/ 行为风险阈值(默认 5 / 0.6)。
- BITBEAM_ADMIN_EMAILS:超级管理员邮箱名单(逗号分隔),这些账号登录后可进 /admin 平台后台。
- BITBEAM_LLM_KEY:文档「问 AI」的模型服务密钥,只作缺省;开关与密钥在后台「平台配置」管理,默认关闭。

---

## Web / H5 SDK

无依赖,一个 <script> 引入,兼容现代浏览器与移动端 WebView(需 https,localhost 除外)。样式由 SDK 自动加载。

四种类型:type:'sense'(智能无感知,点一下即过、可疑流量自动升级为图形验证;可疑来源会被转入严格一段时间,站点也可在控制台设为严格模式——登录 / 注册 / 领券等高价值动作建议严格)、type:'slider'(增强版滑动拼图,默认)、type:'textclick'(文字点选,enhanced:true 文字带旋转更防破解)、type:'iconclick'(图标点选)。无论哪种,通过后都拿到一次性 validate,业务后端二次核销才算数。宽度默认自适应铺满容器并在 minWidth–maxWidth(280–400)间收敛;要固定宽传数字 width:320。

初始化参数 BitCaptcha.init(options):
- element (string|Element,必填):容器
- captchaId (string,必填)
- type (string,默认 'slider'):sense 智能无感知 / slider 滑动拼图 / textclick 文字点选 / iconclick 图标点选
- enhanced (boolean,默认 true):仅文字点选,true 旋转 / false 正放
- mode (string,默认 'embed'):embed 嵌入 / popup 弹出 / float 触发
- width (number|string,默认 '100%'):自适应或固定 px
- theme (默认 light) / lang (默认 auto)
- maxErrors (number,默认 5):连续失败几次后改为点击刷新
- lazy (boolean,默认 true):嵌入 / 触发式滚进视口附近才取题,首屏之外的验证码不提前加载;三端同名(小程序 lazy="{{false}}" 关闭)
- onReady / onVerify(err,data) / onError / onClose

onVerify(err, data):err 通过为 null,失败时 err.code 为错误码(SDK 会 1s 后自动换题;连续失败达到 maxErrors 改为"点击刷新";若某次失败触发了来源冷却,err.retryAfter 给出秒数,控件直接进入倒计时、到点自动重新取题);data.validate 交后端核销;data.token / data.captchaId。

实例方法:refresh() 换题;popUp()/close() 弹出式手动开关;getValidate();reset() 清通过状态并换题;destroy()。

---

## 微信小程序

下载组件包 https://shudun.bitbeam.cn/sdk/miniprogram/bitcaptcha.zip,解压后把 bitcaptcha 目录放到小程序 components/ 下;后台"开发设置 → request 合法域名"加入接口域名。拖动在视图层(WXS)处理,跟手不卡顿。

```
<!-- page.json -->
{ "usingComponents": { "bitcaptcha": "/components/bitcaptcha/index" } }
<!-- page.wxml -->
<bitcaptcha captcha-id="YOUR_CAPTCHA_ID" api-base="https://shudun.bitbeam.cn"
             mode="embed" bind:verify="onVerify" />
<!-- 智能无感知:点一下,安全用户直接过,可疑自动切成拼图 -->
<bitcaptcha captcha-id="YOUR_CAPTCHA_ID" api-base="https://shudun.bitbeam.cn" type="sense" bind:verify="onVerify" />
// page.js
Page({ onVerify(e) { const { validate } = e.detail
  wx.request({ url: '/login', method: 'POST', data: { captcha: validate } }) } })
```

属性:captcha-id / api-base 必填;type / enhanced 同 Web(enhanced="{{false}}" 普通版);mode embed/popup(无 float);width '100%' 或 width="{{320}}";bind:verify e.detail={validate,token,captchaId};bind:error e.detail={code}。

---

## Flutter

包已发布到 pub.dev(https://pub.dev/packages/bitcaptcha_flutter),支持 iOS / Android / Web / 桌面。

```yaml
dependencies:
  bitcaptcha_flutter: ^0.6.2
```

```dart
import 'package:bitcaptcha_flutter/bitcaptcha_flutter.dart';
// 嵌入式
BitCaptcha(
  captchaId: 'YOUR_CAPTCHA_ID', apiBase: 'https://shudun.bitbeam.cn',
  onVerify: (r) => login(captcha: r.validate),
)
// 弹窗式:用户关闭返回 null
final r = await showBitCaptcha(context, captchaId: 'YOUR_CAPTCHA_ID', apiBase: 'https://shudun.bitbeam.cn');
if (r != null) login(captcha: r.validate);
// 文字点选:BitCaptchaText / showBitCaptchaText(enhanced: bool)
// 智能无感知:点一下,安全用户直接过,可疑自动弹出拼图
BitCaptchaSense(captchaId: 'YOUR_CAPTCHA_ID', apiBase: 'https://shudun.bitbeam.cn', onVerify: (r) => login(captcha: r.validate))
```

参数:captchaId / apiBase 必填;onVerify 必填(r.validate/r.token/r.captchaId);fluid(默认 true 铺满父容器)/ width(fluid:false 时固定,默认 320);theme / lang / maxErrors 同 Web;lazy(默认 true,滚进视口附近才取题 / 准备无感知,三端同名)。

---

## 错误码

客户端 onVerify 的 err.code(小程序 bind:error 的 detail.code)。都由 SDK 自动处理,列出便于埋点:
- mismatch:没拼到位。提示"验证失败",1s 后换题。
- behavior:轨迹或环境判定为机器。提示"操作异常",1s 后换题。
- token_expired:题目超 2 分钟或已校验过。换题。
- token_mismatch:取题与校验不是同一客户端。换题。
- bad_payload:载荷无法解密(SDK 与服务端版本不一致)。换题,持续出现请升级 SDK。

加载失败的分类:取题 / 无感知请求失败时走 onError(小程序 bind:error,Flutter onError 收到 BitCaptchaException),错误对象带 code,三端把原因分开告诉用户:
- rate_limited / cooldown:请求过于频繁,或短时间内失败过多进入冷却;响应带 Retry-After(秒),错误对象里是 retryAfter。用户看到"操作太频繁,N 秒后自动重试",倒计时期间点击无效,到点自动重新取题。
- network:请求没到服务端(断网 / 超时 / 图片没下下来)。用户看到"网络不给力,点击重试"。
- server:服务端 5xx。用户看到"服务开小差了,点击重试"。
- quota_exceeded:账号本月额度用完且没有余额。用户看到"加载失败,点击重试"(额度是商户侧的事,不向终端用户解释;控制台会提前提示)。
- http:其它 4xx(400 未知 captcha_id;403 来源不在 Origin 白名单 / 账号已停用)。用户看到"加载失败,点击重试";接入时看 err.status / err.detail 排查。

---

## 额度与账单

按验证次数计费:用户提交答案一次、或智能无感知直接通过一次,各算一次;加载与换题不计。额度属于账号,名下所有站点共用。
- 每月 10,000 次免费额度,按 UTC 自然月、每月 1 日重置;控制台「概览」看本月用量与进度,「用量」页看按月账单。
- 免费额度用完后自动从次数包扣,按到期先后扣;次数包在控制台「充值」页购买(支付宝),12 个月有效,支付成功立即到账、不影响已有余额。
- 免费额度用完且没有余额时,取题接口返回 429 quota_exceeded,验证码显示"加载失败",充值或下月重置后自动恢复;超额只影响取题,已发出的题仍可完成校验与核销。
- 企业客户、发票、对公转账或不限量方案联系我们,后台入账即时生效。

---

## 多语言与主题

内置 zh-CN / zh-TW / en / ja / ko,lang:'auto' 按浏览器 / 系统语言归并。三端键名一致,可用 i18n 逐条覆盖:

```js
BitCaptcha.init({ ..., lang: 'en', i18n: { slide: 'Drag to verify', success: 'Welcome back' } })
```

主题:Web 端除 theme:'dark' 外可覆盖 CSS 变量;Flutter 用 BitCaptchaTheme(primary:..., success:...)。
```css
#captcha .bc { --bc-primary: #7c3aed; --bc-primary-soft: #ede9fe; }
```

---

## AI 接入 (MCP)

星辉数盾提供两种给 AI / 自动化工具的接入方式:

1) llms.txt 约定:把 /llms.txt(索引)或本文件 /llms-full.txt 的 URL 给 ChatGPT / Claude,即可就星辉数盾接入答疑。

2) MCP server:一个只读的 MCP 服务,暴露工具供 Claude Desktop / Cursor 等 AI 客户端调用:
- search_docs(query):在文档里检索,返回相关章节。
- get_snippet(platform, type):返回某端(web/mp/flutter/server)的接入代码。
- service_health():查询服务健康。

Claude Desktop 配置(claude_desktop_config.json):
```json
{
  "mcpServers": {
    "shudun": {
      "command": "python",
      "args": ["integrations/mcp-server/server.py"],
      "env": { "BITBEAM_HOST": "https://shudun.bitbeam.cn" }
    }
  }
}
```

服务器代码见仓库 integrations/mcp-server/。
