API 请求示例
API 请求示例
参见 HTTP 开发规范 · accessToken · v2 设备接口:能力使用。
以下以 accessToken 为例。将示例代码复制到工程中即可快速调试;跑通后,可参照同样流程调用其他 OpenAPI 方法。
1. Java 示例
/**
* Imou 开放平台 — accessToken(获取管理员 Token)Java 示例
*
* 接口文档:https://open.imoulife.com/book/zh/05-api/02.accessToken.html
* 开发规范(sign 计算):https://open.imou.com/document/pages/c20750/
*
* 注意:
* 1. appId / appSecret 在控制台「我的应用 → 应用信息」获取,勿将真实密钥提交到代码仓库。
* 2. accessToken 有效期约 3 天,仅在临近过期或返回 TK1002 时刷新,避免频繁调用。
* 3. 将请求域名中的 [DataCenter] 替换为应用所属数据中心(如 sg、or)。
* 4. 示例中的 appId / appSecret 仅为占位,请替换为真实值。
*/
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.time.Duration;
import java.time.Instant;
import java.util.Base64;
import java.util.UUID;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class AccessTokenDemo {
/** 替换为实际数据中心域名,例如 openapi-sg.easy4ip.com */
private static final String OPENAPI_HOST = "https://openapi-[DataCenter].easy4ip.com";
private static final String APP_ID = "your_appId_here";
private static final String APP_SECRET = "your_appSecret_here";
public static void main(String[] args) throws Exception {
log("========== 开始请求 accessToken ==========");
String responseBody = requestAccessToken(APP_ID, APP_SECRET);
log("========== 请求结束 ==========");
log("接口原始响应: " + responseBody);
}
public static String requestAccessToken(String appId, String appSecret) throws Exception {
log("[步骤 1] 生成鉴权参数");
long time = Instant.now().getEpochSecond();
String nonce = UUID.randomUUID().toString();
String requestId = UUID.randomUUID().toString();
log(" time = " + time);
log(" nonce = " + nonce);
log(" requestId = " + requestId);
log(" appId = " + appId);
log("[步骤 2] 计算 sign(HMAC-SHA256 + Base64)");
String sign = calcSign(time, nonce, appSecret);
log(" sign = " + sign);
log("[步骤 3] 组装请求体");
String body = ""
+ "{"
+ "\"system\":{"
+ "\"ver\":\"1.0\","
+ "\"appId\":\"" + escapeJson(appId) + "\","
+ "\"sign\":\"" + escapeJson(sign) + "\","
+ "\"time\":" + time + ","
+ "\"nonce\":\"" + escapeJson(nonce) + "\""
+ "},"
+ "\"id\":\"" + escapeJson(requestId) + "\","
+ "\"params\":{}"
+ "}";
log(" requestBody = " + body);
String url = OPENAPI_HOST + "/openapi/accessToken";
log("[步骤 4] 发送 HTTP POST");
log(" url = " + url);
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.timeout(Duration.ofSeconds(30))
.header("Content-Type", "application/json;charset=UTF-8")
.POST(HttpRequest.BodyPublishers.ofString(body, StandardCharsets.UTF_8))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
log("[步骤 5] 收到响应");
log(" httpStatus = " + response.statusCode());
if (response.statusCode() / 100 != 2) {
log(" error body = " + response.body());
throw new IllegalStateException("Unexpected HTTP status: " + response.statusCode() + ", body=" + response.body());
}
return response.body();
}
public static String calcSign(long time, String nonce, String appSecret) throws Exception {
String signTemplate = "time:" + time + ",nonce:" + nonce + ",appSecret:" + appSecret;
String rawForLog = "time:" + time + ",nonce:" + nonce + ",appSecret:***";
log(" sign 原串(已脱敏)= " + rawForLog);
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
byte[] secretDigest = sha256.digest(appSecret.getBytes(StandardCharsets.UTF_8));
StringBuilder passwordBuilder = new StringBuilder(64);
for (byte b : secretDigest) {
passwordBuilder.append(String.format("%02x", b));
}
String password = passwordBuilder.toString();
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(password.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] digest = mac.doFinal(signTemplate.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(digest);
}
private static void log(String message) {
System.out.println("[AccessTokenDemo] " + message);
}
private static String escapeJson(String value) {
if (value == null) {
return "";
}
return value
.replace("\\", "\\\\")
.replace("\"", "\\\"");
}
}
2. Python 示例
"""
Imou 开放平台 — accessToken(获取管理员 Token)Python 示例
接口文档:https://open.imoulife.com/book/zh/05-api/02.accessToken.html
开发规范(sign 计算):https://open.imou.com/document/pages/c20750/
"""
from __future__ import annotations
import base64
import hashlib
import hmac
import json
import time
import uuid
import urllib.error
import urllib.request
OPENAPI_HOST = "https://openapi-[DataCenter].easy4ip.com"
APP_ID = "your_appId_here"
APP_SECRET = "your_appSecret_here"
def log(message: str) -> None:
print(f"[AccessTokenDemo] {message}")
def calc_sign(ts: int, nonce: str, app_secret: str) -> str:
sign_template = f"time:{ts},nonce:{nonce},appSecret:{app_secret}"
raw_for_log = f"time:{ts},nonce:{nonce},appSecret:***"
log(f" sign 原串(已脱敏)= {raw_for_log}")
password = hashlib.sha256(app_secret.encode("utf-8")).hexdigest().lower()
digest = hmac.new(
password.encode("utf-8"),
sign_template.encode("utf-8"),
hashlib.sha256,
).digest()
return base64.b64encode(digest).decode("utf-8")
def request_access_token(app_id: str, app_secret: str) -> str:
log("[步骤 1] 生成鉴权参数")
ts = int(time.time())
nonce = str(uuid.uuid4())
request_id = str(uuid.uuid4())
log(f" time = {ts}")
log(f" nonce = {nonce}")
log(f" requestId = {request_id}")
log(f" appId = {app_id}")
log("[步骤 2] 计算 sign(HMAC-SHA256 + Base64)")
sign = calc_sign(ts, nonce, app_secret)
log(f" sign = {sign}")
log("[步骤 3] 组装请求体")
body_obj = {
"system": {
"ver": "1.0",
"appId": app_id,
"sign": sign,
"time": ts,
"nonce": nonce,
},
"id": request_id,
"params": {},
}
body = json.dumps(body_obj, ensure_ascii=False, separators=(",", ":"))
log(f" requestBody = {body}")
url = f"{OPENAPI_HOST}/openapi/accessToken"
log("[步骤 4] 发送 HTTP POST")
log(f" url = {url}")
request = urllib.request.Request(
url,
data=body.encode("utf-8"),
headers={"Content-Type": "application/json;charset=UTF-8"},
method="POST",
)
try:
with urllib.request.urlopen(request, timeout=30) as response:
response_body = response.read().decode("utf-8")
http_status = response.getcode()
except urllib.error.HTTPError as e:
error_body = e.read().decode("utf-8", errors="replace")
log(f" httpStatus = {e.code}")
log(f" error body = {error_body}")
raise RuntimeError(f"Unexpected HTTP status: {e.code}, body={error_body}") from e
log("[步骤 5] 收到响应")
log(f" httpStatus = {http_status}")
if http_status // 100 != 2:
log(f" error body = {response_body}")
raise RuntimeError(f"Unexpected HTTP status: {http_status}, body={response_body}")
return response_body
if __name__ == "__main__":
log("========== 开始请求 accessToken ==========")
response_body = request_access_token(APP_ID, APP_SECRET)
log("========== 请求结束 ==========")
log(f"接口原始响应: {response_body}")
