客户端配置指南
应用创建后获取对应客户端 Public Key,在业务前端配置展示即可,无需在后台创建主题或逐个添加 login、register 场景。Server Key 只在业务后端使用。
配置优先级
客户端明确传入的参数 → SDK 默认值。服务端 /config 返回的风险规则仍然有效,但 language、product 不再覆盖 SDK 的前端展示参数。Web 自定义 loadConfig() 本身属于前端代码,其展示值可作为默认值,显式顶层参数优先。
scene 是业务动作标识;业务后端核验时使用该接口预期的场景。challengeMode 是题型偏好,服务端可以拒绝或升级;前端必须按返回的 challenge_type 展示实际挑战。
升级时:原先依赖后台 product=invisible 或固定语言的业务,应在初始化参数中明确填写对应 product / language。默认 popup 不会自动启动验证,需点击 SDK 触发器或调用 Web 的 open()。
公开参数
| 参数 | 默认值 / 范围 | 用途 |
|---|---|---|
| Public Key | 必填,各客户端使用自己的凭证 | Web captchaId;其余 publicKey |
| API 地址 | 按下方各端说明 | HTTPS 服务地址,不能混用站点根路径和完整 API 路径 |
scene |
推荐 default,或 login / register 等 |
前后端必须一致;无需逐个预建 |
clientType / clientId |
对应平台与应用标识 | Web/TypeScript 显式传入;原生固定平台;Flutter 自动读取实际包名/Bundle ID |
language |
auto |
指定语言或使用运行环境语言;原生自绘 UI 还需绑定本地化资源 |
product |
popup;Flutter 弹窗默认 invisible |
popup 点击触发;float 浮层;bind 绑定业务按钮;invisible 初始化后直接启动,仍可能显示交互挑战 |
appearance.theme |
light / dark / auto,默认 light |
auto 跟随系统明暗主题 |
appearance.primaryColor |
#4f6bff,仅 #RRGGBB |
主操作颜色;Web/Flutter 自动选择有对比度的按钮文字颜色 |
appearance.borderRadius |
12,整数 0–24 | 验证外层卡片圆角,单位 CSS px / 逻辑像素;不改变题图坐标 |
hapticFeedback |
true |
是否允许触觉反馈;无硬件能力时不震动 |
challengeMode |
smart |
smart、slide、click、grid、onetap、rotate、iconcrush、gobang、space、dynamic、voice |
| 请求超时 | 通常 12 秒,3–30 秒 | Web/Flutter/小程序 requestTimeoutMs;Flutter 使用 Duration;Swift timeout 秒;Kotlin timeoutMillis;HarmonyOS timeoutMs;TypeScript request.timeoutMs |
| 配置重试 | Web 2;Flutter/小程序 0;范围 0–3 | 仅配置 GET 的网络/服务错误可重试,挑战创建和提交不能自动重复;原生请求层由调用方重试配置读取 |
支持语言:zh-CN、zh-TW、en、es、pt-BR、fr、de、ja、ko、ru、ar、hi、id、tr、vi、th、it、nl、pl、uk、fa、he、ms、fil。共享 Web 组件提供这些语言;原生自绘界面须自行提供对应文案。没有浏览器语言环境时建议显式传入设备语言。
以下为 Web 专属交互接口:container(挂载点)、bindTrigger(绑定已有按钮)、open()(手动打开)、reset()(重置)、destroy()(销毁)、onSuccess(取得待核验 Proof)、onState(ready/required/verified/error)、onEvent(生命周期事件)、onError(展示错误)。Flutter 通过 Future<Proof?> 返回成功/取消,onEvent 用于观察生命周期;其他原生和小程序的完成/错误通过 async/Promise 返回,界面事件由业务 UI 管理。
Web 的 enabled、offlineBypass 是兼容参数:只影响本地组件和失败展示,不会生成可信凭证。生产保持 enabled=true、offlineBypass=false,请求失败应允许用户重试。不要用这些开关跳过业务后端核验。
TypeScript 低阶请求支持 headers、fetch、signal、beforeRequest、afterResponse 等扩展;仅在需要自定义传输时使用。小程序支持 request 适配器、sessionId、telemetry。这些客户端数据不应被业务后端直接当作放行依据。
Web / H5
const captcha = RozeCaptcha.init({
container: '#captcha',
captchaId: '你的 Web Public Key',
apiBase: 'https://pink.ya.wang/api/captcha',
scene: 'login', clientType: 'web', clientId: 'web',
language: 'zh-CN', product: 'bind', bindTrigger: '#login-button',
appearance: { theme: 'auto', primaryColor: '#167d50', borderRadius: 8 },
challengeMode: 'smart', hapticFeedback: true,
requestTimeoutMs: 12000, configRetries: 2,
onSuccess: proof => submitLoginToYourBackend(proof),
onError: error => showError(error.message),
onEvent: event => recordCaptchaEvent(event),
})
// 页面卸载:captcha.destroy()
一个页面可以挂载多个实例,各自主题互不影响;弹窗 Teleport 到 body 后仍保留自己的配置。题图宽高和拼图位置不可由业务 CSS 单独拉伸,应使用 SDK 的响应式布局。
在 onState 的 ready=true 后调用 open();初始化未完成时应让业务触发按钮保持禁用。题图内容、缺口坐标与旋转中心由服务端挑战决定,不属于前端外观配置。
Flutter Android / iOS
final proof = await PinkCaptcha.verify(context, options: PinkCaptchaOptions(
publicKey: platformPublicKey,
apiBase: Uri.parse('https://pink.ya.wang/api/captcha'),
scene: 'login', language: 'zh-CN', product: 'invisible',
appearance: PinkCaptchaAppearance(
theme: 'auto', primaryColor: '#167d50', borderRadius: 8,
),
hapticFeedback: true, configRetries: 1,
requestTimeout: const Duration(seconds: 12),
onEvent: (event) => recordCaptchaEvent(event),
));
if (proof != null) await submitToYourBackend(proof.toJson());
Flutter 包内自带交互组件,配置直接生效;不需要业务另写 WebView 页面。product=invisible 避免在已经打开的原生弹窗内再点一次触发按钮。原生标题/错误支持中文和英文,题图内文案使用共享组件语言。
iOS Swift
let options = RozeCaptchaOptions(
baseURL: URL(string: "https://pink.ya.wang")!,
publicKey: publicKey, scene: "login", clientId: Bundle.main.bundleIdentifier!,
language: "zh-CN", product: "popup", hapticFeedback: true,
appearance: .init(theme: "auto", primaryColor: "#167d50", borderRadius: 8)
)
let client = try RozeCaptchaClient(options: options)
let tokens = options.appearance.viewTokens(darkMode: isSystemDark)
// 原生界面:用 tokens 中的 backgroundColor/textColor/primaryColor/borderRadius 设置自己的视图。
let webOptions = options.webOptions()
// 如已有 WebView 容器:JSONSerialization 编码 webOptions,传给共享 RozeCaptcha.init。
Android Kotlin
val options = RozeCaptchaOptions(
baseUrl = "https://pink.ya.wang", publicKey = publicKey,
scene = "login", clientId = context.packageName,
language = "zh-CN", product = "popup", hapticFeedback = true,
appearance = RozeCaptchaAppearance("auto", "#167d50", 8),
)
val client = RozeCaptchaClient(options)
val tokens = options.appearance.viewTokens(darkMode = isSystemDark)
// 将 tokens 绑定到自绘界面;或把 options.webOptions() 序列化后交给已有 WebView。
Swift/Kotlin 包提供请求层、配置校验、界面颜色与圆角参数,以及共享 Web SDK 参数映射,不会自动创建原生验证码弹窗。viewTokens() 返回普通数据:业务 UI 需绑定这些值,主题变化时重新计算;hapticFeedback 为 true 时才调用系统震动 API。使用共享 Web 组件则由它应用样式和触觉反馈。
HarmonyOS NEXT
const client = new RozeCaptchaClient({
baseUrl: 'https://pink.ya.wang', publicKey: publicKey,
scene: 'login', clientId: bundleName, language: 'zh-CN',
product: 'popup', hapticFeedback: true,
appearance: new RozeCaptchaAppearance('auto', '#167d50', 8),
})
const tokens = client.viewTokens(isSystemDark)
const webOptions = client.webOptions()
ArkUI 自绘界面绑定 tokens;已有 ArkWeb 容器可使用 webOptions 初始化共享 Web 组件。SDK 不自动创建 ArkUI 验证弹窗。
微信 / 支付宝 / 抖音小程序
const { createWechatCaptchaClient } = require('./sdk/wechat')
const client = createWechatCaptchaClient({
baseUrl: 'https://pink.ya.wang/api/captcha', publicKey,
scene: 'login', clientId: appId, language: 'zh-CN', product: 'popup',
appearance: { theme: 'auto', primaryColor: '#167d50', borderRadius: 8 },
challengeMode: 'smart', hapticFeedback: true,
requestTimeoutMs: 12000, configRetries: 1,
})
this.setData({ captchaPresentation: client.presentation, captchaTokens: client.viewTokens(isSystemDark) })
// 在 WXML/AXML/TTML 中绑定背景色、文字色、圆角和主按钮颜色。
// 产品模式/交互事件由本地组件实现,不能仅设置数据后就认为已渲染验证码。
支付宝换用 createAlipayCaptchaClient,抖音换用 createDouyinCaptchaClient,其他配置相同。传输层不会绘制题图,需使用原生界面完成交互;不能将这些包宣传为内置完整 UI。
TypeScript 自定义界面
import { createCaptchaClient } from './sdk/client-config'
const client = createCaptchaClient({
baseUrl: 'https://pink.ya.wang', publicKey,
scene: 'login', clientType: 'web', clientId: 'web',
language: 'zh-CN', product: 'popup',
appearance: { theme: 'auto', primaryColor: '#167d50', borderRadius: 8 },
request: { timeoutMs: 12000, maxAttempts: 2 },
})
// 自绘界面读取 client.presentation。
// 共享 Web UI:RozeCaptcha.init({ container: '#captcha', ...client.webOptions(), onSuccess })
const challenge = await client.createChallenge()
captcha-public.ts 为生成的低阶 API;新代码优先使用 client-config.ts,避免将展示字段放进生成的请求结构。服务端 Node SDK 没有用户界面,不接受主题参数,仍负责消费 Proof 和判断联合验证结果。
必须由服务端处理
前端不能设置放行结果、跳过交互后伪造成功、降低风控阈值、延长凭证寿命或允许重放。只有业务后端核验得到 decision=allow 且 verification=passed 才执行登录/注册等操作。用户取消、网络超时、配置错误都不代表通过。
原生 WebView 接入应加载可信的随包/自托管 Web SDK,使用 JSON 序列化传参,限制页面跳转和消息来源,验证完整 Proof 后再交给业务后端;不要拼接未转义的 HTML/JS 或把 Server Key 放在客户端。