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

7.4 KiB
Raw Blame History

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 数学验证码答案

请求示例

{
  "name": "张三",
  "email": "zhangsan@example.com",
  "phone": "13800138000",
  "subject": "产品咨询",
  "message": "我想了解贵公司的软件开发服务。",
  "submitTime": "1709827200000",
  "mathHash": "MTAwLTE3MDk4MjcxMDAwMDA=",
  "mathTimestamp": "1709827100000",
  "mathAnswer": 100
}

响应参数

参数 类型 描述
success boolean 请求是否成功
message string 成功消息(成功时)
error string 错误消息(失败时)

成功响应

{
  "success": true,
  "message": "消息已发送,我们会尽快与您联系!"
}

错误响应

{
  "success": false,
  "error": "请填写必填字段"
}

错误码说明

HTTP 状态码 错误信息 描述
200 - 蜜罐字段被填充(静默拒绝)
400 请填写必填字段 缺少必填字段
400 请输入有效的邮箱地址 邮箱格式不正确
400 提交过快,请稍后再试 提交时间间隔过短
400 验证码错误,请重新计算 数学验证码错误
500 发送失败,请稍后重试 邮件发送失败

安全机制

1. 蜜罐字段 (Honeypot)

通过隐藏字段 website 检测机器人提交:

// 前端隐藏字段
<input name="website" className="hidden" tabIndex={-1} autoComplete="off" />

// 后端检测
if (website) {
  // 检测到机器人,静默返回成功
  return NextResponse.json({ success: true });
}

2. 提交时间验证

验证表单提交时间间隔,防止快速自动提交:

if (submitTime) {
  const timeDiff = Date.now() - parseInt(submitTime);
  if (timeDiff < 2000) {
    // 提交过快,拒绝请求
    return NextResponse.json({ success: false, error: '提交过快' });
  }
}

3. 数学验证码

使用数学运算验证码防止机器人:

// 前端生成验证码
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. 邮箱验证

验证邮箱格式:

const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
  return NextResponse.json({ success: false, error: '请输入有效的邮箱地址' });
}

5. XSS 防护

使用 DOMPurify 清理用户输入:

import DOMPurify from 'dompurify';

const sanitizedName = DOMPurify.sanitize(name);

邮件服务

Resend 配置

项目使用 Resend 服务发送邮件:

RESEND_API_KEY=re_xxxxx
COMPANY_EMAIL=contact@novalon.cn

邮件模板

邮件使用 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

'use server';

export async function submitContactForm(formData: FormData) {
  // 服务端表单处理逻辑
}

优势:

  • 无需创建 API 路由
  • 自动 CSRF 保护
  • 类型安全
  • 更简洁的错误处理

环境变量

必需配置

# Resend API 密钥
RESEND_API_KEY=re_xxxxx

# 公司邮箱
COMPANY_EMAIL=contact@novalon.cn

可选配置

# 环境
NODE_ENV=production

# 站点 URL
NEXT_PUBLIC_SITE_URL=https://www.novalon.cn

请求限制

速率限制

建议在生产环境配置速率限制:

// 示例:使用 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:

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;
}

错误处理

统一错误响应格式

interface ApiResponse {
  success: boolean;
  message?: string;
  error?: string;
  data?: unknown;
}

错误日志

try {
  await resend.emails.send({ ... });
} catch (error) {
  console.error('邮件发送失败:', error);
  return NextResponse.json(
    { success: false, error: '发送失败,请稍后重试' },
    { status: 500 }
  );
}

测试接口

使用 cURL

curl -X POST http://localhost:3000/api/contact \
  -H "Content-Type: application/json" \
  -d '{
    "name": "测试用户",
    "email": "test@example.com",
    "subject": "测试主题",
    "message": "测试消息内容"
  }'

使用 Playwright

// 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 - 性能监控

日志格式

console.log({
  timestamp: new Date().toISOString(),
  level: 'info',
  message: '联系表单提交',
  data: { email, subject },
});