獲取和使用 API Key
在 EasyAR 開發中心創建 API Key 無數量限制,建議爲不同應用分配獨立的 API Key,以便更精細地管控權限。
創建 API Key
登錄到 EasyAR 開發中心,如果您是首次使用 API Key,請先創建一個 API Key,步驟如下:
- 在“授權”下,點擊“雲服務 API KEY”
- 在“API KEY”頁面點擊“創建 API KEY”按鈕

- 填寫“應用名稱”
- 根據您的應用需求進行勾選所需雲服務,不建議全部授權。
- 點擊“確定”
提示
使用 SpatialMap,勾選 SpatialMap。
使用雲識別,勾選雲識別。
使用 Mega Landmark,勾選 Mega Landmark,使用此功能前需要向商務申請。
使用 AR 運營中心,勾選 AR 運營中心,使用此功能前需要向商務申請。
使用 Mega Block 雲定位,勾選 Mega Block。

- 此時會在頁面生成 API Key 與 API Secret,如下圖所示,注意不要泄露。

警告
不要在客戶端(如 Web,微信小程序等)應用上直接使用 API Key 與 API Secret。
獲取 Token
有兩種方式可以獲取到 Token:1. 從開發中心直接獲取;2. 編寫代碼獲取。如果你對資源的訪問權限有控制需求,建議使用第2種方式。下面將分別介紹這兩種獲取方式,可根據您的需求自行選擇。
從開發中心獲取 Token
- 選擇一個您要使用的 API Key,點擊右側的“管理”

- 選擇一個 Token 的有效期
- 點擊“生成 Token”
- 點擊“複製”即可

