Checkify
开发人员文档

在后端验证

浏览器嵌入完成后,您的服务器必须使用站点API密钥验证结果,然后才能允许注册、结帐或任何受保护的操作。

服务器验证将在 5 分钟内完成

  1. 将 Checkify 浏览器嵌入代码添加到您的页面。
  2. 嵌入程序启动 Checkify 会话并将验证参考写入您的表单。
  3. 您的后端读取隐藏字段的值。
  4. 您的后端将该值作为 request_id 发送到 POST /v1/qr/results/verify。
  5. 如果所需的索赔获得批准,则允许进行受保护的行为。
  6. 永远不要只相信前端状态。

隐藏的表单字段可能名为 checkify_token,但其值为 Checkify request_id。

端到端流程

1。创建站点API key

在您的业务仪表板中,打开 开发者 并为您正在集成的站点创建一个站点 API 密钥。仅将其存储在服务器环境变量中 - 切勿将其发送到浏览器。

使用前端SDK?

您无需手动调用 GET /v1/qr/pass/{PASS_ID}/start。Checkify 和 JavaScript 嵌入代码会自动启动会话、接收请求 ID 并将其写入您的表单。

您的后端只需要:

2. 在您的服务器上接收 request_id

用户完成验证后,前端 SDK 会将 Checkify 的 request_id 写入一个隐藏的表单字段。默认字段名为 checkify_token——这只是字段名称,并非单独的令牌类型。将该字段值作为 request_id 发送到验证端点。

移动应用切换时,页面 URL 中可能会返回 checkify_request_id。SDK 会在页面加载时读取该值;您的服务器仍然会验证相同的 request_id 值。

前端表单 POST

{
  "email": "user@example.com",
  "checkify_token": "56a57761-ff5b-42f0-9c97-6c13e223e017"
}

验证来自后端的请求

{
  "request_id": "56a57761-ff5b-42f0-9c97-6c13e223e017",
  "required_claims": ["human_verified"],
  "required_fields": [],
  "consume": true
}

仅手动前端集成

3. 使用 cURL 进行手动测试

后端开发人员通常不会调用 `/start`。仅当构建自定义前端或在不嵌入代码的情况下进行测试时才使用此部分。在 zsh/bash 中,URL 需要加引号,以避免 `?` 被视为通配符。

/start 请求需要 Origin 标头。

Pass start 仅适用于已注册的网站域名。浏览器会自动发送 Origin 参数;cURL 不会。请发送 Origin 参数(或 X-Checkify-Site-Url 参数),并指定“站点”→“允许的域名”下列出的主机名。主机名必须完全匹配——checkify.me 和 www.checkify.me 是不同的。

最常见的测试问题

如果 /start 返回 HTTP 403 错误,您的 Pass ID 可能仍然有效。通常的原因是请求的域名不在允许的域名列表中,或者已注册了 www.example.com 但使用了 example.com(反之亦然)。

使用专用测试站点,并在您的 Checkify 控制面板中通过集成测试。站点 API 密钥使用 csk_ 前缀;没有单独的测试密钥格式。在确认成功和拒绝流程之前,请勿针对生产环境进行测试。

# Step A — start a session (replace PASS_ID and YOUR_REGISTERED_DOMAIN)
curl -sS \
  -H "Accept: application/json" \
  -H "Origin: https://YOUR_REGISTERED_DOMAIN" \
  "https://checkify.me/v1/qr/pass/chk_live_YOUR_PASS_ID/start?request_type=human"

# Response includes request_id and qr_url — open qr_url and complete verification

# Step B — verify on your server (after the user completes verification)
curl -sS -X POST "https://checkify.me/v1/qr/results/verify" \
  -H "Authorization: Bearer $CHECKIFY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "request_id": "PASTE_request_id_FROM_STEP_A",
    "required_claims": ["human_verified"],
    "consume": true
  }'

仅在验证调用中使用您的站点密钥 API。请在调用验证调用之前完成应用程序中的验证,否则您将收到“待处理”状态。

用例所需的声明

设置 required_claims 以匹配受保护操作所需的证明。声明名称必须与 Checkify 为该验证会话批准的名称一致。年龄检查使用 age_over_{N}(例如 age_over_18)。当嵌入请求匹配的请求类型时,支持 10 到 110 之间的动态阈值。

