| 版本 | 更新日期 | 更新说明 | 修改人 |
|---|---|---|---|
| v1.0.1 | 2026-03-25 | 调整部分字段说明 | 严永龙 |
| V1.0.0 | 2025-09-09 | 新建文档 | 陈鲁彬 |
1.3、token个性化改造示例:
-H "token: xxxxxxxx" 中的token是开发者自己的服务端的鉴权参数。默认key=token,但key可以在js配置时自定义为别的值。例如
init({"token_keyname":"authority"}),则js会默认发起类似如下的请求:
curl -X POST http://localhost:13001/api/v2/token \
-H "Content-Type: application/json" \
-H "openid: tengda" \
-H "authority: xxxxxxxx" \
-d '{
"DID": "device123",
"IMEI": "imei456",
"data": "test_data"
}'
1、secretKey 为重要敏感信息,勿放在前端h5、小程序端、app端;
2、如何使用api代码,可跳过此章节,直接到下一部分。
2.1.3、参数说明
| 参数 | 是否必要参数 | 传值 | 备注 |
|---|---|---|---|
| DID | 是 | 印在设备上的唯一ID; | 设备id必传 |
| IMEI | 否 | 设备IMEI | 不确定场景时传空字符串 |
| openid | 是 | 传前面提到的 appid 或 openid | appid和openid相同,只是叫法不同 |
| timestamp | 时 | 当前时间戳(秒) | 服务器接收到设备报警时的时间戳(秒)。因设备的时间不一定准确,所以不是设备本身的时间。 |
| nonce | 是 | 随机字符串,传8~12位 | 随机码 |
| data | 否 | 每个业务场景有data的生成规则 | 不确定场景时传空字符串 |
| secretKey | 是 | 传前面提到的密钥 secret key | 加密使用的秘钥 |
import (
"crypto/md5"
"encoding/hex"
"fmt"
"strconv"
)
func GenerateSignature(DID, IMEI, openid string, timestamp int64, nonce, data, secretKey string) string {
// 拼接参数字符串
concatenated := DID + IMEI + openid + strconv.FormatInt(timestamp, 10) + nonce + data + secretKey
// 计算MD5哈希
hash := md5.Sum([]byte(concatenated))
// 返回32位小写hex字符串
return hex.EncodeToString(hash[:])
}
/**
* 生成MD5签名token
* @param DID 设备唯一标识
* @param IMEI 设备IMEI号,可不传,
* @param openid 开放平台ID,示例"tengda"
* @param timestamp 时间戳(秒)
* @param nonce 随机字符串
* @param data 业务数据,可以不传
* @param secretKey 签名密钥
* @return MD5签名结果(32位小写hex字符串),出错时返回null
*/
public static String getTokenV2(String DID, String IMEI, String openid,
long timestamp, String nonce,
String data, String secretKey) {
try {
// 拼接字符串
String concatenated = DID + IMEI + openid + timestamp + nonce + data + secretKey;
// 获取MD5实例
MessageDigest md = MessageDigest.getInstance("MD5");
// 计算哈希值
byte[] hashBytes = md.digest(concatenated.getBytes());
// 转换为十六进制字符串
StringBuilder hexString = new StringBuilder();
for (byte b : hashBytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
1、示例代码中,SECRET_KEY 需要从配置文件里读
2、示例代码中,除了sign,nonce和timestamp也由服务端生成。但并不要求开发者也一定要这么做。
3、本示例代码仅作参考,实际运行过程中,受各语言所在的os环境,依赖安装不同而有不同
| 字段 | 位置 | 是否必传 | 值类型 | 值来源 | 备注 |
|---|---|---|---|---|---|
| openid | 请求头 | 是 | string | 管理员提供的 app open id | |
| token | 请求头 | 是 | string | 前端应用程序的session key。是开发者自己的服务端的鉴权参数。默认key=token,但key可以在js配置时自定义为别的值。 | 表格下面有个性化改造后的示例。 |
| did | body | 是 | string | 机器上的设备编号 | |
| IMEI | body | 否 | string | 设备的imei,一般不传 | |
| data | body | 否 | string | 业务数据。需根据实际的业务切换景传入值。 |
| 字段 | 值类型 | 值说明 | 备注 |
|---|---|---|---|
| error_code | int | 返回0表示正常,其它值为异常 | |
| error_message | string | 有异常时,此字段有值。但不一定保证有返回值。 | |
| error_tips | string | 一般是可以用于前端弹窗的提示语。但不一定保证有返回值。 | |
| data | string | ||
| data.sign | string | 返回的签名 | |
| data.nonce | string | 返回的随机字符串 | |
| data.timestamp | int | 返回的时间戳(秒) |
curl -X POST http://localhost:13001/api/v2/token \
-H "Content-Type: application/json" \
-H "openid: myopenid" \
-H "token: xxxxxxxx" \
-d '{
"DID": "device123",
"IMEI": "imei456",
"data": "test_data"
}'
npm install express cors
const express = require('express');
const crypto = require('crypto');
const app = express();
const PORT = 13001;
const SECRET_KEY = 'your_server_secret_key';
function generateConcatenatedString(DID, IMEI = '', openid, timestamp, nonce, data = '', secretKey) {
return `${DID}${IMEI}${openid}${timestamp}${nonce}${data}${secretKey}`;
}
app.use(express.json());
app.post('/api/v2/token', (req, res) => {
try {
const openid = req.headers['openid'];
const { DID, IMEI = '', data = '' } = req.body;
if (!openid || !DID) {
return res.status(200).json({
error_code: 400,
error_message: "Missing required parameters",
data: {}
});
}
const nonce = crypto.randomBytes(16).toString('hex');
const timestamp = Math.floor(Date.now() / 1000);
const concatenated = generateConcatenatedString(DID, IMEI, openid, timestamp, nonce, data, SECRET_KEY);
const sign = crypto.createHash('md5').update(concatenated).digest('hex');
res.status(200).json({
error_code: 0,
error_message: {},
data: { sign, nonce, timestamp }
});
} catch (error) {
console.error('API Error:', error);
res.status(200).json({
error_code: 500,
error_message: "Internal server error",
data: {}
});
}
});
app.listen(PORT, () => {
console.log(`MD5 API服务运行在 http://localhost:${PORT}`);
});
生成sign接口
https://open.eye4cloud.com/{{open_id}}/open/v1/device/generalSign| 字段名 | 是否必传 | 类型 | 备注 |
|---|---|---|---|
| device_id | 是 | string | 设备id |
| timestamp | 是 | int64 | 时间戳,单位:秒 |
| nonce | 是 | string | 随机字符串,8~20个字符 |
| openId | 是 | string | appid |
| secretKey | 是 | string | secretKey |
| imei | 否 | string | imei |
| data | 否 | string | data |
curl 'https://open.eye4cloud.com/{{open_id}}/open/v1/device/generalSign' \
-H 'Content-Type: application/json' \
--data-raw '{
"device_id": "xxxx",
"timestamp": 1758867195,
"nonce": "123456",
"openId": "xxx",
"secretKey": "xxx",
"password": "xxxxx"
}'
| 字段名 | 类型 | 备注 |
|---|---|---|
| error_code | int | 状态码:0正常,其他异常 |
| error_message | string | 错误信息:正常为success |
| data | object | {} |
| data.sign | string | sign |
示例:
{
"error_code": 0,
"error_message": "success",
"error_tips": "",
"data": {
"sign":"xxxx"
}
}