附註
安全性是 Token 有效期設置的首要原因。 如果 Token 有效期過長,一旦被泄露或竊取,攻擊者可長期使用,導致數據泄露或未授權操作;有效期限制了 Token 的有效窗口,即使泄露,危害也僅限於短時間。
使用 API Key 與 API Secret 生成 Token
Token 的生成過程要求核心參數進行簽名操作,確保傳輸安全性。隨後,這些簽名後的數據被髮送到 STS(Security Token Service)服務進行身份驗證。STS 服務驗證通過後,會頒發一個臨時訪問 Token,該 Token 僅在指定時間窗口內有效,超時後需重新發起認證流程。
警告
不要在客戶端代碼中生成 Token,而是在服務器端生成 Token 後傳給客戶端使用。
請求參數
| 字段名 |
類型 |
是否必填 |
描述 |
| apiKey |
string |
是 |
API Key |
| expires |
int |
是 |
生成的 Token 有效時間, 單位爲秒 |
| acl |
string |
是 |
訪問控制列表 (Access Control List),控制 token 可訪問資源權限 |
| timestamp |
long |
是 |
時間戳,單位爲毫秒 |
| signature |
string |
是 |
簽名 |
acl: 由一個或多個 AC(訪問控制)組成,每個 AC 包含 service,effect,resource,permission 四個部分。
- service:服務類型,當前支持 ecs:crs(雲識別),ecs:spatialmap(稀疏空間地圖),ecs:cls(Mega Block 雲定位),ecs:vps1(landmark)
- resource: 具體服務的 app id,例如雲識別庫的 CRS AppId
- effect: 指定與該條 resource 配置項匹配的訪問能否執行, 取值 Allow,Deny
- permission: 權限取值 READ,WRITE
結構舉例如下:
[
{
"service": "ecs:crs",
"resource": ["f7ff497727ab2d55ea01d9984ef8068c"],
"effect": "Allow",
"permission": ["READ"]
}
]
簽名方法
- 將請求的所有參數按鍵名排序
- 對於每個參數,將其鍵名與值拼接成字符串
- 將這樣得到的所有字符串拼接,在最後拼上 API Secret
- 計算字符串 sha256 哈希的十六進制即爲簽名
簽名樣例
<?php
// 您的 API Key 與 API Secret
$apiKey = '6a47f7f8ff6......68744b4bcf';
$apiSecret = '87745d866345256b......fbae27c502a';
// 您的服務 App ID
$appId = 'f7ff497727ab2d55ea01d9984ef8068c';
// 有效時間, 單位爲秒
$expires = 3600;
// 構建待簽名參數
$data = [
'apiKey' => $apiKey,
'expires' => $expires,
'acl' => '[{"service":"ecs:crs","resource":["'. $appId .'"],"effect":"Allow","permission":["READ"]}]',
'timestamp' => time() * 1000,
];
// 排序
ksort($data);
// 拼接字符串
$builder = [];
foreach ($data as $key => $value) {
array_push($builder, $key . $value);
}
// 拼接 API Secret
array_push($builder, $apiSecret);
// 生成簽名
$signature = hash('sha256', implode('', $builder));
echo $signature;
const crypto = require('crypto');
// 您的 API Key 與 API Secret
const apiKey = '6a47f7f8ff6......68744b4bcf'
const apiSecret = '87745d866345256b......fbae27c502a'
// 您的服務 App ID
const appId = 'f7ff497727ab2d55ea01d9984ef8068c';
// 有效時間, 單位爲秒
const expires = 3600
// 構建待簽名參數
const data = {
apiKey: apiKey,
expires: expires,
acl: `[{"service":"ecs:crs","resource":["${appId}"],"effect":"Allow","permission":["READ"]}]`,
timestamp: Date.now(),
}
// 排序與拼接字符串
let builder = [];
Object.keys(data).sort().forEach(key => builder.push(`${key}${data[key]}`));
// 拼接 API Secret
builder.push(apiSecret);
// 生成簽名
const signature = crypto.createHash('sha256').update(builder.join('')).digest('hex');
console.info(signature);
import time
import hashlib
# 您的 API Key 與 API Secret
apiKey = '6a47f7f8ff6......68744b4bcf'
apiSecret = '87745d866345256b......fbae27c502a'
# 您的服務 App ID
appId = 'f7ff497727ab2d55ea01d9984ef8068c'
# 有效時間, 單位爲秒
expires = 3600
# 構建待簽名參數
data = dict(sorted({
'apiKey': apiKey,
'expires': expires,
'acl': '[{"service":"ecs:crs","resource":["'+ appId +'"],"effect":"Allow","permission":["READ"]}]',
'timestamp': int(time.time() * 1000),
}.items()))
# 拼接字符串
builder = [f'{key}{value}' for key, value in data.items()]
# 拼接 API Secret
builder.append(apiSecret)
# 生成簽名
signature = hashlib.sha256(''.join(builder).encode('utf8')).hexdigest()
print(signature)
package com.easyar;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.SortedMap;
import java.util.TreeMap;
public class App {
public static void main(String[] args) throws NoSuchAlgorithmException {
// 您的 API Key 與 API Secret
String apiKey = "6a47f7f8ff6......68744b4bcf";
String apiSecret = "87745d866345256b......fbae27c502a";
// 服務的 App ID
String appId = "f7ff497727ab2d55ea01d9984ef8068c";
// 有效時間, 單位爲秒
int expires = 3600;
// 構建待簽名參數
SortedMap<String, Object> data = new TreeMap<>();
data.put("apiKey", apiKey);
data.put("expires", expires);
data.put("timestamp", System.currentTimeMillis());
data.put("acl", "[{\"service\":\"ecs:crs\",\"resource\":[\"" + appId + "\"],\"effect\":\"Allow\",\"permission\":[\"READ\"]}]");
// 拼接字符串
StringBuilder builder = new StringBuilder();
data.forEach((key, value) -> builder.append(String.format("%s%s", key, value)));
// 拼接 API Secret
builder.append(apiSecret);
// 生成簽名
String signature = sha256(builder.toString());
System.out.println(signature);
}
private static String sha256(String str) throws NoSuchAlgorithmException {
StringBuilder builder = new StringBuilder();
MessageDigest digest = MessageDigest.getInstance("sha-256");
digest.update(str.getBytes(StandardCharsets.UTF_8));
byte[] bytes = digest.digest();
for (byte b : bytes) {
String hex = Integer.toHexString(b & 0XFF);
if (hex.length() == 1) {
builder.append("0");
}
builder.append(hex);
}
return builder.toString();
}
}
using System.Text;
using System.Security.Cryptography;
namespace EasyAR {
static class Program {
static void Main(string[] args) {
// 您的 API Key 與 API Secret
string apiKey = "6a47f7f8ff6......68744b4bcf";
string apiSecret = "87745d866345256b......fbae27c502a";
// 服務的 App ID
string appId = "f7ff497727ab2d55ea01d9984ef8068c";
// 有效時間, 單位爲秒
int expires = 3600;
// 構建待簽名參數
SortedDictionary<string, object> data = new() {
{ "apiKey", apiKey },
{ "expires", expires },
{ "timestamp", DateTimeOffset.Now.ToUnixTimeMilliseconds() },
{ "acl", "[{\"service\":\"ecs:crs\",\"resource\":[\"" + appId + "\"],\"effect\":\"Allow\",\"permission\":[\"READ\"]}]" }
};
// 拼接字符串
StringBuilder builder = new StringBuilder();
data.ToList().ForEach(pair => builder.Append($"{pair.Key}{pair.Value}"));
// 拼接 API Secret
builder.Append(apiSecret);
// 生成簽名
string signature = Sha256(builder.ToString());
Console.WriteLine(signature);
}
static string Sha256(string str) {
byte[] data = SHA256.HashData(Encoding.UTF8.GetBytes(str));
StringBuilder builder = new StringBuilder();
for (int i = 0; i < data.Length; i++) {
builder.Append(data[i].ToString("x2"));
}
return builder.ToString();
}
}
}
package main
import (
"crypto/sha256"
"fmt"
"sort"
"strings"
"time"
)
func main() {
// 您的 API Key 與 API Secret
apiKey := "6a47f7f8ff6......68744b4bcf"
apiSecret := "87745d866345256b......fbae27c502a"
// 您的服務 App ID
appId := "f7ff497727ab2d55ea01d9984ef8068c"
// 有效時間, 單位爲秒
expires := 3600
// 構建待簽名參數
data := map[string]any{
"apiKey": apiKey,
"expires": expires,
"acl": `[{"service":"ecs:crs","resource":["` + appId + `"],"effect":"Allow","permission":["READ"]}]`,
"timestamp": time.Now().Unix() * 1000,
}
// 排序
keys := []string{}
for key := range data {
keys = append(keys, key)
}
sort.Strings(keys)
// 拼接字符串
builder := strings.Builder{}
for _, key := range keys {
builder.WriteString(fmt.Sprintf("%s%v", key, data[key]))
}
// 拼接 API Secret
builder.WriteString(apiSecret)
// 生成簽名
signature := fmt.Sprintf("%x", sha256.Sum256([]byte(builder.String())))
fmt.Println(signature)
}
提示
加入簽名時需要 ACL 轉換爲 JSON 字符串。
獲取 Token
將上述生成好的簽名加入到參數列表中,發送請求到 /token/v2 接口,獲取 Token。
- 請求地址:
https://uac.easyar.com/token/v2 或 https://uac-na1.easyar.com/token/v2 (北美1區)
- 請求方式:POST
- 請求頭:Content-Type: application/json
- 請求參數:
{"apiKey":"6a47f7f8ff6......68744b4bcf","expires":3600,"acl":"[{\"service\":\"ecs:crs\",\"resource\":[\"f7ff497727ab2d55ea01d9984ef8068c\"],\"effect\":\"Allow\",\"permission\":[\"READ\"]}]","timestamp":1765954279002,"signature":"32f18a37fc3c18......55c4943af9"}
示例如下:
curl -X POST https://uac.easyar.com/token/v2 \
-H 'Content-Type: application/json' \
-d '{"apiKey":"6a47f7f8ff6......68744b4bcf","expires":3600,"acl":"[{\"service\":\"ecs:crs\",\"resource\":[\"f7ff497727ab2d55ea01d9984ef8068c\"],\"effect\":\"Allow\",\"permission\":[\"READ\"]}]","timestamp":1765954279002,"signature":"32f18a37fc3c18......55c4943af9"}'
返回結果中如果 statusCode 爲 0,則表示成功。
正常返回格式:
{
"statusCode": 0,
"timestamp": 1765954874399,
"msg": "Success",
"result": {
"apiKey": "6a47f7f8ff6......68744b4bcf",
"expires": 3600,
"token": "nuPDCj......xstQX",
"expiration": "2025-12-17T08:01:14.399+0000"
}
}
- token: 業務請求認證的 Token。
- expiration: token 的到期時間,過期過後需要重新申請 token。
錯誤返回格式:
{
"statusCode": 4001017,
"timestamp": 1765954666624,
"msg": "AppId is not authorized by this API Key",
"result": null
}
使用 Token
在業務 https 請求中,將 Token 加入請求頭,格式:{"Authorization": "nuPDCj......xstQX"}。
發送業務 API 請求時,需要添加參數 appId(獲取出處請在開發中心查看相關服務)。
錯誤碼說明
在 Token 生成與 Token 使用過程中,可能會引發各類錯誤或異常情況。
爲幫助開發者快速定位問題並採取有效解決措施,以下詳細說明常見錯誤碼及其含義:
| 錯誤碼 |
錯誤信息 |
錯誤說明 |
解決方案 |
| 4001011 |
API Key invalid |
API Key 無效 |
查看“雲服務 API KEY”下是否有此 API Key |
| 4001012 |
Timestamp invalid |
時間戳無效 |
時間戳單位爲毫秒,且與標準時間誤差不要超過 5 分鐘 |
| 4001015 |
Signature invalid |
簽名無效 |
檢查簽名算法是否正確,以及查看 API Secret 與 API KEY 是否匹配 |
| 4001017 |
AppId is not authorized by this API Key |
API Key 未獲此 AppId 授權 |
檢查 AppId 所在的服務是否關聯到此 API Key |
| 4001018 |
Base64 decode error |
請求頭中設置的 Authorization 不是有效 base64 格式 |
獲取到的 Token,不要作任何處理,直接使用 |
| 4001019 |
Decryption error |
請求頭中設置的 Authorization 不是 EasyAR 生成的 |
獲取到的 Token,不要作任何處理,直接使用 |
| 4001022 |
API Key's resource is empty |
API Key 沒有關聯的雲服務 |
檢查 API Key 是否關聯了雲服務及關聯的雲服務是否已經過期 |
| 4001024 |
Token is expired |
Token 已過期 |
重新生成 |
| 4001025 |
Token generate fail |
Token 生成失敗 |
與技術支持聯繫:support@easyar.com |