Files
novalon-website/docs/api.md
T
张翔 0175799004 docs: 删除过时的文档和测试报告文件
删除不再需要的文档、测试报告和计划文件,包括标题层级规范、颜色优化报告、测试框架文档等
2026-03-07 15:37:19 +08:00

383 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
// 前端隐藏字段
<input name="website" className="hidden" tabIndex={-1} autoComplete="off" />
// 后端检测
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
<html>
<head>
<style>
/* 响应式样式 */
</style>
</head>
<body>
<div class="container">
<div class="header">
<!-- 公司品牌 -->
</div>
<div class="content">
<!-- 表单数据 -->
</div>
<div class="footer">
<!-- 页脚信息 -->
</div>
</div>
</body>
</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 },
});
```