用例 建议的必需声明 笔记
机器人/CAPTCHA替换 ["human_verified"] 确认真实用户已完成 Checkify 流程。
13岁以上内容或面向青少年的产品 ["age_over_13"] 当您的通行证要求年龄超过 13 岁时使用。
16岁以上内容或地区年龄限制 ["age_over_16"] 当您的通行证要求年龄超过 16 岁时使用。
电子烟、酒精或18岁以上结账 ["age_over_18"] 根据产品和市场情况选择合适的年龄门槛。
21岁以上人士可购买限制产品(如适用) ["age_over_21"] 当您的通行证要求年龄超过 21 岁时使用。
挑战25美元或更严格的零售政策 ["age_over_25"] 当您的通行证要求年龄超过 25 岁时使用。
自定义年龄阈值 ["age_over_N"] 使用 age_over_N,其中 N 为 10–110,与您的嵌入请求类型一致。

嵌入请求类型 → 服务器声明

浏览器请求类型必须与您在服务器端验证的声明相匹配。

嵌入请求类型必需声明
human["human_verified"]
age_over_13["age_over_13"]
age_over_16["age_over_16"]
age_over_18["age_over_18"]
age_over_21["age_over_21"]
age_over_25["age_over_25"]
age_over_N["age_over_N"] (N = 10–110)

可选必填字段

除 required_claims 外,当集成已收集时,您还可以要求特定的已批准身份字段(例如国家或年龄段)。在 required_fields 中传入字段名——若批准结果中缺失,verify 会返回 missing_required_fields,并在 error.details 中提供 missing_fields。

4. 在您的服务器上调用验证功能

在授予访问权限之前,请使用您网站的 API 密钥调用 POST /v1/qr/results/verify 请求。在 Checkify 确认结果之前,请将浏览器引用(请求 ID 或旧版轮询令牌)视为不可信。

POST https://checkify.me/v1/qr/results/verify
Authorization: Bearer YOUR_SITE_API_KEY
Content-Type: application/json

{
  "request_id": "56a57761-ff5b-42f0-9c97-6c13e223e017",
  "required_claims": ["human_verified"],
  "consume": true
}

您也可以发送 token 而不是 request_id. API 键的作用域限定于您的 Checkify 站点——您无需在请求正文中发送 site_id。

实现示例

# checkify_token from your form POST is sent as request_id
curl -sS -X POST "https://checkify.me/v1/qr/results/verify" \
  -H "Authorization: Bearer $CHECKIFY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "request_id": "56a57761-ff5b-42f0-9c97-6c13e223e017",
    "required_claims": ["human_verified"],
    "consume": true
  }'

何时使用消耗

对最终受保护的操作使用 consume: true — 结账、注册、密码重置、年龄限制购买、受保护的内容访问

仅当 — 测试、调试或非最终检查,其结果需要稍后再次验证。

对于受监管或高风险的操作,建议使用 consume: true,这样同一个验证结果就不能用于多个受保护的决策。

因受监管行为而关闭

如果您的后端无法连接到 Checkify,则在没有确认服务器端结果的情况下,不得允许年龄限制结账、赌博访问、成人内容访问、电子烟或酒精购买或其他受保护的操作。

使用较短的 HTTP 超时时间(例如 10 秒)。对于瞬态 5xx 错误或网络错误,重试一到两次,然后拒绝访问。在服务器端记录事件,并显示对用户安全的提示信息。不要向客户暴露内部 Checkify 错误详情。

try {
  const verdict = await verifyCheckifyResult(requestId);

  if (!verdict.allow) {
    return res.status(403).json({ error: "Verification required" });
  }

  // Continue protected action
} catch (err) {
  console.error("Checkify verification unavailable", err);

  return res.status(403).json({
    error: "Verification is temporarily unavailable. Please try again.",
  });
}

服务器 SDKs 和工具

The Checkify monorepo includes @checkify/server (Node.js) and checkify-server (Python) packages for server-side verify calls. There is no published OpenAPI spec or Postman collection yet — use the examples on this page and POST /v1/qr/results/verify directly.

@checkify/server v1.0.0 已发布在 npm 上。Python checkify-server 包包含在 Checkify SDK monorepo 中。

结果有效期

已完成的验证将在 QR_RESULT_MAX_AGE_SECONDS 秒后过期(默认值为 900 秒/15 分钟)。过期后,验证将返回 result_expired,并提示用户重新验证。

状态轮询端点(自定义前端)

JavaScript 和 SDK 处理标准嵌入式应用的会话状态。仅当您构建自定义前端并手动调用 GET /v1/qr/pass/{pass_id}/start 时才使用这些。

响应处理

成功时,Checkify 返回 HTTP 200,其中 success: true,status: completed。仅当存在必需的声明(例如 human_verified: true)时才允许访问。

