Files
wenzi/docs/API_INTEGRATION_GUIDE.md
Your Name 0eed01e9eb docs: 完善项目文档并清理过时文件
新增文档:
- API_INTEGRATION_GUIDE.md: API集成指南(快速开始、SDK示例、常见场景)
- DEPLOYMENT_GUIDE.md: 部署指南(环境要求、生产部署、Docker部署)
- CONFIGURATION_GUIDE.md: 配置指南(环境配置、数据库、Redis、安全)
- DEVELOPMENT_GUIDE.md: 开发指南(环境搭建、项目结构、开发规范)

文档更新:
- api.md: 补充8个缺失的API端点(分享跟踪、回调、用户奖励)

文档清理:
- 归档18个过时文档到 docs/archive/2026-03-04-cleanup/
- 删除3个调试文档(ralph-loop-*)

代码清理:
- 删除4个.bak备份文件
- 删除1个.disabled测试文件

文档结构优化:
- 从~40个文档精简到12个核心文档
- 建立清晰的文档导航体系
- 完善文档间的交叉引用
2026-03-04 10:41:38 +08:00

17 KiB
Raw Blame History

🔌 API集成指南

版本: 1.0 更新时间: 2026-03-04

📋 目录

  1. 快速开始
  2. 认证配置
  3. SDK集成
  4. 常见场景
  5. 错误处理
  6. 最佳实践

🚀 快速开始

前置条件

  • 已获取API密钥通过管理后台创建
  • 已获取Bearer Token用于用户相关接口
  • 了解基本的RESTful API概念

5分钟快速集成

// 1. 配置API客户端
const API_BASE_URL = 'https://api.example.com';
const API_KEY = 'your-api-key-here';
const BEARER_TOKEN = 'your-bearer-token-here';

// 2. 创建活动
async function createActivity() {
  const response = await fetch(`${API_BASE_URL}/api/v1/activities`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': API_KEY,
      'Authorization': `Bearer ${BEARER_TOKEN}`
    },
    body: JSON.stringify({
      name: '春季特惠活动',
      startTime: '2025-03-01T10:00:00+08:00',
      endTime: '2025-03-31T23:59:59+08:00'
    })
  });

  const result = await response.json();
  console.log('活动创建成功:', result.data);
  return result.data;
}

// 3. 获取排行榜
async function getLeaderboard(activityId) {
  const response = await fetch(
    `${API_BASE_URL}/api/v1/activities/${activityId}/leaderboard?page=0&size=20`,
    {
      headers: {
        'X-API-Key': API_KEY,
        'Authorization': `Bearer ${BEARER_TOKEN}`
      }
    }
  );

  const result = await response.json();
  console.log('排行榜数据:', result.data);
  return result.data;
}

// 4. 创建分享跟踪
async function trackShare(activityId, userId) {
  const response = await fetch(`${API_BASE_URL}/api/v1/share/track`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': API_KEY,
      'Authorization': `Bearer ${BEARER_TOKEN}`
    },
    body: JSON.stringify({
      activityId: activityId,
      inviterUserId: userId,
      source: 'wechat'
    })
  });

  const result = await response.json();
  console.log('分享跟踪创建成功:', result.data);
  return result.data;
}

🔐 认证配置

API密钥认证

