Files
wenzi/docs/API_INTEGRATION_GUIDE.md

714 lines
18 KiB
Markdown
Raw Permalink 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集成指南
> 版本: 1.0
> 更新时间: 2026-03-04
## 📋 目录
1. [快速开始](#快速开始)
2. [认证配置](#认证配置)
3. [SDK集成](#sdk集成)
4. [常见场景](#常见场景)
5. [错误处理](#错误处理)
6. [最佳实践](#最佳实践)
## 🚀 快速开始
### 前置条件
- 已获取API密钥通过管理后台创建
- 已获取Bearer Token用于用户相关接口
- 了解基本的RESTful API概念
### 5分钟快速集成
```javascript
// 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 Key 和 Bearer TokenJWT
| 路径模式 | 认证方式 | 说明 |
|----------|----------|------|
| `/r/**` | 无需认证 | 短链接跳转 |
| `/actuator/**` | 无需认证 | Spring Boot Actuator |
| `/api/v1/callback/**` | X-API-Key | 第三方回调接口 |
| `/api/v1/share/**` | X-API-Key + Bearer Token | 分享跟踪接口 |
| `/api/v1/me/**` | Bearer Token | 用户中心接口 |
| `/api/v1/activities/**` | Bearer Token | 用户端活动接口 |
| `/api/v1/activities/admin/**` | Bearer Token + 权限校验 | 管理后台活动接口 |
| `/api/v1/rewards/admin/**` | Bearer Token + 权限校验 | 管理后台奖励接口 |
| `/api/v1/roles/**` | Bearer Token + 权限校验 | 角色管理接口 |
| `/api/v1/departments/**` | Bearer Token + 权限校验 | 部门管理接口 |
| `/api/v1/approval/**` | Bearer Token + 权限校验 | 审批中心接口 |
| `/api/v1/users/**` | Bearer Token + 权限校验 | 用户管理接口 |
| `/api/v1/permissions/**` | Bearer Token + 权限校验 | 权限管理接口 |
| `/api/v1/invites/**` | Bearer Token + 权限校验 | 邀请管理接口 |
| `/api/v1/notifications/**` | Bearer Token + 权限校验 | 通知管理接口 |
| `/api/v1/risk/**` | Bearer Token + 权限校验 | 风险管理接口 |
| `/api/v1/audit/**` | Bearer Token + 权限校验 | 审计日志接口 |
| `/api/v1/system/**` | Bearer Token + 权限校验 | 系统管理接口 |
| `/api/v1/dashboard/**` | Bearer Token + 权限校验 | 仪表盘接口 |
| `/api/v1/api-keys/**` | Bearer Token + 权限校验 | API密钥管理接口 |
### API密钥认证
仅第三方回调和分享跟踪接口需要 `X-API-Key` 请求头:
```http
POST /api/v1/callback/register
X-API-Key: a1b2c3d4-e5f6-7890-1234-567890abcdef
Content-Type: application/json
{"trackingId": "track-abc123", "externalUserId": "user456", "timestamp": 1699999999999}
```
**获取API密钥**
```bash
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` 请求头:
```http
GET /api/v1/me/invitation-info
X-API-Key: a1b2c3d4-e5f6-7890-1234-567890abcdef
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```
### 双重认证
某些端点需要同时提供API密钥和Bearer Token
```javascript
const headers = {
'X-API-Key': API_KEY,
'Authorization': `Bearer ${BEARER_TOKEN}`,
'Content-Type': 'application/json'
};
```
## 📦 SDK集成
### Java SDK
```xml
<!-- Maven依赖 -->
<dependency>
<groupId>com.mosquito</groupId>
<artifactId>mosquito-sdk</artifactId>
<version>1.0.0</version>
</dependency>
```
```java
// 初始化客户端
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
```bash
npm install @mosquito/sdk
```
```typescript
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
```bash
pip install mosquito-sdk
```
```python
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用户邀请流程
```javascript
// 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活动数据分析
```javascript
// 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回调集成
```javascript
// 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({
trackingId: 'track-abc123',
externalUserId: 'user456',
timestamp: Date.now(),
deviceFingerprint: 'fp-xxx',
ip: '192.168.1.1'
})
});
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');
});
```
## ⚠️ 错误处理
### 统一错误处理
```javascript
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);
}
}
```
### 重试机制
```javascript
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. 使用连接池
```javascript
// 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. 实现请求缓存
```javascript
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. 批量请求优化
```javascript
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. 监控和日志
```javascript
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. 安全最佳实践
```javascript
// ❌ 不要在客户端暴露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);
});
```
## 📚 相关资源
- [API文档](./api.md) - 完整的API端点参考
- [部署指南](./DEPLOYMENT_GUIDE.md) - 如何部署应用
- [配置指南](./CONFIGURATION_GUIDE.md) - 配置选项说明
- [开发指南](./DEVELOPMENT_GUIDE.md) - 如何参与开发
## 🆘 获取帮助
- **技术支持**: support@example.com
- **问题反馈**: https://github.com/your-org/mosquito/issues
- **API状态**: https://status.example.com
---
**文档版本**: 1.0
**最后更新**: 2026-03-04