Skip to content

OPC · 验证码

验证码接入(人机 + 短信)

给表单、注册、登录这类入口挡机器——先过算术题人机验证,需要确认手机号的再发短信码;服务端带频控,防刷防轰炸。

验证码计费

前提

已在控制台「开放能力」建好应用,手里有 site_key(公开);验证码类接口前端就可以调(不碰 secret)。

短信发送额度与档位见计费与额度;短信链路依赖平台侧短信配置:未配置时接口回 503 并明说「未配置」,以控制台公告为准。

能力拆两层 ​

人机验证

算术题一次一用,验过发一次性 ticket。

接口:challenge / verify

可以只接人机(表单防刷)。

短信验证码

先过人机,再给手机号发码;验码发一次性 sms_ticket。

接口:sms/send / sms/verify

人机 + 短信全接:注册、绑定手机。

1. 人机验证 ​

取题 ​

http
GET /api/open/captcha/challenge?site_key={site_key}
json
{
  "challenge_token": "opc_ch_...",
  "question": "6 × 7 = ?",
  "expires_in": 240
}
  • 题是一次性的:验过即作废;答案错了同样作废(防对着同一道题爆破);
  • 时效约 4 分钟,过期要重新取题。

验题 ​

http
POST /api/open/captcha/verify
Content-Type: application/json

{
  "site_key": "{site_key}",
  "challenge_token": "opc_ch_...",
  "answer": 42
}
json
{
  "ok": true,
  "ticket": "opc_tk_...",
  "expires_in": 300
}
  • ticket 是一次性凭证(约 5 分钟):可以拿去换短信,也可以直接当「这人过了人机」的表单防刷凭证(提交表单时带上,服务端核);
  • 验失败回 400,题已作废,前端重新取题。

2. 短信验证码 ​

发送(必须先过人机) ​

http
POST /api/open/sms/send
Content-Type: application/json

{
  "site_key": "{site_key}",
  "phone": "1xxxxxxxxxx",
  "ticket": "opc_tk_..."
}

少一次往返的写法:不传 ticket,改传现场题的 challenge_token + challenge_answer,发送成功会把当场烧掉这张票。

json
{
  "ok": true,
  "phone": "138****6789",
  "ttlSeconds": 300,
  "resendAfter": 60
}
  • 没有人机凭证直接拒:防脚本轰炸短信通道;
  • 频控在服务端:同号约 5 条/小时、约 10 条/天(具体以服务端为准),到限回明确文案;
  • 重发间隔 resendAfter(约 60 秒),前端倒计时用这个值;
  • 短信码约 5 分钟有效。

校验 ​

http
POST /api/open/sms/verify
Content-Type: application/json

{
  "site_key": "{site_key}",
  "phone": "1xxxxxxxxxx",
  "code": "123456"
}
json
{
  "ok": true,
  "sms_ticket": "opc_tk_...",
  "phone": "138****6789",
  "expires_in": 300
}
  • sms_ticket 是「手机号已验证」的一次性凭证,你的服务端收下后做绑定 / 放行;
  • 错码次数有上限(约 5 次),超了这张码作废、要重新获取,防爆破。

前端接法(示意) ​

js
// 1) 取题
const ch = await fetch(`/api/open/captcha/challenge?site_key=${SITE_KEY}`).then((r) => r.json())
// 2) 展示 ch.question,收集用户答案后验题
const v = await fetch('/api/open/captcha/verify', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ site_key: SITE_KEY, challenge_token: ch.challenge_token, answer: Number(userAnswer) })
}).then((r) => r.json())
// 3a) 表单防刷:提交时带上 v.ticket
// 3b) 要发短信:带着 v.ticket 去 /api/open/sms/send

常见坑 ​

  • 题 / 票复用:challenge_token、ticket、sms_ticket 全是一次一用,复用必失败;每次交互按「取题 → 验题 → 用票」重新走;
  • 答案当字符串比:接口收的是算术结果(数字),前端别把带空格或非数字原样丢过去;
  • 跳过人机直接打短信:必被拒;要省一次往返就用「题 + 答案」直发的写法;
  • 忽略 429:日配额(quota_daily)超了回 429,前端应提示「今日额度用完」而不是死循环重试——口径见计费与额度;
  • 把 ticket 当登录态:ticket 只证明「过了验证」,不含用户身份;要身份走统一登录。
滑块验证码

滑块 / 无感人机正在随登录与注册链路建设中,形态与接入路径见站内登录页说明与控制台公告;在公布之前,请按上文算术题人机验证接。

下一步 ​

本页讨论

0 条评论

还没有评论,来说第一句。

Ctrl + Enter 发布