所有 /api/** 端点都需要 X-API-Key 请求头:

GET /api/v1/activities/1
X-API-Key: a1b2c3d4-e5f6-7890-1234-567890abcdef

获取API密钥

curl -X POST https://api.example.com/api/v1/api-keys \
  -H "Content-Type: application/json" \
  -H "X-API-Key: admin-key" \
  -H "Authorization: Bearer admin-token" \
  -d '{
    "activityId": 1,
    "name": "我的应用密钥"
  }'

Bearer Token认证

用户相关端点需要 Authorization 请求头:

GET /api/v1/me/invitation-info
X-API-Key: a1b2c3d4-e5f6-7890-1234-567890abcdef
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

双重认证

某些端点需要同时提供API密钥和Bearer Token

const headers = {
  'X-API-Key': API_KEY,
  'Authorization': `Bearer ${BEARER_TOKEN}`,
  'Content-Type': 'application/json'
};

📦 SDK集成

Java SDK

<!-- Maven依赖 -->
<dependency>
  <groupId>com.mosquito</groupId>
  <artifactId>mosquito-sdk</artifactId>
  <version>1.0.0</version>
</dependency>
// 初始化客户端
MosquitoClient client = MosquitoClient.builder()
    .baseUrl("https://api.example.com")
    .apiKey("your-api-key")
    .bearerToken("your-bearer-token")
    .build();

// 创建活动
Activity activity = client.activities()
    .create(CreateActivityRequest.builder()
        .name("春季特惠活动")
        .startTime(ZonedDateTime.now())
        .endTime(ZonedDateTime.now().plusDays(30))
        .build());

// 获取排行榜
List<LeaderboardEntry> leaderboard = client.activities()
    .getLeaderboard(activityId, 0, 20);

// 创建分享跟踪
ShareTrackingResponse tracking = client.share()
    .track(activityId, userId, "wechat");

JavaScript/TypeScript SDK

npm install @mosquito/sdk
import { MosquitoClient } from '@mosquito/sdk';

// 初始化客户端
const client = new MosquitoClient({
  baseUrl: 'https://api.example.com',
  apiKey: 'your-api-key',
  bearerToken: 'your-bearer-token'
});

// 创建活动
const activity = await client.activities.create({
  name: '春季特惠活动',
  startTime: new Date('2025-03-01T10:00:00+08:00'),
  endTime: new Date('2025-03-31T23:59:59+08:00')
});

// 获取排行榜
const leaderboard = await client.activities.getLeaderboard(activityId, {
  page: 0,
  size: 20
});

// 创建分享跟踪
const tracking = await client.share.track({
  activityId,
  inviterUserId: userId,
  source: 'wechat'
});

Python SDK

pip install mosquito-sdk
from mosquito import MosquitoClient

# 初始化客户端
client = MosquitoClient(
    base_url='https://api.example.com',
    api_key='your-api-key',
    bearer_token='your-bearer-token'
)

# 创建活动
activity = client.activities.create(
    name='春季特惠活动',
    start_time='2025-03-01T10:00:00+08:00',
    end_time='2025-03-31T23:59:59+08:00'
)

# 获取排行榜
leaderboard = client.activities.get_leaderboard(
    activity_id=activity_id,
    page=0,
    size=20
)

# 创建分享跟踪
tracking = client.share.track(
    activity_id=activity_id,
    inviter_user_id=user_id,
    source='wechat'
)

🎯 常见场景

场景1用户邀请流程

// 1. 用户登录后获取邀请信息
async function getUserInvitationInfo(activityId, userId) {
  const response = await fetch(
    `${API_BASE_URL}/api/v1/me/invitation-info?activityId=${activityId}&userId=${userId}`,
    { headers: { 'X-API-Key': API_KEY, 'Authorization': `Bearer ${BEARER_TOKEN}` } }
  );
  const result = await response.json();
  return result.data; // { code, path, originalUrl }
}

// 2. 生成分享海报
async function generatePoster(activityId, userId, template = 'default') {
  const imageUrl = `${API_BASE_URL}/api/v1/me/poster/image?activityId=${activityId}&userId=${userId}&template=${template}`;
  return imageUrl;
}

// 3. 用户分享后创建跟踪
async function trackUserShare(activityId, userId, source) {
  const response = await fetch(`${API_BASE_URL}/api/v1/share/track`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': API_KEY,
      'Authorization': `Bearer ${BEARER_TOKEN}`
    },
    body: JSON.stringify({ activityId, inviterUserId: userId, source })
  });
  return await response.json();
}

// 4. 查看邀请的好友列表
async function getInvitedFriends(activityId, userId, page = 0) {
  const response = await fetch(
    `${API_BASE_URL}/api/v1/me/invited-friends?activityId=${activityId}&userId=${userId}&page=${page}&size=20`,
    { headers: { 'X-API-Key': API_KEY, 'Authorization': `Bearer ${BEARER_TOKEN}` } }
  );
  const result = await response.json();
  return result.data;
}

// 5. 查看用户奖励
async function getUserRewards(activityId, userId, page = 0) {
  const response = await fetch(
    `${API_BASE_URL}/api/v1/me/rewards?activityId=${activityId}&userId=${userId}&page=${page}&size=20`,
    { headers: { 'X-API-Key': API_KEY, 'Authorization': `Bearer ${BEARER_TOKEN}` } }
  );
  const result = await response.json();
  return result.data;
}

场景2活动数据分析

// 1. 获取活动统计数据
async function getActivityStats(activityId) {
  const response = await fetch(
    `${API_BASE_URL}/api/v1/activities/${activityId}/stats`,
    { headers: { 'X-API-Key': API_KEY, 'Authorization': `Bearer ${BEARER_TOKEN}` } }
  );
  const result = await response.json();
  return result.data; // { totalParticipants, totalShares, dailyStats }
}

// 2. 获取裂变网络图
async function getActivityGraph(activityId, rootUserId = null, maxDepth = 3) {
  const params = new URLSearchParams({
    ...(rootUserId && { rootUserId }),
    maxDepth,
    limit: 1000
  });

  const response = await fetch(
    `${API_BASE_URL}/api/v1/activities/${activityId}/graph?${params}`,
    { headers: { 'X-API-Key': API_KEY, 'Authorization': `Bearer ${BEARER_TOKEN}` } }
  );
  const result = await response.json();
  return result.data; // { nodes, edges }
}

// 3. 获取分享指标
async function getShareMetrics(activityId, startTime, endTime) {
  const params = new URLSearchParams({
    activityId,
    ...(startTime && { startTime }),
    ...(endTime && { endTime })
  });

  const response = await fetch(
    `${API_BASE_URL}/api/v1/share/metrics?${params}`,
    { headers: { 'X-API-Key': API_KEY, 'Authorization': `Bearer ${BEARER_TOKEN}` } }
  );
  const result = await response.json();
  return result.data;
}

// 4. 获取转化漏斗
async function getConversionFunnel(activityId, startTime, endTime) {
  const params = new URLSearchParams({
    activityId,
    ...(startTime && { startTime }),
    ...(endTime && { endTime })
  });

  const response = await fetch(
    `${API_BASE_URL}/api/v1/share/funnel?${params}`,
    { headers: { 'X-API-Key': API_KEY, 'Authorization': `Bearer ${BEARER_TOKEN}` } }
  );
  const result = await response.json();
  return result.data;
}

// 5. 导出排行榜CSV
async function exportLeaderboard(activityId, topN = null) {
  const params = new URLSearchParams({
    ...(topN && { topN })
  });

  const response = await fetch(
    `${API_BASE_URL}/api/v1/activities/${activityId}/leaderboard/export?${params}`,
    { headers: { 'X-API-Key': API_KEY, 'Authorization': `Bearer ${BEARER_TOKEN}` } }
  );

  const blob = await response.blob();
  const url = window.URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = `leaderboard_${activityId}.csv`;
  a.click();
}

场景3Webhook回调集成

// 1. 注册Webhook
async function registerWebhook(activityId, callbackUrl, events) {
  const response = await fetch(`${API_BASE_URL}/api/v1/callback/register`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': API_KEY,
      'Authorization': `Bearer ${BEARER_TOKEN}`
    },
    body: JSON.stringify({
      activityId,
      callbackUrl,
      events, // ['user.registered', 'user.invited', 'reward.granted']
      secret: 'your-webhook-secret'
    })
  });
  return await response.json();
}

// 2. 处理Webhook回调服务端
const express = require('express');
const crypto = require('crypto');

app.post('/webhook', express.json(), (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const payload = JSON.stringify(req.body);
  const secret = 'your-webhook-secret';

  // 验证签名
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  if (signature !== `sha256=${expectedSignature}`) {
    return res.status(401).send('Invalid signature');
  }

  // 处理事件
  const { eventType, data } = req.body;

  switch (eventType) {
    case 'user.registered':
      console.log('新用户注册:', data);
      break;
    case 'user.invited':
      console.log('用户邀请:', data);
      break;
    case 'reward.granted':
      console.log('奖励发放:', data);
      break;
  }

  res.status(200).send('OK');
});

⚠️ 错误处理

统一错误处理

class APIError extends Error {
  constructor(code, message, details) {
    super(message);
    this.code = code;
    this.details = details;
  }
}

async function apiCall(url, options) {
  try {
    const response = await fetch(url, options);
    const result = await response.json();

    if (result.code !== 200 && result.code !== 201) {
      throw new APIError(
        result.error?.code || 'UNKNOWN_ERROR',
        result.message || 'Unknown error',
        result.error?.details
      );
    }

    return result.data;
  } catch (error) {
    if (error instanceof APIError) {
      throw error;
    }
    throw new APIError('NETWORK_ERROR', 'Network request failed', error);
  }
}

// 使用示例
try {
  const activity = await apiCall(`${API_BASE_URL}/api/v1/activities/1`, {
    headers: { 'X-API-Key': API_KEY }
  });
  console.log('活动数据:', activity);
} catch (error) {
  if (error.code === 'NOT_FOUND') {
    console.error('活动不存在');
  } else if (error.code === 'INVALID_API_KEY') {
    console.error('API密钥无效');
  } else {
    console.error('请求失败:', error.message);
  }
}

重试机制

async function apiCallWithRetry(url, options, maxRetries = 3) {
  let lastError;

  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch(url, options);

      // 处理速率限制
      if (response.status === 429) {
        const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
        console.log(`速率限制,等待 ${retryAfter} 秒后重试...`);
        await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
        continue;
      }

      // 处理服务器错误
      if (response.status >= 500) {
        console.log(`服务器错误,${i + 1}/${maxRetries} 次重试...`);
        await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
        continue;
      }

      return await response.json();
    } catch (error) {
      lastError = error;
      if (i < maxRetries - 1) {
        console.log(`网络错误,${i + 1}/${maxRetries} 次重试...`);
        await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
      }
    }
  }

  throw lastError;
}

💡 最佳实践

1. 使用连接池

// Node.js
const https = require('https');

const agent = new https.Agent({
  keepAlive: true,
  maxSockets: 50,
  maxFreeSockets: 10,
  timeout: 60000
});

const response = await fetch(url, {
  agent,
  headers: { 'X-API-Key': API_KEY }
});

2. 实现请求缓存

const cache = new Map();
const CACHE_TTL = 60000; // 1分钟

async function cachedApiCall(url, options, ttl = CACHE_TTL) {
  const cacheKey = `${url}:${JSON.stringify(options)}`;
  const cached = cache.get(cacheKey);

  if (cached && Date.now() - cached.timestamp < ttl) {
    return cached.data;
  }

  const data = await apiCall(url, options);
  cache.set(cacheKey, { data, timestamp: Date.now() });

  return data;
}

3. 批量请求优化

async function batchGetActivities(activityIds) {
  // 并发请求,但限制并发数
  const BATCH_SIZE = 10;
  const results = [];

  for (let i = 0; i < activityIds.length; i += BATCH_SIZE) {
    const batch = activityIds.slice(i, i + BATCH_SIZE);
    const promises = batch.map(id =>
      apiCall(`${API_BASE_URL}/api/v1/activities/${id}`, {
        headers: { 'X-API-Key': API_KEY }
      })
    );

    const batchResults = await Promise.all(promises);
    results.push(...batchResults);
  }

  return results;
}

4. 监控和日志

function logApiCall(url, options, duration, result) {
  console.log({
    timestamp: new Date().toISOString(),
    url,
    method: options.method || 'GET',
    duration: `${duration}ms`,
    status: result.code,
    success: result.code === 200 || result.code === 201
  });
}

async function monitoredApiCall(url, options) {
  const startTime = Date.now();
  try {
    const result = await apiCall(url, options);
    logApiCall(url, options, Date.now() - startTime, result);
    return result;
  } catch (error) {
    logApiCall(url, options, Date.now() - startTime, { code: error.code, error: error.message });
    throw error;
  }
}

5. 安全最佳实践

// ❌ 不要在客户端暴露API密钥
// const API_KEY = 'a1b2c3d4-e5f6-7890-1234-567890abcdef';

// ✅ 通过后端代理API请求
async function proxyApiCall(endpoint, options) {
  const response = await fetch(`/api/proxy${endpoint}`, {
    ...options,
    headers: {
      ...options.headers,
      'Authorization': `Bearer ${userToken}` // 只传用户token
    }
  });
  return await response.json();
}

// 后端代理Node.js/Express
app.use('/api/proxy', async (req, res) => {
  const response = await fetch(`${API_BASE_URL}${req.path}`, {
    method: req.method,
    headers: {
      'X-API-Key': process.env.API_KEY, // 从环境变量读取
      'Authorization': req.headers.authorization,
      'Content-Type': 'application/json'
    },
    body: req.method !== 'GET' ? JSON.stringify(req.body) : undefined
  });

  const result = await response.json();
  res.json(result);
});

📚 相关资源

🆘 获取帮助


文档版本: 1.0 最后更新: 2026-03-04