Skip to Content
API 参考认证鉴权

API 鉴权说明

概述

本 API 使用 API Key + HMAC 签名 的鉴权方案,确保请求的安全性和完整性。

认证方式

1. API Key 认证

最简单的认证方式,适用于服务端到服务端的调用。

curl -H "Authorization: Bearer YOUR_API_KEY" \ https://api.procure-core.com/v1/purchase-requests

2. OAuth 2.0

标准的 OAuth 2.0 流程,适用于第三方应用集成。

授权码流程

# 1. 获取授权码 https://api.procure-core.com/oauth/authorize? response_type=code& client_id=YOUR_CLIENT_ID& redirect_uri=YOUR_REDIRECT_URI& scope=read:purchase-requests write:orders& state=random_string # 2. 交换访问令牌 curl -X POST https://api.procure-core.com/oauth/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=authorization_code" \ -d "code=AUTHORIZATION_CODE" \ -d "client_id=YOUR_CLIENT_ID" \ -d "client_secret=YOUR_CLIENT_SECRET" \ -d "redirect_uri=YOUR_REDIRECT_URI"

客户端凭证流程

curl -X POST https://api.procure-core.com/oauth/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials" \ -d "client_id=YOUR_CLIENT_ID" \ -d "client_secret=YOUR_CLIENT_SECRET" \ -d "scope=read:suppliers write:contracts"

3. JWT 令牌

用于用户会话认证,前端应用常用。

// 获取 JWT 令牌 const response = await fetch('https://api.procure-core.com/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ username: 'user@company.com', password: 'your_password' }) }); const { token } = await response.json(); // 使用令牌调用 API const apiResponse = await fetch('https://api.procure-core.com/v1/profile', { headers: { 'Authorization': `Bearer ${token}` } });

权限范围 (Scopes)

可用范围

{ "read:purchase-requests": "读取采购需求", "write:purchase-requests": "创建和修改采购需求", "read:suppliers": "读取供应商信息", "write:suppliers": "管理供应商信息", "read:orders": "读取订单信息", "write:orders": "创建和修改订单", "read:contracts": "读取合同信息", "write:contracts": "管理合同信息", "read:reports": "读取报表数据", "admin": "管理员权限" }

权限检查

API 会根据令牌的权限范围检查访问权限:

{ "error": { "code": "insufficient_scope", "message": "The request requires higher privileges than provided by the access token.", "required_scope": "write:purchase-requests" } }

令牌管理

令牌刷新

访问令牌有有效期,需要定期刷新:

curl -X POST https://api.procure-core.com/oauth/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=refresh_token" \ -d "refresh_token=YOUR_REFRESH_TOKEN" \ -d "client_id=YOUR_CLIENT_ID" \ -d "client_secret=YOUR_CLIENT_SECRET"

令牌撤销

主动撤销不再使用的令牌:

curl -X POST https://api.procure-core.com/oauth/revoke \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "token=ACCESS_TOKEN_OR_REFRESH_TOKEN" \ -d "client_id=YOUR_CLIENT_ID" \ -d "client_secret=YOUR_CLIENT_SECRET"

安全最佳实践

1. 安全存储

  • 永远不要在前端代码中硬编码密钥
  • 使用环境变量存储敏感信息
  • 定期轮换 API 密钥

2. HTTPS 传输

所有 API 调用必须使用 HTTPS:

# ❌ 错误 - 不安全 curl http://api.procure-core.com/v1/orders # ✅ 正确 - 安全 curl https://api.procure-core.com/v1/orders

3. 令牌有效期

  • 访问令牌:1小时有效期
  • 刷新令牌:30天有效期
  • API 密钥:永不过期(建议定期轮换)

4. IP 白名单

生产环境建议配置 IP 白名单:

{ "api_key": "ak_live_xxx", "allowed_ips": [ "192.168.1.100", "10.0.0.0/8" ] }

错误处理

认证错误

{ "error": { "code": "unauthorized", "message": "Invalid or missing authentication credentials" } }

权限错误

{ "error": { "code": "forbidden", "message": "Insufficient permissions for this operation" } }

令牌过期

{ "error": { "code": "token_expired", "message": "The access token has expired" } }

代码示例

Node.js 示例

const axios = require('axios'); class ProcureBotAPI { constructor(apiKey) { this.apiKey = apiKey; this.baseURL = 'https://api.procure-core.com/v1'; this.client = axios.create({ baseURL: this.baseURL, headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' } }); // 响应拦截器处理认证错误 this.client.interceptors.response.use( response => response, error => { if (error.response?.status === 401) { console.error('Authentication failed. Please check your API key.'); } return Promise.reject(error); } ); } async getPurchaseRequests() { const response = await this.client.get('/purchase-requests'); return response.data; } async createOrder(orderData) { const response = await this.client.post('/orders', orderData); return response.data; } } // 使用示例 const api = new ProcureBotAPI(process.env.PROCUREBOT_API_KEY);

Python 示例

import requests import os class ProcureBotAPI: def __init__(self, api_key): self.api_key = api_key self.base_url = 'https://api.procure-core.com/v1' self.session = requests.Session() self.session.headers.update({ 'Authorization': f'Bearer {api_key}', 'Content-Type': 'application/json' }) def get_suppliers(self): response = self.session.get(f'{self.base_url}/suppliers') response.raise_for_status() return response.json() def create_purchase_request(self, request_data): response = self.session.post( f'{self.base_url}/purchase-requests', json=request_data ) response.raise_for_status() return response.json() # 使用示例 api = ProcureBotAPI(os.getenv('PROCUREBOT_API_KEY')) suppliers = api.get_suppliers()

PHP 示例

<?php class ProcureBotAPI { private $apiKey; private $baseUrl = 'https://api.procure-core.com/v1'; public function __construct($apiKey) { $this->apiKey = $apiKey; } private function makeRequest($method, $endpoint, $data = null) { $url = $this->baseUrl . $endpoint; $options = [ CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . $this->apiKey, 'Content-Type: application/json' ] ]; if ($method === 'POST') { $options[CURLOPT_POST] = true; $options[CURLOPT_POSTFIELDS] = json_encode($data); } $curl = curl_init(); curl_setopt_array($curl, $options); $response = curl_exec($curl); $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); curl_close($curl); if ($httpCode >= 400) { throw new Exception("API Error: HTTP {$httpCode}"); } return json_decode($response, true); } public function getContracts() { return $this->makeRequest('GET', '/contracts'); } public function createContract($contractData) { return $this->makeRequest('POST', '/contracts', $contractData); } } // 使用示例 $api = new ProcureBotAPI($_ENV['PROCUREBOT_API_KEY']); $contracts = $api->getContracts(); ?>

提示: 建议在开发环境中使用测试 API 密钥,生产环境中使用正式密钥。测试密钥以 ak_test_ 开头,正式密钥以 ak_live_ 开头。