跳到正文

验证码

验证码令牌校验与控件发放。

1. 概览

基础路径: https://api.infrai.cc/v1/captcha
鉴权头: Authorization: Bearer $INFRAI_API_KEY
bash
# Call any /v1/captcha capability over raw HTTP — no SDK to install.
# curl:
curl https://api.infrai.cc/v1/captcha/... \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json"

2. 方法 (1)

2.1captcha.verify

POST /v1/captcha/verify

校验来自浏览器的验证码令牌。

参数

名称类型必填说明
tokenstring
必填
验证码控件返回的令牌。
≥ 1 chars
vendor"hcaptcha" | "recaptcha" | "turnstile" | "infrai"可选固定使用某个供应商,而非自动路由。
remote_ipstring可选用于风险评分的客户端 IP。
min_scorenumber可选可接受的最低分(基于分数的供应商)。

返回

CaptchaVerifyResult { valid, score?, vendor, hostname?, action? }
名称类型说明
successboolean验证码校验是否通过
scorenumber | null0=机器人,1=人类(归一化)。
0–1
hostnamestring | null验证码被解决的站点主机名
actionstring | null执行的操作(如 created、updated、deleted)
challenge_tsstringISO 8601 时间戳:the captcha challenge was issued(ISO 8601)
format: date-time
vendorstring处理此请求的供应商
reasons("timeout-or-duplicate" | "invalid-input-response" | "invalid-sitekey" | "low-score" | "hostname-mismatch")[]reasons contributing to the risk score列表

示例

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/captcha/verify \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"token": "sample"}'
高级:指定 vendor

默认情况下 infrai 会把每次调用智能路由到最佳可用供应商——无需自己挑选 vendor。作为高级逃生口,本能力支持可选的 vendor 入参以锁定某个供应商。本能力当前所有可用 vendor 可通过该能力 id 对应的 discovery 端点实时获取——参见 discovery API

GET /v1/discovery/{capability}

captcha.verify

3. 全部能力

本模块全部已路由能力——完整的对外 REST 契约。上方方法是带讲解的入门示例,此表是完整参考。

captcha.verifyPOST /v1/captcha/verify

Verify a client-submitted CAPTCHA token against the vendor and return the success result; idempotent.

参数 (10)
名称类型必填说明
tokenstring必填One-time vendor response token from the client widget.
≥ 1 chars
vendorstring | null可选Pin to a specific vendor (turnstile/hcaptcha/recaptcha). Default: routed.
ipstring | null可选End-user IP for vendor-side risk scoring. Alias: `remoteip`.
remoteipstring | null可选Alias of `ip` (module accepts both; `ip = ip or remoteip`).
actionstring | null可选Action name bound at challenge time; rejected if mismatched (anti cross-form replay).
expected_hostnamestring | null可选If set, token hostname must match.
score_thresholdnumber | null可选Minimum acceptable score [0,1]; below → fail with low-score reason.
0–1
mode"default_vendor" | "verified_account"可选Routing axis (CaptchaMode); orthogonal to widget_mode.
default: "default_vendor"
sitekey_labelstring可选KeyPool entry name selecting which sitekey/secret to verify against (multi-sitekey accounts).
default: "default"
idempotency_keystring | null可选Carries one-time-token semantics; duplicate replay → CAPTCHA_IDEMPOTENCY_KEY_CONFLICT.

4. 完整示例

本模块的生产级端到端范例:先一次性配置,再运行业务流程,尽量覆盖本模块的多数 API。

单文件可运行 Python 程序(仅标准库、无 SDK):拷贝后填入 INFRAI_API_KEY 运行,即可按真实业务流逐步体验本模块核心 API——每一步都真实调用并计费,后续步骤复用前一步返回的真实字段。12 行 helper 就是全部集成代码。

python
#!/usr/bin/env python3
"""Infrai · captcha — runnable real-app example (single file, zero deps).

Copy this file, set your key, run it: every step is a REAL call to
api.infrai.cc, billed at the real (tiny) per-call price, printing the
live JSON response. Get a key at https://infrai.cc/login (Google/
GitHub sign-in grants $2 free credit); add funds at
https://infrai.cc/billing. No SDK — the 12-line helper below is the
entire integration."""
import json
import os
from urllib import error, request

KEY = os.environ.get("INFRAI_API_KEY") or "ifr_..."  # <- your key
BASE = "https://api.infrai.cc"


# Same raw HTTPS POST/GET as every per-method example on this page —
# wrapped once for reuse. There is nothing else to it: no SDK.
def infrai(method, path, body=None):
    req = request.Request(
        BASE + path, method=method,
        data=json.dumps(body).encode() if body is not None else None,
        headers={"Authorization": f"Bearer {KEY}",
                 "Content-Type": "application/json"})
    try:
        with request.urlopen(req, timeout=60) as r:
            return json.loads(r.read())
    except error.HTTPError as e:
        return json.loads(e.read())


def show(label, resp):
    print(f"\n== {label} ==")
    print(json.dumps(resp, indent=2, ensure_ascii=False))
    return resp


# 1) capture token — client widget handoff
r1 = show("capture token", {"note": "Render the CAPTCHA widget in the browser, then copy the one-time token into the verify step below."})

# 2) captcha.verify — POST /v1/captcha/verify · Verify a client-submitted CAPTCHA token against the vendor and return the success result; idempotent.
r2 = show("captcha.verify", infrai("POST", "/v1/captcha/verify", {"token":"<client-captcha-token>","remote_ip":"203.0.113.5"}))