Kanorio

商业系统

表单

将 Kanorio 表单放置在您自己的前端,并为您处理机器人防护、文件上传、同意与联系人收集。

请在后台的 营销 › 在线表单 建立表单,然后将其显示在您的前端。Kanorio 会检查机器人与垃圾信息、保存提交内容、创建或更新联系人、发送确认与团队邮件,并触发 customers.form.submitted Webhook。

开始之前,请从后台复制表单 ID。如果浏览器从您自己的域名调用 API,请将该域名新增至 网站设置 › 开发者 下的 允许的来源。localhost 始终是被允许的。

选项 1:表单元素

<KanorioForm> 可渲染所有问题类型、文件上传与同意复选框,并为您执行机器人防护。这是最快的方法,且无需升级即可获得新的防护规则。

import { KanorioProvider, KanorioForm } from "@kanorio/elements";
import "@kanorio/elements/elements.css";

export function ContactSection() {
  return (
    <KanorioProvider siteUrl="https://s-xxxxxxxxxxxx.kanorio.com">
      <KanorioForm formId="cform12345678901234567890" siteName="Sourdough Studio" />
    </KanorioProvider>
  );
}

若未使用 React,请使用 <kanorio-form site-url="…" form-id="…">。请参阅 Elements。

选项 2:您自己的标记

当您想要完全控制 HTML 时,请直接使用 Content Delivery API。

1. 加载表单

GET /api/v1/forms/{id} 会返回问题、同意设置以及表单是否正在接受回答。如果 availability.accepting 为 false,请显示关闭消息而非输入字段。

2. 在显示表单时获取机器人检查

GET /api/v1/forms/{id}/challenge 会返回此提交的机器人检查。其 provider 由网站拥有者在 网站设置 › 机器人防护 中设置:

  • kanorio (默认):altcha 中的内置工作量证明挑战。SDK 会为您解决(在中端手机上约需半秒),并将结果作为 _tk 发送。
  • turnstile、recaptcha 或 hcaptcha:拥有者自己的密钥。请使用 siteKey 和 action(Turnstile 亦需 cData)渲染该提供者的组件,并将其令牌作为 captchaToken 传递。服务器会根据网站设置决定验证哪个提供者,因此来自任何其他提供者的令牌将被拒绝。

每次提交请获取新的挑战:挑战与组件令牌皆为单次使用。

3. 提交

发送以问题 ID 为键的答案,并附上防护字段。蜜罐 (Honeypot) 字段必须为空。

import { forms } from "@kanorio/sdk/forms";

const SITE_URL = "https://s-xxxxxxxxxxxx.kanorio.com";
const FORM_ID = "cform12345678901234567890";
const client = forms.client({ siteUrl: SITE_URL });

// when the form is shown
const renderedAt = Date.now();
const challenge = await client.challenge(FORM_ID);

// when the visitor submits
// built-in: the SDK solves the challenge; third-party: pass the widget token
const protection = await forms.protectionFromChallenge(FORM_ID, challenge, renderedAt, {
  captchaToken: challenge.provider === "kanorio" ? undefined : widgetToken,
});

const result = await client.submit(FORM_ID, {
  answers: { name: "Ada", email: "ada@example.com", message: "Do you ship?" },
  consent: "checked",
  pagePath: window.location.pathname,
  protection,
});

if (!result.ok) {
  // result.error.code, and result.error.issues for INVALID_ANSWERS
}

若未使用 SDK,请使用此内容 POST /api/v1/forms/{id}/submit(显示内置检查;若使用第三方提供者,请发送 captchaToken 取代 _tk):

{
  "answers": { "name": "Ada", "email": "ada@example.com" },
  "consent": "checked",
  "pagePath": "/contact",
  "_hp": "",
  "_ts": 1793520000000,
  "_tk": "<solved ALTCHA payload>",
  "_ctx": "cform12345678901234567890"
}

成功的提交会返回 200 与 {}。如果表单在此期间关闭,内容则为 { "state": "closed" }、"not_open" 或 "full"。

错误代码处理方式
INVALID_ANSWERS显示 details.issues 中的消息,并以问题 ID 作为键值
VERIFICATION_EXPIRED获取新的验证挑战(并重置小工具)后重新提交
DUPLICATE_SUBMISSION告知访客表单已提交
RATE_LIMITED等待 Retry-After 指定的时间后重试

文件上传

对于文件问题,请先使用 POST /api/v1/forms/{id}/upload-request 请求上传票据,并附上问题 ID、文件名、类型与大小,以及来自 forms.uploadProtectionFromChallenge(FORM_ID, challenge, renderedAt, solved) 的防护字段:使用内置检查时,这与您提交时使用的已解决挑战相同;使用第三方提供者时,它会使用挑战的 uploadToken,因为组件令牌为单次使用且会在提交时检查。使用返回的 headers 将文件 PUT 至 uploadUrl,然后将 uploadId 作为该问题的答案发送。超过问题限制的文件会失败并返回 413 FILE_TOO_LARGE。

提交后

  • 提交内容会出现在后台以及 Management API 的 submissions 下。
  • 联系人会根据电子邮件或电话答案进行创建或更新。
  • 确认与团队邮件会按照表单设置发送。
  • Webhook 订阅者会收到 customers.form.submitted。

从您的服务器转发

您可以从自己的服务器提交,例如 Next.js 服务器动作。速率限制适用于每位访客,因此直接从浏览器提交最能保护您的配额。如果您进行转发,请保持浏览器的防护字段不变。