{
  "success": true,
  "status": "completed",
  "message": "Verification result confirmed",
  "request_id": "56a57761-ff5b-42f0-9c97-6c13e223e017",
  "site_id": "YOUR_SITE_ID",
  "business_id": "YOUR_BUSINESS_ID",
  "approved_claims": {
    "human_verified": true
  },
  "approved_fields": [],
  "signed_result": {
    "payload": { "...": "..." },
    "signature": "...",
    "signature_algorithm": "EdDSA",
    "key_id": "checkify:default"
  }
}

签名结果

signed_result 对象可让您的后端保存防篡改审计记录,证明 Checkify 在核验时批准了所需声明。大多数集成只需 approved_claims。受监管或高风险业务也可存储 signed_result。嵌套的 proof_metadata 可能包含密码学或运营证据(例如 assurance 元数据、证据类型或同意哈希)——不是身份证件或原始出生日期。请勿将嵌套 assurance 字段视为认证或信任保证;请检查 certification_status 与您自身的政策。请勿存储超出必要范围的个人信息。

如果用户尚未完成应用内的操作,Checkify 将返回 HTTP 200 状态码,其中 success: false,status: pending。拒绝受保护的操作,并要求用户完成验证。

{
  "success": false,
  "status": "pending",
  "message": "Verification is not completed yet",
  "request_id": "56a57761-ff5b-42f0-9c97-6c13e223e017",
  "approved_claims": {},
  "signed_result": null
}
字段含义
successtrue 验证完成且要求匹配时
statuscompleted 或 pending
approved_claims声明Checkify已批准,例如 human_verified: true
signed_result用于审计跟踪的可选签名负载

JSON 错误载荷

当验证无法进行时,Checkify 返回 HTTP 4xx/5xx 错误,并附带结构化的 JSON 响应体。检查 error.code 并将 error.details 记录到服务器端。向最终用户返回通用消息。

{
  "success": false,
  "error": {
    "code": "verification_failed",
    "message": "The verification did not include all required claims.",
    "details": {
      "missing_claims": ["age_over_18"]
    }
  }
}
代码 HTTP 意义 建议采取的措施
missing_authorization401未发送授权标头。仅通过服务器端代码发送授权:Bearer YOUR_SITE_API_KEY。
invalid_token401Bearer 令牌缺失、格式错误或不是有效的站点 API 密钥。在您的业务仪表板中验证密钥,并将其存储在环境变量中。
expired_token401站点 API 密钥已被撤销。创建一个新的站点 API 密钥,并在您的服务器上轮换使用。
missing_required_field400 / 422JSON 请求体中缺少 request_id 或 token。传递隐藏表单字段中的 request_id,或者如果您的集成仍然使用 poll token,则传递 poll token。
invalid_request_id400规范化后,引用无法解析或为空。请确保前端提交的 Checkify 请求 ID 保持不变。
result_not_found404该参考编号不存在验证请求。拒绝此操作。用户可能篡改了隐藏字段或提交了旧的会话。
result_expired410验证完成时间过长,不足以用于此操作。请用户再次扫描并使用新的 request_id 调用 verify。
verification_failed403 / 409站点/业务不匹配、结果已被消费(HTTP 409),或一般核验失败。拒绝访问。检查 error.details。声明/字段缺口请参见 missing_required_claims 与 missing_required_fields。
missing_required_claims403developers_server.err_missing_required_claims_meaningdevelopers_server.err_missing_required_claims_action
missing_required_fields403developers_server.err_missing_required_fields_meaningdevelopers_server.err_missing_required_fields_action
unknown_required_attributes400developers_server.err_unknown_required_attributes_meaningdevelopers_server.err_unknown_required_attributes_action
business_not_operational403企业账户已被锁定、存档或无法使用。请联系企业主或Checkify支持团队。账户激活前,请勿执行受保护的操作。
validation_errors422JSON 正文模式验证失败(HTTP 422)。检查 error.details.validation_errors 中的字段级错误信息。在重试之前,修复 request_id、required_claims 或 required_fields 的类型。
rate_limited429短时间内验证呼叫次数过多。使用指数退避算法重试。仅在受保护的操作中进行验证,而不是在每次页面浏览时都进行验证。
server_error500+由于服务器暂时出现问题,Checkify 无法完成验证。重试一两次,如果失败则关闭并记录事件。

Webhooks 和异步验证

目前,服务器验证是同步的:后端会在用户提交受保护的操作时验证 request_id。对于结账、注册和访问控制流程,这是推荐的方法。标准集成不需要通用验证 Webhook。GoHighLevel 和其他合作伙伴集成可以在业务控制面板中使用单独的出站 Webhook 配置。

常见错误

安全提醒

将隐藏字段视为不可信参考,而不是证据。在授予访问权限之前,请务必使用服务器上的站点 API 密钥进行验证。使用 consume: true 进行注册或密码重置等一次性操作。

下一步