拼装版 API 鉴权
拼装版 API 的鉴权全程应在接入方服务端完成:先用 AK/SK 签名换取 token,再用统一的三个 Header 调用开放 API。
完成一次 API 鉴权
| 你要完成什么 | 关键点 |
|---|---|
获取 token | 接入方服务端调用 GET /api/grant/token |
| 生成签名 | 使用 Secret Key 对 GET@/api/grant/token/@{timestamp} 计算 HmacSHA1 |
| 调用开放 API | 请求 Header 携带 x-api-key、x-token 和 x-channel |
| 保护凭证 | Secret Key 和 token 不应暴露给浏览器页面 |
写代码前确认四件事
| 检查项 | 要求 |
|---|---|
| 开放平台凭证 | 已获取 App Key 和 Secret Key |
| 用户标识 | 已确定接入方用户唯一标识 uid |
| 调用位置 | token 获取和开放 API 调用都应在接入方服务端完成 |
| 前端安全 | 不要把 Secret Key 或 token 暴露给浏览器页面 |
鉴权链路
- 接入方服务端构造待签字符串。
- 使用
Secret Key计算x-signature。 - 调用
GET /api/grant/token获取token。 - 服务端调用开放 API 时携带
x-api-key、x-token和x-channel。 - 根据
time_expire缓存并刷新token。
签名规则
| 字段 | 取值 |
|---|---|
| 请求方法 | GET |
| 签名路径 | /api/grant/token/ |
| 待签字符串 | GET@/api/grant/token/@{timestamp} |
| 签名算法 | HmacSHA1 后进行 Base64 编码 |
Node.js 服务端完整示例
ts
import CryptoJS from 'crypto-js'
const API_ORIGIN = 'https://co.aippt.cn'
const apiKey = process.env.AIPPT_API_KEY!
const apiSecret = process.env.AIPPT_API_SECRET!
function createSignature(path: string, timestamp: number) {
const apiUri = path.endsWith('/') ? path : `${path}/`
const stringToSign = `GET@${apiUri}@${timestamp}`
const hash = CryptoJS.HmacSHA1(stringToSign, apiSecret)
return CryptoJS.enc.Base64.stringify(hash)
}
export async function getAipptToken(uid: string, channel = '') {
const path = '/api/grant/token'
const timestamp = Math.floor(Date.now() / 1000)
const signature = createSignature(path, timestamp)
const url = new URL(path, API_ORIGIN)
url.searchParams.set('uid', uid)
url.searchParams.set('channel', channel)
const response = await fetch(url, {
method: 'GET',
headers: {
'x-api-key': apiKey,
'x-timestamp': String(timestamp),
'x-signature': signature
}
})
const result = await response.json()
if (!response.ok || result.code !== 0) {
throw new Error(result.msg || `获取 token 失败:${response.status}`)
}
return {
token: result.data.token as string,
expiresIn: result.data.time_expire as number,
apiKey: result.data.api_key as string,
uid: result.data.uid as string
}
}其他语言签名片段
以下示例只负责生成 x-signature。实际请求时还需要同时传入 x-api-key 和同一个 timestamp。
Java
java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
String apiSecret = "<apiSecret>";
long timestamp = System.currentTimeMillis() / 1000;
String stringToSign = "GET@/api/grant/token/@" + timestamp;
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA1"));
String signature = Base64.getEncoder().encodeToString(
mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8))
);Python
python
import base64
import hashlib
import hmac
import time
api_secret = "<apiSecret>"
timestamp = int(time.time())
string_to_sign = f"GET@/api/grant/token/@{timestamp}"
signature = base64.b64encode(
hmac.new(api_secret.encode(), string_to_sign.encode(), hashlib.sha1).digest()
).decode()Go
go
package main
import (
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"fmt"
"time"
)
func main() {
apiSecret := "<apiSecret>"
timestamp := time.Now().Unix()
stringToSign := fmt.Sprintf("GET@/api/grant/token/@%d", timestamp)
mac := hmac.New(sha1.New, []byte(apiSecret))
mac.Write([]byte(stringToSign))
signature := base64.StdEncoding.EncodeToString(mac.Sum(nil))
fmt.Println(signature)
}PHP
php
<?php
$apiSecret = '<apiSecret>';
$timestamp = time();
$stringToSign = 'GET@/api/grant/token/@' . $timestamp;
$signature = base64_encode(hash_hmac('sha1', $stringToSign, $apiSecret, true));
?>请求 Header 中的 x-timestamp 必须与待签字符串里的 {timestamp} 保持一致。
获取 token
业务流程图
接口说明
| 接口描述 | token有效期目前是3天,建议接入方服务端缓存并跟踪 x-token 的过期时间并及时更新,避免频繁调用(token有效期未来可能能随时更改,建议使用接口响应time_expire时间作为缓存有效期) | ||
| 接口地址 | /api/grant/token | 请求方式 | GET |
| 权限校验 | 是 | 请求参数 | json |
请求参数
请求示例
bash
curl --location 'https://co.aippt.cn/api/grant/token?uid=1&channel=' \
--header 'x-api-key: <apiKey>' \
--header 'x-timestamp: 1696821929' \
--header 'x-signature: <signature>'<signature> 必须按以下签名规则实时计算,不要复用示例值。
响应内容
响应示例
json
{
"code": 0,
"data": {
"api_key": "xxxx",
"uid": "123",
"token": "xxxx",
"time_expire": 2592000
},
"msg": "ok"
}调用开放 API
AiPPT 开放 API 请求需要携带以下 Header:
示例:
bash
curl --location --request POST 'https://co.aippt.cn/api/ai/chat/v2/task' \
--header 'x-api-key: <apiKey>' \
--header 'x-channel: ' \
--header 'x-token: <token>' \
--form 'title="毕业季"' \
--form 'type="1"'过期处理
| 场景 | 建议处理 |
|---|---|
token 即将过期 | 接入方服务端根据 time_expire 提前重新获取。 |
| API 返回鉴权失败 | 检查 x-api-key、x-token、x-channel 是否来自同一接入方和用户链路。 |
| 签名失败 | 检查签名路径末尾 /、x-timestamp 和待签字符串是否一致。 |
