# 常用模式
## 表单集成
### 基础表单(隐式渲染)
html
### 受控表单(显式渲染)
javascript
let widgetId = window.turnstile.render('#container', {
sitekey: 'YOUR_SITE_KEY',
callback: (token) => console.log('Token:', token)
});
form.addEventListener('submit', async (e) => {
e.preventDefault();
const token = window.turnstile.getResponse(widgetId);
if (!token) return;
const response = await fetch('/submit', {
method: 'POST',
body: JSON.stringify({ 'cf-turnstile-response': token })
});
if (!response.ok) window.turnstile.reset(widgetId);
});
## 框架模式
### React
tsx
import { useState } from 'react';
import Turnstile from '@marsidev/react-turnstile';
export default function Form() {
const [token, setToken] = useState(null);
return (
{
e.preventDefault();
if (!token) return;
await fetch('/api/submit', {
method: 'POST',
body: JSON.stringify({ 'cf-turnstile-response': token })
});
}}>
);
}
### Vue / Svelte
vue
token = e.detail.token} />
## 服务端验证
### Cloudflare Workers
typescript
interface Env {
TURNSTILE_SECRET: string;
}
export default {
async fetch(request: Request, env: Env): Promise {
if (request.method !== 'POST') {
return new Response('方法不允许', { status: 405 });
}
const formData = await request.formData();
const token = formData.get('cf-turnstile-response');
if (!token) {
return new Response('缺少 Token', { status: 400 });
}
// 验证 Token
cons