名称: API集成专家 描述: 专长于集成第三方API,具备适当的认证、错误处理、速率限制和重试逻辑。在集成REST API、GraphQL端点、webhook或外部服务时使用。专精于OAuth流程、API密钥管理、请求/响应转换和构建稳健的API客户端。
API集成专家
为将外部API集成到应用程序提供专家指导,包括生产就绪的模式、安全最佳实践和全面的错误处理。
何时使用此技能
在以下情况使用此技能:
- 集成第三方API(如Stripe、Twilio、SendGrid等)
- 构建API客户端库或包装器
- 实施OAuth 2.0、API密钥或JWT认证
- 设置webhook和事件驱动的集成
- 处理速率限制、重试和断路器
- 转换API响应以供应用使用
- 调试API集成问题
核心集成原则
1. 认证与安全
API密钥管理:
// 将密钥存储在环境变量中,切勿存储在代码中
const apiClient = new APIClient({
apiKey: process.env.SERVICE_API_KEY,
baseURL: process.env.SERVICE_BASE_URL
});
OAuth 2.0 流程:
// 授权代码流程
const oauth = new OAuth2Client({
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
redirectUri: process.env.REDIRECT_URI,
scopes: ['read:users', 'write:data']
});
// 获取授权URL
const authUrl = oauth.getAuthorizationUrl();
// 用代码交换令牌
const tokens = await oauth.exchangeCode(code);
2. 请求/响应处理
标准化的请求结构:
async function makeRequest(endpoint, options = {}) {
const defaultHeaders = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`,
'User-Agent': 'MyApp/1.0.0'
};
const response = await fetch(`${baseURL}${endpoint}`, {
...options,
headers: { ...defaultHeaders, ...options.headers }
});
if (!response.ok) {
throw new APIError(response.status, await response.json());
}
return response.json();
}
响应转换:
class APIClient {
async getUser(userId) {
const raw = await this.request(`/users/${userId}`);
// 将外部API格式转换为内部模型
return {
id: raw.user_id,
email: raw.email_address,
name: `${raw.first_name} ${raw.last_name}`,
createdAt: new Date(raw.created_timestamp)
};
}
}
3. 错误处理
结构化的错误类型:
class APIError extends Error {
constructor(status, body) {
super(`API 错误: ${status}`);
this.status = status;
this.body = body;
this.isAPIError = true;
}
isRateLimited() {
return this.status === 429;
}
isUnauthorized() {
return this.status === 401;
}
isServerError() {
return this.status >= 500;
}
}
指数退避重试逻辑:
async function retryWithBackoff(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (!error.isAPIError || !error.isServerError()) {
throw error; // 不重试客户端错误
}
if (i === maxRetries - 1) throw error;
const delay = Math.pow(2, i) * 1000; // 1秒, 2秒, 4秒
await sleep(delay);
}
}
}
4. 速率限制
客户端速率限制器:
class RateLimiter {
constructor(maxRequests, windowMs) {
this.maxRequests = maxRequests;
this.windowMs = windowMs;
this.requests = [];
}
async acquire() {
const now = Date.now();
this.requests = this.requests.filter(t => now - t < this.windowMs);
if (this.requests.length >= this.maxRequests) {
const oldestRequest = this.requests[0];
const waitTime = this.windowMs - (now - oldestRequest);
await sleep(waitTime);
return this.acquire();
}
this.requests.push(now);
}
}
const limiter = new RateLimiter(100, 60000); // 每分钟100个请求
async function rateLimitedRequest(endpoint, options) {
await limiter.acquire();
return makeRequest(endpoint, options);
}
5. Webhook处理
Webhook验证:
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
app.post('/webhooks/stripe', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['stripe-signature'];
if (!verifyWebhookSignature(req.body, signature, process.env.STRIPE_WEBHOOK_SECRET)) {
return res.status(401).send('无效签名');
}
const event = JSON.parse(req.body);
handleWebhookEvent(event);
res.status(200).send('已接收');
});
集成模式
REST API客户端模式
class ServiceAPIClient {
constructor(config) {
this.apiKey = config.apiKey;
this.baseURL = config.baseURL;
this.timeout = config.timeout || 30000;
}
async request(method, endpoint, data = null) {
const options = {
method,
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
timeout: this.timeout
};
if (data) {
options.body = JSON.stringify(data);
}
const response = await retryWithBackoff(() =>
fetch(`${this.baseURL}${endpoint}`, options)
);
return response.json();
}
// 资源方法
async getResource(id) {
return this.request('GET', `/resources/${id}`);
}
async createResource(data) {
return this.request('POST', '/resources', data);
}
async updateResource(id, data) {
return this.request('PUT', `/resources/${id}`, data);
}
async deleteResource(id) {
return this.request('DELETE', `/resources/${id}`);
}
}
分页处理
async function* fetchAllPages(endpoint, pageSize = 100) {
let cursor = null;
do {
const params = new URLSearchParams({
limit: pageSize,
...(cursor && { cursor })
});
const response = await apiClient.request('GET', `${endpoint}?${params}`);
yield response.data;
cursor = response.pagination?.next_cursor;
} while (cursor);
}
// 用法
for await (const page of fetchAllPages('/users')) {
processUsers(page);
}
最佳实践
安全
- 将API密钥存储在环境变量或秘密管理中
- 所有API调用使用HTTPS
- 验证webhook签名
- 对敏感操作实施请求签名
- 定期轮换API密钥
可靠性
- 实施指数退避重试逻辑
- 优雅处理速率限制
- 设置适当的超时
- 对失败的服务使用断路器
- 记录所有API交互以供调试
性能
- 适当缓存响应
- 当API支持时批处理请求
- 对大响应使用流式处理
- 实施连接池
- 监控API使用情况和成本
监控
- 跟踪API响应时间
- 在错误率增加时发出警报
- 监控速率限制消耗
- 记录失败请求及其上下文
- 为关键集成设置健康检查
常见集成示例
Stripe支付处理
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
async function createPaymentIntent(amount, currency = 'usd') {
return await stripe.paymentIntents.create({
amount,
currency,
automatic_payment_methods: { enabled: true }
});
}
SendGrid电子邮件发送
const sgMail = require('@sendgrid/mail');
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
async function sendEmail(to, subject, html) {
await sgMail.send({
to,
from: process.env.FROM_EMAIL,
subject,
html
});
}
Twilio短信
const twilio = require('twilio')(
process.env.TWILIO_ACCOUNT_SID,
process.env.TWILIO_AUTH_TOKEN
);
async function sendSMS(to, body) {
await twilio.messages.create({
to,
from: process.env.TWILIO_PHONE_NUMBER,
body
});
}
故障排除
认证问题
- 验证API密钥是否正确设置
- 检查令牌过期
- 确保适当的OAuth作用域
- 验证签名生成
速率限制
- 实施客户端速率限制
- 当可用时使用批处理端点
- 在时间上分散请求
- 考虑升级API层级
超时错误
- 为慢速端点增加超时值
- 实施请求取消
- 对大负载使用流式处理
- 检查网络连接
在集成API时,优先考虑安全性、可靠性和可维护性。始终在生产部署前测试错误场景和边缘情况。