从 curl 到工程封装:2FA 动态验证码 API 接入全指南
适用场景双因素认证2FA已成为提升系统安全性的标配手段。TOTP基于时间的一次性密码是其中最流行的实现兼容 Google Authenticator、Microsoft Authenticator 等主流验证器。2FA 动态验证码 API 提供了一套完整的 TOTP 生成与校验能力适用于以下场景用户登录二次验证在密码验证通过后要求用户输入身份验证器上的 6 位码。敏感操作确认如修改密码、转账、删除资源等高风险操作增加动态码校验。服务间鉴权为内部 API 调用生成临时的 TOTP 令牌替代静态密钥。批量返回前后周期码某些情况需要同时使用上一、当前、下一个周期码如网络延迟补偿API 的 batch 模式可直接返回三组数据。接口能力边界该 API 基于 RFC6238 标准实现提供生成、验证、批量三种操作模式。以下是关键约束请求方法POST接口地址https://v1.apizero.cn/api/2faQPS20 次/秒匿名调用与携带 API Key 调用共享此限流具体额度以文档为准密钥要求Base32 编码字符串自动忽略空格、连字符不区分大小写。验证码位数4~8 位默认 6 位。有效期10~120 秒默认 30 秒。安全性密钥仅参与计算不存储、不回显验证采用恒定时间比较防止时序攻击。请求参数与鉴权Header 参数参数名必填类型说明Authorization否stringBearer 你的API Key可选携带后获更高调用额度Content-Type是string固定为application/json请求体字段字段名必填类型描述secret是stringBase32 编码的 TOTP 密钥action否string操作类型generate(生成)、verify(校验)、batch(批量)默认generatecode否string当actionverify时必填待校验的验证码period否number验证码有效期秒范围 10~120默认 30digits否number验证码位数范围 4~8默认 6请求体为一个 JSON 对象示例{ secret: JBSWY3DPEHPK3PXP, action: generate, period: 30, digits: 6 }从 curl 快速接入以下示例演示如何使用 curl 直接调用接口。$APIZERO_API_KEY可替换为你的 API Key若不携带也可匿名调用但额度较低。1. 生成一个 TOTP 验证码curl -sS \ -X POST \ -H Content-Type: application/json \ -d {secret:JBSWY3DPEHPK3PXP,action:generate,period:30,digits:6} \ https://v1.apizero.cn/api/2fa成功响应示例{ code: 0, msg: 成功, data: { digits: 6, next_refresh: 2026-06-30 12:00:30, period: 30, remaining_seconds: 17, timestamp: 1782000000, totp_code: 123456 }, request_id: abc123 }2. 校验一个验证码curl -sS \ -X POST \ -H Content-Type: application/json \ -d {secret:JBSWY3DPEHPK3PXP,code:678901,action:verify,period:30,digits:6} \ https://v1.apizero.cn/api/2fa校验模式下若code匹配当前周期验证码响应data中应包含valid: true具体字段请以文档为准。3. 批量获取验证码curl -sS \ -X POST \ -H Content-Type: application/json \ -d {secret:JBSWY3DPEHPK3PXP,action:batch,period:30,digits:6} \ https://v1.apizero.cn/api/2fabatch模式会返回previous、current、next三个周期的验证码及相关时间信息适用于网络延迟较大的场景。返回值解读通用响应结构{ code: 0, // 业务状态码0 表示成功 msg: 成功, // 状态描述 data: { /* 具体数据 */ }, request_id: abc123 }generate 模式 data 字段字段类型说明totp_codestring当前周期的 TOTP 验证码digitsnumber验证码实际位数periodnumber验证码有效期秒remaining_secondsnumber当前码剩余有效秒数next_refreshstring下一次刷新时间格式YYYY-MM-DD HH:mm:sstimestampnumber服务器当前 Unix 时间戳秒verify 模式 data 字段该模式返回valid布尔值表示校验结果。具体字段名以文档为准。batch 模式 data 字段返回三个周期的验证码对象分别键名为previous、current、next每个对象结构与 generate 的 data 相同。常见错误处理HTTP 状态码业务 code常见原因处理建议40040001secret缺失或非合法 Base32 字符串检查密钥格式确保不含非法字符40040002code位数不符或包含非数字字符确认 code 长度等于digits40040003period或digits超出允许范围限制 period 10~120digits 4~8401401携带了无效的 Authorization Header检查 API Key 是否过期或格式错误429429请求频率超过 20 QPS引入本地限流如令牌桶或队列5xx-服务端临时故障建议指数退避重试间隔 1s/2s/4s 等工程封装建议1. 封装一个客户端类或函数示例Python 风格伪代码import requests import time class TOTPClient: def __init__(self, base_url: str, api_key: str None): self.base_url base_url self.headers {Content-Type: application/json} if api_key: self.headers[Authorization] fBearer {api_key} def generate(self, secret: str, period: int 30, digits: int 6) - dict: payload {secret: secret, action: generate, period: period, digits: digits} resp requests.post(self.base_url, jsonpayload, headersself.headers) resp.raise_for_status() return resp.json() def verify(self, secret: str, code: str, period: int 30, digits: int 6) - bool: payload {secret: secret, code: code, action: verify, period: period, digits: digits} resp requests.post(self.base_url, jsonpayload, headersself.headers) data resp.json() if data[code] ! 0: raise Exception(fVerify failed: {data[msg]}) return data[data][valid]2. 错误重试机制对于 5xx 错误或网络超时使用指数退避重试。注意区分业务错误如 code 错误与可重试错误import time from requests.exceptions import RequestException def retry_request(func, max_retries3, base_delay1): for attempt in range(max_retries): try: return func() except RequestException as e: if attempt max_retries - 1: raise time.sleep(base_delay * (2 ** attempt))3. 密钥存储Base32 密钥是敏感信息不要硬编码在代码中。建议通过环境变量、密钥管理服务或配置中心注入。同时注意日志输出时避免打印密钥。4. 并发与限流单账户 QPS 上限为 20。若服务需要高频调用建议本地维护一个令牌桶每秒补充 20 个 token请求前获取 token。也可将请求排队串行化。5. 日志与监控记录每次请求的request_id、action、响应码和耗时。对code!0或validfalse的请求单独告警方便排查问题。6. 时区与时间同步TOTP 基于时间窗口服务端与客户端时间偏差会导致验证失败。生产环境中建议使用 NTP 同步时间并在 verify 时允许一定的时钟漂移窗口API 服务端已内部处理客户端无需额外配置。参考文档2FA 动态验证码 API 文档原始文档Markdown