# API 文档 ## API 概述 项目使用 Next.js API Routes 实现服务端接口,主要用于处理联系表单提交等后端逻辑。 ## 基础信息 - **基础 URL**: `/api` - **内容类型**: `application/json` - **字符编码**: `UTF-8` ## 接口列表 ### 1. 联系表单 API #### 提交联系表单 **接口地址** ``` POST /api/contact ``` **请求头** | 参数 | 类型 | 必填 | 描述 | |------|------|------|------| | Content-Type | string | 是 | application/json | **请求参数** | 参数 | 类型 | 必填 | 描述 | |------|------|------|------| | name | string | 是 | 联系人姓名 | | email | string | 是 | 联系人邮箱 | | phone | string | 否 | 联系人电话 | | subject | string | 是 | 咨询主题 | | message | string | 是 | 咨询内容 | | website | string | 否 | 蜜罐字段(用于反垃圾) | | submitTime | string | 否 | 表单提交时间戳 | | mathHash | string | 否 | 数学验证码哈希 | | mathTimestamp | string | 否 | 数学验证码时间戳 | | mathAnswer | number | 否 | 数学验证码答案 | **请求示例** ```json { "name": "张三", "email": "zhangsan@example.com", "phone": "13800138000", "subject": "产品咨询", "message": "我想了解贵公司的软件开发服务。", "submitTime": "1709827200000", "mathHash": "MTAwLTE3MDk4MjcxMDAwMDA=", "mathTimestamp": "1709827100000", "mathAnswer": 100 } ``` **响应参数** | 参数 | 类型 | 描述 | |------|------|------| | success | boolean | 请求是否成功 | | message | string | 成功消息(成功时) | | error | string | 错误消息(失败时) | **成功响应** ```json { "success": true, "message": "消息已发送,我们会尽快与您联系!" } ``` **错误响应** ```json { "success": false, "error": "请填写必填字段" } ``` **错误码说明** | HTTP 状态码 | 错误信息 | 描述 | |-------------|----------|------| | 200 | - | 蜜罐字段被填充(静默拒绝) | | 400 | 请填写必填字段 | 缺少必填字段 | | 400 | 请输入有效的邮箱地址 | 邮箱格式不正确 | | 400 | 提交过快,请稍后再试 | 提交时间间隔过短 | | 400 | 验证码错误,请重新计算 | 数学验证码错误 | | 500 | 发送失败,请稍后重试 | 邮件发送失败 | ## 安全机制 ### 1. 蜜罐字段 (Honeypot) 通过隐藏字段 `website` 检测机器人提交: ```tsx // 前端隐藏字段 // 后端检测 if (website) { // 检测到机器人,静默返回成功 return NextResponse.json({ success: true }); } ``` ### 2. 提交时间验证 验证表单提交时间间隔,防止快速自动提交: ```tsx if (submitTime) { const timeDiff = Date.now() - parseInt(submitTime); if (timeDiff < 2000) { // 提交过快,拒绝请求 return NextResponse.json({ success: false, error: '提交过快' }); } } ``` ### 3. 数学验证码 使用数学运算验证码防止机器人: ```tsx // 前端生成验证码 const num1 = Math.floor(Math.random() * 10) + 1; const num2 = Math.floor(Math.random() * 10) + 1; const answer = num1 + num2; const timestamp = Date.now(); const hash = btoa(`${answer}-${timestamp}`); // 后端验证 const expectedHash = btoa(`${mathAnswer}-${mathTimestamp}`); if (expectedHash !== mathHash) { return NextResponse.json({ success: false, error: '验证码错误' }); } ``` ### 4. 邮箱验证 验证邮箱格式: ```tsx const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(email)) { return NextResponse.json({ success: false, error: '请输入有效的邮箱地址' }); } ``` ### 5. XSS 防护 使用 DOMPurify 清理用户输入: ```tsx import DOMPurify from 'dompurify'; const sanitizedName = DOMPurify.sanitize(name); ``` ## 邮件服务 ### Resend 配置 项目使用 Resend 服务发送邮件: ```env RESEND_API_KEY=re_xxxxx COMPANY_EMAIL=contact@novalon.cn ``` ### 邮件模板 邮件使用 HTML 模板,包含: - 公司品牌头部 - 表单数据展示 - 时间戳信息 - 响应式设计 **邮件模板结构** ```html
``` ## Server Actions ### 联系表单 Server Action 位于 `src/app/(marketing)/contact/actions.ts`: ```tsx 'use server'; export async function submitContactForm(formData: FormData) { // 服务端表单处理逻辑 } ``` **优势:** - 无需创建 API 路由 - 自动 CSRF 保护 - 类型安全 - 更简洁的错误处理 ## 环境变量 ### 必需配置 ```env # Resend API 密钥 RESEND_API_KEY=re_xxxxx # 公司邮箱 COMPANY_EMAIL=contact@novalon.cn ``` ### 可选配置 ```env # 环境 NODE_ENV=production # 站点 URL NEXT_PUBLIC_SITE_URL=https://www.novalon.cn ``` ## 请求限制 ### 速率限制 建议在生产环境配置速率限制: ```typescript // 示例:使用 Upstash Redis import { Ratelimit } from '@upstash/ratelimit'; import { Redis } from '@upstash/redis'; const ratelimit = new Ratelimit({ redis: Redis.fromEnv(), limiter: Ratelimit.slidingWindow(10, '1 m'), }); const { success } = await ratelimit.limit(ip); if (!success) { return NextResponse.json({ error: '请求过于频繁' }, { status: 429 }); } ``` ## CORS 配置 API 路由默认不允许跨域请求。如需配置 CORS: ```typescript export async function POST(request: NextRequest) { const response = NextResponse.json({ success: true }); response.headers.set('Access-Control-Allow-Origin', 'https://www.novalon.cn'); response.headers.set('Access-Control-Allow-Methods', 'POST'); return response; } ``` ## 错误处理 ### 统一错误响应格式 ```typescript interface ApiResponse { success: boolean; message?: string; error?: string; data?: unknown; } ``` ### 错误日志 ```typescript try { await resend.emails.send({ ... }); } catch (error) { console.error('邮件发送失败:', error); return NextResponse.json( { success: false, error: '发送失败,请稍后重试' }, { status: 500 } ); } ``` ## 测试接口 ### 使用 cURL ```bash curl -X POST http://localhost:3000/api/contact \ -H "Content-Type: application/json" \ -d '{ "name": "测试用户", "email": "test@example.com", "subject": "测试主题", "message": "测试消息内容" }' ``` ### 使用 Playwright ```typescript // e2e/src/tests/api/contact.spec.ts test('提交联系表单', async ({ request }) => { const response = await request.post('/api/contact', { data: { name: '测试用户', email: 'test@example.com', subject: '测试主题', message: '测试消息内容', }, }); expect(response.ok()).toBeTruthy(); const data = await response.json(); expect(data.success).toBe(true); }); ``` ## API 版本控制 当前项目 API 不包含版本号。如需版本控制,建议: ``` /api/v1/contact /api/v2/contact ``` ## 监控与日志 ### 推荐集成 - **Sentry** - 错误监控 - **LogRocket** - 会话回放 - **Vercel Analytics** - 性能监控 ### 日志格式 ```typescript console.log({ timestamp: new Date().toISOString(), level: 'info', message: '联系表单提交', data: { email, subject }, }); ```